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"
- 可以在第二次使用变量作用域的时候,设置可重用属性为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])
- 可以在需要复用变量名时,使用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])
- 可以在第一次时,使用属性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])
变量作用域使用规则:
- 可以在变量作用域中使用之前定义好的变量作用域,此时变量作用域名称是其本身
- 可以在变量作用域中重新定义新的变量作用域,此时变量作用域的名称是:父变量作用域+/+本身的变量作用域。
- 内部变量作用域中的变量可以和外部变量作用域中的变量同名(毕竟作用域的名称不同了,联想一下文件命名规则,同一文件夹下不能同名,子文件夹的文件可以和父文件夹的文件同名,因为唯一寻址地址不一样,不会影响查找)
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" # 保持不变
变量作用域初始化:
- 可以在变量作用域定义时,默认携带初始化器,这样内部的变量会被初始化成相同的值。
- 如果内部定义了子变量作用域,那么优先使用内部变量作用域的初始化器。
- 如果内部变量自带初始化器,那么变量自身的初始化器的优先级更高。
- 优先级: 变量初始化器>内部变量作用域初始化器>外部变量作用域初始化器
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"