1. 程式人生 > >[翻譯] Tensorflow中name scope和variable scope的區別是什麽

[翻譯] Tensorflow中name scope和variable scope的區別是什麽

iter res .cn push init const images ges variables

翻譯自:https://stackoverflow.com/questions/35919020/whats-the-difference-of-name-scope-and-a-variable-scope-in-tensorflow

問題:下面這幾個函數的區別是什麽?

tf.variable_op_scope(values, name, default_name, initializer=None)
Returns a context manager for defining an op that creates variables. This context manager validates that the given values are from the same graph, ensures that that graph is the default graph, and pushes a name scope and a variable scope.

tf.op_scope(values, name, default_name=None) Returns a context manager for use when defining a Python op. This context manager validates that the given values are from the same graph, ensures that that graph is the default graph, and pushes a name scope.

tf.name_scope(name)
Wrapper for Graph.name_scope() using the default graph. See Graph.name_scope() for more details.

tf.variable_scope(name_or_scope, reuse=None, initializer=None)
Returns a context for variable scope. Variable scope allows to create new variables and to share already created ones while providing checks to not create or share by accident. For details, see the Variable Scope How To, here we present only a few basic examples.

回答1:

首先簡單介紹一下變量共享(variable sharing)。這是Tensorflow中的一種機制,它允許在代碼的不同位置可以訪問到共享變量(在不需要傳遞變量引用的情況下)。tf.get_variable方法可以將變量的名字作為參數,以創建具有該名稱的新變量或者如果已經存在這個變量了,就取回這個變量。這與 tf.Variable是不同的。每次調用 tf.Variable都會創建一個新的變量(如果具有此名稱的變量已經存在,則可能向變量名添加後綴)。針對共享變量機制,引進了scope (variable scope) 。

結果,我們有2中不同的scopes類型:

  • name scope, created using tf.name_scope
  • variable scope, created using tf.variable_scope

這兩個scopes在所有的操作(operation)和使用tf.Variable創建的變量上都有相同的作用。

然而,tf.get_variable會忽略name scope,我們可以看看如下的例子:

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

在一個scope中使用tf.get_variable來使得變量可以被訪問唯一方法就是使用一個variable scope,例子如下:

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

這可以使得我們在程序的不同地方可以很容易的共享變量,甚至在不同的name scope中:

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

更新:

Tensorflow版本r0.11之後,op_scopevariable_op_scope都被棄用了,替代的是op_scopevariable_op_scope

回答2:

舉了一個例子,並將其可視化。

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()

輸出結果如下:

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中可視化如下:

技術分享

從上面的可以看出來,tf.variable_scope()為所有變量(不管你是怎麽創建的)、操作(ops)、常量(constant)添加一個前綴,而tf.name_scope()會忽視使用tf.get_variable()創建的變量,因為它假設你知道你使用的變量位於哪個scope中。

Sharing variables文檔中告訴你:

tf.variable_scope(): Manages namespaces for names passed to tf.get_variable().

更詳細的可以查看官方文檔。

[翻譯] Tensorflow中name scope和variable scope的區別是什麽