Utilizzo di un word embedding pre-addestrato (word2vec o Glove) in TensorFlow


95

Di recente ho esaminato un'interessante implementazione per la classificazione del testo convoluzionale . Tuttavia, tutto il codice TensorFlow che ho recensito utilizza vettori di incorporamento casuali (non pre-addestrati) come il seguente:

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)

Qualcuno sa come utilizzare i risultati di Word2vec o di un word embedding pre-addestrato GloVe invece di uno casuale?

Risposte:


130

Ci sono alcuni modi in cui puoi utilizzare un incorporamento pre-addestrato in TensorFlow. Supponiamo che tu abbia l'incorporamento in un array NumPy chiamato embedding, con vocab_sizerighe e embedding_dimcolonne e desideri creare un tensore Wche può essere utilizzato in una chiamata a tf.nn.embedding_lookup().

  1. Crea semplicemente Wcome un valore tf.constant()che prende embeddingcome valore:

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

    Questo è l'approccio più semplice, ma non è efficiente in termini di memoria perché il valore di a tf.constant()viene archiviato più volte in memoria. Poiché embeddingpuò essere molto grande, dovresti usare questo approccio solo per esempi di giocattoli.

  2. Crea Wcome a tf.Variablee inizializzalo dall'array NumPy tramite 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})
    

    Ciò evita di memorizzare una copia di embeddingnel grafico, ma richiede memoria sufficiente per mantenere due copie della matrice in memoria contemporaneamente (una per l'array NumPy e una per la tf.Variable). Nota che ho assunto che tu voglia mantenere costante la matrice di incorporamento durante l'allenamento, quindi Wviene creata con trainable=False.

  3. Se l'incorporamento è stato addestrato come parte di un altro modello TensorFlow, è possibile utilizzare a tf.train.Saverper caricare il valore dal file del punto di arresto dell'altro modello. Ciò significa che la matrice di incorporamento può bypassare del tutto Python. Crea Wcome nell'opzione 2, quindi procedi come segue:

    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")
    

Creo W come segue: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = '') che crea come riga: ['in' '0.070312 ...... '-0.0625']. Ci sono problemi qui! devo considerare questo come la mia W dopo aver rimosso "in" e convertito i numeri da stringa a float32? se questo è il caso, allora come connettere "in" al suo rispettivo vettore? OPPURE devo convertire le figure in float32 e poi lasciare "in" così com'è; ti aspetti che tensorflow esegua tutte le elaborazioni richieste? Grazie!
user3147590

4
Ah, hai un paio di opzioni qui. Si potrebbe utilizzare il tensorflow tf.decode_csv()op per convertire il file di testo in un tensore, ma questo potrebbe essere costoso (in particolare, si richiede di crearne uno Tensorper ogni colonna e quindi concatenare quelli numerici insieme). Forse un'alternativa più semplice sarebbe usare pandas.read_csv()e pandas.DataFrame.as_matrix()ottenere l'input come array NumPy.
mrry

3
L'array NumPy dovrebbe essere raccolto dalla spazzatura dopo la chiamata a sess.run(embedding_init, ...)return (supponendo che non si mantenga un riferimento ad esso nel programma). A seconda della struttura del tuo programma, potresti voler del embedding(dov'è embeddingl'array NumPy) rilasciare l'array prima.
mrry

1
@mrry: puoi parlare di più dell'opzione 1 e più specificamente "non è efficiente in termini di memoria perché il valore di un tf.constant () è memorizzato più volte in memoria". Memoria inefficiente per la GPU o la CPU? Più in generale, perché tf.constant () deve avere più copie in memoria, mentre il segnaposto tf.Variable () + feed dell'opzione 2 non ha questo problema?
Gabriel Parent

1
Se vi chiedete anche perché "il valore di un tf.constant () è memorizzato più volte in memoria" dare un'occhiata a questa risposta: stackoverflow.com/a/42450418/5841473
alyaxey

33

Uso questo metodo per caricare e condividere l'incorporamento.

W = tf.get_variable(name="W", shape=embedding.shape, initializer=tf.constant_initializer(embedding), trainable=False)

L'incorporamento dovrebbe essere colonne o righe nella matrice numpy?
Greyshack

6

La risposta di @mrry non è corretta perché provoca la sovrascrittura dei pesi degli incorporamenti ogni volta che la rete viene eseguita, quindi se stai seguendo un approccio minibatch per addestrare la tua rete, stai sovrascrivendo i pesi degli incorporamenti. Quindi, dal mio punto di vista, la strada giusta per i matrimoni pre-formati è:

embeddings = tf.get_variable("embeddings", shape=[dim1, dim2], initializer=tf.constant_initializer(np.array(embeddings_matrix))

Esatto duplicato della risposta di LiuJia.
TimZaman

4
@TimZaman .. In effetti, gli manca l'argomento addestrabile = Falso, e quindi finirà per mettere a punto i suoi incorporamenti nel processo.
Shatu

4
Inoltre, penso che il ragionamento di Eugenio non sia corretto. Semplicemente non devi eseguire l'operazione "embedding_init" con ogni mini-batch e tutto andrà bene. Cioè, basta eseguire l'inizializzazione dell'incorporamento solo una volta all'inizio dell'addestramento.
Shatu

@Shatu come posso assicurarmi che l'inizializzazione dell'incorporamento venga eseguita solo all'inizio della formazione?

1
@ dust0x .. Se la dimensione degli incorporamenti è abbastanza piccola, puoi semplicemente specificarli come valore iniziale. Se sono abbastanza grandi, puoi passarli nel feed_dict quando esegui l'inizializzatore per tutte le variabili. Fammi sapere se non è abbastanza chiaro e cercherò di pubblicare un codice di esempio per entrambi gli approcci.
Shatu

6

Risposta compatibile 2.0 : ci sono molti incorporamenti pre-addestrati, che sono sviluppati da Google e che sono stati open source.

Alcuni di loro lo sono Universal Sentence Encoder (USE), ELMO, BERT, ecc. Ed è molto facile riutilizzarli nel codice.

Il codice per riutilizzare il Pre-Trained Embedding, Universal Sentence Encoderè mostrato di seguito:

  !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)

Per ulteriori informazioni sugli incorporamenti pre-addestrati sviluppati e open source da Google, fare riferimento a TF Hub Link .


5

Con tensorflow versione 2 è abbastanza facile se usi il livello Embedding

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)


3

Stavo anche affrontando problemi di incorporamento, quindi ho scritto un tutorial dettagliato con il set di dati. Qui vorrei aggiungere quello che ho provato Puoi provare anche questo metodo,

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]}))

Ecco un esempio dettagliato di Tutorial Ipython funzionante se vuoi capire da zero, dai un'occhiata.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.