Wie zu beschleunigen Gensim Word2vec Modell laden Zeit?
Baue ich einen chatbot, also muss ich Vektorisieren die Eingabe des Benutzers mit Word2Vec.
Ich bin mit einem pre-trainierte Modell mit 3 Millionen Wörter, die von Google (GoogleNews-Vektoren-negative300).
So, ich lade das Modell mit Gensim:
import gensim
model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
Das problem ist, dass es dauert etwa 2 Minuten, um das Modell zu laden. Ich kann nicht zulassen, dass der Benutzer so lange warten.
Also, was kann ich tun zur Beschleunigung der Ladezeit?
Dachte ich über das setzen jedes der 3 Millionen Wörter und Ihre entsprechenden Vektor in eine MongoDB-Datenbank. Das würde sicherlich beschleunigt, aber die intuition sagt mir, es ist keine gute Idee.
Du musst angemeldet sein, um einen Kommentar abzugeben.
In den letzten gensim-Versionen können Sie laden eine Teilmenge ausgehend von der front der Datei mit der optionalen
limit
parameterload_word2vec_format()
. (Die GoogleNews-Vektoren scheinen sich in etwa die meisten - am wenigsten - Häufig um, so dass die ersten N sind in der Regel die N-sortierte Teilmenge würden Sie wollen. So verwendenlimit=500000
zu bekommen, die meisten häufigen 500.000 Wörtern' Vektoren – immer noch einen ziemlich großen Wortschatz – Einsparung 5/6ths der Speicher/load-Zeit.)So, dass kann ein bisschen helfen. Aber wenn Sie re-loading für jede web-Anfrage, Sie werden immer noch verletzt aus dem laden ist IO-bound-Geschwindigkeit, und die redundanten Speicher-overhead für die Speicherung jedes re-load.
Gibt es einige tricks, die Sie verwenden können, in Kombination, um zu helfen.
Beachten Sie, dass nach dem laden solche Vektoren, die in Ihrer ursprünglichen word2vec.c-format entstanden, können Sie re-speichern Sie mithilfe von gensim native
save()
. Wenn Sie Sie speichern unkomprimiert, und die backing-array groß genug ist (und die GoogleNews-set ist definitiv groß genug), der Träger array wird anschließend in einer separaten Datei in einem raw-binary-format. Diese Datei kann später mit zugewiesenem Speicher von der Festplatte, mit gensim native[load(filename, mmap='r')][1]
option.Zunächst wird der laden scheint bissig – eher als das Lesen der array von der Festplatte, wird das Betriebssystem nur anzeigen virtuelle Adresse, die Regionen auf der Festplatte Daten, so dass einige Zeit später, wenn der code greift auf jene Speicherbereiche, die notwendigen Bereiche Lesen von der Festplatte. So weit, So gut!
Jedoch, wenn Sie dabei sind, die typischen Operationen wie
most_similar()
werden Sie immer noch mit großen lags, nur ein wenig später. Das ist, weil dieser Vorgang erfordert sowohl eine erste scan-und-Berechnung über alle Vektoren (beim ersten Aufruf, zum erstellen von unit-Länge normalisierte Vektoren für jedes Wort), und dann noch eine scan-und-Berechnung über alle die normierte Vektoren (bei jedem Anruf zu finden, die N-meisten-ähnlichen Vektoren). Diejenigen, die full-scan-Zugriffe-Seite-in-RAM das ganze array wieder kostet das paar von Minuten von disk-IO.Was Sie wollen, ist zu vermeiden Redundant zu tun, dass Einheit-Normalisierung und die zahlen der IO-Kosten, nur einmal. Das erfordert halten die Vektoren im Speicher für die Wiederverwendung durch alle nachfolgenden web-requestes (oder sogar mehrere parallele web-Anfragen). Zum Glück memory-mapping kann auch hier helfen, wenn auch mit ein paar extra-prep Schritte.
Laden Sie zuerst die word2vec.c-format Vektoren, mit
load_word2vec_format()
. Verwenden Sie dannmodel.init_sims(replace=True)
zu zwingen, die Einheit-Normalisierung, destruktiv in-place (Stress für den nicht-normalisierte Vektoren).Speichern Sie dann das Modell, um einen neuen Dateinamen-Präfix: Modell.speichern('GoogleNews-Vektoren-gensim-genormt.bin". (Beachten Sie, dass dies tatsächlich erstellt mehrere Dateien auf der Festplatte, die gehalten werden müssen, zusammen für das Modell neu geladen.)
Nun, wir machen ein kurzes Python Programm, welches dazu dient, sowohl die Speicher-Karte laden Sie die Vektoren und Kraft, die das gesamte array in den Speicher. Wir wollen auch, dass dieses Programm zu hängen, bis extern beendet (wobei die Zuordnung lebendig), und vorsichtig sein, nicht neu zu berechnen, die bereits normierte Vektoren. Dies erfordert einen anderen trick, weil die geladenen KeyedVectors eigentlich gar nicht wissen, dass die Vektoren sind normiert. (In der Regel nur die raw-Vektoren gespeichert sind, und die normierte Versionen neu berechnet, wenn notwendig).
Ungefähr Folgendes sollte funktionieren:
Das wird noch eine Weile dauern, aber muss nur einmal gemacht werden, die vor/außerhalb einer web-Anfragen. Während der Prozess ist lebendig, die Vektoren bleiben in den Speicher gemappt. Weiter, es sei denn,/bis es die anderen virtuellen-Speicher-Druck, die Vektoren bleiben sollte, die in den Speicher geladen. Das ist wichtig für das, was als Nächstes kommt.
Schließlich in Ihrem web-request-handling-code, du kannst jetzt nur Folgendes tun:
Mehrere Prozesse teilen können read-only memory-mapped-Dateien. (Das ist, wenn das Betriebssystem weiß, dass Datei X wird im Arbeitsspeicher an einer bestimmten position, jeder andere Prozess, der auch will, einen nur-lese-mapped version von X gelenkt werden, um re-use, dass Daten, die an dieser position.).
So, in diesem web-reqeust
load()
, und alle nachfolgenden Zugriffe, können alle re-verwenden Sie die Daten, die vor der Arbeit schon gebracht address-space und active-Speicher. Operationen die ähnlichkeit-calcs gegen jeden Vektor wird noch die Zeit nehmen, um auf mehrere GB RAM, und führen Sie die Berechnungen/Sortierung, wird aber nicht mehr erfordern zusätzliche disk-IO und redundante re-Normalisierung.Wenn das system konfrontiert ist, anderen Arbeitsspeicher, reicht der array kann fallen aus Speicher, bis die nächsten Seiten Lesen Sie wieder ein. Und wenn die Maschine fehlt der RAM immer voll laden der Vektoren, dann ist jeder scan erfordert eine Vermischung von paging-ein-und-aus, und die Leistung ist frustrierend schlecht, egal was. (In diesem Fall ist: Holen Sie mehr RAM oder eine kleinere vector set.)
Aber wenn man nicht genug RAM haben, diese Winde machen die ursprüngliche/Natürliche Belastung-und-Einsatz-direkt-code "einfach so" funktionieren, in einer Recht schnellen Art und Weise, ohne einen zusätzlichen web-service-Schnittstelle, da die Maschine freigegebene Datei-mapped-memory-Funktionen als service-Schnittstelle.
Ich habe das problem immer wenn ich den google news-Datensatz. Die Frage ist, gibt es weitere Worte, die in das dataset als Sie jemals brauchen werden. Es gibt eine riesige Menge von Tipp-und was nicht. Was ich tun ist, Scannen Sie die Daten, die ich arbeite, bauen Sie ein Wörterbuch von sagen wir 50k häufigsten Wörter, Holen Sie sich die Vektoren mit Gensim und speichern Sie das Wörterbuch. Laden Sie dieses Wörterbuch nimmt eine halbe Sekunde statt 2 Minuten.
Wenn Sie keine speziellen Datensatz, den Sie verwenden konnten, die 50 oder 100k häufigsten Wörter aus einem großen Datensatz, wie ein news-Datensatz von WMT, um Ihnen den Einstieg.
Andere Optionen sind stets Gensim läuft. Sie können erstellen Sie eine FIFO für ein Skript ausgeführt Gensim. Das Skript verhält sich wie ein "server", den man Lesen kann, eine Datei, für die ein "Kunde" schreibt, gerade für Vektor-Anfragen.
Ich denke, die eleganteste Lösung ist, um einen web-service die Bereitstellung von word-Einbettungen. Überprüfen Sie heraus die word2vec API als ein Beispiel. Nach der Installation bekommen Sie die Einbettung für "restaurant" ist einfach:
Ich wirklich Liebe vzhong Einbettung Bibliothek. https://github.com/vzhong/embeddings
Speichert word Vektoren in SQLite, was bedeutet, brauchen wir nicht zu laden-Modell, aber nur fetch entsprechenden Vektoren aus DB 😀
Erfolg Methode:
Modell = Word2Vec.load_word2vec_format('wikipedia-pubmed-und-PMC-w2v.bin',binary=True)
Modell.init_sims(replace=True)
Modell.speichern('bio_word')
später das Modell laden
Word2Vec.load('bio_word',mmap='r')
https://groups.google.com/forum/#!Thema/gensim/OvWlxJOAsCo