tensorflow学习之路(2-2):tf.variable

xiaoxiao2021-02-28  56

在tensorflow学习之路(2-1):tf.variable_scope(),tf.name_scope(),tf.get_variable()的认识这篇中,并没有对他们有一个很好的认识,仅仅介绍了他们的使用。而在这篇文章中,将会重新从整体上去理解他们,算是对上篇的一个更好的总结吧。


简要概括:我们可以通过tf.Variable()来新建变量,但是,在tensorflow程序中,我们又需要共享变量(share variables),于是,就有了tf.get_variable()(新建变量或者取已经存在的变量)。但是,因为一般变量命名比较短,那么,此时,我们就需要类似目录工作一样的东西来管理变量命名,于是,就有了tf.variable_scope(),同时,设置reuse标志,就可以来决定tf.get_variable()的工作方式(新建变量或者取得已经存在变量)。此外,在tensorflow中,还存在ops操作,而tf.variable_scope()可以同时对variable和ops的命名有影响,即加前缀;而tf.name_scope()只能对ops的命名加前缀。



先介绍背景: 在简单的模型中,我们可以创建多个variable。而在复杂的模型中,我们往往需要共享大量的variables,且需要在同一位置初始化他们。因此,出现了tf.variable_scope()和tf.get_variable()。

一般可以通过使用dictionary也可以达到共享变量的目的,但是,其在代码外创建变量打破了封装原则,同时,当代码改变时,需要创建更多或者更少或者新建变量。


在tensorflow中的Variable Scope Mechanism 主要包含了下面两个函数:

tf.get_variable()tf.variable_scope()

tf.get_variable()主要用于得到或者新建一个variable变量,而不是直接调用tf.Variable().于tf.Variable()之间使用值初始化变量不同,tf.get_variable()主要是通过initializer这个function来初始化新建变量的。此外,variable变量名字较短,容易重复,所以,就需要tf.variable_scope()为变量创建一个命名空间。例如,cnn的每一层中,均有weights和biases这两个变量,通过tf.variable_scope()为每一卷积层命名,就可以防止变量name重复。


Variable Scope是如何工作的呢?


首先,理解tf.get_variable()是如何工作的。一般通过下面方式调用tf.get_variable():

v = tf.get_variable(name, shape, dtype, initializer)

而tf.get_variable()是新建变量还是取得已存在变量取决于调用它的scope.

情况1:若scope设置为新建变量,例如,tf.get_variable_scope().reuse == False.(说明:tf.get_variable_scope()得到当前的scope) 在这种情况下,v就是一个给定shape和initializer的新建的tf.Variable。新建变量的full name则就是scope的name+tf.get_variable()函数中的name,同时,还会检查是否已经存在这个full name的变量。如果存在这个full name 的变量,函数会报ValueError错误。

情况2:若scope设置为重新使用已有变量,例如,tf.get_variable_scope().reuse == True. 在这种情况下,这个调用则会寻找full name为 scope的name + tf.get_variable()函数中的name的变量。如果不存在,则会报ValueError错误。如果存在,则会返回这个变量。



tf.variable_scope()相关

tf.variable_scope()的基本作用主要是给变量名加前缀和设置reuse标志以此来区分tf.get_variable()的两种情况(新建变量或者重新使用已有变量)。加前缀类似于目录的工作。

我们已经知道tf.get_variable_scope()可以获取当前variable scope.而通过下面的调用,可以设置当前的variable scope的reuse标志为True:

tf.get_variable_scope().reuse_variables() #Example with tf.variable_scope("foo"): v = tf.get_variable("v", [1]) tf.get_variable_scope().reuse_variables() v1 = tf.get_variable("v", [1]) assert v1 is v

注意:不要显示的设置reuse=False.reuse的取值为None和True.默认reuse=None,即不共享参数。当reuse=True时,共享参数,并且,在此scope下的所有sub-scope的reuse都为True.



此外,关于tf.variable_scope()还有一下几点需要注意:

1.tf.variable_scope(name_or_scope,…)中的name_or_scope可以是VariableScope Object(一般用于较复杂的情况),具体如下:

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]) assert v1 is v assert w1 is w

2.使用之前已经存在的scope来打开一个variable scope,能够跳出当前variable scope前缀而为一个完全不同的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.

3.在一个区域内,可以为所有的variables设置默认的initializer。设置默认的initializer能够被sub-scope继承,且会传送给同区域的每一个tf.get_variable()。可以通过显示指定另一个initializer来重写initializer。如下:

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.

4.关于tf.variable_scope()和tf.name_scope()。tf.variable_scope()可以同时对variable和ops加前缀,而tf.name_scope()只能对ops加前缀,对variables的命名没有影响。如下:

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

参考资料: https://www.tensorflow.org/programmers_guide/variable_scope http://blog.csdn.net/u012436149/article/details/53696970 http://blog.csdn.net/u012436149/article/details/53081454

转载请注明原文地址: https://www.6miu.com/read-96935.html

最新回复(0)