2017-04-12 162 views
2

我想实现一个嵌入层。嵌入将使用预先训练的手套嵌入进行初始化。对于可以在手套中找到的词语,它将被固定。对于那些没有戴手套的话,它会随机初始化,并且可以训练。我如何做tensorflow?我知道整个张量都有一个tf.stop_gradient,对于这种情况,有没有任何stop_gradient api?或者,有没有解决这个问题的方法?任何建议表示赞赏如何在张量流中停止张量的某些输入的梯度

回答

8

这样的想法是使用masktf.stop_gradient开裂这样的问题:

res_matrix = tf.stop_gradient(mask_h*E) + mask*E

其中在基质mask中,1表示到我想申请梯度条目,0表示对哪个条目我不想应用渐变(将渐变设置为0),mask_hmask的反转(1翻转为0,0翻转为1)。然后我们可以从res_matrix中获取。这里是测试代码:

import tensorflow as tf 
import numpy as np 

def entry_stop_gradients(target, mask): 
    mask_h = tf.abs(mask-1) 
    return tf.stop_gradient(mask_h * target) + mask * target 

mask = np.array([1., 0, 1, 1, 0, 0, 1, 1, 0, 1]) 
mask_h = np.abs(mask-1) 

emb = tf.constant(np.ones([10, 5])) 

matrix = entry_stop_gradients(emb, tf.expand_dims(mask,1)) 

parm = np.random.randn(5, 1) 
t_parm = tf.constant(parm) 

loss = tf.reduce_sum(tf.matmul(matrix, t_parm)) 
grad1 = tf.gradients(loss, emb) 
grad2 = tf.gradients(loss, matrix) 
print matrix 
with tf.Session() as sess: 
    print sess.run(loss) 
    print sess.run([grad1, grad2]) 
1

我建议你有两个不同的张量来保存你的数据:一个tf.constant为你的预训练数据,一个tf.Variable为你的新数据进行训练,然后你可以混合既有级联又有张量连接操作。

由于tf.constant无法训练,因此您不必担心停止渐变。

+0

这样我就不得不做很多预处理。这会让我的代码看起来有点难看。我会尝试使用收集并与stop_gradient一起分散,看看是否会起作用。真的希望有一个功能来支持这一点。谢谢。 –

1

我不太了解单词嵌入,但我对您的问题的理解是,您有一个变量v,并且您只想训练它的某些(已知)条目。您可以通过使用“掩模”(即与v相同形状的恒定张量对可训练条目的值为1,否则为0)来实现此目的。

v = your_variable() 
loss = your_loss() #some loss that uses v 
mask = your_mask_as_explained_above() 
opt = tf.train.GradientDescentOptimizer(learning_rate=0.1) 

# Get list (length 1 in our example) of (gradient, variable)-pairs from the optimizer and extract the gradient w.r.t. v 
grads_and_vars = opt.compute_gradients(loss, [v]) 
v_grad = grads_and_vars[0][0] 

# Multiply the gradient with the mask before feeding it back to the optimizer 
sgd_step = opt.apply_gradients([(v, v_grad*mask)]) 

根据您的问题的复杂性,这可能不是一个有效的解决方案,不过,因为全梯度w.r.t.在每个步骤中计算v。在优化器更新中,应用根本不是

如果您对opt.compute_gradientsopt.apply_gradients不熟悉,请在docs中解释。

+0

感谢您的回复,我认为您的解决方案将起作用。我刚刚提出了另一个想法,我已经在下面发布了它。 –