• TensorFlow的梯度裁剪


    在较深的网络,如多层CNN或者非常长的RNN,由于求导的链式法则,有可能会出现梯度消失(Gradient Vanishing)或梯度爆炸(Gradient Exploding )的问题。

    原理

    问题:为什么梯度爆炸会造成训练时不稳定而且不收敛?
    梯度爆炸,其实就是偏导数很大的意思。回想我们使用梯度下降方法更新参数:

    损失函数的值沿着梯度的方向呈下降趋势,然而,如果梯度(偏导数)很大话,就会出现函数值跳来跳去,收敛不到最值的情况,如图:

    当然出现这种情况,其中一种解决方法是,将学习率αα设小一点,如0.0001。

    这里介绍梯度裁剪(Gradient Clipping)的方法,对梯度进行裁剪,论文提出对梯度的L2范数进行裁剪,也就是所有参数偏导数的平方和再开方。

    TensorFlow代码

    方法一:

    optimizer = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.5)
    grads = optimizer.compute_gradients(loss)
    for i, (g, v) in enumerate(grads):
        if g is not None:
            grads[i] = (tf.clip_by_norm(g, 5), v)  # 阈值这里设为5
    train_op = optimizer.apply_gradients(grads)

    其中
    optimizer.compute_gradients()返回的是正常计算的梯度,是一个包含(gradient, variable)的列表。

    tf.clip_by_norm(t, clip_norm)返回裁剪过的梯度,维度跟t一样。

    不过这里需要注意的是,这里范数的计算不是根据全局的梯度,而是一部分的。

    方法二:

    optimizer = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.5)
    grads, variables = zip(*optimizer.compute_gradients(loss))
    grads, global_norm = tf.clip_by_global_norm(grads, 5)
    train_op = optimizer.apply_gradients(zip(grads, variables))

    这里是计算全局范数,这才是标准的。不过缺点就是会慢一点,因为需要全部梯度计算完之后才能进行裁剪。

    总结

    当你训练模型出现Loss值出现跳动,一直不收敛时,除了设小学习率之外,梯度裁剪也是一个好方法。

    然而这也说明,如果你的模型稳定而且会收敛,但是效果不佳时,那这就跟学习率和梯度爆炸没啥关系了。因此,学习率的设定和梯度裁剪的阈值并不能提高模型的准确率。

  • 相关阅读:
    centos7刚安装解决网络问题
    python matplotlib的常用绘图方法
    python实现最小可编辑距离
    JDBC快速入门
    关于MYSQL常用操作查询语言
    3w字详解java集合
    ELK实时日志分析平台环境部署--完整记录(转)
    ELK简介(转)
    python格式化输出(% & format)
    ElasticSearch查询 搜索 | 更新 | 查询
  • 原文地址:https://www.cnblogs.com/zongfa/p/9737698.html
Copyright © 2020-2023  润新知