机器学习初学者 01月25日
【深度学习】突破LSTM,CNN和LSTM时间序列预测 !!
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了如何利用卷积神经网络(CNN)和长短期记忆网络(LSTM)的混合模型进行时间序列预测。文章详细阐述了CNN擅长捕捉局部模式,而LSTM擅长捕捉序列长依赖关系的原理。通过混合这两种网络,模型能够更好地学习时间序列数据中的复杂模式。文章不仅介绍了模型的核心原理和架构,还提供了基于PyTorch的实现代码,并使用虚拟数据集进行演示。此外,还包含了模型的训练、预测以及可视化分析,帮助读者直观理解模型在时间序列预测中的应用。最后,文章还探讨了模型优化和调参的方法,为读者提供了实践指导。

🌐 CNN-LSTM混合模型的核心在于结合CNN提取局部特征和LSTM捕捉长期依赖的优势,从而更有效地处理时间序列数据。

🔍 模型架构包括输入层、卷积层(CNN)、池化层(可选)、LSTM层和全连接层。CNN负责提取局部时间依赖模式,LSTM负责捕捉长期依赖关系,全连接层输出最终预测值。

📊 文章基于PyTorch框架,通过虚拟数据集演示了CNN-LSTM模型的实现过程,包括数据准备、模型构建、训练、预测和可视化分析,帮助读者直观理解模型效果。

📈 通过可视化分析,包括损失曲线、预测曲线、残差分布和残差序列图,可以评估模型的训练效果、预测准确性和误差特征,为模型优化提供依据。

🛠️ 文章还探讨了网络架构优化、正则化与防止过拟合以及超参数调优等方法,为读者提供了模型调优的指导,包括调整卷积核大小、LSTM层数、学习率和批量大小等。

cos大壮 2025-01-24 17:00 浙江

CNN和LSTM各自有不同的特长,CNN擅长局部模式的捕捉,LSTM擅长捕捉序列的长依赖关系。

在很多的时间序列预测任务中,利用卷积神经网络(CNN)和长短期记忆网络(LSTM)的混合模型是目前常见的深度学习解决方案之一。

CNN和LSTM各自有不同的特长,CNN擅长局部模式的捕捉,LSTM擅长捕捉序列的长依赖关系。通过混合这两种网络,可以非常好地学习时间序列数据中的复杂模式。

核心原理

混合模型首先使用 CNN 提取局部特征,然后将这些特征输入到 LSTM 中,进一步捕捉时间序列的长时间依赖模式,从而提高预测精度。

模型架构

    输入层:输入的时间序列数据可以是一个  的矩阵, 其中  表示时间序列的长度, 表示特征的维度。

    卷积层(CNN):通过一维卷积层(1D Convolutional Layer)来提取局部特征。假设卷积核的大小为 ,则卷积操作可以表示为:

其中, 表示卷积操作, 是卷积核, 是偏置, 是激活函数,通常选择 ReLU 或者 Sigmoid。卷积层会提取局部时间窗口内的模式,如趋势或短期波动。

    池化层(可选):通过池化层(Pooling Layer)减少特征的空间尺寸。常用的池化方式包括最大池化(Max Pooling)和平均池化(Average Pooling),以便于减少模型的计算量和防止过拟合。

    LSTM 层:将经过 CNN 处理后的特征序列输入到 LSTM 层,捕捉长期依赖。LSTM 的输入是卷积层的输出特征序列。LSTM 的计算公式如下:

其中, 是遗忘门, 是输入门, 是输出门, 是记忆单元的状态, 是当前的隐藏状态, 和  分别是权重矩阵和偏置项。LSTM 层能够有效捕捉输入序列中长期的依赖关系。

    全连接层:LSTM 输出的隐藏状态  被传递给全连接层,生成最终的预测值。全连接层的输出公式为:

其中, 和  分别是全连接层的权重和偏置项, 是预测的结果。

    损失函数:常见的时间序列预测任务的损失函数为均方误差(MSE):

其中, 是样本数, 是实际值, 是预测值。

公式解释

优势

总的来说,CNN 和 LSTM 的混合模型结合了卷积网络和递归网络的优势,可以在时间序列预测任务中更好地捕捉短期与长期的特征,从而提升预测精度。

一个完整案例

CNN-LSTM 混合模型在时间序列预测中的应用。

时间序列预测是机器学习中的一大热门课题,特别是在金融、气象、能源消耗预测等领域。CNN(卷积神经网络)和 LSTM(长短期记忆网络)分别在特征提取和捕获时间依赖性方面各有独特优势,因此将这两者结合起来构建混合模型,能够有效提升预测性能。

本案例将介绍如何基于 PyTorch 实现一个 CNN-LSTM 混合模型用于时间序列预测,并展示相关的可视化图形,帮助大家直观理解模型表现。

CNN-LSTM 的混合模型结合了 CNN 提取局部特征的能力和 LSTM 学习时序依赖的能力。该模型首先通过 CNN 层对输入的时间序列进行卷积,提取高层次特征,然后将这些特征输入到 LSTM 中,用于捕获时间上的长期依赖,最后通过全连接层输出预测结果。

模型的结构如下图所示:

输入数据 -> CNN层(卷积+池化) -> LSTM层 -> 全连接层 -> 输出预测

这种结构能够有效提取数据的局部特征(CNN)和时间依赖关系(LSTM),在时间序列预测任务中具有优势。

数据准备

我们使用虚拟数据集来模拟时间序列预测任务。假设数据是某种周期性波动和随机噪声叠加的时间序列。

import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.preprocessing import MinMaxScaler
from torch.utils.data import DataLoader, TensorDataset
# 生成虚拟时间序列数据
np.random.seed(42)
time = np.arange(010000.1)
data = np.sin(0.05 * time) + np.sin(0.01 * time) + 0.5 * np.random.randn(len(time))
# 标准化数据
scaler = MinMaxScaler(feature_range=(-11))
data = scaler.fit_transform(data.reshape(-11)).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 模型

接下来,定义 CNN-LSTM 模型。我们将使用 1D 卷积层提取时间序列的局部特征,接着将这些特征输入到 LSTM 层进行时序预测。

class CNN_LSTM_Model(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(CNN_LSTM_Model, self).__init__()
        
        # 1D卷积层
        self.cnn = nn.Sequential(
            nn.Conv1d(in_channels=1, out_channels=32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )
        
        # LSTM层
        self.lstm = nn.LSTM(input_size=32, hidden_size=hidden_size, num_layers=num_layers, batch_first=True)
        
        # 全连接层
        self.fc = nn.Linear(hidden_size, 1)
        
    def forward(self, x):
        x = x.unsqueeze(1)  # 增加一个通道维度, 因为1D卷积需要 (batch, channel, seq_len)
        x = self.cnn(x)
        x = x.permute(021)  # 调整维度 (batch, seq_len, features)
        lstm_out, _ = self.lstm(x)
        out = self.fc(lstm_out[:, -1, :])  # 取最后时间步的输出
        return out

模型训练

我们使用均方误差(MSE)作为损失函数,Adam 作为优化器。训练过程将会迭代多个 epoch,并在训练和测试集上记录损失,以便后续可视化分析。

# 超参数
input_size = 32
hidden_size = 64
num_layers = 2
num_epochs = 100
learning_rate = 0.001
# 模型实例化
model = CNN_LSTM_Model(input_size, hidden_size, num_layers)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练模型
train_losses = []
test_losses = []
for epoch in range(num_epochs):
    model.train()
    train_loss = 0
    for batch_X, batch_y in train_loader:
        optimizer.zero_grad()
        outputs = model(batch_X)
        loss = criterion(outputs.squeeze(), batch_y)
        loss.backward()
        optimizer.step()
        train_loss += loss.item()
    
    train_losses.append(train_loss / len(train_loader))
    
    # 测试模型
    model.eval()
    test_loss = 0
    with torch.no_grad():
        for batch_X, batch_y in test_loader:
            outputs = model(batch_X)
            loss = criterion(outputs.squeeze(), batch_y)
            test_loss += loss.item()
    
    test_losses.append(test_loss / len(test_loader))
    
    if (epoch+1) % 10 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss/len(train_loader):.4f}, Test Loss: {test_loss/len(test_loader):.4f}')

预测和可视化

在模型训练完成后,我们在测试集上进行预测,并绘制预测结果和训练过程中的损失变化图。

# 绘制损失变化曲线
plt.figure(figsize=(106))
plt.plot(train_losses, label='Train Loss')
plt.plot(test_losses, label='Test Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Loss Curve')
plt.legend()
plt.grid(True)
plt.show()
# 测试集上的预测曲线
model.eval()
predictions = []
with torch.no_grad():
    for batch_X, _ in test_loader:
        outputs = model(batch_X)
        predictions.append(outputs.detach().numpy())
predictions = np.concatenate(predictions).squeeze()
predictions = scaler.inverse_transform(predictions.reshape(-11)).reshape(-1)
true_values = scaler.inverse_transform(test_y.numpy().reshape(-11)).reshape(-1)
# 绘制预测值与真实值对比
plt.figure(figsize=(106))
plt.plot(true_values, label='True Values', color='b')
plt.plot(predictions, label='Predictions', color='r')
plt.xlabel('Time Steps')
plt.ylabel('Value')
plt.title('Predictions vs True Values')
plt.legend()
plt.grid(True)
plt.show()

损失曲线

第一张图展示了训练过程中模型的损失变化情况,可以观察到训练损失和测试损失逐渐下降的趋势。通过这张图,可以直观地看到模型的收敛情况以及是否出现过拟合。

预测曲线

第二张图展示了模型在测试集上的预测结果与真实值的对比。通过这张图,我们能够直观评估模型在未见过的数据上的表现,观察预测是否准确拟合了数据的趋势。

残差分布

绘制残差(预测值与真实值的差异)的分布图,可以评估模型在预测时的误差特征,是否存在系统性偏差。

# 计算残差
residuals = true_values - predictions
# 绘制残差分布图
plt.figure(figsize=(106))
plt.hist(residuals, bins=50, color='purple', alpha=0.7)
plt.title('Residuals Distribution')
plt.xlabel('Residual')
plt.ylabel('Frequency')
plt.grid(True)
plt.show()

残差序列图

残差序列图可以帮助我们查看误差随时间的变化是否有规律。

# 绘制残差随时间变化图
plt.figure(figsize=(106))
plt.plot(residuals, label='Residuals', color='orange')
plt.xlabel('Time Steps')
plt.ylabel('Residual')
plt.title('Residuals over Time')
plt.grid(True)
plt.show()

模型优化与调参

网络架构优化

正则化与防止过拟合

超参数调优

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

CNN-LSTM 时间序列预测 深度学习 PyTorch 混合模型
相关文章