2016-03-04 2 views
6

Предполагая, что я хочу обновить предварительно подготовленную матрицу встраивания слов во время обучения, существует ли способ обновить только подмножество матрицы встраивания слов?Обновление только части матрицы встраивания слов в Tensorflow

Я смотрел на страницу API Tensorflow и нашел это:

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

Однако, как я могу подать заявление, что к слову-вложение матрицы. Предположим, что я делаю:

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) 

Как затем использовать opt.apply_gradients и tf.scatter_update обновить оригинальную embeddign матрицу? (Кроме того, tensorflow выдает ошибку, если второй аргумент compute_gradient не tf.Variable)

+0

Как вы определяете «подмножество» здесь ? – viksit

+0

Только подмножество строк в матрице встраивания.Поскольку каждая строка является вектором вложения слов, это всего лишь подмножество векторов вложения слов из исходной матрицы вложения слова – user1718064

+0

http://deeplearning.net/software/theano/tutorial/faq_tutorial.html Это то, что я хотел бы как добиться, но в Tensorflow – user1718064

ответ

11

TL; DR: Реализация по умолчанию opt.minimize(loss), TensorFlow будет генерировать разреженный обновления для word_emb, который модифицирует только строки word_emb, которые участвовали в переезде.

Градиент tf.gather(word_emb, indices) оп отношению к word_emb является объектом tf.IndexedSlices (see the implementation for more details). Этот объект представляет собой разреженный тензор, равный нулю всюду, за исключением строк, выбранных indices. Вызов opt.minimize(loss) вызывает AdamOptimizer._apply_sparse(word_emb_grad, word_emb), что делает звонок tf.scatter_sub(word_emb, ...) *, который обновляет только строки word_emb, которые были выбраны indices.

Если с другой стороны, вы хотите изменить tf.IndexedSlices, возвращаемый opt.compute_gradients(loss, word_emb), вы можете выполнять произвольные операции TensorFlow на его indices и values свойств, а также создать новый tf.IndexedSlices, который может быть передан в opt.apply_gradients([(word_emb, ...)]). Например, можно ограничить градиенты, используя MyCapper() (как в приведенном выше примере), используя следующие вызовы:

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

Аналогично, вы можете изменить набор индексов, которые будут модифицированы путем создания нового tf.IndexedSlices с разными индексами ,


*   В общем, если вы хотите обновить только часть переменной в TensorFlow, вы можете использовать tf.scatter_update(), tf.scatter_add(), or tf.scatter_sub() operators, которые, соответственно, установить, добавить (+=) или вычесть из (-=) значение ранее сохраненное в переменной.

+0

Вы уверены, что это работает как рекламируется? См. Мой вопрос [здесь] (http://stackoverflow.com/questions/35828037/training-a-cnn-with-pre-trained-word-embeddings-is-very-slow-tensorflow) и ссылки в нем. Похоже, что по какой-то причине TensorFlow преобразует IndexedSlices в плотный тензор, и обновления замедляются. – hillel

+0

Это, безусловно, работает, если ваша переменная embedding является прямым аргументом 'params' для' tf.gather() '(или' tf.nn.embedding_lookup() '). «IndexedSlices» преобразуется в плотный тензор, если градиент backpropagag через любые операции, которые не имеют градиентных функций, специализированных для обработки «IndexedSlices» (в настоящее время я считаю, что только tf.concat() имеет такую ​​специализацию). – mrry

+0

Удивление, если это можно использовать для обновления определенных векторов слов только в том случае, если у меня есть предварительно обученные векторы для большинства моих слов, но некоторые из них новы и нуждаются в обучении. – TheM00s3

4

Поскольку вы просто хотите выбрать элементы для обновления (и не менять градиенты), вы можете сделать следующее.

Пусть indices_to_update булева тензор, который указывает индексы, которые вы хотите обновить, и entry_stop_gradients определяется в ссылке, затем:

gather_emb = entry_stop_gradients(gather_emb, indices_to_update) 

(Source)

Смежные вопросы