Es gibt eine Möglichkeit, Doc2Vec usw. zu verwenden, um die Ähnlichkeit zwischen Sätzen zu berechnen, aber es ist ein wenig mühsam, weil ich ein Modell dafür von Grund auf neu erstellen muss. Es ist möglicherweise vielseitiger und einfacher, das Word2Vec-Modell zu verwenden, als wenn Sie nur ein bestimmtes Maß an Genauigkeit erreichen möchten.
Also berechnete ich die Ähnlichkeit zwischen Sätzen basierend auf dem Merkmalsvektor-Durchschnitt der im Satz enthaltenen Wörter und der Kosinus-Ähnlichkeit zwischen Sätzen.
# OS
macOS Sierra
# Python(Verwenden Sie Anaconda)
Python : Python 3.5.3 :: Anaconda custom (x86_64)
pip : 9.0.1 from /Users/username/anaconda/lib/python3.5/site-packages (python 3.5)
Es funktionierte nicht gut mit Python3.6, also Python3.5-Version von Anaconda ([Anaconda 4.2.0 für Python3]) (https://repo.continuum.io/archive/Anaconda3-4.2.0-MacOSX-x86_64] .pkg)) wird verwendet.
Es hat zu lange gedauert, bis mein MacBook Air ein Wörterbuch aus dem Korpus erstellt hat
Das trainierte Modell von fastText wurde veröffentlicht
Wir haben ein veröffentlichtes trainiertes Modell verwendet. Dieses Mal verwenden wir ein Modell (model_neologd.vec), in dem der Text von Wikipedia mit NEologd von MeCab unterteilt und von fastText trainiert wird. (Anzahl der Dimensionen: 300)
import gensim
word2vec_model = gensim.models.KeyedVectors.load_word2vec_format('model/model_neologd.vec', binary=False)
(Da die Datei fast 1 GB groß ist, dauert das Lesen mehrere zehn Sekunden.)
Mit diesem Modell können Sie eine semantische Berechnung von Wörtern mithilfe von Merkmalsvektoren durchführen.
import pprint
pprint.pprint(word2vec_model.most_similar(positive=['Frau', 'König'], negative=['Mann']))
# => [('Königin', 0.7062159180641174),
# ('königlich', 0.6530475616455078),
# ('königlich', 0.6122198104858398),
# ('Prinz', 0.6098779439926147),
# ('königliche Familie', 0.6084121465682983),
# ('Prinzessin', 0.6005773544311523),
# ('Königin', 0.5964134335517883),
# ('König', 0.593998908996582),
# ('Herr', 0.5929002165794373),
# ('Königlicher Palast', 0.5772185325622559)]
#Wenn Sie die Ähnlichkeit zwischen einfachen Wörtern berechnen möchten, modellieren Sie.Kann durch Ähnlichkeit berechnet werden
pprint.pprint(word2vec_model.similarity('König', 'Königin'))
# => 0.74155587641044496
pprint.pprint(word2vec_model.similarity('König', 'Ramen'))
# => 0.036460763469822188
Irgendwie ist das Ergebnis so.
Verwenden Sie MeCab, um die natürliche Sprache in separate Notizen zu zerlegen. Geben Sie mecab-ipadic-neologd an, mit dem auch trainierte Modelle als Wörterbuch generiert werden, und geben Sie die Ausgabe in Form einer Division an.
import MeCab
mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd -Owakati")
mecab.parse("Er hat gestern Hunger bekommen")
# => 'Er hat sich gestern den Bauch gebrochen\n'
Der getrennte Text wird durch Leerzeichen getrennt. Da der Zeilenumbruch am Ende enthalten ist, muss er zum Zeitpunkt der Implementierung gelöscht werden. (MeCab wurde übrigens mit mecab-python3 installiert. Es scheint, dass es mit der python3.6-Serie nicht richtig funktioniert, daher musste ich 2017/5 die python3.5-Serie verwenden.)
Bei diesem Verfahren wird der Merkmalsvektormittelwert der im Satz verwendeten Wörter als Merkmalsvektor des Satzes selbst verwendet, so dass eine Funktion dafür definiert wird.
import numpy as np
def avg_feature_vector(sentence, model, num_features):
words = mecab.parse(sentence).replace(' \n', '').split() #Unterbrechen Sie die Linie am Ende des Mecab(\n)Wird ausgegeben, also entfernen Sie es
feature_vec = np.zeros((num_features,), dtype="float32") #Feature-Vektor-Container initialisieren
for word in words:
feature_vec = np.add(feature_vec, model[word])
if len(words) > 0:
feature_vec = np.divide(feature_vec, len(words))
return feature_vec
Es werden nur die Merkmalsvektoren für jedes Wort gemittelt. (Da die Anzahl der Dimensionen des trainierten Modells 300 beträgt, geben Sie 300 für num_features an.)
avg_feature_vector("Er hat gestern Hunger bekommen", word2vec_model, 300)
# => array([ 6.39975071e-03, -6.38077855e-02, -1.41418248e-01,
# -2.01289997e-01, 1.76049918e-01, 1.99666247e-02,
# : : :
# -7.54096806e-02, -5.46530560e-02, -9.14395228e-02,
# -2.21335635e-01, 3.34903784e-02, 1.81226760e-01], dtype=float32)
Bei der Ausführung denke ich, dass eine 300-dimensionale Merkmalsmenge ausgegeben wird.
Verwenden Sie als Nächstes die obige Funktion, um die Kosinusähnlichkeit des Durchschnittsvektors zwischen den beiden Sätzen zu berechnen.
from scipy import spatial
def sentence_similarity(sentence_1, sentence_2):
#Das diesmal verwendete Word2Vec-Modell wird mit einem 300-dimensionalen Merkmalsvektor generiert, also num_Funktionen auch als 300 angegeben
num_features=300
sentence_1_avg_vector = avg_feature_vector(sentence_1, word2vec_model, num_features)
sentence_2_avg_vector = avg_feature_vector(sentence_2, word2vec_model, num_features)
#Berechnen Sie die Kosinusähnlichkeit, indem Sie den Abstand zwischen Vektoren von 1 subtrahieren
return 1 - spatial.distance.cosine(sentence_1_avg_vector, sentence_2_avg_vector)
Mit dieser Funktion können Sie die Ähnlichkeit zwischen Sätzen leicht berechnen. (Der Bereich liegt zwischen 0 und 1, und je näher er an 1 liegt, desto ähnlicher ist er.)
result = sentence_similarity(
"Er hat gestern ein scharfes Ramen gegessen und ist hungrig geworden",
"Gestern habe ich ein scharfes chinesisches Essen gegessen und bin hungrig geworden"
)
print(result)
# => 0.973996032475
result = sentence_similarity(
"Es ist nicht gut ... Ich muss schnell etwas tun ...",
"Wir liefern sorgfältig ausgewählte Auftragsinformationen"
)
print(result)
# => 0.608137464334
Ich konnte so einen numerischen Wert berechnen!
** Bei langen Sätzen ist der Ähnlichkeitsgrad hoch. ** ** ** Da nur der Durchschnitt der Wörter genommen und verglichen wird, wird es schwierig, den Durchschnittswert zwischen Sätzen in einem langen Satz zu unterscheiden, und die Ähnlichkeit wird selbst in nicht verwandten Sätzen hoch.
result = sentence_similarity(
"Es ist endlich in der Geschichte dieser Geschichte. Endlich würden andere Pädagogen an einen Punkt kommen, an dem sie nicht vorantreiben sollten, aber ich bin sicher, dass sie missverstanden werden, und ich bin bis zu einem gewissen Grad damit zufrieden.",
"Auch wenn ich krank bin, ist es ein guter Tag. Wenn Sie an Gauche als Maus denken, nippte Ihr Gesicht an dem Seufzer der Doremifa und dem nächsten Fuchscello, und der Unterschied zwischen ihnen ist ganz anders."
)
print(result)
# => 0.878950984671
Selbst wenn dies möglich ist, ist der Vergleich zwischen Sätzen mit 10 Wörtern die Grenze.
** Kann nicht mit unbekannten Wörtern umgehen. ** ** ** Da es nicht möglich ist, einen Merkmalsvektor für ein unbekanntes Wort auszugeben, das nicht im trainierten Modell registriert ist, erscheint es notwendig, Maßnahmen zu ergreifen, beispielsweise das Wort selbst mit dem durchschnittlichen Merkmalsvektor anderer Wörter zu füllen. (In diesem Fall weisen unbekannte Wörter jedoch häufig semantische Merkmale auf, was die Genauigkeit der Ähnlichkeit verringert.)
>>> result = sentence_similarity(
... "Die Annahme von Empfehlungen ist in den letzten Jahren populär geworden",
... "Die Ära der Batch-Rekrutierung neuer Absolventen ist vorbei"
... )
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
File "<stdin>", line 5, in sentence_similarity
File "<stdin>", line 6, in avg_feature_vector
File "/Users/username/anaconda/lib/python3.5/site-packages/gensim/models/keyedvectors.py", line 574, in __getitem__
return self.word_vec(words)
File "/Users/username/anaconda/lib/python3.5/site-packages/gensim/models/keyedvectors.py", line 273, in word_vec
raise KeyError("word '%s' not in vocabulary" % word)
KeyError: "word 'Verweisung' not in vocabulary"
In diesem Fall kann ich das Wort "Überweisung" nicht finden und es fehlt mir.
Da die Methode selbst einfach ist, denke ich, dass die Fälle, die verwendet werden können, ziemlich begrenzt sind. Im Gegenteil, wenn es nur notwendig ist, mit kurzen Sätzen umzugehen, scheint es, dass diese Methode auch eine gewisse Genauigkeit liefern kann. Ist es nicht ein einfacher Ansatz, eine Methode wie Doc2Vec zu verwenden, um die Ähnlichkeit zwischen Sätzen ernsthaft zu finden und einen Korpus zu erstellen, der dem Zweck des Modells selbst entspricht? ..
import gensim
import MeCab
import numpy as np
from scipy import spatial
word2vec_model = gensim.models.KeyedVectors.load_word2vec_format('model/model_neologd.vec', binary=False)
mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd -Owakati")
#Berechnen Sie den Durchschnitt der Merkmalsvektoren der im Satz verwendeten Wörter
def avg_feature_vector(sentence, model, num_features):
words = mecab.parse(sentence).replace(' \n', '').split() #Unterbrechen Sie die Linie am Ende des Mecab(\n)Wird ausgegeben, also entfernen Sie es
feature_vec = np.zeros((num_features,), dtype="float32") #Feature-Vektor-Container initialisieren
for word in words:
feature_vec = np.add(feature_vec, model[word])
if len(words) > 0:
feature_vec = np.divide(feature_vec, len(words))
return feature_vec
#Berechnen Sie die Ähnlichkeit zwischen zwei Sätzen
def sentence_similarity(sentence_1, sentence_2):
#Das diesmal verwendete Word2Vec-Modell wird mit einem 300-dimensionalen Merkmalsvektor generiert, also num_Funktionen auch als 300 angegeben
num_features=300
sentence_1_avg_vector = avg_feature_vector(sentence_1, word2vec_model, num_features)
sentence_2_avg_vector = avg_feature_vector(sentence_2, word2vec_model, num_features)
#Berechnen Sie die Kosinusähnlichkeit, indem Sie den Abstand zwischen Vektoren von 1 subtrahieren
return 1 - spatial.distance.cosine(sentence_1_avg_vector, sentence_2_avg_vector)
result = sentence_similarity(
"Er hat gestern ein scharfes Ramen gegessen und ist hungrig geworden",
"Gestern habe ich ein scharfes chinesisches Essen gegessen und bin hungrig geworden"
)
print(result)
# => 0.973996032475
Recommended Posts