最近我一直在努力学习使用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
我糊涂了...
上面的答案在某种程度上是错误的.
让我回答为什么你有两个不同的范围名称,即使它看起来你定义了两个相同的功能:creating
和creating_mod
.
这只是因为您曾经tf.Variable(0.0, name=s)
在函数中创建变量creating_mod
.
tf.get_variable
如果您希望您的变量被范围识别,请始终使用!
有关更多详细信息,请查看此问题.
谢谢!
将"_2"
在"BasicLSTMCell_2"
涉及名称范围,其中,运算outpts[2]
已创建.每次创建新名称范围(带tf.name_scope()
)或变量范围(带tf.variable_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']
输入新名称范围(通过输入with tf.name_scope("..."):
或with tf.variable_scope("..."):
阻止)时,TensorFlow会为范围创建一个新的唯一名称.第一次输入"BasicLSTMCell"
作用域时,TensorFlow会逐字使用该名称,因为它之前(在"RNN/"
作用域中)尚未使用过.下一次,TensorFlow会附加"_1"
到范围以使其独一无二,依此类推"RNN/BasicLSTMCell_4"
.
变量作用域和名称作用域之间的主要区别在于变量作用域还具有一组名称到tf.Variable
绑定.通过调用tf.get_variable_scope().reuse_variables()
,我们指示TensorFlow 在时间步长0之后重用而不是为"RNN/"
范围(及其子节点)创建变量.这确保了权重在多个RNN单元之间正确共享.