Aggiorna solo parte della matrice di incorporamento delle parole in Tensorflow

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?

Ho esaminato la pagina delle API di 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, ) # 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 applicarlo alla matrice di incorporamento delle parole. Supponiamo che io faccia:

 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 faccio quindi a utilizzare opt.apply_gradients e tf.scatter_update per aggiornare la matrice embeddign originale? (Inoltre, tensorflow genera un errore se il secondo argomento di compute_gradient non è tf.Variable )

TL; DR: l’implementazione predefinita di opt.minimize(loss) , TensorFlow genererà un aggiornamento sparse per word_emb che modifica solo le righe di word_emb che hanno partecipato al forward forward.

Il gradiente del tf.gather(word_emb, indices) op rispetto a word_emb è un object tf.IndexedSlices ( vedere l’implementazione per maggiori dettagli ). Questo object rappresenta un tensore sparse che è zero ovunque, ad eccezione delle righe selezionate dagli 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 selezionate dagli indices .

Se invece si desidera modificare tf.IndexedSlices restituito da opt.compute_gradients(loss, word_emb) , è ansible eseguire operazioni TensorFlow arbitrarie sulle sue proprietà di indices e values e creare un nuovo file tf.IndexedSlices che può essere passato opt.apply_gradients([(word_emb, ...)]) . Ad esempio, è ansible MyCapper() i gradienti utilizzando MyCapper() (come nell’esempio) utilizzando le seguenti chiamate:

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

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


* In generale, se vuoi aggiornare solo parte di una variabile in TensorFlow, puoi usare gli tf.scatter_update() , tf.scatter_add() o tf.scatter_sub() , che rispettivamente impostano, aggiungi a ( += ) o sottrarre da ( -= ) il valore precedentemente memorizzato in una variabile.

Dato che vuoi solo selezionare gli elementi da aggiornare (e non cambiare i gradienti), puoi fare come segue.

Lascia che indices_to_update sia un tensore booleano che indica gli indici che desideri aggiornare e entry_stop_gradients è definito nel link, quindi:

 gather_emb = entry_stop_gradients(gather_emb, indices_to_update) 

( Fonte )