2016-03-04 6 views
6

Angenommen, ich möchte eine vortrainierte Worteinbettungsmatrix während des Trainings aktualisieren, gibt es eine Möglichkeit, nur eine Teilmenge der Worteinbettmatrix zu aktualisieren?Aktualisiere nur einen Teil der Worteinbettungsmatrix in Tensorflow

Ich habe in die Tensorflow API Seite gesucht und diese gefunden:

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

jedoch wie bewerbe ich mich, dass das Wort-Embedding Matrix. Angenommen, ich mache:

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) 

Wie kann ich dann verwenden opt.apply_gradients und tf.scatter_update, um die ursprüngliche embeddign Matrix zu aktualisieren? (Außerdem wirft tensorflow einen Fehler, wenn das zweite Argument der compute_gradient ist kein tf.Variable)

+0

Wie definieren Sie "Teilmenge" hier ? – viksit

+0

Nur eine Teilmenge der Zeilen in der Einbettungsmatrix.Da jede Zeile ein Worteinbettungsvektor ist, ist es nur eine Untermenge von Worteinbettungsvektoren aus der ursprünglichen Worteinbettungsmatrix – user1718064

+0

http://deeplearning.net/software/theano/tutorial/faq_tutorial.html Dies ist, was ich würde gerne erreichen, aber in Tensorflow – user1718064

Antwort

11

TL; DR: Die Standardimplementierung von opt.minimize(loss) wird TensorFlow erzeugen ein sparse Update für word_emb, die nur die Reihen modifiziert word_emb, die am Vorwärtspass teilgenommen hat.

Der Gradient des tf.gather(word_emb, indices) op bezüglich word_emb ist ein tf.IndexedSlices Objekt (see the implementation for more details). Dieses Objekt stellt einen dünnen Tensor dar, der überall Null ist, mit Ausnahme der Zeilen, die von indices ausgewählt wurden. Ein Anruf an opt.minimize(loss) ruft AdamOptimizer._apply_sparse(word_emb_grad, word_emb) auf, die einen Anruf an tf.scatter_sub(word_emb, ...) * macht, das nur die Zeilen aktualisiert, die von word_emb ausgewählt wurden.

Wenn auf der anderen Seite Sie die tf.IndexedSlices ändern möchten, die von opt.compute_gradients(loss, word_emb) zurückgegeben wird, können Sie beliebige TensorFlow Operationen auf seine indices und values Eigenschaften führen und eine neue tf.IndexedSlices erstellen, die opt.apply_gradients([(word_emb, ...)]) geben werden kann. Zum Beispiel könnten Sie die Gradienten Kappe mit MyCapper() (wie im Beispiel) mit den folgenden Aufrufen:

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

In ähnlicher Weise könnte man den Satz von Indizes ändern, die durch die Schaffung ein neues tf.IndexedSlices mit unterschiedlichen Indizes geändert werden .


*   Im Allgemeinen, wenn Sie nur einen Teil einer Variablen in TensorFlow aktualisieren möchten, können Sie die tf.scatter_update(), tf.scatter_add(), or tf.scatter_sub() operators verwenden, die jeweils festgelegt, in den (+=) oder subtrahieren von (-=) der Wert zuvor gespeicherten in einer Variablen.

+0

sind Sie sicher, dass dies wie beworben funktioniert? Siehe meine Frage [hier] (http://stackoverflow.com/questions/35828037/training-a-cnn-with-pre-trained-word-embeddings-isver-slow-tensorflow) und die Links darin. Es scheint, dass TensorFlow aus irgendeinem Grund die IndexedSlices in einen dichten Tensor umwandelt und die Updates langsamer werden. – hillel

+0

Es funktioniert sicherlich, wenn Ihre Einbettungsvariable das direkte Argument 'params' zu' tf.gather() '(oder' tf.nn.embedding_lookup() ') ist. Die 'IndexedSlices' werden in einen dichten Tensor konvertiert, wenn der Gradient durch weitere Operationen, die keine auf die Behandlung von'IndexedSlices' spezialisierten Gradientenfunktionen haben, zurückgespreizt wird (derzeit glaube ich, dass nur' tf.concat() 'eine solche Spezialisierung hat). – mrry

+0

Fragen, ob dies verwendet werden kann, um bestimmte Wortvektoren nur zu aktualisieren, wie in dem Fall habe ich vortrainierte Vektoren für die meisten meiner Worte, aber ein paar sind neu und benötigen ein Training. – TheM00s3

4

Da Sie nur die Elemente auswählen möchten, die aktualisiert werden sollen (und nicht die Gradienten ändern), können Sie wie folgt vorgehen.

Let indices_to_update ein boolean Tensor, die die Indizes Sie aktualisieren möchten anzeigt, und entry_stop_gradients ist in der Verbindung definiert, dann gilt:

gather_emb = entry_stop_gradients(gather_emb, indices_to_update) 

(Source)

Verwandte Themen