5.3 变量管理(上)

在简单神经网络中可以将计算前向传播结果的过程抽象成一个函数。通过这种方式在训练和测试过程中可以统一调用同一个函数来获得模型的前向传播结果,在5.2.1小节中这个函数定义为:

def inference(input_tensor,avg_class,weights1,biases1,weights2,biases2):

从定义中可以看到,这个函数的参数包含了神经网络中的所有参数。然而,当神经网络的结构更加复杂、参数更多时,就需要一个更好的方式来传递和管理神经网络中的参数了。Tensorflow提供了通过变量名称来创建或者获取一个变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递。Tensorflow中通过变量名称获取变量的机制主要是通过tf.get_variable和tf.variable_scope函数实现的。下面将分别介绍如何使用这两个函数。
第4章介绍了通过tf.Variable函数来创建一个变量。除了tf.Variable函数,Tensorflow还提供了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.get_variable函数调用时提供的维度(shape)信息及初始化方法(initializer)的参数和tf.Variable函数调用时提供的初始化过程中的参数也类似。Tensorflow中提供的initializer函数和3.4.3小节中介绍的随机数以及常量生成函数大部分是一一对应的。比如,在上述样例程序中使用到的常数初始化函数tf.constant_initializer和常数生成函数tf.constant功能上就是一致的。Tensorflow提供了7种不同的初始化函数。
tf.get_variable函数与tf.Variable函数最大的区别在于指定变量名称的参数。对于tf.Variable函数,变量名称是一个可选的参数,通过name="v"的形式给出。但是对于tf.get_variable函数,变量名称是一个必填的参数。tf.get_variable会根据这个名字去创建或者获取变量。在上面的样例程序中,tf.get_variable首先会试图创建一个名为v的参数,如果创建失败(比如已经有同名的参数),那么这个程序就会报错。这是为了避免无意识的变量复用造成的错误。比如在定义神经网络的参数时,第一层网络的权重已经叫weights了,那么在创建第二层神经网络时,如果参数名仍然叫weights,就会触发变量重用的错误。否则两层网络共用一个权重会出现一些比较难以发现的错误。如果需要通过tf.get_variable获取一个已经创建的变量,需要通过tf.variable_scope函数来生成一个上下文管理器,并明确指定在这个上下文管理器中,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))


#因为在命名空间foo中已经存在名字为v的变量,所有下面的代码将会报错:
#Variable foo/v already exists, disallowed. Did you mean to set reuse=True in VarScope? 
#with tf.variable_scope("foo"):
#	v=tf.get_variable("v",[1])

#在生成上下文管理器时,将参数reuse设置为True。这样tf.get_variable函数将直接获取已经声明的变量
with tf.variable_scope("foo",reuse=True):
	v1=tf.get_variable("v",[1])
	print(v==v1)	#输出为True,代表v,v1代表的是相同的Tensorflow中变量

#将参数reuse设置为True时,tf.variable_scope将只能获取已经创建的变量
#因为在命名空间bar中还没有创建变量,所以下面的代码会报错:
# Variable bar/v does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=None in VarScope?
#with tf.variable_scope("bar",reuse=True):
#	v=tf.get_variable("v",[1])

上面的样例简单说明了通过tf.variable_scope函数可以控制tf.get_variable函数的语义。当tf.variable_scope函数使用参数reuse=True生成上下文管理器时,这个上下文管理器内所有的tf.get_variable函数会直接获取已经创建的变量。如果变量不存在,则tf.get_variable函数将报错;相反,如果tf.variable_scope函数使用参数reuse=None或者reuse=False创建上下文管理器,tf.get_variable操作将创建新的变量。如果同名的变量已经存在,则tf.get_variable函数将报错。Tensorflow中tf.variable_scope函数是可以嵌套的。下面的程序说明了当tf.variable_scope函数嵌套时,reuse函数的取值是如何确定的。

with tf.variable_scope("root"):
	#可以通过tf.get_variable_scope().reuse函数来获取当前上下文管理器中reuse参数的取值
	print(tf.get_variable_scope().reuse)	#输出False,即最外层reuse是False

	with tf.variable_scope("foo",reuse=True):	#新建一个嵌套的上下文管理器,并制定reuse为True
		print(tf.get_variable_scope().reuse)	#输出True
		with tf.variable_scope("bar"):			#新建一个嵌套的上下文管理器但不指定reuse,这时reuse的取值会和外面一层保持一致
			print(tf.get_variable_scope().reuse)#输出True
	print(tf.get_variable_scope().reuse)		#输出为False。退出reuse设置为True的上下文之后
												#reuse的值又回到了False

tf.variable_scope函数生成的上下文管理器也会创建一个Tensorflow中的命名空间,在命名空间内创建的变量名称都会带上这个命名空间名作为前缀。所以,tf.variable_scope函数除了可以控制tf.get_variable执行的功能之外,这个函数也提供了一个管理变量命名空间的方式。
留待下篇继续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值