Tensorflow 如何在可变范围内重用LSTM层和变量(注意机制)

Tensorflow 如何在可变范围内重用LSTM层和变量(注意机制),tensorflow,machine-learning,scope,lstm,attention-model,Tensorflow,Machine Learning,Scope,Lstm,Attention Model,我的代码中有一个问题,我想在我的lstm\u解码器中共享权重(因此基本上只使用一个lstm)。我知道网上有一些关于这方面的资源,但我仍然无法理解为什么以下内容不共享权重: initial_input=tf.unstack(tf.zeros(shape=(1,1,hidden_size2))) 对于范围内的索引(窗口大小): 使用tf.variable_scope('lstm_cell_decoder',重用=索引>0): rnn_解码器_cell=tf.nn.rnn_cell.LSTMCell(

我的代码中有一个问题,我想在我的
lstm\u解码器中共享权重(因此基本上只使用一个lstm)。我知道网上有一些关于这方面的资源,但我仍然无法理解为什么以下内容不共享权重:

initial_input=tf.unstack(tf.zeros(shape=(1,1,hidden_size2)))
对于范围内的索引(窗口大小):
使用tf.variable_scope('lstm_cell_decoder',重用=索引>0):
rnn_解码器_cell=tf.nn.rnn_cell.LSTMCell(隐藏的_大小,状态_为_tuple=True)
输出\u解码器,状态\u解码器=tf.nn.static\u rnn(rnn\u解码器\u单元,初始\u输入,初始\u状态=last\u编码器\u状态,数据类型=tf.float32)
#计算源输出向量的分数
分数=tf.matmul(concat_lstm_输出,tf.reforme(输出解码器[-1],(隐藏大小,1)))
注意(分数)
上下文向量=tf.reduce\u sum(tf.multiply(concat\lstm\u输出,tf.restrape(注意系数,(窗口大小,1))),0)
context_vector=tf.重塑(context_vector,(1,隐藏大小))
#计算tilda隐藏状态\tilde{h}u t=tanh(W[c_t,h_t]+b_t)
concat_context=tf.concat([context_vector,output_decoder[-1]],axis=1)
W_tilde=tf.Variable(tf.random_normal(shape=[hidden_size*2,hidden_size*2],stddev=0.1),name=“weights_tilde”,trainable=True)
b_tilde=tf.Variable(tf.zeros([1,hidden_size2]),name=“bias_tilde”,trainable=True)
hidden_tilde=tf.nn.tanh(tf.matmul(concat_上下文,W_tilde)+b_tilde)#hidden_tilde是[1*64]
#为下一时间步骤更新
初始输入=tf.unstack(tf.reformate(隐藏的tilde,(1,1,隐藏的大小2)))
最后一个编码器\状态=状态\解码器
打印(初始输入、最后编码器状态)
#预测目标
W\u target=tf.Variable(tf.random\u normal(shape=[hidden\u size2,1],stddev=0.1),name=“weights\u target”,trainable=True)
打印(W_目标)
logit=tf.matmul(隐藏节点,W_目标)
logits=tf.concat([logits,logit],axis=0)
logits=logits[1:]
我希望在每次循环迭代中使用相同的LSTM单元和相同的W_目标。但是,对于循环中窗口大小=2的
print(初始输入,最后编码器状态)
print(W\u目标)
,我得到以下输出

[]
LSTMStateTuple(c=,h=)
[] 
LSTMStateTuple(c=,h=)
更新:在Maxim的评论之后,我尝试了以下语法

范围内索引的
(窗口大小):
使用tf.variable_scope('lstm_cell_decoder',重用=索引>0):
rnn_解码器_cell=tf.nn.rnn_cell.LSTMCell(隐藏大小,重用=索引>0)
输出译码器,状态译码器=tf.nn.static(译码器单元…)
W_target=tf.get_变量(…)
它现在正确地共享变量W_target,但共享lstm单元格/权重仍然存在问题:

]
LSTMStateTuple(c=,h=)
[]
LSTMStateTuple(c=,h=)

首先,使用
tf创建变量。变量
不会使其可重用。这是和之间的关键区别之一。请参见此示例:

带有tf.variable\u scope('foo',reuse=tf.AUTO\u reuse):
对于范围(3)中的i:
x=tf.Variable(0.0,name='x')
y=tf.get_变量(name='y',shape=())
如果检查创建的变量,您将看到:



接下来,RNN单元提供自己的重用机制。例如,对于它的
重用
构造函数参数:

reuse=tf.AUTO_reuse#也可以尝试True和False
cell1=tf.nn.rnn_cell.LSTMCell(3,重用=重用)
cell2=tf.nn.rnn_cell.LSTMCell(3,重用=重用)
输出1,状态1=tf.nn.dynamic(cell1,X,dtype=tf.float32)
outputs2,states2=tf.nn.dynamic(cell2,X,dtype=tf.float32)

非常感谢Maxim的回答!我还有两个问题:1)在我的版本中,tf.AUTO_REUSE不存在,这与在我的变量第一次定义然后设置为TRUE时将REUSE=FALSE完全相同吗?对于范围(3)中的i,类似这样的东西是:使用tf.variable_scope('foo',reuse=i>0):x=tf.variable(0.0,name='x')y=tf.get_variable(name='y',shape=())print(x)print(y)
是的,这是相同的,但更方便。升级到TF 1.5(甚至可能是1.4.1),
TF.AUTO_REUSE
将可用。请不要将代码发布到注释中。编辑并更新问题当然,我认为格式很糟糕。我会很快更新这个问题,再次感谢:)刚刚编辑了这个问题,打印的输出是循环中的一个窗口大小=2,与以前一样。