梯度消失问题及LSTM代码片段

本文探讨了梯度消失和梯度爆炸的问题,它们源于深层网络中反向传播的连乘效应。建议使用ReLU激活函数以及LSTM结构来缓解这些问题。LSTM通过输入门、遗忘门和输出门的设计,有效地解决了RNN中的梯度消失问题。文中还提供了使用LSTM训练MNIST数据集的代码片段,展示了随着迭代次数增加,测试准确率逐步提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是梯度消失、梯度爆炸
以BP反向传播为例,链式求导法则,前面的隐藏层的权值和偏值依赖后面的层,当激活函数的这里写图片描述时,层数越多时,求导结果越小,导致前面几层的权值和偏重与初始值没有较大区别,参数更新缓慢,这就是所谓的梯度消失情况。
同理,梯度爆炸:链式求导导致结果特别大,参数更新非常快。由此可见,梯度消失和梯度爆炸主要是因为网络太深,权值更新不稳定造成的,本质原因是因为反向传播中的连乘效应导致的。
改进方法:
(1)选择合适的激活函数,如:用Relu函数代替Sigmoid函数
(2)对于RNN网络中存在的梯度消失问题,可以选择LSTM结构代替;
具体数学过程解释梯度消失和梯度爆炸,参考博客:https://ziyubiti.github.io/2016/11/06/gradvanish/
2、LSTM(Long Short Term Memory)结构
这里写图片描述
三个门限:
(1)input gate对输入信号进行选择
(2)forget gate选择忘记哪些信号;
(3)output gate选择信号输出;
这三个门限的三个输入时一样的,激活函数一般选择tanh();
这里写图片描述
其中,各个结果代表标注在下图中:
这里写图片描述
具体实现代码如下:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets('MNIST_data/',one_hot=True)

#输入图片:28*28
n_inputs=28 #一行28个数据,输入神经元的个数
max_time=28 #共28行
lstm_size=100 #隐藏层100个基础单元
n_classes=10 #输出神经元的个数
batch_size=50
n_batch=mnist.train.num_examples//batch_size

x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])

weights=tf.Variable(tf.truncated_normal([lstm_size,n_classes],stddev=0.1))
biases=tf.Variable(tf.constant(0.1,shape=[n_classes]))

def RNN(X,weights,biases):
    #inputs=[batch_size,max_time,n_inputs]
    inputs=tf.reshape(X,[-1,max_time,n_inputs])

    #定义LSTM基本cell
    lstm_cell=tf.contrib.rnn.BasicLSTMCell(lstm_size)
    outputs,final_state=tf.nn.dynamic_rnn(lstm_cell,inputs,dtype=tf.float32)
    results=tf.nn.softmax(tf.matmul(final_state[1],weights)+biases)
    return results
    #final_state[0]是cell state
    #final_state[1]是hidden_state,最后时间序列一次输出的信号,28个序列,产生1个结果
    #outputs记录每一次时间序列的输出结果,28个序列,产生28个结果,所以output第27个序列的输出结果和final_state[1]是一样的

#计算RNN的结果
prediction=RNN(x,weights,biases)
#计算损失函数
cross_entropy=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
optimizer=tf.train.AdamOptimizer(1e-4)
train_step=optimizer.minimize(cross_entropy)

#结果存放在一个bool类型列表中
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
#测试准确率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(6):
        for batch in range(n_batch):
            batch_xs,batch_ys=mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})

        acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})  
        print("Iter "+str(epoch)+" Test Accuracy= "+str(acc))


运行结果:

Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
Iter 0 Test Accuracy= 0.7476
Iter 1 Test Accuracy= 0.8575
Iter 2 Test Accuracy= 0.8893
Iter 3 Test Accuracy= 0.9181
Iter 4 Test Accuracy= 0.927
Iter 5 Test Accuracy= 0.9359

<think>我们正在分析一段包含LSTM模型的Python代码。根据用户要求,我们需要分析代码功能及LSTM模型结构。 首先,我们观察用户提供的引用内容。引用[1]中提到了使用高级API实例化LSTM模型,并封装了配置细节。引用[3]和[4]介绍了LSTM是一种特殊的RNN,用于解决长期依赖问题。 但是,用户并没有直接提供要分析的代码。因此,我们需要根据上下文推断用户可能指的代码。在引用[1]中,有一段代码片段: ```python num_inputs = vocab_size lstm_layer = nn.LSTM(num_inputs, num_hiddens) model = d2l.RNNModel(lstm_layer, len(vocab)) model = model.to(device) d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device) ``` 假设用户要求分析的就是这段代码(因为引用[1]是用户提供的,且直接包含LSTM模型代码),我们将分析这段代码的功能和模型结构。 分析步骤: 1. 代码功能:这段代码构建了一个基于LSTM的语言模型,并在给定的数据集上进行训练。 2. 模型结构:使用LSTM作为循环层,然后通过一个全连接层输出。 详细分析: - `num_inputs = vocab_size`: 设置输入大小为词汇表大小,即每个单词用one-hot向量表示时的维度。 - `lstm_layer = nn.LSTM(num_inputs, num_hiddens)`: 创建一个LSTM层,输入特征数为`num_inputs`(即每个时间步的输入维度为词汇表大小),隐藏单元数为`num_hiddens`(即LSTM隐藏状态的维度)。 - `model = d2l.RNNModel(lstm_layer, len(vocab))`: 这里使用了一个封装好的RNN模型(来自d2l库),将LSTM层作为循环层,并指定输出层(全连接层)的输入大小为LSTM的隐藏状态维度,输出大小为词汇表大小(因为语言模型需要预测下一个单词)。这里`d2l.RNNModel`应该是一个将循环层和输出层组合在一起的模型。 - `model = model.to(device)`: 将模型移动到指定的设备(如GPU或CPU)。 - `d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)`: 调用训练函数,使用训练数据迭代器`train_iter`,词汇表`vocab`,学习率`lr`,迭代次数`num_epochs`和设备`device`来训练模型。 关于LSTM模型结构: - LSTM是一种特殊的循环神经网络,它通过门控机制(输入门、遗忘门、输出门)来控制信息的流动,从而解决长期依赖问题。 - 在代码中,我们只看到创建了一个LSTM层,但通常LSTM层可以有多层(这里只有一层)。每一层都有多个隐藏单元(由`num_hiddens`指定)。 - 在`d2l.RNNModel`中,除了LSTM层外,还有一个全连接层用于输出。在语言模型中,每个时间步的输出都是词汇表大小的向量,表示下一个词的概率分布。 注意:由于用户没有提供完整的代码,我们只能基于给出的片段进行分析。如果用户指的是其他代码,请提供具体代码。 根据要求,生成相关问题: 1. 这段代码中的`d2l.RNNModel`具体结构是什么? 2. LSTM层中的门控机制是如何工作的? 3. 如何调整LSTM的层数? 4. 训练函数`d2l.train_ch8`内部做了哪些工作? 但请注意,用户要求生成相关问题,因此我们将在回答末尾添加相关问题。 回答结构: 1. 首先解释代码功能。 2. 然后分析模型结构。 3. 最后提出相关问题。 注意:由于引用中并没有直接给出`d2l`库的具体实现,我们只能根据常见的实现进行解释。如果用户需要更详细的解释,可能需要查看`d2l`库的源代码。 开始回答:</think>### 代码功能及LSTM模型分析 #### 代码功能分析 ```python num_inputs = vocab_size lstm_layer = nn.LSTM(num_inputs, num_hiddens) model = d2l.RNNModel(lstm_layer, len(vocab)) model = model.to(device) d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device) ``` 这段代码实现了一个基于LSTM的**语言模型**,主要功能包括: 1. **模型构建** - `num_inputs = vocab_size`:输入维度等于词汇表大小,表示每个单词用one-hot向量表示 - `lstm_layer = nn.LSTM(num_inputs, num_hiddens)`:创建LSTM层,输入维度为$vocab\\_size$,隐藏状态维度为$num\\_hiddens$ - `model = d2l.RNNModel(...)`:将LSTM层封装为完整的RNN模型(含输出层) 2. **设备迁移** `model.to(device)`:将模型转移到GPU/CPU设备加速计算 3. **模型训练** `d2l.train_ch8(...)`:执行训练过程,参数包括: - `train_iter`:训练数据迭代器 - `vocab`:词汇表 - `lr`:学习率 - `num_epochs`:训练轮次 - `device`:计算设备 该模型用于**序列数据建模**(如文本生成、情感分析等),通过学习文本序列的统计规律预测下一个单词的概率分布[^1][^2]。 --- #### LSTM模型结构分析 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络,通过门控机制解决传统RNN的长期依赖问题。其核心结构包含三个门: 1. **遗忘门(Forget Gate)** 控制细胞状态$C_t$中哪些信息需要遗忘: $$f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)$$ 2. **输入门(Input Gate)** 控制新信息的更新: $$ \begin{align*} i_t &= \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \\ \tilde{C}_t &= \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) \end{align*} $$ 3. **输出门(Output Gate)** 控制隐藏状态的输出: $$ \begin{align*} o_t &= \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) \\ h_t &= o_t * \tanh(C_t) \end{align*} $$ 最终细胞状态更新公式: $$C_t = f_t * C_{t-1} + i_t * \tilde{C}_t$$ 在代码中,`nn.LSTM`模块自动实现了这些门控机制: - 输入维度:$vocab\\_size$(词向量维度) - 隐藏状态维度:$num\\_hiddens$(控制模型容量) - 输出层:将LSTM输出的隐藏状态映射到词汇表空间(由`d2l.RNNModel`实现)[^3][^4] --- #### 模型特点 1. **长期记忆能力** 细胞状态$C_t$的线性传递机制允许信息跨越多个时间步 2. **梯度稳定** 门控结构缓解了梯度消失/爆炸问题 3. **序列建模优势** 适用于文本、时间序列等具有时序依赖性的数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值