Verwenden einer vorab trainierten Worteinbettung (word2vec oder Glove) in TensorFlow

95

Ich habe kürzlich eine interessante Implementierung für die Klassifizierung von Faltungstexten überprüft . Alle von mir überprüften TensorFlow-Codes verwenden jedoch zufällige (nicht vorab trainierte) Einbettungsvektoren wie die folgenden:

with tf.device('/cpu:0'), tf.name_scope("embedding"):
    W = tf.Variable(
        tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
        name="W")
    self.embedded_chars = tf.nn.embedding_lookup(W, self.input_x)
    self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)

Weiß jemand, wie man die Ergebnisse von Word2vec oder einer von GloVe vorgefertigten Worteinbettung anstelle einer zufälligen verwendet?

user3147590
quelle

Antworten:

130

Es gibt verschiedene Möglichkeiten, wie Sie eine vorab trainierte Einbettung in TensorFlow verwenden können. Angenommen, Sie haben die Einbettung in ein NumPy-Array embeddingmit vocab_sizeZeilen und embedding_dimSpalten aufgerufen und möchten einen Tensor erstellen W, der in einem Aufruf von verwendet werden kann tf.nn.embedding_lookup().

  1. Erstellen Sie einfach Wals ein tf.constant(), das embeddingals seinen Wert nimmt:

    W = tf.constant(embedding, name="W")

    Dies ist der einfachste Ansatz, aber nicht speichereffizient, da der Wert von a tf.constant()mehrfach im Speicher gespeichert wird. Da embeddingdies sehr groß sein kann, sollten Sie diesen Ansatz nur für Spielzeugbeispiele verwenden.

  2. Erstellen Sie Wals tf.Variableund initialisieren Sie es aus dem NumPy-Array über tf.placeholder():

    W = tf.Variable(tf.constant(0.0, shape=[vocab_size, embedding_dim]),
                    trainable=False, name="W")
    
    embedding_placeholder = tf.placeholder(tf.float32, [vocab_size, embedding_dim])
    embedding_init = W.assign(embedding_placeholder)
    
    # ...
    sess = tf.Session()
    
    sess.run(embedding_init, feed_dict={embedding_placeholder: embedding})

    Dadurch wird vermieden, dass eine Kopie von embeddingim Diagramm gespeichert wird. Es ist jedoch genügend Speicher erforderlich, um zwei Kopien der Matrix gleichzeitig im Speicher zu halten (eine für das NumPy-Array und eine für das Array tf.Variable). Beachten Sie, dass ich davon ausgegangen bin, dass Sie die Einbettungsmatrix während des Trainings konstant halten möchten, also Werstellt mit trainable=False.

  3. Wenn die Einbettung als Teil eines anderen TensorFlow-Modells trainiert wurde, können Sie mit a tf.train.Saverden Wert aus der Prüfpunktdatei des anderen Modells laden. Dies bedeutet, dass die Einbettungsmatrix Python insgesamt umgehen kann. Erstellen Sie Wwie in Option 2 und gehen Sie dann wie folgt vor:

    W = tf.Variable(...)
    
    embedding_saver = tf.train.Saver({"name_of_variable_in_other_model": W})
    
    # ...
    sess = tf.Session()
    embedding_saver.restore(sess, "checkpoint_filename.ckpt")
mrry
quelle
Ich erstelle W wie folgt: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = ''), das als Zeile erstellt wird: ['in' '0.070312 ...... '-0.0625']. Hier gibt es Probleme! soll ich dies als mein W betrachten, nachdem ich 'in' entfernt und Zahlen von string in float32 konvertiert habe? Wenn dies der Fall ist, wie kann man dann 'in' mit seinem jeweiligen Vektor verbinden? ODER Ich muss Zahlen in float32 konvertieren und dann 'in' so lassen, wie es ist. Erwarten Sie, dass der Tensorflow die gesamte erforderliche Verarbeitung übernimmt? Vielen Dank!
user3147590
4
Ah, Sie haben hier ein paar Möglichkeiten. Sie können die TensorFlow-Operation verwenden tf.decode_csv(), um die Textdatei in einen Tensor zu konvertieren. Dies kann jedoch teuer sein (insbesondere müssen Sie eine Tensorpro Spalte erstellen und dann die numerischen zusammenfügen). Eine einfachere Alternative wäre vielleicht , die Eingabe als NumPy-Array zu verwenden pandas.read_csv()und pandas.DataFrame.as_matrix()abzurufen.
heiraten
3
Das NumPy-Array sollte nach dem Aufruf von return Garbage gesammelt werden sess.run(embedding_init, ...)(vorausgesetzt, Sie behalten keinen Verweis darauf in Ihrem Programm). Abhängig von der Struktur Ihres Programms möchten Sie möglicherweise del embedding(wo embeddingsich das NumPy-Array befindet) das Array früher freigeben.
Mrry
1
@mrry: Können Sie mehr über Option 1 und genauer gesagt "Es ist nicht speichereffizient, weil der Wert einer tf.constant () mehrmals im Speicher gespeichert ist" sprechen. Speicher ineffizient für die GPU oder die CPU? Warum muss tf.constant () im Allgemeinen mehrere Kopien im Speicher haben, während der Platzhalter tf.Variable () + Feed von Option 2 dieses Problem nicht hat?
Gabriel Parent
1
Wenn Sie sich auch fragen, warum "der Wert einer tf.constant () mehrmals im Speicher gespeichert ist", werfen Sie einen Blick auf diese Antwort: stackoverflow.com/a/42450418/5841473
alyaxey
33

Ich benutze diese Methode, um die Einbettung zu laden und zu teilen.

W = tf.get_variable(name="W", shape=embedding.shape, initializer=tf.constant_initializer(embedding), trainable=False)
LiuJia
quelle
Sollte die Einbettung Spalten oder Zeilen in der Numpy-Matrix sein?
Greyshack
6

Die Antwort von @mrry ist nicht richtig, da sie das Überschreiben der Einbettungsgewichte bei jedem Netzwerkbetrieb provoziert. Wenn Sie also einen Minibatch-Ansatz zum Trainieren Ihres Netzwerks verfolgen, überschreiben Sie die Gewichte der Einbettungen. Aus meiner Sicht ist der richtige Weg zu vorab trainierten Einbettungen:

embeddings = tf.get_variable("embeddings", shape=[dim1, dim2], initializer=tf.constant_initializer(np.array(embeddings_matrix))
Eugenio Martínez Cámara
quelle
Genaues Duplikat von LiuJias Antwort.
TimZaman
4
@TimZaman .. Tatsächlich fehlt ihm das Argument trainable = False, und daher werden seine Einbettungen in diesem Prozess verfeinert.
Shatu
4
Ich denke auch, dass Eugenios Argumentation falsch ist. Sie müssen einfach nicht bei jedem Mini-Batch die Operation "insertding_init" ausführen, und alles wird gut. Führen Sie die Einbettungsinitialisierung zu Beginn des Trainings nur einmal aus.
Shatu
@Shatu Wie stelle ich sicher, dass die Einbettungsinitialisierung nur zu Beginn des Trainings ausgeführt wird?
1
@ Dust0x .. Wenn die Größe der Einbettungen klein genug ist, können Sie sie einfach als Anfangswert angeben. Wenn sie ziemlich groß sind, können Sie sie im feed_dict übergeben, wenn Sie den Initialisierer für alle Variablen ausführen. Lassen Sie mich wissen, wenn es nicht klar genug ist, und ich werde versuchen, einen Beispielcode für beide Ansätze zu veröffentlichen.
Shatu
6

2.0 Kompatible Antwort : Es gibt viele vorgefertigte Einbettungen, die von Google entwickelt wurden und Open Sourced wurden.

Einige von ihnen sind Universal Sentence Encoder (USE), ELMO, BERTusw. und es ist sehr einfach, sie in Ihrem Code wiederzuverwenden.

Code die wiederverwendet werden Pre-Trained Embedding, Universal Sentence Encoderist unten dargestellt:

  !pip install "tensorflow_hub>=0.6.0"
  !pip install "tensorflow>=2.0.0"

  import tensorflow as tf
  import tensorflow_hub as hub

  module_url = "https://tfhub.dev/google/universal-sentence-encoder/4"
  embed = hub.KerasLayer(module_url)
  embeddings = embed(["A long sentence.", "single-word",
                      "http://example.com"])
  print(embeddings.shape)  #(3,128)

Weitere Informationen zu den von Google entwickelten und Open-Source-fähigen Pre-Trained Embeddings finden Sie unter TF Hub Link .

Tensorflow-Unterstützung
quelle
5

Mit Tensorflow Version 2 ist es ganz einfach, wenn Sie die Einbettungsebene verwenden

X=tf.keras.layers.Embedding(input_dim=vocab_size,
                            output_dim=300,
                            input_length=Length_of_input_sequences,
                            embeddings_initializer=matrix_of_pretrained_weights
                            )(ur_inp)
Fei Yan
quelle
3

Ich hatte auch Probleme mit der Einbettung, also schrieb ich ein detailliertes Tutorial mit Datensatz. Hier möchte ich hinzufügen, was ich versucht habe. Sie können diese Methode auch ausprobieren.

import tensorflow as tf

tf.reset_default_graph()

input_x=tf.placeholder(tf.int32,shape=[None,None])

#you have to edit shape according to your embedding size


Word_embedding = tf.get_variable(name="W", shape=[400000,100], initializer=tf.constant_initializer(np.array(word_embedding)), trainable=False)
embedding_loopup= tf.nn.embedding_lookup(Word_embedding,input_x)

with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for ii in final_:
            print(sess.run(embedding_loopup,feed_dict={input_x:[ii]}))

Hier ist ein detailliertes Tutorial Ipython-Beispiel. Wenn Sie es von Grund auf verstehen möchten, schauen Sie es sich an.

Aaditya Ura
quelle