Suchalgorithmus mit word2vec [Python]

Überblick

Ich habe einen Suchalgorithmus mit word2vec erstellt, mit der Erwartung, dass nicht nur exakte Wortübereinstimmungen, sondern auch Synonyme getroffen werden. Infolgedessen waren die word2vec-Informationen allein nicht zufriedenstellend, aber es scheint, dass der erwartete Effekt erzielt wird, sodass ich es für nützlich hielt, sie mit anderen Methoden zu kombinieren.

Umgebung

macOS Catalina 10.15.4 python 3.8.0

Word2vec lernen

Ich werde die detaillierte Methode anderen Artikeln überlassen. Ich habe den vollständigen Text von Wikipedia heruntergeladen, ihn mit mecab-ipadic-neologd geteilt und word2vec mit gensim gelernt. Der Code zum Zeitpunkt des Lernens lautet wie folgt. Ich habe den Code von Erstellen eines word2vec-Modells mit dem Wikipedia-Korpus | Adhesive Devotion Diary ausgeliehen.

from gensim.models import word2vec
import logging

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus('./wiki_wakati_neologd.txt')

model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15)
model.save("./wiki_neologd.model")

Suchalgorithmus

Berechnen Sie die Ähnlichkeit zwischen dem Eingabetext und der Liste der zu durchsuchenden Dokumente mit der folgenden Methode, um den Text mit der höchsten Ähnlichkeit zu erhalten.

Der Code, der das oben genannte erreicht, ist unten.

import re
import neologdn
import MeCab, jaconv
import pandas as pd
from gensim.models import word2vec

#Laden des word2vec-Modells
MODEL_PATH = "wiki_neologd.model"
model = word2vec.Word2Vec.load(MODEL_PATH)
#Objekt für die morphologische Analyse
m = MeCab.Tagger()
#Objekt für die normale Ausdrucksverarbeitung
re_kana = re.compile('[a-zA-Z\u3041-\u309F]')
re_num = re.compile('[0-9]+')

#Dokumentieren Sie die Normalisierungsfunktion vor der morphologischen Analyse
def format_text(text):
  text = neologdn.normalize(text)
  return text

#Funktion zum Extrahieren des Prototyps des unabhängigen Wortes des Satzes mit Ausnahme eines alphanumerischen Zeichens
def extract_words(text):
  words = []
  for token in m.parse(text).splitlines()[:-1]:
    if '\t' not in token: continue

    surface = token.split('\t')[0]
    pos = token.split('\t')[1].split(',')

    ok = (pos[0]=='Substantiv' and pos[1] in ['Allgemeines','固有Substantiv','Verbindung ändern','Adjektiv Verbstamm'])
    ok = (ok or (pos[0]=='Adjektiv' and pos[1] == 'Unabhängigkeit'))
    ok = (ok or (pos[0]=='Adverb' and pos[1] == 'Allgemeines'))
    ok = (ok or (pos[0]=='Verb' and pos[1] == 'Unabhängigkeit'))

    if ok == False: continue

    stem = pos[-3]

    if stem == '*': stem = surface
    if stem == '- -': continue
    if re_kana.fullmatch(stem) and len(stem)==1: continue
    if re_num.fullmatch(stem): continue
    if stem == '': continue

    words.append(stem)
  return words
#Extrahieren Sie unabhängige Wörter aus einer Reihe von Dokumenten und erstellen Sie eine Datenbank.
def get_document_db(documents):
  id_list = list(range(len(documents)))
  words_list = []
  for d in documents:
    d = format_text(d)
    words = extract_words(d)
    #Duplikate ausschließen
    words = set(words)
    #Schließen Sie Wörter aus, die nicht in word2vec enthalten sind
    words = [w for w in words if w in model.wv.vocab]
    words_list.append(words)
  db = pd.DataFrame({"id":id_list, "text":documents, "word":words_list})
  return db

#Gibt die Ähnlichkeit zwischen Wortliste A und Wortliste B zurück
def calc_similarity(words1, words2):
  total = 0
  for w1 in words1:
    if w1 not in model.wv.vocab: continue
    max_sim = 0
    for w2 in words2:
      if w2 not in model.wv.vocab: continue
      sim = model.wv.similarity(w1=w1, w2=w2)
      max_sim = max(max_sim, sim)
    total += max_sim
  return total

#Berechnet die Ähnlichkeit zwischen der Eingabeanweisung und jedem Dokument in db und gibt sie zurück
def add_similarity_to_db(text, db):
  text = format_text(text)
  words1 = extract_words(text)
  #Duplikate ausschließen
  words1 = set(words1)
  words1 = [w for w in words1 if w in model.wv.vocab]
  similarity = []
  for words2 in db.word:
    sim = calc_similarity(words1, words2)
    similarity.append(sim)

  similarity_df = pd.DataFrame({"similarity": similarity})
  db2 = pd.concat([db,similarity_df], axis=1)
  
  db2 = db2.sort_values(["similarity"], ascending=False)
  db2 = db2.reset_index()
  return db2

#Ausgabeprüfung
#Zu durchsuchender Dokumentensatz
#Erstellen Sie eine Liste von Dokumenten, Element für Element. Hier verwende ich als Beispiel Sätze, die angemessen aus meinen früheren Artikeln extrahiert wurden.
documents = [
  'Ich habe eine Funktion erstellt, um die japanische Aussprache in Kana mit MeCab und Python zu erhalten. Wenn Sie beispielsweise "Ich habe heute gut geschlafen" eingeben, wird "Kyowayokunemashita" zurückgegeben.',
  'Ich habe eine Python-Funktion erstellt, die Japanisch (Katakana-Zeichenkette) in Einheiten von Mora (Mora-Division) unterteilt. Mora und Silben sind typische Teilungseinheiten für die japanische Phonologie. Mora ist ein Begrenzer beim Zählen der sogenannten "5, 7, 5" im Haiku, und lange Töne (-), Aufforderungstöne (tsu) und Tonabwehrmittel (n) werden ebenfalls als ein Schlag gezählt. Andererseits werden in Silben lange Noten, Aufforderungstöne und abstoßende Töne nicht einzeln gezählt, sondern als ein Schlag zusammen mit dem Kana betrachtet, das unmittelbar zuvor eine einzelne Silbe sein kann.',
  'Ich habe eine Python-Funktion erstellt, die Japanisch (Katakana-Zeichenkette) in Silben (Sektar-Teilung) unterteilt. Mora und Silben sind typische Teilungseinheiten für die japanische Phonologie. Mora ist ein Begrenzer beim Zählen der sogenannten "5, 7, 5" im Haiku, und lange Töne (-), Aufforderungstöne (tsu) und Tonabwehrmittel (n) werden ebenfalls als ein Schlag gezählt. Andererseits werden in Silben lange Noten, Aufforderungstöne und abstoßende Töne nicht einzeln gezählt, sondern als ein Schlag zusammen mit dem Kana betrachtet, das unmittelbar zuvor eine einzelne Silbe sein kann. Wenn ein langer Ton, ein auffordernder Ton und eine Schallabweisung wie "Brennen" kontinuierlich sind, wird die Anzahl der Mora von 3 oder mehr zu einer Silbe.',
  'In Python habe ich eine Funktion erstellt, die (die unterste Zeile der folgenden Tabelle) nach Phrasen und nicht nach Wörtern (Teilen) unterteilt.',
  '"Finden Sie die 25 Billionen Ziffern der 100 Billionen Etage(Ich habe versucht, das Problem "Notation is decimal system)" mit Python zu lösen. (Die ursprüngliche Geschichte ist die berühmte Frage: "Ist die 25-Billionen-Zahl von rechts von den 100 Billionen Stockwerken gerade oder ungerade?")',
  'Das Standardwörterbuch von MeCab ist mecab-ipadic-Dies ist ein Memo von dem, was ich in meiner Umgebung (macOS) getan habe, um zu NEologd zu wechseln. Wie viele Leute bereits geschrieben haben, kann das Standardwörterbuch durch Bearbeiten einer Datei namens Mecabrc geändert werden. In meiner Umgebung gibt es jedoch mehrere Mecabrc, und ich habe mich gefragt, welche und welche ich bearbeiten soll Ich schreibe darüber, wie es tatsächlich funktioniert hat, einschließlich der Frage, ob eine Datei bearbeitet werden sollte.'
]

db = get_document_db(documents)
input_texts = ["Separates Japanisch","Berechnung des Bodens","Trenne Japanisch mit Mora", "Trennen Sie Japanisch durch Silben"]
for text in input_texts:
  print(text)
  result = add_similarity_to_db(text, db)
  for sim, d in list(zip(result.similarity, result.text))[:10]:
    disp = d
    if len(d)>20: disp = d[:20]+"..."
    print(sim, disp)

Die Ausgabe ist unten. Die Anzahl der Dokumente ist gering und als Beispiel schwer zu verstehen, aber die ersten beiden Ergebnisse sind so. In den beiden letzteren waren die Punktzahlen für Mora und Silben genau gleich. Es scheint, dass Mora und Silben in diesem Dokumentensatz nebeneinander existierten. Das Gewicht der Wörter in jedem Dokument in die Berechnung mit tfidf usw. einzubeziehen, mag besser sein, aber ich möchte es in Zukunft überprüfen.

Separates Japanisch
2.593316972255707 Japanische Minuten (Katakana-Zeichenfolge) in Mora-Einheiten...
2.593316972255707 Japanisch (Katakana-Zeichenfolge) geteilt durch Silbe...
1.6599590480327606 Japanische Aussprache mit MeCab und Python...
1.5144233107566833 Das Standardwörterbuch von MeCab ist mecab-...
1.4240807592868805 In Python keine Einheit von Wörtern (Teilen)...
1.18932443857193 "Finden Sie die 25 Billionen Ziffern der 100 Billionen Etage...
Berechnung des Bodens
1.4738755226135254 "Ermitteln Sie die 25-Billionen-Ziffernzahl des 100-Billionen-Bodens...
1.1860262751579285 Japanische Aussprache mit MeCab und Python...
1.1831795573234558 Japanische Minuten (Katakana-Zeichenfolge) in Mora-Einheiten...
1.1831795573234558 Japanisch (Katakana-Zeichenkette) geteilt durch Silbe...
1.1831795573234558 In Python ist es keine Einheit von Wörtern (Teilen)...
0.7110081613063812 Das Standardwörterbuch von MeCab ist mecab-...
Trenne Japanisch mit Mora
3.0 Minuten Japanisch (Katakana-Zeichenkette) in Mora-Einheiten...
3.0 Ist Japanisch (Katakana-Zeichenfolge) in Silbeneinheiten unterteilt?...
1.754945456981659 Japanische Aussprache mit MeCab und Python...
1.6068530082702637 In Python, nicht in Worten (Teilen)...
1.226668268442154 Das Standardwörterbuch von MeCab ist mecab-...
1.1506744921207428 "Ermitteln Sie die 25-Billionen-Ziffernzahl des 100-Billionen-Bodens...
Trennen Sie Japanisch durch Silben
3.0 Minuten Japanisch (Katakana-Zeichenkette) in Mora-Einheiten...
3.0 Ist Japanisch (Katakana-Zeichenfolge) in Silbeneinheiten unterteilt?...
1.862914353609085 Japanische Aussprache mit MeCab und Python...
1.6907644867897034 In Python, nicht in Worten (Teilen)...
1.2761026918888092 MeCabs Standardwörterbuch mecab-...
1.2211730182170868 "Ermitteln Sie die 25-Billionen-Ziffernzahl des 100-Billionen-Bodens...

Recommended Posts

Suchalgorithmus mit word2vec [Python]
Suchen Sie Twitter mit Python
Algorithmus in Python (Dichotomie)
Python-Algorithmus
Python2 + word2vec
Algorithmus in Python (Breitenprioritätssuche, bfs)
Suche nach Tiefenpriorität mit Stack in Python
Python-Memorandum (Algorithmus)
Algorithmus in Python (ABC 146 C Dichotomie
Durchsuche das Labyrinth mit dem Python A * -Algorithmus
Starten Sie Python
String-Suchalgorithmus
Scraping mit Python
Was ist ein Algorithmus? Einführung in den Suchalgorithmus] ~ Python ~
Python-Pandas: Suchen Sie mit regulären Ausdrücken nach DataFrame
Verbesserte Suche nach Pokemon-Rennwerten mit Python
Ein * Algorithmus (Python Edition)
Sequentielle Suche mit Python
Bearbeiten Sie Redmine mit Python Redmine
Fibonacci-Sequenz mit Python
Python-Übung 1-Breiten-Prioritätssuche
[Python] Suche (itertools) ABC167C
Dichotomie mit Python
Genetischer Algorithmus in Python
[Python] Suche (NumPy) ABC165C
Memo zur Bisektionssuche (python2.7)
[Python] Bisection-Suche ABC155D
Verwenden von Python # externen Paketen
Python Bit vollständige Suche
Algorithmus in Python (Bellman-Ford-Methode, Bellman-Ford)
WiringPi-SPI-Kommunikation mit Python
Lineare Suche in Python
Dichotomie mit Python
Altersberechnung mit Python
Python neu lernen (Algorithmus I)
Dichotomie mit Python 3
Namensidentifikation mit Python
Hinweise zur Verwendung von Python-Unterprozessen
Binäre Suche in Python
Versuchen Sie es mit Tweepy [Python2.7]
Algorithmus in Python (Dijkstra)
Verwenden Sie die Such-API der National Parliament Library in Python
Mit Python abflachen
Scraping mit Python 3.5 async / await
[Python] BFS (Suche nach Breitenpriorität) ABC168D
Speichern Sie Bilder mit Python3-Anforderungen
[S3] CRUD mit S3 unter Verwendung von Python [Python]
[Python] Versuchen Sie, Tkinters Leinwand zu verwenden
Algorithmus in Python (Haupturteil)
In-Graph-Pfadsuche mit Networkx
Verwenden von Quaternion mit Python ~ numpy-quaternion ~
Versuchen Sie es mit Kubernetes Client -Python-
[Python] Verwenden von OpenCV mit Python (Basic)
Emotionsanalyse von Python (word2vec)
Probieren Sie die ähnliche Suche von Image Search mit Python SDK [Search] aus.