2016-03-04 10 views
6

Supponendo che io voglia aggiornare una matrice di incorporamento di parole pre-addestrata durante l'allenamento, c'è un modo per aggiornare solo un sottoinsieme della matrice di incorporamento delle parole?Aggiornare solo parte della matrice di incorporamento delle parole in Tensorflow

ho guardato nella pagina API tensorflow e ho trovato questo:

# Create an optimizer. 
opt = GradientDescentOptimizer(learning_rate=0.1) 

# Compute the gradients for a list of variables. 
grads_and_vars = opt.compute_gradients(loss, <list of variables>) 

# grads_and_vars is a list of tuples (gradient, variable). Do whatever you 
# need to the 'gradient' part, for example cap them, etc. 
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1])) for gv in grads_and_vars] 

# Ask the optimizer to apply the capped gradients. 
opt.apply_gradients(capped_grads_and_vars) 

Tuttavia Come posso richiedere che alla matrice word-embedding. Supponiamo che io faccio:

word_emb = tf.Variable(0.2 * tf.random_uniform([syn0.shape[0],s['es']], minval=-1.0, maxval=1.0, dtype=tf.float32),name='word_emb',trainable=False) 

gather_emb = tf.gather(word_emb,indices) #assuming that I pass some indices as placeholder through feed_dict 

opt = tf.train.AdamOptimizer(1e-4) 
grad = opt.compute_gradients(loss,gather_emb) 

Come posso quindi utilizzare opt.apply_gradients e tf.scatter_update per aggiornare la matrice embeddign originale? (Inoltre, tensorflow genera un errore se il secondo argomento della compute_gradient non è un tf.Variable)

+0

Come si fa a definire "sottoinsieme" qui ? – viksit

+0

Solo un sottoinsieme di righe nella matrice di incorporamento.Poiché ogni riga è un vettore di incorporamento di parole, è solo un sottoinsieme di vettori che incorporano la parola dalla matrice di incorporamento della parola originale – user1718064

+0

http://deeplearning.net/software/theano/tutorial/faq_tutorial.html Questo è ciò che vorrei piace realizzare ma in Tensorflow – user1718064

risposta

11

TL; DR: L'implementazione predefinita di opt.minimize(loss), tensorflow genererà una rada aggiornamento per word_emb che modifica solo le righe di word_emb che ha partecipato al passaggio in avanti.

La pendenza della tf.gather(word_emb, indices) op rispetto ad word_emb è un oggetto tf.IndexedSlices (see the implementation for more details). Questo oggetto rappresenta un tensore sparse che è zero ovunque, ad eccezione delle righe selezionate da indices. Una chiamata a opt.minimize(loss) chiama AdamOptimizer._apply_sparse(word_emb_grad, word_emb), che effettua una chiamata a tf.scatter_sub(word_emb, ...) * che aggiorna solo le righe di word_emb che sono state selezionate da indices.

Se d'altra parte si desidera modificare la tf.IndexedSlices restituito da opt.compute_gradients(loss, word_emb), è possibile eseguire operazioni tensorflow arbitrarie sulle sue indices e values proprietà, e creare un nuovo tf.IndexedSlices che può essere passato a opt.apply_gradients([(word_emb, ...)]). Ad esempio, è possibile ricoprire i gradienti utilizzando MyCapper() (come nell'esempio) utilizzando i seguenti chiamate:

grad, = opt.compute_gradients(loss, word_emb) 
train_op = opt.apply_gradients(
    [tf.IndexedSlices(MyCapper(grad.values), grad.indices)]) 

Allo stesso modo, è possibile modificare il set di indici che sarà modificato creando un nuovo tf.IndexedSlices con diversi indici .


*   In generale, se si desidera aggiornare solo una parte di una variabile in tensorflow, è possibile utilizzare il tf.scatter_update(), tf.scatter_add(), or tf.scatter_sub() operators, che ha fissato, rispettivamente, di aggiungere (+=) o sottrarre (-=) il valore precedentemente memorizzato in una variabile.

+0

sei sicuro che questo funziona come pubblicizzato? Vedi la mia domanda [qui] (http://stackoverflow.com/questions/35828037/training-a-cnn-with-pre-trained-word-embeddings-is-very-slow-tensorflow) e i collegamenti in esso. Sembra che per qualche ragione TensorFlow converta gli IndexedSlices in un denso tensore e gli aggiornamenti rallentino. – hillel

+0

Funziona sicuramente se la tua variabile di incorporamento è l'argomento diretto 'params' di' tf.gather() '(o' tf.nn.embedding_lookup() '). Il 'IndexedSlices' è convertito in un denso denso se il gradiente retropopora attraverso altri ops che non hanno funzioni di gradiente specializzate per gestire' IndexedSlices' (al momento credo che solo 'tf.concat()' abbia una tale specializzazione). – mrry

+0

Mi chiedo se questo può essere usato per aggiornare specifici vettori di parole solo nel caso in cui io abbia vettori pre-addestrati per la maggior parte delle mie parole, ma alcuni sono nuovi e hanno bisogno di addestramento. – TheM00s3

4

Poiché si desidera selezionare solo gli elementi da aggiornare (e non modificare i gradienti), è possibile eseguire le seguenti operazioni.

Sia indices_to_update essere un tensore booleano che indica gli indici che si desidera aggiornare e entry_stop_gradients è definito nel collegamento, quindi:

gather_emb = entry_stop_gradients(gather_emb, indices_to_update) 

(Source)

Problemi correlati