undefined variable怎么解决_梯度爆炸的解决方法之一

今天跟B站“奔跑的东兵卫”大佬的教程,学习了使用tf.clip_by_global_norm处理梯度爆炸(exploding gradient problem)的方法。

梯度爆炸是训练很深的神经网络时,随着层数的增加,导数会出现指数级的下降,则导致梯度消失。或者指数级的增加,导致梯度爆炸;本质是梯度传递的链式法则所导致的矩阵高次幂(反向传播会逐层对函数求偏导相乘)、
深度学习-梯度爆炸和梯度消失_sisteryaya的博客-CSDN博客​blog.csdn.net
605973a4b632d017543329c32942b81d.png

在教程现有的三层网络处理MINST这个情况里很难出现梯度爆炸的现象,大佬费尽心思调整参数才有一点梯度很大的意思,然后用tf.clip_by_global_norm处理后梯度就变小了哈哈。只是为了体验一下这个解决方法啦。

3b28c5e21ea83e984a7dcd9da089cc38.png

可以看到从before到after,六行对应w1, b1, w2, b2, w3, b3六个参数。

处理后,梯度降低了,这个方法我决定本质上就是单纯的限制梯度上限,减缓参数优化的速度(在梯度爆炸情况下就是爆炸的速度)。

我注意到另外一件事,就是W1,W2,W3之间的相对大小,随着迭代次数的增多,可以看到靠近输入层的w1变得比靠近输出层的w3要小很多,也就是前面的层逐渐减慢了优化的速度。这个问题在层次很深的模型中会变得很夸张,就是输入层附近的参数和初始值差不多,不怎么变化,也就是说这些不怎么变化的层次对模型来说是无用的。这其实就是梯度消失现象,如同开头提及的,这是由于求导过程迭代导致的。怎么解决我还不知道,之后遇到再细谈把。

下面放这次的代码

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets, layers, optimizers
import os

os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
print(tf.__version__)

(x, y), _ = datasets.mnist.load_data()
x = tf.convert_to_tensor(x, dtype=tf.float32) / 50.
y = tf.convert_to_tensor(y)
y = tf.one_hot(y, depth=10)
print('x: ', x.shape, 'y: ', y.shape)
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(128).repeat(30)
x,y = next(iter(train_db))
print('sample: ', x.shape, y.shape)

def main():
    w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
    b1 = tf.Variable(tf.zeros([256]))
    w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
    b2 = tf.Variable(tf.zeros([128]))
    w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
    b3 = tf.Variable(tf.zeros([10]))

    optimizer = optimizers.SGD(lr=0.01)

    for step, (x,y) in enumerate(train_db):
        x = tf.reshape(x,(-1, 784))

        with tf.GradientTape() as tape:
            h1 = tf.nn.relu(x @ w1 + b1)
            h2 = tf.nn.relu(h1 @ w2 + b2)
            out = h2 @ w3 +b3

            loss = tf.square(y-out)
            loss = tf.reduce_mean(loss, axis=1)
            loss = tf.reduce_mean(loss)

        #compute gradient
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        print('==before==')
        for g in grads:
            print(tf.norm(g))

        grads, _ = tf.clip_by_global_norm(grads, 15)

        print('==after==')
        for g in grads:
            print(tf.norm(g))
        #update w' = w - lr*grad
        optimizer.apply_gradients(zip(grads, [w1, b1, w2, b2, w3, b3]))

        if step % 100 == 0:
            print(step, 'loss: ', float(loss))

if __name__ == '__main__':
    main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值