最近我一直在努力学习使用TensorFlow,我不明白变量范围是如何工作的。特别是,我有以下问题:
import tensorflow as tf
from tensorflow.models.rnn import rnn_cell
from tensorflow.models.rnn import rnn
inputs = [tf.placeholder(tf.float32,shape=[10,10]) for _ in range(5)]
cell = rnn_cell.BasicLSTMCell(10)
outpts, states = rnn.rnn(cell, inputs, dtype=tf.float32)
print outpts[2].name
# ==> u'RNN/BasicLSTMCell_2/mul_2:0'
'_2'
中的'BasicLSTMCell_2'
来自何处?以后使用tf.get_variable(reuse=True)
再次获取相同变量时它是如何工作的?
编辑:我想我发现了一个相关的问题:
def creating(s):
with tf.variable_scope('test'):
with tf.variable_scope('inner'):
a=tf.get_variable(s,[1])
return a
def creating_mod(s):
with tf.variable_scope('test'):
with tf.variable_scope('inner'):
a=tf.Variable(0.0, name=s)
return a
tf.ops.reset_default_graph()
a=creating('a')
b=creating_mod('b')
c=creating('c')
d=creating_mod('d')
print a.name, '\n', b.name,'\n', c.name,'\n', d.name
输出
test/inner/a:0
test_1/inner/b:0
test/inner/c:0
test_3/inner/d:0
我很困惑......
答案 0 :(得分:8)
上面的答案在某种程度上是错误的。
让我回答为什么你有两个不同的范围名称,即使它看起来你定义了两个相同的函数:creating
和creating_mod
。
这只是因为您使用tf.Variable(0.0, name=s)
在函数creating_mod
中创建变量。
如果您希望范围识别您的变量,请始终使用tf.get_variable
!
有关详细信息,请查看此issue。
谢谢!
答案 1 :(得分:6)
"_2"
中的"BasicLSTMCell_2"
与创建了操作outpts[2]
的{{3}}相关。每次创建新名称范围(使用name scope)或变量范围(使用tf.name_scope()
)时,都会根据给定字符串向当前名称范围添加唯一后缀,可能还有一个附加后缀让它独一无二。对rnn.rnn(...)
的调用具有以下伪代码(为简洁起见,简化并使用公共API方法):
outputs = []
with tf.variable_scope("RNN"):
for timestep, input_t in enumerate(inputs):
if timestep > 0:
tf.get_variable_scope().reuse_variables()
with tf.variable_scope("BasicLSTMCell"):
outputs.append(...)
return outputs
如果您查看outpts
中张量的名称,您会看到它们如下:
>>> print [o.name for o in outpts]
[u'RNN/BasicLSTMCell/mul_2:0',
u'RNN/BasicLSTMCell_1/mul_2:0',
u'RNN/BasicLSTMCell_2/mul_2:0',
u'RNN/BasicLSTMCell_3/mul_2:0',
u'RNN/BasicLSTMCell_4/mul_2:0']
当您输入新名称范围(通过输入tf.variable_scope()
或with tf.name_scope("..."):
块)时,TensorFlow会为范围创建新的唯一名称。第一次输入"BasicLSTMCell"
范围时,TensorFlow会逐字使用该名称,因为之前("RNN/"
范围内)尚未使用该名称。下一次,TensorFlow会将"_1"
附加到范围以使其唯一,依此类推,直到"RNN/BasicLSTMCell_4"
。
变量作用域和名称作用域之间的主要区别在于变量作用域还具有一组名称到with tf.variable_scope("..."):
的绑定。通过调用tf.get_variable_scope().reuse_variables()
,我们指示TensorFlow 重用,而不是在时间步长0之后为"RNN/"
范围(及其子项)创建变量。这可确保权重被正确共享在多个RNN小区之间。