名称范围和张量streamvariables范围有什么区别?

这些function有什么区别?

tf.variable_op_scope(values, name, default_name, initializer=None)

返回一个用于定义创buildvariables的op的上下文pipe理器。 此上下文pipe理器validation给定的值来自同一个图,确保该图是默认图,并推送一个名称范围和一个variables范围。


tf.op_scope(values, name, default_name=None)

返回定义Python操作时使用的上下文pipe理器。 这个上下文pipe理器validation给定的值是来自同一个图,确保该图是默认图,并推送一个名称范围。


tf.name_scope(name)

使用默认graphics封装Graph.name_scope() 。 有关更多详细信息,请参阅Graph.name_scope()


tf.variable_scope(name_or_scope, reuse=None, initializer=None)

返回variables作用域的上下文。 可变范围允许创build新variables并共享已创build的variables,同时提供检查而不会意外创build或共享。 有关详细信息,请参阅variables范围如何,这里我们只提供几个基本示例。

我们先简单介绍一下variables共享。 这是TensorFlow中的一种机制,它允许共享代码不同部分中访问的variables,而无需将引用传递给variables。 tf.get_variable方法可以和variables名作为参数一起使用,用这样的名字创build一个新的variables或者检索之前创build的variables。 这与使用tf.Variable构造函数不同,后者将在每次调用时创build一个新variables(如果已经存在具有该名称的variables,则可能会为variables名添加后缀)。 就variables共享机制而言,引入了一个单独的范围(variables范围)。

结果,我们最终得到两种不同types的范围:

  • 名称范围 ,使用tf.name_scope创build
  • variables作用域 ,使用tf.variable_scope创build

两个作用域对所有操作以及使用tf.Variable创build的variables都具有相同的效果,即范围将作为操作或variables名称的前缀添加。

但是,名称作用域被tf.get_variable忽略。 我们可以看到,在下面的例子中:

 with tf.name_scope("my_scope"): v1 = tf.get_variable("var1", [1], dtype=tf.float32) v2 = tf.Variable(1, name="var2", dtype=tf.float32) a = tf.add(v1, v2) print(v1.name) # var1:0 print(v2.name) # my_scope/var2:0 print(a.name) # my_scope/Add:0 

在一个作用域中放置一个使用tf.get_variable访问的variables的唯一方法是使用一个variables作用域,如下例所示:

 with tf.variable_scope("my_scope"): v1 = tf.get_variable("var1", [1], dtype=tf.float32) v2 = tf.Variable(1, name="var2", dtype=tf.float32) a = tf.add(v1, v2) print(v1.name) # my_scope/var1:0 print(v2.name) # my_scope/var2:0 print(a.name) # my_scope/Add:0 

这使我们可以轻松地在程序的不同部分共享variables,甚至在不同的名称范围内:

 with tf.name_scope("foo"): with tf.variable_scope("var_scope"): v = tf.get_variable("var", [1]) with tf.name_scope("bar"): with tf.variable_scope("var_scope", reuse=True): v1 = tf.get_variable("var", [1]) assert v1 == v print(v.name) # var_scope/var:0 print(v1.name) # var_scope/var:0 

更新:op_scope / variable_op_scope已弃用!

从版本r0.11开始, op_scopevariable_op_scope都被弃用 ,并被name_scopevariable_scope所取代。

命名空间是一种以层次方式组织variables和运算符名称的方法(例如“scopeA / scopeB / scopeC / op1”)

  • tf.name_scope在默认图中为运算符创build名称空间。
  • tf.variable_scope为默认图中的variables和运算符创build名称空间。

  • tf.op_scopetf.op_scope相同,但是用于创build指定variables的graphics。

  • tf.variable_op_scopetf.variable_op_scope相同,但是用于创build指定variables的graphics。

链接到上面的来源有助于消除这个文档问题。

这个例子显示了所有types的作用域都为variables和运算符定义了命名空间,但有以下不同:

  1. tf.variable_op_scopetf.variable_scope定义的作用域与tf.get_variable兼容(它忽略了另外两个作用域)
  2. tf.op_scopetf.variable_op_scope只是从指定的variables列表中select一个graphics来创build一个范围。 除了它们的行为相当于tf.name_scopetf.variable_scope
  3. tf.variable_scopevariable_op_scope添加指定或默认的初始值设定项。

现在已经废弃了variable_op_scope和op_scope ,根本不应该使用。

关于另外两个问题,在我尝试通过创build一个简单的例子来想象所有的东西之前,我也有理解variable_scope和name_scope之间的区别(他们看起来差不多)

 import tensorflow as tf def scoping(fn, scope1, scope2, vals): with fn(scope1): a = tf.Variable(vals[0], name='a') b = tf.get_variable('b', initializer=vals[1]) c = tf.constant(vals[2], name='c') with fn(scope2): d = tf.add(a * b, c, name='res') print '\n '.join([scope1, a.name, b.name, c.name, d.name]), '\n' return d d1 = scoping(tf.variable_scope, 'scope_vars', 'res', [1, 2, 3]) d2 = scoping(tf.name_scope, 'scope_name', 'res', [1, 2, 3]) with tf.Session() as sess: writer = tf.summary.FileWriter('logs', sess.graph) sess.run(tf.global_variables_initializer()) print sess.run([d1, d2]) writer.close() 

这里我创build了一个函数来创build一些variables和常量,并将它们分组在范围中(取决于我提供的types)。 在这个函数中,我也打印所有variables的名字。 之后,我执行graphics来获取结果值的值,并保存事件文件在TensorBoard中进行调查。 如果你运行这个,你会得到以下结果:

 scope_vars scope_vars/a:0 scope_vars/b:0 scope_vars/c:0 scope_vars/res/res:0 scope_name scope_name/a:0 b:0 scope_name/c:0 scope_name/res/res:0 

如果您打开TensorBoard,则会看到类似的模式(因为您看到bscope_name矩形之外): 在这里输入图像描述


这给你答案

现在你看到tf.variable_scope()为所有variables的名称(不pipe你如何创build它们),操作tf.variable_scope()tf.variable_scope()添加一个前缀。 另一方面, tf.name_scope()忽略使用tf.get_variable()创build的variables,因为它假定您知道哪个variables以及您想要在哪个范围内使用。

关于共享variables的一个很好的文档告诉你

tf.variable_scope() :pipe理传递给tf.get_variable()名称的名称空间。

相同的文档提供了更多的细节,variables作用域如何工作以及何时有用。

至于API r0.11, op_scopevariable_op_scope都被弃用 。 name_scopevariable_scope可以嵌套:

 with tf.name_scope('ns'): with tf.variable_scope('vs'): v1 = tf.get_variable("v1",[1.0]) #v1.name = 'vs/v1:0' v2 = tf.Variable([2.0],name = 'v2') #v2.name= 'ns/vs/v2:0' v3 = v1 + v2 #v3.name = 'ns/vs/add:0' 

你可以把它们看作两组: variable_op_scopeop_scope以一组variables作为input,并且被devise来创build操作。 区别在于它们如何影响使用tf.get_variable创buildvariables:

 def mysum(a,b,name=None): with tf.op_scope([a,b],name,"mysum") as scope: v = tf.get_variable("v", 1) v2 = tf.Variable([0], name="v2") assert v.name == "v:0", v.name assert v2.name == "mysum/v2:0", v2.name return tf.add(a,b) def mysum2(a,b,name=None): with tf.variable_op_scope([a,b],name,"mysum2") as scope: v = tf.get_variable("v", 1) v2 = tf.Variable([0], name="v2") assert v.name == "mysum2/v:0", v.name assert v2.name == "mysum2/v2:0", v2.name return tf.add(a,b) with tf.Graph().as_default(): op = mysum(tf.Variable(1), tf.Variable(2)) op2 = mysum2(tf.Variable(1), tf.Variable(2)) assert op.name == 'mysum/Add:0', op.name assert op2.name == 'mysum2/Add:0', op2.name 

注意两个例子中variablesv的名字。

同样的tf.name_scopetf.variable_scope

 with tf.Graph().as_default(): with tf.name_scope("name_scope") as scope: v = tf.get_variable("v", [1]) op = tf.add(v, v) v2 = tf.Variable([0], name="v2") assert v.name == "v:0", v.name assert op.name == "name_scope/Add:0", op.name assert v2.name == "name_scope/v2:0", v2.name with tf.Graph().as_default(): with tf.variable_scope("name_scope") as scope: v = tf.get_variable("v", [1]) op = tf.add(v, v) v2 = tf.Variable([0], name="v2") assert v.name == "name_scope/v:0", v.name assert op.name == "name_scope/Add:0", op.name assert v2.name == "name_scope/v2:0", v2.name 

你可以在教程中阅读关于variables作用域的更多信息。 Stack Overflow 之前也有类似的问题。

从tensorflow文档的这个页面的最后一节: tf.variable_scope()中ops的tf.variable_scope()

当我们with tf.variable_scope("name") ,这隐式地打开了一个tf.name_scope("name") 。 例如:

 with tf.variable_scope("foo"): x = 1.0 + tf.get_variable("v", [1]) assert x.op.name == "foo/add" 

除了variables作用域之外,可以打开名称作用域,然后它们将只影响作用域的名称,而不影响variables的名称。

 with tf.variable_scope("foo"): with tf.name_scope("bar"): v = tf.get_variable("v", [1]) x = 1.0 + v assert v.name == "foo/v:0" assert x.op.name == "foo/bar/add" 

使用捕获的对象而不是string打开variables作用域时,我们不会更改ops的当前名称范围。