tensorflow技术解析与实战——阅读笔记

tensorflow初探四之作用域的概念——Tensorflow

2019-01-29  本文已影响0人  欠我的都给我吐出来

变量作用域

在 TensorFlow 中有两个作用域(scope),一个是 name_scope,另一个是 variable_scope。

variable_scope

1. variable_scope简单介绍

variable_scope 变量作用域机制在 TensorFlow 中主要由两部分组成:

v = tf.get_variable(name, shape, dtype, initializer) # 通过所给的名字创建或是返回一个变量
tf.variable_scope(<scope_name>) # 为变量指定命名空间

主要是为了共享变量,在循环神经网络中很有用,因为RNN需要大量的共享变量。

可以在作用域内创建新变量,但是默认情况下,不能在作用同一个变量作用域中创建同名变量,否则会报错。

with tf.variable_scope("foo"):
  v = tf.get_variable("v", [1])
  v2 = tf.get_variable("v", [1])#这里v变量已经定义过了,所以会报错
assert v.name == "foo/v:0"
  1. 可以在第二次使用变量作用域的时候,设置可重用属性为True
with tf.variable_scope("foo") as scope:
      v = tf.get_variable("v", [1])
with tf.variable_scope("foo", reuse=True):
      v1 = tf.get_variable("v", [1])
  1. 可以在需要复用变量名时,使用scope.reuse_variables()语句:
with tf.variable_scope("foo") as scope:
    v = tf.get_variable("v", [1])
    scope.reuse_variables()
    v1 = tf.get_variable("v", [1])
  1. 可以在第一次时,使用属性reuse=tf.AUTO_REUSE
with tf.variable_scope("eoo",reuse=tf.AUTO_REUSE) as scope:
    v = tf.get_variable("v", [1])
    v1 = tf.get_variable("v", [1])
2. 获取变量作用域以及变量作用域的初始化

变量作用域可以看成是变量,因为它也可以命名,并通过使用变量名的方式被调用。

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

变量作用域使用规则:

  1. 可以在变量作用域中使用之前定义好的变量作用域,此时变量作用域名称是其本身
  2. 可以在变量作用域中重新定义新的变量作用域,此时变量作用域的名称是:父变量作用域+/+本身的变量作用域。
  3. 内部变量作用域中的变量可以和外部变量作用域中的变量同名(毕竟作用域的名称不同了,联想一下文件命名规则,同一文件夹下不能同名,子文件夹的文件可以和父文件夹的文件同名,因为唯一寻址地址不一样,不会影响查找)
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" # 保持不变

变量作用域初始化:

  1. 可以在变量作用域定义时,默认携带初始化器,这样内部的变量会被初始化成相同的值。
  2. 如果内部定义了子变量作用域,那么优先使用内部变量作用域的初始化器。
  3. 如果内部变量自带初始化器,那么变量自身的初始化器的优先级更高。
  4. 优先级: 变量初始化器>内部变量作用域初始化器>外部变量作用域初始化器
with tf.variable_scope("foo", initializer=tf.constant_initializer(0.4),reuse=tf.AUTO_REUSE):
    v = tf.get_variable("v", [1])
    assert v.eval() == 0.4 # 被作用域初始化
    w = tf.get_variable("w", [1], initializer=tf.constant_initializer(0.3))
    assert w.eval() == 0.3 # 重写初始化器的值
    with tf.variable_scope("bar"):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.4 # 继承默认的初始化器
    with tf.variable_scope("baz", initializer=tf.constant_initializer(0.2)):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.2 # 重写父作用域的初始化器的值
# 代码会报错:FailedPreconditionError: Attempting to use uninitialized value foo/v

name_scope

用于为变量划分范围。在TensorFlow 中常常会有数以千计的节点,在可视化的过程中很难一下子展示出来,因此用 name_scope 为变量划分范围,在可视化中,这表示在计算图中的一个层级。name_scope会影响 op_name,不会影响用 get_variable()创建的变量,而会影响通过 Variable()创建的变量以及操作的名称,给他们添加一个前缀

with tf.variable_scope("foo"):
    with tf.name_scope("bar"):
        v = tf.get_variable("v", [1])
        b = tf.Variable(tf.ones([1]), name='b')
        x = 1.0 + v
assert v.name == "foo/v:0" #这个0后缀是什么?不是变量的内容,也不是变量出现的次数
assert b.name == "foo/bar/b:0"
assert x.op.name == "foo/bar/add"
上一篇下一篇

猜你喜欢

热点阅读