美文网首页
tf.gradients计算导数和gradient clippi

tf.gradients计算导数和gradient clippi

作者: EO_eaf6 | 来源:发表于2020-06-10 16:32 被阅读0次

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

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

    相关文章

      网友评论

          本文标题:tf.gradients计算导数和gradient clippi

          本文链接:https://www.haomeiwen.com/subject/daeptktx.html