随着神经网络的结构更加复杂,参数更多时,需要一个更好的方式来传递和管理变量。在TF中提供了通过变量的名字来创建或者获取一个变量的机制,通过这个机制不同函数可以直接通过变量的名字来直接使用变量。这机制主要是通过tf.get_variable和tf.variable_scope实现的。
除了tf.Variable创建函数,TF也提供了tf.get_variable函数来创建或者获取变量。当tf.get_variable用来创建变量时,其功能与tf.Variable是等价的。比如:
v = tf.get_variable('v', shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1], name='v'))
tf.Variable和tf.get_variable最大的区别在于指定变量名称的参数。对于tf.Variable,变量名称是一个可选的参数,通过name='v'给出。但是对于tf.get_variable函数,变量名称是一个必填的参数,tf.get_variable会根据这个名字去创建参数。但是如果试图创建一个已经存在的名字,那么这个函数就会报错。
如果需要通过tf.get_variable来获取一个已经创建的变量,则需要通过tf.variable_scope来生成一个上下文管理器来控制tf.get_variable函数获取已创建的变量:
#在名字为foo的命名空间中创建名字为v的变量
with tf.variable_scope('foo'):
v = tf.get_variable('v',[1],initializer=tf.constant_initializer(1.0))
#由于已经存在v,所以以下代码将会报错
with tf.variable_scope('foo'):
v = tf.get_variable('v',[1])
#Variable foo/v already exists, disallowed. Did you mean to set reuse=True in VarScope?
#在生成上下文管理器时,将reuse设置为True,即可获取变量
with tf.variable_scope('foo', reuse=True):
v = tf.get_variable('v',[1])
tf.variable_scope函数会创建一个TF的命名空间,在命名空间内创建的变量名称都会带上这个空间名字作为前缀,所以这个函数也提供了一个管理变量命名空间的方式:
v1= tf.get_variable('v', [1])
print(v1.name)
#v:0
#0表示是这个变量运算的第一个结果
with tf.variable_scope('foo'):
v2 = tf.get_variable('v', [1])
print(v2.name)
#foo/v:0
with tf.variable_scope('foo'):
with tf.variable_scope('bar'):
v3 = tf.get_variable('v', [1])
print(v3.name)
#foo/bar/v:0
with tf.variable_scope('',reuse=True):
v5 = tf.get_variable('foo/bar/v', [1])
print(v5 = v3)
#True
使用这种方法对本文刚开始的TF模型进行改进,这种方法可以提高复杂程序的可读性:
def inference(input_tensor,avg_class,regularizer):
if avg_class==None:
with tf.variable_scope('layer1'):
weights = tf.get_variable('weights', [INPUT_NODE, LAYER1_NODE], initializer=tf.truncated_normal_initializer(stddev=0.1))
biases = tf.get_variable("biases", [LAYER1_NODE], initializer=tf.constant_initializer(0.0))
layer1 = tf.nn.relu(tf.matmul(input_tensor, weights) + biases)
with tf.variable_scope('layer2'):
weights = tf.get_variable('weights', [LAYER1_NODE, OUT_NODE], initializer=tf.truncated_normal_initializer(stddev=0.1))
biases = tf.get_variable("biases", [OUT_NODE], initializer=tf.constant_initializer(0.0))
layer2 = tf.matmul(layer1, weights) + biases
return layer2
else:
with tf.variable_scope('layer1',reuse=True):
weights = tf.get_variable('weights', [INPUT_NODE, LAYER1_NODE], initializer=tf.truncated_normal_initializer(stddev=0.1))
biases = tf.get_variable("biases", [LAYER1_NODE], initializer=tf.constant_initializer(0.0))
layer1 = tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights))+avg_class.average(biases))
with tf.variable_scope('layer2',reuse=True):
weights = tf.get_variable('weights', [LAYER1_NODE, OUT_NODE], initializer=tf.truncated_normal_initializer(stddev=0.1))
biases = tf.get_variable("biases", [OUT_NODE], initializer=tf.constant_initializer(0.0))
layer2 = tf.matmul(layer1,avg_class.average(weights))+avg_class.average(biases)
return layer2
x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')
y = inference(x)
#若需要使用训练好的神经网络进行推导时
new_x = ...
new_y = inference(new_x, True)