举例说明
当我们创建两层卷积的过滤器时,每输入一次图片都要创建一次过滤器变量()但我们更希望所有图片都共享同一过滤器变量。通常的做法是: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"
本文介绍了在TensorFlow中如何使用variable scope实现变量共享,通过举例说明了tf.variable_scope()和tf.get_variable()的工作机制,解释了如何在不同层之间重用变量,并详细阐述了variable scope的理解,包括其初始化器、算子影响和名称作用域的关联。
&spm=1001.2101.3001.5002&articleId=89848528&d=1&t=3&u=c00ce160f7fc4532b3ab4c22a28d542b)
372

被折叠的 条评论
为什么被折叠?



