在很多的时间序列预测任务中,利用卷积神经网络(CNN)和长短期记忆网络(LSTM)的混合模型是目前常见的深度学习解决方案之一。
CNN和LSTM各自有不同的特长,CNN擅长局部模式的捕捉,LSTM擅长捕捉序列的长依赖关系。通过混合这两种网络,可以非常好地学习时间序列数据中的复杂模式。
核心原理
CNN 部分
:CNN 的优势在于能够从输入数据中提取局部特征。对于时间序列预测问题,时间序列可以看作一维数据序列。CNN 可以通过一维卷积操作提取时间序列的局部时间依赖模式,如趋势、周期性波动等局部特征。
LSTM 部分
:LSTM 是一种递归神经网络(RNN)的变体,专门设计用来解决长期依赖问题。通过记忆门控机制(如输入门、遗忘门、输出门),LSTM 能够很好地捕捉序列中长期的时间依赖关系,并对未来的值进行预测。
混合模型首先使用 CNN 提取局部特征,然后将这些特征输入到 LSTM 中,进一步捕捉时间序列的长时间依赖模式,从而提高预测精度。
模型架构
输入层
:输入的时间序列数据可以是一个
的矩阵, 其中
表示时间序列的长度,
表示特征的维度。
卷积层(CNN)
:通过一维卷积层(1D Convolutional Layer)来提取局部特征。假设卷积核的大小为
,则卷积操作可以表示为:
其中,
表示卷积操作,
是卷积核,
是偏置,
是激活函数,通常选择 ReLU 或者 Sigmoid。卷积层会提取局部时间窗口内的模式,如趋势或短期波动。
池化层(可选)
:通过池化层(Pooling Layer)减少特征的空间尺寸。常用的池化方式包括最大池化(Max Pooling)和平均池化(Average Pooling),以便于减少模型的计算量和防止过拟合。
LSTM 层
:将经过 CNN 处理后的特征序列输入到 LSTM 层,捕捉长期依赖。LSTM 的输入是卷积层的输出特征序列。LSTM 的计算公式如下:
其中,
是遗忘门,
是输入门,
是输出门,
是记忆单元的状态,
是当前的隐藏状态,
和
分别是权重矩阵和偏置项。LSTM 层能够有效捕捉输入序列中长期的依赖关系。
全连接层
:LSTM 输出的隐藏状态
被传递给全连接层,生成最终的预测值。全连接层的输出公式为:
其中,
和
分别是全连接层的权重和偏置项,
是预测的结果。
损失函数
:常见的时间序列预测任务的损失函数为均方误差(MSE):
其中,
是样本数,
是实际值,
是预测值。
公式解释
卷积操作
:在时间序列中,1D 卷积可以理解为将卷积核应用到连续的时间点上,提取时间窗口内的特征。公式中的
表示当前时间点
及其前后
个时间点的数据。通过这种方式,CNN 能够在不丧失时间顺序的情况下提取局部模式。
LSTM 结构
:LSTM 是通过门控机制来控制信息的流动。遗忘门
控制哪些历史信息需要保留,输入门
控制哪些新信息需要加入,输出门
决定了当前时刻的隐藏状态输出。记忆单元
记录着每个时刻的重要信息,从而保留了时间序列的长期依赖性。
优势
局部和全局模式捕捉
:CNN 擅长在短期窗口内捕捉局部时间模式(例如季节性波动),而 LSTM 擅长捕捉长期依赖。结合二者可以更好地应对复杂的时间序列预测任务。
降维与特征提取
:CNN 提取特征的同时减少数据的维度,减少了输入 LSTM 的信息量,避免了 LSTM 因输入序列过长导致的效率问题。
总的来说,CNN 和 LSTM 的混合模型结合了卷积网络和递归网络的优势,可以在时间序列预测任务中更好地捕捉短期与长期的特征,从而提升预测精度。
一个完整案例
CNN-LSTM 混合模型在时间序列预测中的应用。
时间序列预测是机器学习中的一大热门课题,特别是在金融、气象、能源消耗预测等领域。CNN(卷积神经网络)和 LSTM(长短期记忆网络)分别在特征提取和捕获时间依赖性方面各有独特优势,因此将这两者结合起来构建混合模型,能够有效提升预测性能。
本案例将介绍如何基于 PyTorch 实现一个 CNN-LSTM 混合模型用于时间序列预测,并展示相关的可视化图形,帮助大家直观理解模型表现。
CNN-LSTM 的混合模型结合了 CNN 提取局部特征的能力和 LSTM 学习时序依赖的能力。该模型首先通过 CNN 层对输入的时间序列进行卷积,提取高层次特征,然后将这些特征输入到 LSTM 中,用于捕获时间上的长期依赖,最后通过全连接层输出预测结果。
模型的结构如下图所示:
输入数据 -> CNN层(卷积+池化) -> LSTM层 -> 全连接层 -> 输出预测
这种结构能够有效提取数据的局部特征(CNN)和时间依赖关系(LSTM),在时间序列预测任务中具有优势。
数据准备
我们使用虚拟数据集来模拟时间序列预测任务。假设数据是某种周期性波动和随机噪声叠加的时间序列。
import numpy as npimport matplotlib.pyplot as pltimport torchimport torch.nn as nnimport torch.optim as optimfrom sklearn.preprocessing import MinMaxScalerfrom torch.utils.data import DataLoader, TensorDataset# 生成虚拟时间序列数据 np.random.seed(42 ) time = np.arange(0 , 1000 , 0.1 ) data = np.sin(0.05 * time) + np.sin(0.01 * time) + 0.5 * np.random.randn(len(time))# 标准化数据 scaler = MinMaxScaler(feature_range=(-1 , 1 )) data = scaler.fit_transform(data.reshape(-1 , 1 )).reshape(-1 )# 准备时间序列数据集 (输入序列, 预测值) def create_sequences (data, seq_length) : xs = [] ys = [] for i in range(len(data)-seq_length-1 ): x = data[i:(i+seq_length)] y = data[i+seq_length] xs.append(x) ys.append(y) return np.array(xs), np.array(ys) seq_length = 50 # 时间序列长度 X, y = create_sequences(data, seq_length)# 转换为 PyTorch 张量 X = torch.from_numpy(X).float() y = torch.from_numpy(y).float()# 划分训练集和测试集 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_dataset = TensorDataset(train_X, train_y) test_dataset = TensorDataset(test_X, test_y) train_loader = DataLoader(train_dataset, batch_size=64 , shuffle=True ) test_loader = DataLoader(test_dataset, batch_size=64 , shuffle=False )
构建 CNN-LSTM 模型