HINTERGRUND
Ich habe Vektoren mit einigen Beispieldaten und jeder Vektor hat einen Kategorienamen (Orte, Farben, Namen).
['john','jay','dan','nathan','bob'] -> 'Names'
['yellow', 'red','green'] -> 'Colors'
['tokyo','bejing','washington','mumbai'] -> 'Places'
Mein Ziel ist es, ein Modell zu trainieren, das eine neue Eingabezeichenfolge verwendet und vorhersagt, zu welcher Kategorie es gehört. Wenn zum Beispiel eine neue Eingabe "violett" ist, sollte ich in der Lage sein, "Farben" als die richtige Kategorie vorherzusagen. Wenn die neue Eingabe "Calgary" ist, sollte "Places" als die richtige Kategorie vorhergesagt werden.
ANSATZ
Ich habe etwas recherchiert und bin auf Word2vec gestoßen. Diese Bibliothek hat eine "Ähnlichkeits-" und "Mostsimilarity" -Funktion, die ich verwenden kann. Ich dachte an eine Brute-Force-Methode:
So zum Beispiel für die Eingabe "pink" kann ich die Ähnlichkeit mit Wörtern in Vektor "Namen" berechnen, einen Durchschnitt nehmen und dann das für die anderen 2 Vektoren auch tun. Der Vektor, der den höchsten Ähnlichkeitsmittelwert ergibt, wäre der korrekte Vektor, zu dem die Eingabe gehört.
PROBLEM
Aufgrund meiner begrenzten Kenntnisse in NLP und maschinellem Lernen bin ich nicht sicher, ob dies der beste Ansatz ist. Daher suche ich Hilfe und Vorschläge für bessere Lösungsansätze für mein Problem. Ich bin offen für alle Vorschläge und weise auch auf mögliche Fehler hin, die ich gemacht habe, da ich im Bereich des maschinellen Lernens und der NLP-Welt neu bin.
Wenn Sie nach der einfachsten/schnellsten Lösung suchen, empfiehlt es sich, die vorbereiteten Word-Einbettungen (Word2Vec oder GloVe) zu nutzen und einfach ein einfaches Abfragesystem darauf aufzubauen. Die Vektoren wurden an einem riesigen Korpus trainiert und enthalten wahrscheinlich eine hinreichende Annäherung an Ihre Domain-Daten.
Hier ist meine Lösung unten:
import numpy as np
# Category -> words
data = {
'Names': ['john','jay','dan','nathan','bob'],
'Colors': ['yellow', 'red','green'],
'Places': ['tokyo','bejing','washington','mumbai'],
}
# Words -> category
categories = {Word: key for key, words in data.items() for Word in words}
# Load the whole embedding matrix
embeddings_index = {}
with open('glove.6B.100d.txt') as f:
for line in f:
values = line.split()
Word = values[0]
embed = np.array(values[1:], dtype=np.float32)
embeddings_index[Word] = embed
print('Loaded %s Word vectors.' % len(embeddings_index))
# Embeddings for available words
data_embeddings = {key: value for key, value in embeddings_index.items() if key in categories.keys()}
# Processing the query
def process(query):
query_embed = embeddings_index[query]
scores = {}
for Word, embed in data_embeddings.items():
category = categories[Word]
dist = query_embed.dot(embed)
dist /= len(data[category])
scores[category] = scores.get(category, 0) + dist
return scores
# Testing
print(process('pink'))
print(process('frank'))
print(process('moscow'))
Um es auszuführen, müssen Sie die vorab trainierten GloVe-Daten von hier (vorsichtig, 800 MB!) Herunterladen und auspacken. Beim Laufen sollte es so etwas erzeugen:
{'Colors': 24.655489603678387, 'Names': 5.058711671829224, 'Places': 0.90213905274868011}
{'Colors': 6.8597321510314941, 'Names': 15.570847320556641, 'Places': 3.5302454829216003}
{'Colors': 8.2919375101725254, 'Names': 4.58830726146698, 'Places': 14.7840416431427}
... das sieht ziemlich vernünftig aus. Und das ist es! Wenn Sie kein so großes Modell benötigen, können Sie die Wörter in glove
nach ihrem tf-idf score filtern. Beachten Sie, dass die Modellgröße nur von den Daten und Wörtern abhängt, die Sie möglicherweise abfragen möchten.
Und was ist es wert, PyTorch hat eine gute und schnellere Implementierung von Glove in diesen Tagen.