2016-02-28 8 views
65

Ho recentemente esaminato un'implementazione interessante per convolutional text classification. Tuttavia tutto il codice tensorflow ho rivisto utilizza un casuale (non pre-formati) i vettori che incorporano come la seguente:Utilizzo di un incorporamento di parole pre-formato (word2vec o Glove) in TensorFlow

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 un guanto di parola embedding invece di pre-addestrato uno casuale?

risposta

97

Esistono alcuni modi per utilizzare un incorporamento pre-formato in TensorFlow. Supponiamo che tu abbia l'incorporamento in un array NumPy chiamato embedding, con righe vocab_size e colonne embedding_dim e che tu voglia creare un tensore W che può essere utilizzato in una chiamata a tf.nn.embedding_lookup().

  1. È sufficiente creare W come tf.constant() che prende embedding il suo valore:

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

    Questo è l'approccio più semplice, ma non è efficiente della memoria, perché il valore di un tf.constant() è memorizzato più volte in memoria. Poiché embedding può essere molto grande, è necessario utilizzare questo approccio solo per esempi di giocattoli.

  2. Creare W come tf.Variable e inizializzare dalla matrice NumPy tramite un 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}) 
    

    Questo evita memorizzare una copia embedding nel grafico, ma richiede memoria sufficiente per mantenere due copie la matrice in memoria in una volta (una per l'array NumPy e una per lo tf.Variable). Si noti che ho assunto che si desidera mantenere costante la matrice di incorporamento durante l'allenamento, pertanto viene creato W con trainable=False.

  3. Se l'incorporamento è stato addestrato come parte di un altro modello TensorFlow, è possibile utilizzare un tf.train.Saver per caricare il valore dal file del punto di arresto dell'altro modello. Ciò significa che la matrice di incorporamento può bypassare completamente Python. Creare W come in opzione 2, quindi effettuare le seguenti operazioni:

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

creo W come segue: W = np.loadtxt ("/ media/w2vTest.txt", DTYPE = 'string', delimitatore = '') che crea come una riga: ['in' '0.070312 ......'- 0.0625']. Ci sono problemi qui! devo considerare questo come mio W dopo aver rimosso "in" e convertito i numeri da stringa a float32? se questo è il caso, allora come collegare 'in' al rispettivo vettore? O devo convertire le figure in float32 e poi lasciare "in" così com'è; mi aspetto che tensorflow faccia tutto il processo necessario? Grazie! – user3147590

+3

Ah, hai un paio di opzioni qui. Tu * potresti * usare il TensorFlow 'tf.decode_csv() 'op per convertire il file di testo in un tensore, ma potrebbe essere costoso (in particolare richiede di creare un' Tensore' per colonna e quindi concatenare insieme i valori numerici). Forse un'alternativa più semplice sarebbe usare ['pandas.read_csv()'] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html) e ['pandas.DataFrame.as_matrix() '] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.as_matrix.html) per ottenere l'input come un array NumPy. – mrry

+0

Usando l'opzione 2, c'è un modo per gettare via l'array NumPy e risparmiare un po 'di memoria? – morphe

23

Io uso questo metodo per caricare e condividere incorporamento.

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

La risposta di @mrry non è giusta perché provoques la sovrascrittura dei pesi incastri viene eseguito ogni rete, quindi se si sta seguendo un approccio minibatch per addestrare la rete, si sta sovrascrivendo i pesi del incastri. Così, il mio punto di vista il modo giusto incastri di pre-addestrato è:

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

Esatto duplicato della risposta di LiuJia. – TimZaman

+3

@TimZaman .. In effetti, gli manca l'argomento Trainable = False, e quindi finirà per mettere a punto le sue incursioni nel processo. – Shatu

+3

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

Problemi correlati