Dies ist der Artikel am 8. Tag des Adventskalenders 2019, NTT Docomo Service Innovation Department. Dieses Mal werde ich die Daten von ** Wikidata **, einer der strukturierten Wissensdatenbanken, mit ** Neo4j **, einer der Graph-DBs, visualisieren.
Einfach ausgedrückt handelt es sich um eine Datenbank, die Diagrammstrukturen verarbeiten kann. Im Vergleich zur beliebten RDB handelt es sich um eine Datenbank, die für die Verarbeitung von ** Beziehungen ** zwischen Daten [^ 1] ausgelegt ist. Ein Diagramm ist übrigens kein Liniendiagramm oder Balkendiagramm, sondern eine Datenstruktur wie in der folgenden Abbildung dargestellt, die durch eine Reihe von Knoten (Kontaktpunkten) und Kanten (Zweigen) dargestellt wird (zitiert aus Wikipedia).
Ich weiß nicht, was es nützlich ist, diese Figur allein zu betrachten, aber die Diagrammstruktur ist sehr nützlich, um verschiedene Dinge in der realen Welt auszudrücken. Wenn Sie sich beispielsweise einen Bahnhof als Knoten und eine Eisenbahn als Kante vorstellen, können Sie eine Streckenkarte als Grafik ausdrücken. Wenn Sie sich eine Stadt als Knoten und eine Straße als Kante vorstellen, können Sie ein Transportproblem ausdrücken. Sie können SNS auch grafisch darstellen, indem Sie Konten als Knoten und Beziehungen zwischen Konten als Kanten betrachten. In Bezug auf die praktische Anwendung scheint es, dass die Kaufhistorie in einer grafischen Struktur ausgedrückt und für die Produktempfehlung verwendet werden kann [^ 2].
Monogoto, das ausgedrückt werden kann | Knoten | Kante |
---|---|---|
Straßenkarte | Bahnhof | Linie |
Logistik | Stadt | Straße |
SNS | Konto | Konto間の関係 |
Internes Personal | Mitarbeiter | Mitarbeiter同士の関係 |
Wikipedia | Seite | Seite間のリンク |
In jüngster Zeit scheint die Aufmerksamkeit für die Grafikstruktur auch im Bereich der Sprachverarbeitung zuzunehmen. Beispielsweise wurde bei ACL, der internationalen Top-Konferenz zur Verarbeitung natürlicher Sprache, im vergangenen Jahr 3 GCN-bezogene Beiträge (Graph Convolutional Netowrk) eingereicht. In diesem Jahr ist die Zahl deutlich auf 11 gestiegen.
Verwenden wir diese Diagramm-DB, um die Beziehung zwischen bestimmten Fakten zu visualisieren.
Für die Visualisierung müssen Daten visualisiert werden, es ist jedoch schwierig, Daten manuell von Grund auf neu zu erstellen. Daher verwenden wir dieses Mal den Speicherauszug von ** Wikidata ** [^ 3], einer vorstrukturierten Wissensdatenbank, um die Daten zu erstellen, die in die Diagramm-DB importiert werden sollen. "Strukturiert" bedeutet "einfach mit einem Computer zu handhaben".
Wikidata ist eine kollaborative Wissensbasis und eines der gleichen Wikimedia-Projekte wie Wikipedia. In Wikidata zum Beispiel wird "Wissen", dass "John Lennons Nationalität das Vereinigte Königreich ist", in Drillingen wie (John Lennon, Nationalität, Vereinigtes Königreich) ausgedrückt. Diese Form von (Entität 1, Eigenschaft, Entität 2) wird als ** Beziehungsdreifach ** bezeichnet. Sie können sich die Entität hier als Titel einer Seite auf Wikipedia vorstellen. Jede Entität hat eine Wikidata-spezifische Kennung, die mit "Q" beginnt (z. B. bezieht sich Q5 auf "Mensch"). Ebenso verfügt die Eigenschaft über eine Wikidata-spezifische Kennung, die mit "P" beginnt.
Alle Wikidata-Daten werden ungefähr jeden Mittwoch im JSON-Format ausgegeben. Verwenden Sie diese Daten also als Daten, die in die Diagramm-DB importiert werden sollen. Laden Sie entweder latest-all.json.bz2
oder latest-all.json.gz
von [hier] herunter (https://dumps.wikimedia.org/wikidatawiki/entities/).
Weitere Informationen zur Struktur des JSON finden Sie unter hier.
Im Moment können Sie das Python-Skript wie unten gezeigt ausführen, um Entitäts- und Eigenschaftsinformationen oder relationale Tripel aus dem Speicherauszug zu extrahieren (beachten Sie, dass dies zeitaufwändig und speicherintensiv sein kann).
#!/usr/bin/env python
# coding: utf-8
import bz2
import json
import codecs
triples = []
qs = []
with bz2.BZ2File('latest-all.json.bz2', 'r') as rf, \
codecs.open('rdf.tsv', 'w', 'utf-8') as rdff, \
codecs.open('q_id.tsv', 'w', 'utf-8') as qf:
next(rf) #Überspringen Sie die erste Zeile
for i, line in enumerate(rf, 1):
try:
line = json.loads(line[:-2])
except json.decoder.JSONDecodeError:
print(i)
rdff.write('\n'.join(['\t'.join(x) for x in triples]) + '\n')
qf.write('\n'.join(['\t'.join(x) for x in qs]) + '\n')
triples = []
qs = []
continue
try:
ett_id = line['id']
except KeyError:
ett_id = None
try:
ett_name = line['labels']['ja']['value']
except KeyError:
ett_name = None
if ett_id is not None and ett_name is not None:
qs.append((ett_id, ett_name))
triple = []
for _, props in line['claims'].items():
for prop in props:
p_id = prop['mainsnak']['property']
try:
id_ = prop['mainsnak']['datavalue']['value']['id']
except Exception as e:
# print(ett_id, p_id, e)
continue
triple.append((ett_id, p_id, id_))
triples.extend(triple)
triple = []
if i % 10000000 == 0:
print(i)
rdff.write('\n'.join(['\t'.join(x) for x in triples]) + '\n')
qf.write('\n'.join(['\t'.join(x) for x in qs]) + '\n')
rdff.write('\n'.join(['\t'.join(x) for x in triples]) + '\n')
qf.write('\n'.join(['\t'.join(x) for x in qs]) + '\n')
q_id.tsv
ist eine durch Tabulatoren getrennte Datei, wie in der folgenden Tabelle gezeigt (diese Datei enthält nicht nur Q ID, sondern auch P ID).
Q ID | Entitätsname |
---|---|
Q31 | Belgien |
Q8 | Glück |
Q23 | George Washington |
Q24 | Jack Bauer |
Q42 | Douglas Adams |
Außerdem sind "rdf.tsv" tabulatorgetrennte Daten, wie in der folgenden Tabelle gezeigt.
Entität 1 | Eigentum | Entität 2 |
---|---|---|
Q31 | P1344 | Q1088364 |
Q31 | P1151 | Q3247091 |
Q31 | P1546 | Q1308013 |
Q31 | P5125 | Q7112200 |
Q31 | P38 | Q4916 |
Kombinieren Sie die beiden oben genannten Dateien, um zwei Dateitypen zu erstellen. Fügen Sie zunächst einen Header zu "q_id.tsv" hinzu, um die durch Tabulatoren getrennten Daten "node.tsv" zu erstellen und zu speichern, wie in der folgenden Tabelle gezeigt (die dritte Spalte ": LABEL" kann vorhanden sein oder nicht). Es gibt so etwas nicht, also können Sie den Dateinamen einfach umbenennen.
id:ID | name | :LABEL |
---|---|---|
Q31 | Belgien | Entity |
Q8 | Glück | Entity |
Q23 | George Washington | Entity |
Q24 | Jack Bauer | Entity |
Q42 | Douglas Adams | Entity |
Gleichzeitig werden die Eigenschaften zwischen Entitäten auch als tabulatorgetrennte Daten "ratios.tsv" gespeichert, wie in der folgenden Tabelle gezeigt. Fügen Sie einfach einen Header zu "rdf.tsv" hinzu und ersetzen Sie ": TYPE" in der zweiten Spalte durch eine Zeichenfolge aus "P000", indem Sie auf "q_id.tsv" verweisen (tatsächlich besteht keine Notwendigkeit, dies ebenfalls zu ersetzen. Es gibt so etwas nicht, also können Sie einfach den Dateinamen umbenennen.
:START_ID | :TYPE | :END_ID |
---|---|---|
Q23 | Ehepartner | Q191789 |
Q23 | Vater | Q768342 |
Q23 | Mutter | Q458119 |
Q23 | Brüder und Schwestern | Q850421 |
Q23 | Brüder und Schwestern | Q7412891 |
Es gibt verschiedene Arten von Eigenschaften wie "Nationalität", "Ehepartner", "Geburtsort" und "Geburtstag", aber es gibt zu viele, wie sie sind, also in dieser Visualisierung zwischen Menschen Ich habe mich auf die Eigenschaften beschränkt, die definiert werden können. Zum Beispiel "Verwandte", "Väter", "Mütter", "Meister" und "Jünger". Außerdem sind die Entitäten auf solche mit japanischen Namen beschränkt.
Es gibt verschiedene Arten von Graph-DBs, aber hier werden wir Neo4j [^ 4] vorstellen, das relativ beliebt ist. Neben Neo4j finde ich Amazon Neptune berühmt (der Name ist cool) [^ 5].
Für macOS wird empfohlen, Homebrew zu installieren.
$ brew cask install homebrew/cask-versions/adoptopenjdk8 #Wenn Java nicht enthalten ist
$ brew install neo4j
Wenn die Version von "Java" anders ist
neo4j: Java 1.8 is required to install this formula.
Install AdoptOpenJDK 8 with Homebrew Cask:
brew cask install homebrew/cask-versions/adoptopenjdk8
Error: An unsatisfied requirement failed this build.
Bitte beachten Sie, dass Sie wütend werden.
Wenn Sie "$ which neo4j" eingeben und die Meldung "/ usr / local / bin / neo4j" angezeigt wird, ist die Installation abgeschlossen.
Importieren Sie die zuvor erstellten node.tsv
und ratios.tsv
in Neo4j. Drücken Sie den folgenden Befehl, um die Daten zu importieren.
$ neo4j-admin import --nodes ./Downloads/nodes.tsv --relationships ./Downloads/relationships.tsv --delimiter="\t"
Wenn der Import erfolgreich ist
IMPORT DONE in 9s 735ms.
Imported:
2269484 nodes
201763 relationships
6808452 properties
Peak memory usage: 1.05 GB
Wird angezeigt.
Verwenden Sie die folgenden Befehle, um den Neo4j-Server zu starten und zu stoppen.
$ neo4j start #Beim Starten des Servers
$ neo4j stop #Beim Stoppen des Servers
Versuchen Sie nach dem Starten des Servers, auf "http: // localhost: 7474" zuzugreifen. Wenn Sie zum ersten Mal darauf zugreifen, werden Sie aufgefordert, sich anzumelden. Geben Sie daher "neo4j" in den Benutzernamen bzw. das Kennwort ein. Danach werden Sie aufgefordert, das Passwort zu ändern. Ändern Sie es daher in ein beliebiges Passwort.
Jetzt bist du bereit. Verwenden wir sofort Neo4j. Neo4j verwendet eine SQL-ähnliche Sprache namens ** Cypher ** als Abfrage (Cypher wird im Folgenden als CQL bezeichnet). Bitte beachten Sie, dass dieser Artikel keine detaillierte Erklärung von CQL enthält.
Der 8. Dezember, wenn dieser Artikel veröffentlicht wird, ist John Lennons Sterbedatum. Nehmen wir also John Lennon als Thema. Nebenbei mag ich "Jealous Guy" am meisten.
Wenn Sie beispielsweise die mit "John Lennon" verknüpfte Entität anzeigen möchten, geben Sie die folgende CQL aus. Diese CQL gibt alle Entitätsknoten vom "John Lennon" -Knoten an 3-Hop zurück.
match p=((:Entity{name:"John Lennon"})-[*1..3]-()) return p
Es ist etwas verwirrend, aber der "John ..." - Knoten unten links in der Mitte ist der "John Lennon" -Knoten. Zum Beispiel von "John Lennon" aufwärts "Ono Yoko" (1) → "Zenzaburo Yasuda" (2) → "Kataoka Jinzaemon" (3) und die Beziehung erstreckt sich auf 3-Hop. Ich werde. Der untere rechte Klumpen ist der bekannte Paul McCartney und seine Familie.
Leider gibt es in dieser Grafik keine Namen von Ringo Star oder George Harrison, die Mitglieder der Beatles waren.
Neo4j kann nach der kürzesten Route suchen, was eines der Hauptmerkmale ist.
Versuchen wir, den kürzesten Weg zwischen "Natsume Soseki" und "Mori Kogai", den literarischen Meistern der Meiji-Ära, zu finden. Der 8. Dezember hat nichts damit zu tun. Nebenbei mag ich "Keibi-Kusa" am meisten.
Stellen Sie eine CQL aus, die der folgenden ähnelt: Schließen Sie einfach das CQL "Alle Knoten zwischen" Natsume Soseki "und" Mori Kogai "" mit "kürzestem Pfad" ein.
match p=shortestpath((:Entity{name:"Natsume Soseki"})-[*]-(:Entity{name:"Mori Kogai"})) return p
"John ..." an der Spitze ist nicht John Lennon, sondern "John Manjiro".
Die beiden lebten zur gleichen Zeit, aber basierend auf dem Wissen von Wikidata ist die Beziehung überraschend weit entfernt. Nach historischen Fakten scheint es keine Interaktion zu geben, die ein Austausch miteinander zu sein schien, da sie sich kannten.
Was ist dann der kürzeste Weg zwischen "John Lennon" und "Natsume Soseki", die nichts miteinander zu tun zu haben scheinen?
match p=shortestpath((:Entity{name:"Natsume Soseki"})-[*]-(:Entity{name:"John Lennon"})) return p
Nachdem er von "Natsume Soseki" zu "Ryunosuke Akutagawa" und "Samuel Beckett" (Autor des Dramas "Waiting for Godo") gearbeitet hatte, war er berühmt für "Bob Dylan" ("Like a Rolling Stone" und gewann den Nobelpreis für Literatur. ), Nachdem Sie die Brücke zwischen Literatur und Musik passiert haben, scheinen Sie "Jimi Hendrix", "Prince", "Shakira" und "John Lennon" zu erreichen. Um ehrlich zu sein, kann ich das Gefühl nicht leugnen, ein wenig abrupt zu sein und einen Umweg zu machen [^ 6].
Wikidata sind ziemlich große strukturierte Daten, aber sie scheinen für die sofortige Verwendung als Wissensbasis etwas unzureichend zu sein. Sie müssen Ihre Wissensbasis beispielsweise mit ** Beziehungsextraktion ** erweitern. Die Beziehungsextraktion ist eine Technik zum Extrahieren des Beziehungs-Tripels (Natsume Soseki, Autor, "Botsuchiyan") aus dem Satz "Natsume Soseki, der Autor von" Botsuchiyan "."
Ich habe versucht, das Wissen über Wikidata mit Neo4j zu visualisieren. Das mit Neo4j gezeichnete Diagramm kann im Browser wellig verschoben werden und macht Spaß. Üben und berühren Sie es daher selbst.
[^ 2]: https://ja.wikipedia.org/wiki/ Ich bin mit der Graphentheorie vertraut
[^ 5]: Herr Hayashi hat letztes Jahr einen Artikel in unserem Adventskalender geschrieben → https://qiita.com/dcm_hayashi/items/9b2536b6fbffa0118fad
[^ 6]: "Nakamura Yoshiko", der beste Freund von "Natsume Soseki" aus der Highschool-Zeit, ist als einer der Vertrauten von "Goto Shinpei" bekannt, der als Präsident Mantetsu und Bürgermeister von Tokio gedient hat. Danach war es "Zenjiro Yasuda", der dem von Fuji vorgeschlagenen Stadtplan zustimmte (übrigens wurde zu dieser Zeit die öffentliche Halle von Hibiya gebaut). Und wenn Sie Yasudas Urenkel folgen, wie Sie "Ono Yoko" und ihren Ehepartner als "John Lennon" kennen, kann dies viel kürzer sein als das Ergebnis von Wikidata.
Recommended Posts