tf.gradients计算导数和gradient clippi

2020-06-10  本文已影响0人  EO_eaf6

在训练神经网络的时候,我们经常会碰到梯度消失和梯度爆炸的问题,而将梯度下降控制在一定范围内有助于解决梯度消失/爆炸问题,本文我们介绍如何手动计算梯度下降方向,并且进行人为控制。

在神经网络模型中通常我们通过下面的代码来进行优化参数,首先定义一个优化器,然后指定最小化的损失,最后在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})

在这个过程中,调用minimize方法的时候,底层进行的工作包括:

  1. 计算trainable_variables 集合中所有参数的梯度,这个在Tensorflow学习笔记(2): 变量及共享变量 37中进行了介绍
  2. 然后将梯度应用到变量上进行梯度下降
  3. 然后我们在调用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)))


1. tf.gradients

用来进行梯度求解,代码如下所示

import tensorflow as tf

w1 = tf.Variable([[1,2]])
w2 = tf.Variable([[3]])

res1 = tf.matmul(w1, [[1],[1]]) + w2

grads = tf.gradients([res1],[w1,w2])

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    re = sess.run(grads)
    print(type(re))
    print re
************************************输出**************************************
<type 'list'>
[array([[1, 1]], dtype=int32), array([[1]], dtype=int32)]

tf.gradients(ys, xs),其中ys表示xs里的变量的计算之后的结果,表示计算 [图片上传失败...(image-3523b-1591777862757)]

,结果为list,每个list元素表示每个xs里的x的导数。在上面的例子中,我们查看res1和w1的关系

res1 = 1 * x + 1 * y

因此得到的结果是[array([[1,1]], dtype=int32)


2. tf.clip_by_global_norm

tf.clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None)

其中

  1. t_list 表示梯度张量
  2. clip_norm是截取的比率

在应用这个函数之后,t_list[i]的更新公示变为:

global_norm = sqrt(sum(l2norm(t)**2 for t in t_list))
t_list[i] = t_list[i] * clip_norm / max(global_norm, clip_norm)

也就是分为两步:

  1. 计算所有梯度的平方和global_norm
  2. 如果梯度平方和 global_norm 超过我们指定的clip_norm,那么就对梯度进行缩放;否则就按照原本的计算结果,这个应该很好理解。

3. gradient clipping实例

基于循环神经网络的语言模型的介绍与TensorFlow实现(4):TensorFlow实现RNN-based语言模型 16中我们的神经网络语言模型的训练部分代码如下所示:

        trainable_variables = tf.trainable_variables() # 获取到模型中所有需要训练的变量
        grads, _ = tf.clip_by_global_norm(tf.gradients(self.cost, trainable_variables), MAX_GRAD_NORM) # 求导,并且进行截断
        optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1.0)
        self.train_op = optimizer.apply_gradients(
            zip(grads, trainable_variables)
        )

如果我们采用没有加入gradient clipping的方法来替换,如下所示

        optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1.0)
        self.train_op = optimizer.minimize(self.cost)

那么运行结果如下所示,可以看到由于梯度下降的原因,复杂度已经到达正无穷,大家可以自行验证,完整代码请见TensorFlowExamples/Chapter9/language_model.ipynb 18

In iteration: 1
After 0 steps, perplexity is  10010.877
/Users/apple/Library/Python/2.7/lib/python/site-packages/ipykernel_launcher.py:30: RuntimeWarning: overflow encountered in exp
After 100 steps, perplexity is  inf
After 200 steps, perplexity is  inf
After 300 steps, perplexity is  inf
After 400 steps, perplexity is  inf

转自:https://bigquant.com/community/t/topic/121493

上一篇 下一篇

猜你喜欢

热点阅读