在线查询企业搜索引擎优化的意思
- 作者: 五速梦信息网
- 时间: 2026年04月20日 06:50
当前位置: 首页 > news >正文
在线查询企业,搜索引擎优化的意思,wordpress woocommerce 插件,wordpress社区模版目录 一、前言1.1、深度学习时间序列一般是几维数据#xff1f;每个维度的名字是什么#xff1f;通常代表什么含义#xff1f;1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路#xff1f;1.4、RNN存在哪些问题? 二、… 目录 一、前言1.1、深度学习时间序列一般是几维数据每个维度的名字是什么通常代表什么含义1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路1.4、RNN存在哪些问题? 二、LSTM的基本架构2.1 记忆细胞2.2 遗忘门2.3 输入门2.4 输出门 三、应用案例3.1 TensorFlow版3.2 PyTorch版3.2.1 LSTM的输入参数3.2.2 LSTM的三个输出3.2.3 LSTM进行时间序列预测的基本流程3.2.4 案例 四、拓展思考4.1 为什么说 C t C_t Ct是主导长期记忆 h t h_t ht是主导短期记忆4.2 RNN为什么容易梯度消失和梯度爆炸?4.3 LSTM解决梯度消失和梯度爆炸问题吗? 时间序列相关参考文章 时间序列预测算法—ARIMA 时间序列预测算法—Prophet 时间序列预测算法—LSTM 长时间序列预测算法—Informer 时间序列分类任务—tsfresh 有季节效应的非平稳序列分析 python时间序列处理 时间序列异常值检测方法 时间序列异常值处理方法
一、前言
1.1、深度学习时间序列一般是几维数据每个维度的名字是什么通常代表什么含义 答时间序列可以是一维、二维、三维甚至更高维度的数据在深度学习世界中常见的是三维时间序列这三个维度分别是batch_size,time_step,input_dimensions其中batch_size在训练模型时一次输入到模型中的样本数量time_step每个样本的时间步数即每个样本包含的时间序列长度input_dimensions每个时间步的特征数量。
1.2、为什么机器学习/深度学习算法无法处理时间序列数据? 答时间序列数据属于序列化数据的范畴其特点在于各样本之间存在内在的逻辑关联。这类数据按照一定的顺序组织其顺序不可随意更改因为这种顺序性反映了样本间的依赖关系。在分析序列数据时我们不仅需要理解特征与目标标签之间的关系还需掌握样本间的相互作用因为序列中各样本的顺序对彼此及最终预测结果均产生影响。 多数传统机器学习和深度学习模型默认样本间是独立的它们主要关注于特征与标签间的映射而忽略了样本间的序列依赖性。这一局限性使得这些算法在处理时间序列数据时显得力不从心无法充分捕捉数据中的时间动态特征这也是它们在时间序列分析中适用性受限的主要原因。
1.3、RNN(循环神经网络)处理时间序列数据的思路 答在时间序列数据中样本间的关系体现为连续时间点之间的依赖性。为了捕捉这种连续性循环神经网络RNN及其变体采用了一种策略逐个处理时间点并将先前时间点的信息传递至后续时间点。这种方法允许每个时间点接收前一时间点的上下文信息从而在连续的时间点之间建立联系。这种递归信息传递机制是早期深度学习算法处理时间序列数据时的标准做法。
1.4、RNN存在哪些问题? 答RNN算法思路新颖但是却存在众多实践中的问题其中“记忆机制相关的问题十分显著包括但不限于 1.RNN对所有信息照单全收记忆机制中毫无重点。 从常识来判断无论是在时间序列中还是在文字序列中过去时间步上的信息对未来时间步上信息的影响可能是不同的。但RNN为了节约计算资源设置了全样本权重共享机制这意味着RNN处理所有时间步信息的方式是完全相同。因此在RNN吸纳信息时它无法辨别不同时间点上的信息对未来的不同影响在使用这些信息进行预测的时候RNN也无法辨别不同时间步上的标签最需要的信息有哪些这会严重影响算法的整体预测效果。到今天这依然是影响RNN预测效果的关键因素之一。 2.RNN中的新信息会强制覆盖旧信息导致长期记忆被遗忘 虽然循环网络家族建立起了时间点之间的联系但这种联系有时不总是有效的当一个时间点上包含的历史时间点信息越多那些久远的历史时间点的信息就不太容易对当下的预测构成影响。在RNN的计算流程中虽然理论上最后一个时间步中包含了所有时间步上的信息但是真正有影响力的只要非常接近最后一个时间步的几个时间步而已。大部分信息都被RNN遗忘导致RNN很难处理较长的序列。 基于以上两点问题研究者们在设计LSTM的时候存在一个根本诉求——要创造一个全新的架构、一套全新的数据流为循环神经网络赋予选择性记忆和选择性传递信息的能力。这里的选择性包含多层含义包括: 1.循环网络必须自行选择吸纳多少新信息只留重点拒绝照单全收 2.循环网络必须自行选择遗忘多少历史信息主动遗忘无效内容保留有效内容 3.循环网络必须自行判断、对当前时间步的预测来说最重要的信息是哪些并将该信息输出给当前时间步这样既可以保证当前时间步上的预测是最高效的也不会影响向下一个时间步传递的信息。
二、LSTM的基本架构 在上述提到的三个能力当中前两个能力允许循环神经网络决定“哪些长期信息会被传递下去最后一个能力允许循环神经网络决定“哪些短期信息对当前时间步的预测是最重要的。这三种能力构成了LSTM的基本结构。
2.1 记忆细胞 首先LSTM依然是一个循环神经网络因此LSTM的网络架构与RNN高度相似同时LSTM也是需要遍历所有时间步不断完成循环和嵌套的。但不同的是RNN由输入层、隐藏层和输出层构成而LSTM由输入层、记忆细胞和输出层构成其中输入、输出层与RNN的输入、输出层完全一致而记忆细胞是LSTM独有的结构。 记忆细胞是LSTM的基本计算单元在记忆细胞中我们分割长期信息与短期信息同时赋予循环网络对信息做选择的能力。在之前我们提到循环网络必须自行决定哪些长期信息会被传递下去哪些短期信息对当前的预测最为有效因此在记忆细胞当中LSTM设置了两个关键变量主要负责记忆短期信息、尤其是当前时间步信息的隐藏状态h以及主要负责长期记忆的细胞状态C。 这两个变量都随着时间步进行迭代。在迭代开始时LSTM会同时初始化 h 0 h_0 h0和 C 0 C0 C0在任意时间步t上记忆细胞会同时接受来自上一个时间步的长期记忆 C t − 1 C{t-1} Ct−1、短期信息 h t − 1 h_{t-1} ht−1以及当前时间步上输入的新信息 X t X_t Xt三个变量结合三者进行运算后记忆细胞会输出当前时间步上的长期记忆 C t C_t Ct和短期信息 h t h_t ht并将它们传递到下一个时间步上。同时在每个时间步上 h t ht ht还会被传向当前时间步的输出层用于计算当前时间步的预测值。 横向上它可以被分割为C长期记忆的传播的传递和h短期记忆的传播的传递两条路径在纵向上它可以被分为三个不同的路径 1.帮助循环网络选择吸纳多少新信息的输入门 2.帮助循环网络选择遗忘多少历史信息的遗忘门 3.帮助循环网络选择出对当前时间步的预测来说最重要的信息、并将该信息输出给当前时间步的输出门。
2.2 遗忘门 遗忘门是决定要留下多少长期信息C的关键计算单元其数学本质是令上一个时间步传入的 C t − 1 C{t-1} Ct−1乘以一个[01]之间的比例以此筛选掉部分旧信息。假设遗忘门令 C t − 1 C_{t-1} Ct−1乘以0.7就是说遗忘门决定了要保留70%的历史信息遗忘30%的历史信息这30%的信息空间就可以留给全新的信息来使用。核心就是计算 f t f_t ft 求得比例。 遗忘门会参考当前时间步的信息 X t Xt Xt与上一个时间步的短时信息 h t − 1 h{t-1} ht−1来计算该比例其中σ是sigmoid函数 W f W_f Wf是动态影响最终权重大小的参数 f t ft ft就是[0,1]之间的、用于影响 C t − 1 C{t-1} Ct−1的比例。 在LSTM的设计逻辑之中考虑 X t Xt Xt和 h t − 1 h{t-1} ht−1实际是在考虑离当前时间步最近的上下文信息而权重 W f W_f Wf会受到损失函数和算法整体表现的影响不断调节遗忘门中计算出的比例 f 的大小因此遗忘门能够结合上下文信息、损失函数传来的梯度信息、以及历史信息共同计算出全新的、被留下的长期记忆 C t C_t Ct。
2.3 输入门 输入门是决定要吸纳多少新信息来融入长期记忆C的计算单元其数学本质是在当前时间步传入的所有信息上乘以一个[0,1]之间的比例以筛选掉部分新信息将剩余的新信息融入长期记忆C。 计算过程中首先要计算出当前时间步总共吸收了多少全新的信息这个计算全新信息的方式就与RNN中计算ht的方式高度相似因此也会包含用于影响新信息传递的参数 W c W_c Wc和RNN中常见的tanh函数。然后要依据上下文信息依然是 X t Xt Xt和 h t − 1 h{t-1} ht−1以及参数 W t W_t Wt来筛选新信息的比例 i t it it。最后将二者相乘并加入到长期记忆C当中。 相比RNN的数据输入过程LSTM的输入过程灵活了非常多在输入门当中不仅对输入数据加上了一个比例it还分别使用了两个受损失函数影响的权重Wt和Wc来控制新信息聚合和比例计算的流程。在这一比例和两大参数的作用下输入数据可以被高度灵活地调节以便满足最佳的损失函数需求。 更新细胞状态当遗忘门决定了哪些信息要被遗忘输入门决定了哪些信息要被加入到长期记忆后就可以更新用于控制长期记忆的细胞状态了。如下图所示上一个时间步的长期记忆 C t − 1 C{t-1} Ct−1将乘以遗忘门给出的比例 f t f_t ft再加上新信息乘以新信息筛选的比例 i t i_t it同时考虑放弃过去的信息、容纳新信息以此来构成传递下一个时间步的长期信息 C t C_t Ct。 C t Ct Ct是在 C t − 1 C{t-1} Ct−1基础上直接迭代更新得到的所以 C t C_t Ct整合了[1,t]所有时间步的历史信息并负责将这些信息不断传递下去。因此 C t C_t Ct是长期记忆的象征。
2.4 输出门 输出门是从全新的长期信息 C t C_t Ct中筛选出最适合当前时间步的短期信息ht的计算单元本质是令已经计算好的长期信息 C t C_t Ct乘以一个[0,1]之间的比例以此筛选出对当前时间步最有效的信息用于当前时间步的预测。 这个流程分为三步 1、首先要借助上下文信息和权重 W o W_o Wo来求解出比例 O t O_t Ot 2、对长期信息 C t C_t Ct进行tanh标准化处理 3、将 O t O_t Ot乘以标准化后的长期信息 C t C_t Ct之上用于筛选出 h t h_t ht 为什么要对长期信息Ct做标准化处理呢 答:Tanh标准化可以限制有效长期信息 C t C_t Ct的数字范围避免历史信息在传递过程中变得越来越大同时还能为输出门赋予一定的非线性性质这个过程被实践证明有助于保持训练稳定、还能够强化算法学习能力因此在LSTM最终的设计中被保留下来。 h t ht ht和 h t − 1 h{t-1} ht−1之间没有直接的迭代关系虽然二者有一定的联系但 h t − 1 h{t-1} ht−1不是构成ht的核心。在记忆细胞中 h t − 1 h{t-1} ht−1只是用来辅助C进行迭代的变量之一而 h t h_t ht是为了在当前时间步上生成 y t yt yt而计算出来的全新变量影响ht具体取值的核心不是上个时间步的信息 h t − 1 h{t-1} ht−1,而是当前时间步上的输入信息和预测标签的需求因此 h t h_t ht是一个主要承载短期信息、尤其是当前时间步上信息的变量它是为了在当前时间步预测出最准确的标签而存在的。 LSTM是一种RNN特殊的类型可以学习长期依赖信息。LSTM和基线RNN并没有特别大的结构不同用了不同的函数来计算隐状态。LSTM的“记忆”我们叫做细胞这些“细胞”会决定哪些之前的信息和状态需要保留/记住而哪些要被抹去。实际的应用中发现这种方式可以有效地保存很长时间之前的关联信息。 RNN 会受到短时记忆的影响。如果一条序列足够长那它们将很难将信息从较早的时间步传送到后面的时间步。因此如果你正在尝试处理一段文本进行预测RNN 可能从一开始就会遗漏重要信息。RNN会忘记它在较长序列中以前看到的内容因此RNN只具有短时记忆。
三、应用案例
通过网盘分享的文件LSTM数据 链接: https://pan.baidu.com/s/1coExt1KeR6Ke4QqcJhCE1A 提取码: 2zxk
3.1 TensorFlow版
import pandas as pd
import numpy as np
data pd.read_excel(zgpa_train.xlsx)
data.head()pricedata.loc[:,收盘]
#归一化
price_normprice/max(price)
price_norm#可视化
%matplotlib inline
from matplotlib import pyplot as plt# 设置中文显示和负号显示
plt.rcParams[font.sans-serif] [SimHei] # 黑体
plt.rcParams[axes.unicode_minus] False # 负号正常显示fig1plt.figure(figsize(10,6))
plt.plot(data[日期],price)
plt.title(收盘价)
plt.xlabel(time)
plt.ylabel(价格)
plt.show()#定义x、y的值:将原始数据处理成可以供模型训练的格式。数据通过滑动窗口技术time_step进行处理生成适合模型输入的 x和 y
def extract_data(data,time_step):x[] #数据y[] #标签for i in range(len(data)-time_step):x.append([a for a in data[i:itime_step]]) #time_step8,x[0,1,2,3,4,5,6,7]y.append(data[itime_step]) #第8xnp.array(x)xx.reshape(x.shape[0],x.shape[1],1) #将x数据的形状调整为 (样本数, 时间步数, 特征数)在这个例子中特征数1因为每个时间步只包含一个数据点例如一个股价ynp.array(y)return x,y
time_step8
x,yextract_data(price_norm,time_step)
print(x[0,:,:])
print(y[0])from keras.models import Sequential
from keras.layers import Dense, SimpleRNN, Inputmodel Sequential()
使用 Input 层显式定义输入形状
model.add(Input(shape(time_step, 1))) # 输入层
添加 RNN 层
model.add(SimpleRNN(units5, activationrelu))
添加输出层
model.add(Dense(units1, activationlinear))
模型配置
model.compile(optimizeradam, lossmean_squared_error)
model.summary()#训练模型
model.fit(x,y,batch_size30,epochs200)#预测
y_train_predictmodel.predict(x)*max(price)
y_train[i*max(price) for i in y]fig2plt.figure(figsize(10,6))
r2 r2_score(y_train,y_train_predict)
plt.title(fR-squared: {r2:.2f})
plt.plot(y_train,labelreal price)
plt.plot(y_train_predict,labeltrain predict price)
plt.xlabel(time)
plt.ylabel(价格)
plt.legend()
plt.show()#测试数据预测
data_test pd.read_excel(zgpa_test.xlsx)
price_testdata_test.loc[:,收盘]
price_test_normprice_test/max(price_test)
x_test_norm,y_test_normextract_data(price_test_norm,time_step)y_test_predictmodel.predict(x_test_norm)*max(price_test)
y_test[i*max(price_test) for i in y_test_norm]fig3plt.figure(figsize(10,6))
r2 r2_score(y_test,y_test_predict)
plt.title(fR-squared: {r2:.2f})
plt.plot(y_test,labelreal price_test)
plt.plot(y_test_predict,labeltest predict price_test)
plt.xlabel(time)
plt.ylabel(价格)
plt.legend()
plt.show()3.2 PyTorch版
3.2.1 LSTM的输入参数 LSTM类与RNN类高度相似这两个类的参数都很少、结构相当简单。虽然该类的名字叫做LSTM但实际上nn.LSTM并不是完整的LSTM算法而是LSTM中的输入层和隐藏层。nn.LSTM的输入层是在线性层的基础上改进后的层隐藏层则是包含记忆细胞的层这两个层除了最基本的匹配权重、神经元结果加和、激活函数、向前向后传播等功能外还负责执行将上个时间步的中间变量传递给下个时间步的功能。对RNN来说传递的是隐藏状态 h t h_t ht对LSTM来说同时传递细胞状态 c t c_t ct和隐藏状态 h t h_t ht。
nn.LSTM(self,input_size,hidden_size,num_layers1,biasTrue,batch_firstFalse,dropout0.0,
bidirectionalFalse,proj_size0,deviceNone,dtypeNone)
input_size输入特征的数量也是输入层的神经元数量对输入数据为三维数据的LSTMinput_size就是input_dimension。
hidden_size:隐藏层的神经元数量对LSTM来说就是隐藏层上的记忆细胞的数量。
num_layers:隐藏层的数量。
batch_first:如果为True输入和输出Tensor的形状为[batch_size,seq_len,input_dimensions],否则为[seq_len,batch_size,input_dimensions]
drop_out: 在神经网络中常见的抗过拟合机制在Pytorch被内置在LSTM里帮助对抗过拟合。Dropout是在神经网络传播过程中随机让部分参数为0的抗过拟合方法。令参数为0就可以切断神经网络层与层之间的链接从而切断信息的传播以此来阻碍神经网络的学习达到对抗过拟合的目的drop_out这一参数中我们一般填写[0,1)之间的小数。例如填写0.5就代表在每次正向传播中随机令50%的参数为0。这一随机性是不可控制的任何随机数种子都不能让Dropout的随机性变得固定因此Dropout会让神经网络的训练过程变得无法复现。在LSTM中Dropout被施加在隐藏层与隐藏层之间而不是记忆细胞之间也就是说Dropout是施加在 h t h_t ht通向输出层的传播路径上而不影响 C t C_t Ct和 h t h_t ht在时间步上的传播路径。 需要注意的是和任意神经网络中的Dropout模式一致dropout参数默认会在训练过程中起作用而在模型的预测、评估或推理阶段不起作用。因此在训练LSTM的时候我们会需要使用 train() 和 eval() 两种模式来帮助模型分辨当前正在进行的是训练还是预测任务。
3.2.2 LSTM的三个输出 LSTM类有三个输出一个是 output一个是 h n h_n hn还有一个是 c n c_n cn。LSTM类只有输入层和隐藏层。 output代表所有时间步上最后一个隐藏层上输出的隐藏状态的集合。如下图红色方框中的方向上的隐藏状态的集合。对单层的LSTM来说output代表了唯一一个隐藏层上的隐藏状态。output的形状都为[seq_len,batch_size,hidden_size],不受隐藏层数量的影响。当batch_firstTrue时output的形状为[batch_size,seq_len,hidden_size] h t h_t ht是最后一个时间步的、所有隐藏层上的隐藏状态。形状为[num_layers,batch_size,hidden_size]。无论batch_first参数取什么值都不改变 h t h_t ht的输出。 C t C_t Ct是最后一个时间步的、所有隐藏层上的细胞状态。形状为[num_layers,batch_size,hidden_size]。无论batch_first参数取什么值都不改变 C n C_n Cn的输出。 虽然LSTM的每个时间步、每个隐藏层都会输出隐藏状态h和细胞状态C但是LSTM类却只会“选择性”地帮助我们输出部分隐藏状态例如output在深层神经网络中只会保留最后一个隐藏层的隐藏状态而hn和Cn则是只显示最后一个时间步的隐藏状态。不难发现其实output、hn、cn都不能代表nn.LSTM层在循环中所传输的全部信息它们都只能代表部分信息。 如果我们需要执行对每一个时间步进行预测的任务比如预测每一分钟的股价预测明天是否会下雨预测每个单词的情感倾向预测每个单词的词性此时我们就会关注每个时间步在最后一个隐藏层上的输出。此时我们要关注的是整个output。 如果我们需要执行的是对每个时间序列表单、每个句子进行预测的任务时比如对句子进行情感分类预测某个时间段内用户的行为、看过所有的句子之后对后续的文字进行生成等任务我们就只会关注最后一个时间步的输出。此时我们更可能使用hn或者cn来进行下一步的预测。同时在进行生成式的任务的时候我们大概率也只关心最后一个时间步上的输出。 需要注意的是无论是output还是hn还是cn都只是lstm层的输出不是整个神经网络真正的输出因为nn.LSTM层缺乏关键性结构输出层。因此在构建网络的时候我们需要在LSTM层之后再增加一个输出层通常是线性层用于补完整个网络架构。
3.2.3 LSTM进行时间序列预测的基本流程
数据预处理时间序列的数据预处理是一个复杂的过程可能涉及到使用动态的标准来进行数据的编码、缺失值处理、数据大小的处理、对数据进行滑窗、对数据进行分割等等。 数据导入对深度学习数据来说需要先将数据处理好再导入为tensor。对于相对简单的数据或许可以直接使用FloatTensor之类的工具进行转换但对于结构复杂、或者尺寸过大的数据则一般需要自定义继承自Datasets的数据导入函数。该流程的核心职责是将普通数据集整理出成深度学习算法所必须的输入形式大部分时候数据导入的代码非常灵活而且会根据数据的情况发生变化十分复杂。 架构定义自定义基于LSTM层的各类架构。最为简单的方式就是在PyTorch中自定义神经网络类当然也可以使用Huggingface中的一系列高级LSTM相关融合架构。 定义训练流程所需的全部代码在这个过程中我们需要定义各类超参数、定义损失函数、定义优化算法、定义是否使用GPU、决定是否进行early stop、决定打印怎样的内容、决定是否进行持续的模型保存等等具体的流程。幸运的是深度学习中的训练代码都是十分类似的。 进行初次训练根据初次训练结果调整模型架构、模型参数、训练流程 不断进行训练、决定是否完成数据增强等工作
3.2.4 案例
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams[font.sans-serif] [SimHei] # 黑体
plt.rcParams[axes.unicode_minus] False # 负号正常显示
data pd.read_excel(zgpa_train.xlsx)timeseries data[[收盘]].values.astype(float32)
#训练集与测试集分割:不能改变时间顺序因此没有使用train_test_split等操作
train_size int(len(timeseries) * 0.8)
test_size len(timeseries) - train_size
train, test timeseries[:train_size], timeseries[train_size:]
#数据格式转换为tensor
train_tensor torch.FloatTensor(train).view(-1, train.shape[0], 1) #升为三维数据
test_tensor torch.FloatTensor(test).view(-1, test.shape[0], 1)
print(train_tensor.shape,test_tensor.shape) #输出结果torch.Size([1, 584, 1]) torch.Size([1, 147, 1])#定义网络架构
import torch
import torch.nn as nn
class LSTMModel(nn.Module):def init(self, input_size1, hidden_size50, num_layers1, output_size1):super(LSTMModel, self).init()self.hidden_size hidden_sizeself.num_layers num_layers#LSTM层self.lstm nn.LSTM(input_size, hidden_size, num_layers,batch_firstTrue)#输出层self.fc nn.Linear(hidden_size, output_size)def forward(self, x):#初始化h0和c0h0 torch.rand(self.num_layers, x.size(0), self.hidden_size).requiresgrad()c0 torch.rand(self.num_layers, x.size(0), self.hidden_size).requiresgrad()#LSTM的向前传播此时我们关注的是所有时间步上的输出还是最后一个时间步上的输出#所有时间步上的输出因此我们要输出的是output而不是hn和cnoutput, (_, _) self.lstm(x, (h0.detach(), c0.detach()))#output的结构为[batch_size, seq_len, hidden_size]#因此我们要取出对我们有用的维度out self.fc(output[:, :, :])return out
model LSTMModel() #实例化
model(train_tensor).shape #尝试查看输出数据的结构def MSE(Y_ture,Y_predict):return ((Y_ture - Y_predict)**2).sum()/Y_ture.shape[0]
#对照如果不使用神经网络预测只将均值当做预测标签计算MSE的话。LSTM模型的mse不能比之高
MSE(train,train.mean()),MSE(test,test.mean()) #输出(np.float32(233.31065), np.float32(9.202034))超参数设置与架构设置
#超参数设置
input_size 1
hidden_size 50
num_layers 1
output_size 1
learning_rate 0.01
num_epochs 300#实例化模型
model1 LSTMModel(input_size, hidden_size, num_layers, output_size)#定义损失函数与优化算法
criterion nn.MSELoss(reductionmean)
optimizer torch.optim.Adam(model1.parameters(), lrlearning_rate)#开始进行训练的循环
for epoch in range(num_epochs):outputs model1(train_tensor)optimizer.zero_grad()loss criterion(outputs, train_tensor[:, :, :])loss.backward()optimizer.step()if (epoch1) % 50 0:print(fEpoch [{epoch1}/{num_epochs}], Loss: {loss.item():.4f})model1.eval()
test_outputs model1(test_tensor).detach().numpy()
MSE(test,test_outputs) #输出67.62194模型验证集MSE较验证集均值大模型存在过拟合。优化模型超参数与架构设置。
#超参数设置
input_size 1
hidden_size 100
num_layers 5
output_size 1
learning_rate 0.1
num_epochs 1500#实例化模型
model LSTMModel(input_size, hidden_size, num_layers, output_size)#定义损失函数与优化算法
criterion nn.MSELoss(reductionmean)
optimizer torch.optim.Adam(model.parameters(), lrlearning_rate)#开始进行训练的循环
for epoch in range(num_epochs):outputs model(train_tensor)optimizer.zero_grad()loss criterion(outputs, train_tensor[:, -1, :])loss.backward()optimizer.step()if (epoch1) % 150 0:print(fEpoch [{epoch1}/{num_epochs}], Loss: {loss.item():.4f})model.eval()
test_outputs model(test_tensor).detach().numpy()
MSE(test,test_outputs) #输出10.368058模型依然存在过拟合风险。 增加滑动窗口进行处理数据。
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import matplotlib.pyplot as plt# 1. 数据加载
替换为您的数据文件名
file_path zgpa_train.xlsx data pd.read_excel(file_path)# 提取收盘价并归一化 price data.loc[:, 收盘] price_norm price / max(price)# 2. 数据集构建
数据提取函数
def extract_data(data, time_step):x, y [], []for i in range(len(data) - time_step):x.append([a for a in data[i:i time_step]])y.append(data[i time_step])x np.array(x)y np.array(y)x x.reshape(x.shape[0], x.shape[1], 1)return x, y# 定义时间步 time_step 8 x, y extract_data(price_norm, time_step)# 转换为Tensor device torch.device(cuda if torch.cuda.is_available() else cpu) x torch.tensor(x, dtypetorch.float32).to(device) y torch.tensor(y, dtypetorch.float32).to(device)# 数据划分 train_size int(len(x) * 0.8) train_x, test_x x[:train_size], x[train_size:] train_y, test_y y[:train_size], y[train_size:]# 数据加载器 train_loader DataLoader(TensorDataset(train_x, train_y), batch_size64, shuffleTrue)# 3. 定义LSTM模型 class LSTM(nn.Module):def init(self, input_size, hidden_size, num_layers, output_size):super(LSTM, self).init()self.hidden_size hidden_sizeself.num_layers num_layers# 定义LSTM层self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue)# 定义全连接层self.fc nn.Linear(hidden_size, output_size)def forward(self, x):# 初始化隐藏状态和细胞状态h0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)c0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)# 前向传播out, _ self.lstm(x, (h0, c0))out self.fc(out[:, -1, :]) # 取最后一个时间步的输出return out# 超参数设置 input_size 1 hidden_size 32 num_layers 2 output_size 1 learning_rate 0.05 epochs 100# 实例化模型 model LSTM(input_size, hidden_size, num_layers, output_size).to(device) criterion nn.MSELoss() optimizer optim.Adam(model.parameters(), lrlearning_rate)# 4. 模型训练 losses [] for epoch in range(epochs):model.train()for batch_x, batch_y in train_loader:outputs model(batch_x)loss criterion(outputs.squeeze(), batch_y)optimizer.zero_grad()loss.backward()optimizer.step()losses.append(loss.item())if (epoch1) % 10 0:print(fEpoch [{epoch1}/{epochs}], Loss: {loss.item():.4f})# 5. 模型评估 model.eval() with torch.no_grad():pred_y model(test_x).cpu().numpy()true_y test_y.cpu().numpy()# 反归一化 max_price max(price) pred_y pred_y * max_price
6. 可视化结果
plt.figure(figsize(12, 6)) plt.plot(range(len(price)), price, labelOriginal Data) plt.plot(range(train_size time_step, train_size time_step len(pred_y)), pred_y, labelPredicted Data, colorred) # plt.xlabel(Time) plt.ylabel(Normalized Price) plt.title(LSTM Stock Price Prediction) plt.legend() plt.show()# 保存模型
torch.save(model.state_dict(), lstm_stock_model.pth)四、拓展思考
4.1 为什么说 C t C_t Ct是主导长期记忆 h t h_t ht是主导短期记忆 C t Ct Ct是在历史的 C t − 1 C{t-1} Ct−1基础上加上新信息迭代更新得到的(这是说我们可以写出一个形似 C t Ct Ct w C t − 1 C{t-1} Ct−1b的公式)所以 C t C_t Ct整合了[1,t]所有时间步的历史信息并负责将这些信息不断传递下去。 h t ht ht和 h t − 1 h{t-1} ht−1之间没有直接的选代关系虽然二者有一定的联系但 h t − 1 h{t-1} ht−1不是构成ht的核心。在记忆细胞中 h t − 1 h{t-1} ht−1只是用来辅助C长期记忆进行迭代的变量之一影响 h t ht ht具体取值的核心不是上个时间步的信息 h t − 1 h{t-1} ht−1而是当前时间步上的输入信息和预测标签的需求因此 h t ht ht是一个主要承载短期信息、尤其是当前时间步上信息的变量它是为了在当前时间步预测出最准确的标签而存在的。 4.2 RNN为什么容易梯度消失和梯度爆炸? 梯度消失和梯度爆炸是RNN在反向传播过程中常见的问题RNN的反向传播是通过时间的反向传播Backpropagation Through TimeBPTT其运行流程与一般的反向传播大有不同。在不同类型NLP任务会有不同的输出层结构、会有不同的标签输出方式。例如在对词语/样本进行预测的任务中(情感分类、词性标注、时间序列等任务)RNN会在每个时间步都输出词语对应的相应预测标签;但是在对句子进行预测的任务中(例如生成式任务、seq2seq的任务、或以句子为单位进行标注、分类的任务)RNN很可能只会在最后一个时间步输出句子相对应的预测标签。输出标签的方式不同反向传播的流程自然会有所区别。 假设现在我们有一个最为简单的RNN需要完成针对每个词语的情感分类任务。该RNN由输入层、一个隐藏层和一个输出层构成全部层都没有截距项总共循环 t t t个时间步。该网络的输入数据为 X X X输出的预测标签为 y ^ \hat{y} y^真实标签为 y y y激活函数为 σ \sigma σ输入层与隐藏层之间的权重矩阵为 W x h W{xh} Wxh隐藏层与输出层之间的权重矩阵为 W h y W{hy} Why隐藏层与隐藏层之间的权重为 W h h W{hh} Whh损失函数为 L ( y ^ , y ) L(\hat{y},y) L(y^,y)t时刻的损失函数我们简写为 L t Lt Lt。此时在时间步t上这个RNN的正向传播过程可以展示如下 RNN中存在至少三个权重矩阵需要迭代输入层与隐藏层之间的权重矩阵 W x h W{xh} Wxh隐藏层与输出层之间的权重矩阵 W h y W{hy} Why隐藏层与隐藏层之间的权重 W h h W{hh} Whh。当完成正向传播后我们需要在反向传播过程中对以上三个权重求解梯度、并迭代权重以 W h h W{hh} Whh为例 h t σ ( W x h X t W h h h t − 1 ) σ ( W x h X t W h h σ ( W x h X t − 1 W h h h t − 2 ) ) y ^ t W h y h t L t L ( y ^ t y t ) \begin{align*} \mathbf{h}{t} \sigma(\mathbf{W}{xh} \mathbf{X}{t} \mathbf{W}{hh} \color{red}{\mathbf{h}{t-1}}) \ \sigma(\mathbf{W}_{xh} \mathbf{X}t \mathbf{W}{hh} \color{red}{\sigma(\mathbf{W}{xh} \mathbf{X}{t-1} \mathbf{W}{hh} \mathbf{h}{t-2})}) \ \ \mathbf{\hat{y}}{t} \mathbf{W}{hy} \mathbf{h}{t} \ \ L{t} L(\mathbf{\hat{y}}{t}\mathbf{y}{t}) \end{align} hty^tLtσ(WxhXtWhhht−1)σ(WxhXtWhhσ(WxhXt−1Whhht−2))WhyhtL(y^tyt) L t L_{t} Lt可以展开展示为 L t L ( y ^ t , y t ) L ( W h y h t , y t ) L ( W h y σ ( W x h X t W h h h t − 1 ) , y t ) \begin{align} L{t} L(\mathbf{\hat{y}}{t}, \mathbf{y}{t}) \ \ L(\mathbf{W}{hy} \mathbf{h}{t}, \mathbf{y}{t}) \ \ L(\mathbf{W}{hy} \sigma(\mathbf{W}{xh} \mathbf{X}{t} \mathbf{W}{hh} \mathbf{h}{t-1}), \mathbf{y}{t}) \end{align} LtL(y^t,yt)L(Whyht,yt)L(Whyσ(WxhXtWhhht−1),yt) 因此根据链式法则有 ∂ L t ∂ W h y ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ W h y ∂ L t ∂ W x h ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ h t ∗ ∂ h t ∂ W x h ∂ L t ∂ W h h ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ h t ∗ ∂ h t ∂ W h h \begin{align} \ \frac{\partial L{t}}{\partial W{hy}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial W{hy}} \ \ \ \frac{\partial L{t}}{\partial W{xh}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial W{xh}} \ \ \ \frac{\partial L{t}}{\partial W{hh}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial W{hh}} \end{align} ∂Why∂Lt ∂Wxh∂Lt ∂Whh∂Lt∂y^t∂Lt∗∂Why∂y^t∂y^t∂Lt∗∂ht∂y^t∗∂Wxh∂ht∂y^t∂Lt∗∂ht∂y^t∗∂Whh∂ht h t ht ht作为一个复合函数不止能以 W x h W{xh} Wxh和 W h h W{hh} Whh为自变量还能以上层的隐藏状态 h t − 1 h{t-1} ht−1作为自变量而 h t − 1 h{t-1} ht−1本身又是以 W x h W{xh} Wxh和 W h h W_{hh} Whh为自变量的函数 L t L ( y ^ t , y t ) L ( W h y h t , y t ) L ( W h y σ ( W x h X t W h h h t − 1 ) , y t ) L ( W h y σ ( W x h X t W h h σ ( W x h X t W h h h t − 2 ) , y t ) \begin{align} L{t} L(\mathbf{\hat{y}}{t}, \mathbf{y}{t}) \ \ L(\mathbf{W}{hy} \mathbf{h}{t}, \mathbf{y}{t}) \ \ L(\mathbf{W}{hy} \sigma(\mathbf{W}{xh} \mathbf{X}{t} \mathbf{W}{hh} \color{red}{\mathbf{h}{t-1}}), \mathbf{y}{t}) \ \ L(\mathbf{W}{hy} \sigma(\mathbf{W}{xh} \mathbf{X}{t} \mathbf{W}{hh} \color{red}{\sigma(\mathbf{W}{xh} \mathbf{X}{t} \mathbf{W}{hh} \mathbf{h}{t-2})},\mathbf{y}{t}) \end{align*} LtL(y^t,yt)L(Whyht,yt)L(Whyσ(WxhXtWhhht−1),yt)L(Whyσ(WxhXtWhhσ(WxhXtWhhht−2),yt) 甚至我们还可以将 h t − 1 h{t-1} ht−1继续拆解为 σ ( W x h X t − 1 W h h h t − 2 ) \sigma(\mathbf{W}{xh} \mathbf{X}{t-1} \mathbf{W}{hh} \mathbf{h}{t-2}) σ(WxhXt−1Whhht−2)还可以将 h t − 2 h{t-2} ht−2继续拆解为 σ ( W x h X t − 2 W h h h t − 3 ) \sigma(\mathbf{W}{xh} \mathbf{X}{t-2} \mathbf{W}{hh} \mathbf{h}_{t-3}) σ(WxhXt−2Whhht−3)我们可以将嵌套函数无止尽地拆解下去直到拆到 h 1 σ ( W x h X 1 W h h h 0 ) \mathbf{h}1 \sigma(\mathbf{W}{xh} \mathbf{X}1 \mathbf{W}{hh} \mathbf{h}0) h1σ(WxhX1Whhh0)为止。在这个过程中只要拆解足够多我们可以从 L t L{t} Lt求解出t个针对和 W h h W{hh} Whh的导数。因此惊人的事实是在时间步t上我们可以计算t个用于迭代 W x h W{xh} Wxh和 W h h W{hh} Whh的梯度 ∂ L t ∂ W h h ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ h t ∗ ∂ h t ∂ h t − 1 ∗ ∂ h t − 1 ∂ h t − 2 ∗ … ∗ ∂ h 2 ∂ h 1 ∗ ∂ h 1 ∂ W h h \begin{align*} \ \frac{\partial L{t}}{\partial W{hh}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial h{t-1}} * \frac{\partial h{t-1}}{\partial h_{t-2}} * \ \ … \ \ * \frac{\partial h_2}{\partial h_1} * \frac{\partial h1}{\partial W{hh}} \ \ \end{align} ∂Whh∂Lt∂y^t∂Lt∗∂ht∂y^t∗∂ht−1∂ht∗∂ht−2∂ht−1∗ … ∗∂h1∂h2∗∂Whh∂h1 此时在这个公式中许多偏导数的求解就变得非常简单例如 ∵ y ^ t W h y h t , ∴ ∂ y ^ t ∂ h t W h y ∵ h t W x h X t W h h h t − 1 , ∴ ∂ h t ∂ h t − 1 W h h ∵ h t − 1 W x h X t − 1 W h h h t − 2 , ∴ ∂ h t − 1 ∂ h t − 2 W h h ⋮ ∵ h 2 W x h X 2 W h h h 1 , ∴ ∂ h 2 ∂ h 1 W h h ∵ h 1 W x h X 1 W h h h 0 , ∴ ∂ h 1 ∂ W h h h 0 \begin{align} \because {\hat{y}}{t} W{hy} h{t},\ \ \therefore \frac{\partial \hat{y}{t}}{\partial h{t}} {W}{hy} \ \ \because {h}{t} {W}{xh} {X}{t} {W}{hh} {h}{t-1}, \ \ \therefore \frac{\partial h{t}}{\partial h{t-1}} {W}{hh} \ \ \because {h}{t-1} {W}{xh} {X}{t-1} {W}{hh} {h}{t-2}, \ \ \therefore \frac{\partial h{t-1}}{\partial h{t-2}} {W}{hh} \ \ \vdots \ \ \because {h}2 {W}{xh} {X}{2} {W}{hh} {h}_{1}, \ \ \therefore \frac{\partial h_2}{\partial h1} {W}{hh} \ \ \because {h}1 {W}{xh} {X}{1} {W}{hh} {h}_{0}, \ \ \therefore \frac{\partial h1}{\partial {W}{hh}} {h}{0} \end{align} ∵y^tWhyht, ∴∂ht∂y^tWhy∵htWxhXtWhhht−1, ∴∂ht−1∂htWhh∵ht−1WxhXt−1Whhht−2, ∴∂ht−2∂ht−1Whh⋮∵h2WxhX2Whhh1, ∴∂h1∂h2Whh∵h1WxhX1Whhh0, ∴∂Whh∂h1h0 所以最终的梯度表达式为 ∂ L t ∂ W h h ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ h t ∗ ∂ h t ∂ h t − 1 ∗ ∂ h t − 1 ∂ h t − 2 ∗ … ∗ ∂ h 2 ∂ h 1 ∗ ∂ h 1 ∂ W h h ∂ L t ∂ y ^ t ∗ W h y ∗ W h h ∗ W h h ∗ … ∗ W h h ∗ h 0 ∂ L t ∂ y ^ t ∗ W h y ∗ ( W h h ) t − 1 ∗ h 0 \begin{align} \ \frac{\partial L{t}}{\partial W{hh}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial h{t-1}} * \frac{\partial h{t-1}}{\partial h_{t-2}} * \ \ … \ \ * \frac{\partial h_2}{\partial h_1} * \frac{\partial h1}{\partial W{hh}} \ \ \frac{\partial L{t}}{\partial \hat{y}{t}} * W{hy} * W{hh} * W{hh} * \ \ … \ \ * W{hh} * h0 \ \ \frac{\partial L{t}}{\partial \hat{y}{t}} * W{hy} * (W_{hh})^{t-1}* h0 \ \ \end{align*} ∂Whh∂Lt∂y^t∂Lt∗∂ht∂y^t∗∂ht−1∂ht∗∂ht−2∂ht−1∗ … ∗∂h1∂h2∗∂Whh∂h1∂y^t∂Lt∗Why∗Whh∗Whh∗ … ∗Whh∗h0∂y^t∂Lt∗Why∗(Whh)t−1∗h0 不难发现在这个梯度表达式中出现了 ( W h h ) t − 1 (W{hh})^{t-1} (Whh)t−1这样的高次项这就是循环神经网络非常容易梯度爆炸和梯度消失的根源所在——假设 W h h W{hh} Whh是一个小于1的值那 ( W h h ) t − 1 (W{hh})^{t-1} (Whh)t−1将会非常接近于0从而导致梯度消失假设 W h h W{hh} Whh大于1那 ( W h h ) t − 1 (W{hh})^{t-1} (Whh)t−1将会接近无穷大从而引发梯度爆炸其中梯度消失发生的可能性又远远高于梯度爆炸。 在深度神经网络中在应用链式法则后我们也会面临复合函数梯度连乘的问题但由于普通神经网络中并不存在“权值共享”的现象因此每个偏导数的表达式求解出的值大多是不一致的在连乘的时候有的偏导数值较大、有的偏导数值较小相比之下就不那么容易发生梯度爆炸或梯度消失问题的问题。 4.3 LSTM解决梯度消失和梯度爆炸问题吗? 或许很早就听说过LSTM能够很好地解决RNN的梯度消失/梯度爆炸问题甚至可能认为LSTM是为了解决梯度消失和梯度爆炸而诞生的但我们在进行深度原理研究的过程中却发现并非如此。 ∂ L t ∂ W h f ∂ L t ∂ y ^ t ∗ ∂ y ^ t ∂ h t ∗ ∂ h t ∂ C t ∗ ∂ C t ∂ f t ∗ ∂ f t ∂ h t − 1 ∗ ∂ h t − 1 ∂ C t − 1 … ∗ ∂ f 1 ∂ W h f ∂ L t ∂ y ^ t ∂ y ^ t ∂ h t ∗ ∂ h t ∂ C t ∗ [ ∂ C t ∂ C t − 1 ∗ ∂ C t − 1 ∂ C t − 2 … ∗ ∂ C 2 ∂ C 1 ] ∗ ∂ C 1 ∂ f 1 ∗ ∂ f 1 ∂ w h f ∂ L t ∂ y ^ t ∂ y ^ t ∂ h t ∗ ∂ h t ∂ C t ∗ [ f t ∗ f t − 1 ∗ f t − 2 … ∗ f 1 ] ∗ ∂ C 1 ∂ f 1 ∗ ∂ f 1 ∂ w h f \begin{align*} \ \frac{\partial L{t}}{\partial W{hf}} \frac{\partial L{t}}{\partial \hat{y}{t}} * \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial C{t}} * \frac{\partial C{t}}{\partial f{t}} * \frac{\partial f{t}}{\partial h{t-1}}* \frac{\partial h{t-1}}{\partial C{t-1}}\ \ … \ \ * \frac{\partial f1}{\partial W{hf}} \ \ \frac{\partial L{t}}{\partial \hat{y}{t}} \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial C{t}} * [ \frac{\partial Ct}{\partial C{t-1}} * \frac{\partial C{t-1}}{\partial C{t-2}} \ \ … \ \ * \frac{\partial C2}{\partial C{1}}] * \frac{\partial C_1}{\partial f_1} * \frac{\partial f1}{\partial w{hf}} \ \ \frac{\partial L{t}}{\partial \hat{y}{t}} \frac{\partial \hat{y}{t}}{\partial h{t}} * \frac{\partial h{t}}{\partial C{t}} * [ft * f{t-1} * f_{t-2} … * f_1] * \frac{\partial C_1}{\partial f_1} * \frac{\partial f1}{\partial w{hf}} \ \ \end{align*} ∂Whf∂Lt∂y^t∂Lt∗∂ht∂y^t∗∂Ct∂ht∗∂ft∂Ct∗∂ht−1∂ft∗∂Ct−1∂ht−1 … ∗∂Whf∂f1∂y^t∂Lt∂ht∂y^t∗∂Ct∂ht∗[∂Ct−1∂Ct∗∂Ct−2∂Ct−1 … ∗∂C1∂C2]∗∂f1∂C1∗∂whf∂f1∂y^t∂Lt∂ht∂y^t∗∂Ct∂ht∗[ft∗ft−1∗ft−2…∗f1]∗∂f1∂C1∗∂whf∂f1 通过避开共享权重的相乘LSTM将循环网络梯度爆炸和梯度消失的危险性降低到了一般神经网络的水平。由于 f t f{t} ft在0~1之间因此就意味着梯度爆炸的风险将会很小至于会不会梯度消失取决于是否接近于1。如果当下时刻的长期记忆比较依赖于历史信息那么就会接近于1这时候历史的梯度信息也正好不容易消失;如果很接近于0那么就说明当下的长期记忆不依赖于历史信息这时候就算梯度消失也无妨了。 f t f{t} ft在0~1之间这个特性决定了它梯度爆炸的风险很小同时 f t f_{t} ft表明了模型对历史信息的依赖性也正好是历史梯度的保留程度两者相互自洽所以LSTM也能较好地缓解梯度消失问题。因此LSTM同时较好地缓解了梯度消失/爆炸问题。
- 上一篇: 在线查看qq空间网站长沙建个网站要多少钱
- 下一篇: 在线查询网站收录局域网网站建设步骤
相关文章
-
在线查看qq空间网站长沙建个网站要多少钱
在线查看qq空间网站长沙建个网站要多少钱
- 技术栈
- 2026年04月20日
-
在线表情包制作网站高密做网站的公司
在线表情包制作网站高密做网站的公司
- 技术栈
- 2026年04月20日
-
在线h5免费制作网站广州有哪些网站建设
在线h5免费制作网站广州有哪些网站建设
- 技术栈
- 2026年04月20日
-
在线查询网站收录局域网网站建设步骤
在线查询网站收录局域网网站建设步骤
- 技术栈
- 2026年04月20日
-
在线查询网站收录如何做营销策划方案
在线查询网站收录如何做营销策划方案
- 技术栈
- 2026年04月20日
-
在线短视频网站开发费用优质网站的衡量标准
在线短视频网站开发费用优质网站的衡量标准
- 技术栈
- 2026年04月20日
