两种定义图变量的方法
- tf.Variable
tf.Variable(initial_value, trainable=True, collections=None, validate_shape=True, name=None)
虽然有一堆参数,但只有第一个参数initial_value是必需的,用法如下(assign函数用于给图变量赋值)
import tensorflow as tf
v = tf.Variable(3, name='v')
v2 = v.assign(5)
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 这里sess.run(v.initializer)
print(sess.run(v)) # 输出3
print(sess.run(v2)) # 输出5
- tf.get_Variable
tf.get_variable跟tf.Variable都可以用来定义图变量,但是前者的必需参数(即第一个参数)并不是图变量的初始值,而是图变量的名称。
tf.get_Variable的用法要更丰富一点,当指定名称的图变量已经存在时表示获取它,当指定名称的图变量不存在时表示定义它,用法如下:
tf.get_variable( name, shape=None, dtype=None, initializer=None,
regularizer=None, trainable=True, collections=None,
caching_device=None, partitioner=None, validate_shape=True,
use_resource=None, custom_getter=None, constraint=None)
Scope如何划分命名空间
一个深度学习模型的参数变量往往是成千上万的,不加上命名空间加以分组整理,将会成为可怕的灾难。TensorFlow的命名空间分为两种,tf.variable_scope和tf.name_scope。
- tf.variable_scope
下面示范使用tf.variable_scope把图变量划分为4组:
import tensorflow as tf
for i in range(4):
with tf.variable_scope('scope-{}'.format(i)):
for j in range(25):
v = tf.Variable(1, name=str(j))
当使用tf.get_variable定义变量时,如果出现同名的情况将会引起报错
>>> v1 = tf.get_variable('var', [1])
>>> v2 = tf.get_variable('var', [1])
执行结果: ValueError: Variable var already exists
而对于tf.Variable来说,却可以定义“同名”变量
>>> v1 = tf.Variable(1, name='var')
>>> v2 = tf.Variable(2, name='var')
执行结果:正确执行
print(v1.name) # var_5:0
print(v2.name) # var_6:0
是把这些图变量的name属性打印出来,就可以发现它们的名称并不是一样的。
如果想使用tf.get_variable来定义另一个同名图变量,可以考虑加入新一层scope,比如:
import tensorflow as tf
with tf.variable_scope('scope1'):
v1 = tf.get_variable('var', shape=[1])
with tf.variable_scope('scope2'):
v2 = tf.get_variable('var', shape=[1])
print(v1.name)
print(v2.name)
执行结果:
scope1/var:0
scope2/var:0
- tf.name_scope
当tf.get_variable遇上tf.name_scope,它定义的变量的最终完整名称将不受这个tf.name_scope的影响,如下:
import tensorflow as tf
with tf.variable_scope('v_scope'):
with tf.name_scope('n_scope'):
x = tf.Variable([1], name='x')
y = tf.get_variable('x', shape=[1], dtype=tf.int32)
z = x + y
print(x.name, y.name, z.name)
执行结果:
v_scope/n_scope/x:0, v_scope/x:0, v_scope/n_scope/add:0
图变量的复用
想象一下,如果我们正在定义一个循环神经网络RNN,想复用上一层的参数以提高模型最终的表现效果,应该怎么做呢?
方法一:
import tensorflow as tf
with tf.variable_scope('scope'):
v1 = tf.get_variable('var', [1])
tf.get_variable_scope().reuse_variables()
v2 = tf.get_variable('var', [1])
print(v1.name, v2.name)
执行结果:
scope/var:0, scope/var:0
方法二:
import tensorflow as tf
with tf.variable_scope('scope'):
v1 = tf.get_variable('x', [1])
with tf.variable_scope('scope', reuse=True):
v2 = tf.get_variable('x', [1])
print(v1.name, v2.name)
执行结果:
scope/var:0, scope/var:0
tf.variable_scope和tf.name_scope的用法总结:
- tf.variable_scope可以让变量有相同的命名,包括tf.get_variable得到的变量,还有tf.Variable的变量
- tf.name_scope可以让变量有相同的命名,只是限于tf.Variable的变量