TensorFlow之variable scope

  Tensorflow为了更好的管理变量,提供了variable scope机制,其官方解释如下:
  Variable scope object to carry defaults to provide to get_variable.
  Many of the arguments we need for get_variable in a variable store are most easily handled with a context. This object is used for the defaults. Attributes:

  • name: name of the current scope, used as prefix in get_variable.
  • initializer: 传给get_variable的默认initializer。如果get_variable的时候指定了initializer,那么将覆盖这个默认的initializer
  • regularizer: 传给get_variable的默认regulizer
  • reuse: Boolean or None, setting the reuse in get_variable.
  • caching_device: string, callable, or None: the caching device passed to get_variable.
  • partitioner: callable or None: the partitioner passed to get_variable.
  • custom_getter: default custom getter passed to get_variable.
  • name_scope: The name passed to tf.name_scope.
  • dtype: default type passed to get_variable (defaults to DT_FLOAT).

  regularizer参数的作用是给在本variable_scope下创建的weights加上正则项,这样我们就可以不同variable_scope下的参数加不同的正则项了。可以看出,用variable scope管理get_varibale是很方便的。

确定get_variable的prefixed name

  代码示例如下:

import tensorflow as tf

with tf.variable_scope("tet1"):
    var3 = tf.get_variable("var3", shape=[2], dtype=tf.float32)
    print(var3.name)

with tf.variable_scope("tet2"):
    var4 = tf.get_variable("var4", shape=[2], dtype=tf.float32)
    print(var4.name)

执行结果:

tet1/var3:0
tet2/var4:0

variable scope是可以嵌套的:

import tensorflow as tf

with tf.variable_scope("tet1"):
    var3 = tf.get_variable("var3", shape=[2], dtype=tf.float32)
    print(var3.name)

    with tf.variable_scope("tet2"):
        var4 = tf.get_variable("var4", shape=[2], dtype=tf.float32)
        print(var4.name)

执行结果:

tet1/var3:0
tet1/tet2/var4:0

  get_varibale.name以创建变量的scope作为名字的prefix

import tensorflow as tf

def te2():
    with tf.variable_scope("te2"):
        var2 = tf.get_variable("var2", shape=[2], dtype=tf.float32)
        print(var2.name)

        def te1():
            with tf.variable_scope("te1"):
                var1 = tf.get_variable("var1", shape=[2], dtype=tf.float32)

            return var1

        return te1()  # 在scope的te2内调用的

res = te2()
print(res.name)

执行结果:

te2/var2:0
te2/te1/var1:0

对比下面的代码:

import tensorflow as tf

def te2():
    with tf.variable_scope("te2"):
        var2 = tf.get_variable("var2", shape=[2], dtype=tf.float32)
        print(var2.name)

        def te1():
            with tf.variable_scope("te1"):
                var1 = tf.get_variable("var1", shape=[2], dtype=tf.float32)

            return var1

    return te1()  # 在scope的te2外面调用的

res = te2()
print(res.name)

执行结果:

te2/var2:0
te1/var1:0

  需要注意一点的是tf.variable_scope("name")tf.variable_scope(scope)的区别,代码1如下:

import tensorflow as tf

with tf.variable_scope("scope"):
    var1 = tf.get_variable("w", shape=[1])
    print(var1.name)  # 执行结果“scope/w”

    with tf.variable_scope("scope"):
        var2 = tf.get_variable("w", shape=[1])
        print(var2.name)  # 执行结果“scope/scope/w”

代码2如下:

import tensorflow as tf

with tf.variable_scope("scope"):
    var1 = tf.get_variable("w", shape=[1])
    print(var1.name)  # 执行结果“scope/w”
    scope = tf.get_variable_scope()

    with tf.variable_scope(scope):  # 这种方式设置的scope,是用的外部的scope
        var2 = tf.get_variable("w", shape=[1])  # 这个变量的name也是“scope/w”,因此会报出错误
        print(var2.name)

共享变量

  共享变量的前提是变量的名字是一样的,变量的名字是由变量名和其scope前缀一起构成,tf.get_variable_scope().reuse_variables()允许共享当前scope下的所有变量。

import tensorflow as tf

with tf.variable_scope("level1"):
    var1 = tf.get_variable("w", shape=[1])
    print(var1.name)
    scope = tf.get_variable_scope()

    with tf.variable_scope("level2"):
        var2 = tf.get_variable("w", shape=[1])
        print(var2.name)

with tf.variable_scope("level1", reuse=True):
    var1 = tf.get_variable("w", shape=[1])
    print(var1.name)
    scope = tf.get_variable_scope()

    with tf.variable_scope(scope):
        var2 = tf.get_variable("w", shape=[1])
        print(var2.name)

执行结果:

level1/w:0
level1/level2/w:0
level1/w:0
level1/w:0

  在Tensorflow中,有两个scope,一个是name_scope,另一个是variable_scope,这两个scope到底有什么区别呢?
  先看第一个程序:

import tensorflow as tf

with tf.name_scope("hello") as name_scope:
    arr1 = tf.get_variable("arr1", shape=[2, 10], dtype=tf.float32)
    print(name_scope)
    print(arr1.name)
    print("scope_name:%s " % tf.get_variable_scope().original_name_scope)

执行结果:

hello/
arr1:0
scope_name:

可以看出,tf.name_scope返回的是一个string,在name_scope中定义的variablename并没有hello/前缀;tf.get_variable_scopeoriginal_name_scope是空。
  第二个程序如下:

import tensorflow as tf

with tf.variable_scope("hello") as variable_scope:
    arr1 = tf.get_variable("arr1", shape=[2, 10], dtype=tf.float32)
    print(variable_scope)
    print(variable_scope.name)  # 打印出变量空间名字
    print(arr1.name)
    # tf.get_variable_scope获取的就是variable_scope
    print(tf.get_variable_scope().original_name_scope)

    with tf.variable_scope("xixi") as v_scope2:
        # tf.get_variable_scope获取的就是v_scope2
        print(tf.get_variable_scope().original_name_scope)

执行结果:

<tensorflow.python.ops.variable_scope.VariableScope object at 0x00000000086649B0>
hello
hello/arr1:0
hello/
hello/xixi/

可以看出,tf.variable_scope返回的是一个op对象,variable_scope中定义的variablename加上了hello/前缀;tf.get_variable_scopeoriginal_name_scope是嵌套后的scope name
  第三个程序如下:

import tensorflow as tf

with tf.name_scope("name1"):
    with tf.variable_scope("var1"):
        w = tf.get_variable("w", shape=[2])
        res = tf.add(w, [3])

print(w.name)
print(res.name)

执行结果:

var1/w:0
name1/var1/Add:0

可以看出,variable scopename scope都会给opname加上前缀。
  对比三个程序可以看出:

  • name_scopeget_variable创建的变量的名字不会有任何影响,而创建的op会被加上前缀。
  • tf.get_variable_scope返回的只是variable_scope,不管name_scope,所以以后我们在使用tf.get_variable_scope().reuse_variables()时可以无视name_scope

  其它情况如下:

import tensorflow as tf

with tf.name_scope("scope1") as scope1:
    with tf.name_scope("scope2") as scope2:
        print(scope2)  # 结果为“scope1/scope2/”

另外一个:

import tensorflow as tf

with tf.variable_scope("scope1") as scope1:
    with tf.variable_scope("scope2") as scope2:
        print(scope2.name)  # 结果为“scope1/scope2”

name_scope可以用来干什么?

  典型的TensorFlow可以有数以千计的节点,如此多而难以一下全部看到,甚至无法使用标准图表工具来展示。为简单起见,我们为op/tensor名划定范围,并且可视化把该信息用于在图表中的节点上定义一个层级。默认情况下,只有顶层节点会显示。下面这个例子使用tf.name_scopehidden命名域下定义了三个操作:

import tensorflow as tf

with tf.name_scope('hidden') as scope:
    a = tf.constant(5, name='alpha')
    W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0), name='weights')
    b = tf.Variable(tf.zeros([1]), name='biases')
    print(a.name)
    print(W.name)
    print(b.name)

执行结果:

hidden/alpha:0
hidden/weights:0
hidden/biases:0

name_scope是给op_name加前缀,variable_scope是给get_variable创建的变量的名字加前缀。
  tf.variable_scope有时也会处理命名冲突:

import tensorflow as tf

def test(name=None):
    with tf.variable_scope(name, default_name="scope") as scope:
        w = tf.get_variable("w", shape=[2, 10])

test()
test()
ws = tf.trainable_variables()

for w in ws:
    print(w.name)

执行结果:

scope/w:0
scope_1/w:0

可以看出,如果只是使用default_name这个属性来创建variable_scope的时候,会处理命名冲突。
  tf.name_scope(None)有清除name scope的作用:

import tensorflow as tf

with tf.name_scope("hehe"):
    w1 = tf.Variable(1.0)

    with tf.name_scope(None):
        w2 = tf.Variable(2.0)

print(w1.name)
print(w2.name)

执行结果:

hehe/Variable:0
Variable:0

  简单来看:

  • 使用tf.Variable的时候,tf.name_scopetf.variable_scope都会给Variableopname属性加上前缀。
  • 使用tf.get_variable的时候,tf.name_scope就不会给tf.get_variable创建出来的Variable加前缀。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值