在训练神经网络的时候,我们经常会碰到梯度消失和梯度爆炸的问题,而将梯度下降控制在一定范围内有助于解决梯度消失/爆炸问题,本文我们介绍如何手动计算梯度下降方向,并且进行人为控制。
在神经网络模型中通常我们通过下面的代码来进行优化参数,首先定义一个优化器,然后指定最小化的损失,最后在session中进行运行。
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1.0)
self.train_op = optimizer.minimize(self.cost)
sess.run([train_op], feed_dict={x:data, y:labels})
我们都知道feed_dict的作用是给使用placeholder创建出来的tensor赋值。其实,他的作用更加广泛:feed使用一个值临时替换一个op的输出结果。你可以提供feed数据作为run()调用的参数。feed只在调用它的方法内有效,方法结束,feed就会消失。
在这个过程中,调用minimize方法的时候,底层进行的工作包括:
- 计算trainable_variables 集合中所有参数的梯度,这个在Tensorflow学习笔记(2): 变量及共享变量中进行了介绍
- 然后将梯度应用到变量上进行梯度下降
- 然后我们在调用sess.run(train_op)的时候,会对variables进行更新
如果我们希望对梯度进行截断,那么就要自己计算出梯度,然后进行clip,最后应用到变量上,代码如下所示,接下来我们一一介绍其中的主要步骤
#return a list of trainable variable in you model
params = tf.trainable_variables()
#create an optimizer
opt = tf.train.GradientDescentOptimizer(self.learning_rate)
#compute gradients for params
gradients = tf.gradients(loss, params)
#process gradients
clipped_gradients, norm = tf.clip_by_global_norm(gradients,max_gradient_norm)
train_op = opt.apply_gradients(zip(clipped_gradients, params)))