tensorflow变量作用域(variable scope)

本文介绍了在TensorFlow中如何使用variable scope实现变量共享,通过举例说明了tf.variable_scope()和tf.get_variable()的工作机制,解释了如何在不同层之间重用变量,并详细阐述了variable scope的理解,包括其初始化器、算子影响和名称作用域的关联。

举例说明

当我们创建两层卷积的过滤器时,每输入一次图片都要创建一次过滤器变量()但我们更希望所有图片都共享同一过滤器变量。通常的做法是:1.创建这些变量的全局变量,但是这样会打破封装性。2.将模型封装成类。
tensorflow提供了variable scope这种方式来共享变量,其主要涉及到两个函数

tf.get_variable(<name>, <shape>, <initializer>)   //创建或返回给定名称的变量
tf.variable_scope(<scope_name>)      //管理传给get_variable()的变量名称的作用域

例如下边的语句创建了一个的变量

wgight = tf.get_variable('weight',kernel_shape,
        initializer=tf.random_normal_initializer())

但是我们需要两个卷积层,这时可以通过tf.variable_scope()指定作用域进行区分

with tf.variable_scope('conv1')
...
with tf.variable_scope('conv2')

最后在image_filters这个作用域重复使用第一张图片输入时创建的变量,调用函数reuse_variables(),代码如下:

with tf.variable_scope("image_filters") as scope:
    ...
    scope.reuse_variables()

tf.get_variable()工作机制

当tf.get_variable_scope().reuse == False,调用该函数会创建新的变量.
当tf.get_variable_scope().reuse == True,调用该函数会重用已经创建的变量

with tf.variable_scope("test1"):
    v = tf.get_variable("v", [1])
with tf.variable_scope("test2", reuse=True):
    v1 = tf.get_variable("v", [1])

tf.variable_scope理解

当前环境的作用于可以通过get_variable_scope获得,而且reuse标志可以通过reuse_variables设为true,如下:

with tf.variable_scope("test1"):
    v = tf.get_variable("v", [1])
    tf.get_variable_scope().reuse_variables()
    v1 = tf.get_variable("v", [1])

作用域中的reuse默认为false,可以通过reuse_variables设为true,一旦设为true,则不能返回false,而且作用域的子空间的reuse均为true,如果不想重用变量,那么可以退回到上层作用域,相当于exit当前作用域,如:

with tf.variable_scope("test1"):
    # At start, the scope is not reusing.
    assert tf.get_variable_scope().reuse == False
    with tf.variable_scope("test2"):
        # Opened a sub-scope, still not reusing.
        assert tf.get_variable_scope().reuse == False
    with tf.variable_scope("foo", reuse=True):
        # Explicitly opened a reusing scope.
        assert tf.get_variable_scope().reuse == True
        with tf.variable_scope("bar"):
            # Now sub-scope inherits the reuse flag.
            assert tf.get_variable_scope().reuse == True
    # Exited the reusing scope, back to a non-reusing one.
    assert tf.get_variable_scope().reuse == False

一个作用域可以做另一个作用于的参数

    with tf.variable_scope("foo") as foo_scope:
    v = tf.get_variable("v", [1])
with tf.variable_scope(foo_scope):
    w = tf.get_variable("w", [1])
with tf.variable_scope(foo_scope, reuse=True):
    v1 = tf.get_variable("v", [1])
    w1 = tf.get_variable("w", [1])

不管作用域如何嵌套,当使用with tf.variable_scope()打开一个已经存在的作用域时,就会跳转到这个作用域。

 with tf.variable_scope("foo") as foo_scope:
    assert foo_scope.name == "foo"
with tf.variable_scope("bar"):
    with tf.variable_scope("baz") as other_scope:
        assert other_scope.name == "bar/baz"
        with tf.variable_scope(foo_scope) as foo_scope2:
            assert foo_scope2.name == "foo"  # Not changed

variable scope的Initializers可以创递给子空间和tf.get_variable()函数,除非中间有函数改变,否则不变。

with tf.variable_scope("foo", initializer=tf.constant_initializer(0.4)):
    v = tf.get_variable("v", [1])
    assert v.eval() == 0.4  # Default initializer as set above.
    w = tf.get_variable("w", [1], initializer=tf.constant_initializer(0.3)):
    assert w.eval() == 0.3  # Specific initializer overrides the default.
    with tf.variable_scope("bar"):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.4  # Inherited default initializer.
    with tf.variable_scope("baz", initializer=tf.constant_initializer(0.2)):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.2  # Changed default initializer.

算子(ops)会受变量作用域(variable scope)影响,相当于隐式地打开了同名的名称作用域(name scope),如+这个算子的名称为foo/add

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

除了变量作用域,还可以显式的打开名称作用域,名称作用域仅影响算子的算子的名称,不影响变量的名称。另外如果tf.variable_scope()传入字符参数,创建变量作用域的同时会隐式创建同名的名称作用域。如下面的例子,变量v的作用域是test1,而算子x的算子变为test1/test2,因为有隐式创建名称作用域test2

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

参考自: https://www.cnblogs.com/MY0213/p/9208503.html.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值