关于张量流中变量范围的名称

About names of variable scope in tensorflow

最近我一直在尝试学习使用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'

'BasicLSTMCell_2'中的'_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

我很困惑...

"BasicLSTMCell_2" 中的 "_2"name scope in which the op outpts[2] was created. Every time you create a new name scope (with tf.name_scope()) or variable scope (with tf.variable_scope()) 相关的是,根据给定的字符串,一个唯一的后缀被添加到当前的名称范围,可能还有一个额外的后缀来制作它独一无二。对 rnn.rnn(...) 的调用具有以下伪代码(为清楚起见,已简化并使用 public 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("..."): or with tf.variable_scope("..."): 块)时,TensorFlow 会为该范围创建一个新的、唯一的 名称。第一次进入 "BasicLSTMCell" 范围时,TensorFlow 会逐字使用该名称,因为之前没有使用过(在 "RNN/" 范围内)。下一次,TensorFlow 将 "_1" 附加到范围以使其唯一,依此类推直至 "RNN/BasicLSTMCell_4".

变量作用域和名称作用域之间的主要区别是变量作用域还有一组 name-to-tf.Variable 绑定。通过调用 tf.get_variable_scope().reuse_variables(),我们指示 TensorFlow 在时间步 0 之后 重用 而不是为 "RNN/" 范围(及其子级)创建变量。这确保了权重在多个 RNN 单元之间正确共享。

上面的回答有些误导。

让我来回答为什么你有两个不同的作用域名称,即使看起来你定义了两个相同的函数:creatingcreating_mod.

这只是因为您使用 tf.Variable(0.0, name=s) 在函数 creating_mod 中创建了变量。

如果你想让你的变量被作用域识别,请总是使用tf.get_variable

查看此 issue 了解更多详情。

谢谢!