简介这份资源面向具备一定深度学习基础、希望上手时间序列预测实战的开发者与学习者聚焦LSTM与Transformer混合模型的构建与落地。压缩包共13个文件约1.74MB以csv数据集、py脚本、xml配置、txt需求文档和png结果图为主涵盖训练与测试数据、模型实现代码、数据读取与预处理脚本以及预测值与真实值对比的可视化结果另附项目需求说明便于理解任务目标。内容围绕LSTM捕捉序列局部依赖、Transformer自注意力机制建模全局模式这一组合思路展开同时涉及数据清洗、归一化、缺失值填充等预处理环节并给出模型性能评估的可视化方式。已有1099人学习下载适合想系统理解混合模型预测流程、对照代码复现实验并掌握评估方法的读者参考。1. 拆开这个 LSTMTransformer 混合预测包它到底能跑出什么结果拿到一个名为“混合模型时间序列预测实战-讲了.rar”的压缩包第一反应通常不是急着解压而是先判断它值不值得花时间。这个包的核心价值在于它把 LSTM 和 Transformer 拼在一起做时间序列预测并且附带了真实值预测值画图.png、data.csv、ceshi.csv 以及数据读取测试.py。换句话说它不是纯理论笔记而是一套能直接跑起来、能看到预测曲线对比的工程文件。适合谁适合已经了解 LSTM 基本结构、想看看 Transformer 自注意力机制怎么塞进时序预测里的人也适合手头有类似单变量或多变量时序数据、想找个能改的代码骨架的从业者。它解决的不是“从零教你深度学习”而是“给你一个混合模型的落地起点让你少写几百行胶水代码”。但要注意这个包里的 .idea 目录和 .iml 文件是 PyCharm 工程配置跟模型逻辑无关别被它们分散注意力。2. LSTMTransformer 混合结构为什么这样拼以及数据怎么喂进去2.1 混合模型的选型逻辑LSTM 管局部Transformer 管全局时间序列预测里LSTM 擅长捕捉短期依赖和顺序模式比如前几个时间步对当前值的影响。但遇到长序列里跨较远位置的关联LSTM 的遗忘门再强也会漏信息。Transformer 的自注意力机制可以直接计算任意两个时间步之间的关系权重不依赖递归所以对长距离依赖更敏感。把两者串起来常见做法是先用 LSTM 层提取序列的局部时序特征输出的隐藏状态序列再送入 Transformer 编码器让自注意力在更高层做全局加权。这样既保留了 LSTM 对顺序的归纳偏置又补上了 Transformer 的全局视野。在这个包里lstmtransformer.py 大概率就是按这个思路搭的。你拿到代码后先看 forward 函数里 LSTM 的输出是取了最后一步还是完整序列——这决定了 Transformer 接收的是单个向量还是序列直接影响后续维度。2.2 数据读取与预处理data.csv 和 ceshi.csv 怎么用包里有 data.csv 和 ceshi.csv还有数据读取测试.py。通常 data.csv 是训练集ceshi.csv 是测试集或验证集。时间序列预测不能随机打乱顺序否则就泄露了未来信息。常见做法是按时间切分比如前 80% 做训练后 20% 做测试。数据读取测试.py 里应该包含读取、归一化、滑动窗口构造样本的代码。归一化建议用 MinMaxScaler 或 StandardScaler注意 scaler 只能在训练集上 fit然后 transform 测试集否则测试集的分布信息会渗进训练。滑动窗口的窗口长度是一个关键参数比如用过去 24 个时间步预测下一个点那 window_size24。这个值需要根据数据周期调整太小会欠拟合太大会引入噪声。import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler # 读取数据假设 data.csv 只有一列目标值 df pd.read_csv(data.csv) values df.values.astype(float32) # 归一化只在训练集上 fit scaler MinMaxScaler(feature_range(0, 1)) train_size int(len(values) * 0.8) train_data values[:train_size] test_data values[train_size:] scaler.fit(train_data) train_scaled scaler.transform(train_data) test_scaled scaler.transform(test_data) # 构造滑动窗口样本 def create_dataset(data, window_size24): X, y [], [] for i in range(len(data) - window_size): X.append(data[i:iwindow_size, 0]) y.append(data[iwindow_size, 0]) return np.array(X), np.array(y) window_size 24 X_train, y_train create_dataset(train_scaled, window_size) X_test, y_test create_dataset(test_scaled, window_size) # 调整为 LSTM 需要的形状 [样本数, 时间步, 特征数] X_train X_train.reshape((X_train.shape[0], X_train.shape[1], 1)) X_test X_test.reshape((X_test.shape[0], X_test.shape[1], 1))这段代码的逻辑是先按时间顺序切分再归一化最后用滑动窗口把一维序列变成监督学习样本。参数 window_size 控制回看长度reshape 里的 1 表示单变量。如果你的数据是多变量把特征数改成对应列数并在 create_dataset 里保留所有列。2.3 模型搭建LSTM 层与 Transformer 编码器的拼接细节在 PyTorch 里搭这个混合模型核心是定义好 LSTM 的输出维度和 Transformer 的输入维度匹配。常见写法是 LSTM 输出 hidden_size然后 TransformerEncoderLayer 的 d_model 也设成 hidden_size。如果 LSTM 是双向的输出维度会翻倍需要加一个线性层压回 d_model。另外Transformer 本身没有位置信息需要加位置编码。时间序列的位置编码可以用正弦余弦也可以用一个可学习的 Embedding。下面是一个可跑的骨架import torch import torch.nn as nn import math class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len500): super().__init__() pe torch.zeros(max_len, d_model) position torch.arange(0, max_len).unsqueeze(1).float() div_term torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] torch.sin(position * div_term) pe[:, 1::2] torch.cos(position * div_term) self.register_buffer(pe, pe.unsqueeze(0)) def forward(self, x): return x self.pe[:, :x.size(1), :] class LSTMTransformer(nn.Module): def __init__(self, input_dim1, d_model64, nhead4, num_layers2, dropout0.1): super().__init__() self.lstm nn.LSTM(input_dim, d_model, batch_firstTrue, bidirectionalFalse) self.pos_encoder PositionalEncoding(d_model) encoder_layer nn.TransformerEncoderLayer(d_modeld_model, nheadnhead, dropoutdropout, batch_firstTrue) self.transformer_encoder nn.TransformerEncoder(encoder_layer, num_layersnum_layers) self.fc nn.Linear(d_model, 1) def forward(self, x): lstm_out, _ self.lstm(x) # [batch, seq_len, d_model] lstm_out self.pos_encoder(lstm_out) trans_out self.transformer_encoder(lstm_out) out self.fc(trans_out[:, -1, :]) # 取最后一个时间步 return out逻辑说明LSTM 先把输入序列编码成隐藏状态序列位置编码给 Transformer 提供顺序信息TransformerEncoder 做全局注意力最后取最后一个时间步的全连接输出预测值。参数 d_model 要和 LSTM 隐藏单元数一致nhead 必须能整除 d_model。如果训练时 loss 不降先检查输入是否归一化、位置编码是否加对、以及 Transformer 的 dropout 是否过大。3. 训练、预测与画图把真实值预测值画图.png 复现出来3.1 训练循环与损失函数选择时间序列回归常用 MSELoss 或 SmoothL1Loss。MSE 对异常值敏感如果数据里有尖峰SmoothL1 更稳。优化器用 Adam学习率从 1e-3 开始试。训练时注意 batch_size 不要太大时序数据样本间相关性高大 batch 容易陷入平坦梯度。每个 epoch 后可以在验证集上算 loss保留验证 loss 最低的模型权重。下面是一个训练片段from torch.utils.data import DataLoader, TensorDataset # 转为 tensor X_train_t torch.tensor(X_train, dtypetorch.float32) y_train_t torch.tensor(y_train, dtypetorch.float32).unsqueeze(1) train_loader DataLoader(TensorDataset(X_train_t, y_train_t), batch_size32, shuffleFalse) model LSTMTransformer(input_dim1, d_model64, nhead4, num_layers2) criterion nn.SmoothL1Loss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) for epoch in range(50): model.train() total_loss 0 for batch_x, batch_y in train_loader: optimizer.zero_grad() pred model(batch_x) loss criterion(pred, batch_y) loss.backward() optimizer.step() total_loss loss.item() print(fEpoch {epoch1}, Loss: {total_loss/len(train_loader):.6f})注意 shuffleFalse因为时序数据不能打乱。batch_size 和 epoch 数根据数据量调数据少就减小 batch、增加 epoch但要注意过拟合。3.2 预测与反归一化把曲线画回原始量纲训练完必须反归一化才能和真实值对比。用训练时 fit 的 scaler 对预测结果做 inverse_transform。然后画图横轴时间纵轴数值真实值一条线预测值一条线。这个包里的真实值预测值画图.png 应该就是这种对比图。如果预测曲线整体滞后或平移通常是窗口构造时错位了如果预测值几乎是一条直线可能是模型没学到东西检查学习率和归一化。model.eval() with torch.no_grad(): X_test_t torch.tensor(X_test, dtypetorch.float32) pred_scaled model(X_test_t).numpy() # 反归一化 pred scaler.inverse_transform(pred_scaled) y_true scaler.inverse_transform(y_test.reshape(-1, 1)) import matplotlib.pyplot as plt plt.figure(figsize(12, 5)) plt.plot(y_true, label真实值) plt.plot(pred, label预测值) plt.legend() plt.savefig(真实值预测值画图.png) plt.show()参数说明inverse_transform 的输入形状要和 fit 时一致这里都是二维。画图时如果测试集太长可以只画前 200 个点否则曲线挤在一起看不出细节。3.3 评估指标除了看图还要算 MAE 和 RMSE图能直观看出趋势但量化评估不能少。MAE 反映平均绝对误差RMSE 对大误差更敏感。两个都算一下如果 RMSE 远大于 MAE说明存在个别预测偏差很大的点可能是异常值或模型在某些区段失效。from sklearn.metrics import mean_absolute_error, mean_squared_error mae mean_absolute_error(y_true, pred) rmse np.sqrt(mean_squared_error(y_true, pred)) print(fMAE: {mae:.4f}, RMSE: {rmse:.4f})如果 MAE 和 RMSE 都很大先别调模型回头检查数据里有没有缺失值被填成 0、归一化范围是否合理、以及窗口是否跨越了训练集和测试集边界。4. 避坑与排查跑这个混合模型时最容易翻车的五个地方4.1 现象loss 降到某个值就不动了预测全是均值原因学习率太大导致在局部极小值震荡或者 LSTM 和 Transformer 的维度没对齐梯度传不下去。解决把学习率降到 1e-4 试检查 LSTM 输出维度和 Transformer 的 d_model 是否一致双向 LSTM 要加线性层压维。4.2 现象预测曲线比真实值滞后一个窗口原因构造样本时把未来值当成了输入或者反归一化时索引错位。解决检查 create_dataset 里 X 和 y 的切片范围确保 y 是窗口后的下一个点不是窗口内最后一个点。4.3 现象测试集 loss 远小于训练集 loss原因归一化时用了全部数据 fit scaler测试集信息泄露。解决严格只在训练集上 fit scaler测试集只 transform。另外检查是否在训练前就构造了测试窗口。4.4 现象Transformer 层加进去后效果反而变差原因数据量太小Transformer 参数量大过拟合了。解决减少 Transformer 层数num_layers 降到 1增大 dropout或者先只用 LSTM 跑一个基线再逐步加 Transformer。4.5 现象画图时中文显示成方框原因matplotlib 默认字体不支持中文。解决在画图前设置plt.rcParams[font.sans-serif] [SimHei]或者把标签改成英文。5. 进阶技巧用这个包做多变量预测和超参搜索这个包目前看起来是单变量预测但 data.csv 如果有多列完全可以改成多变量输入。做法是把 create_dataset 里的data[i:iwindow_size, 0]改成data[i:iwindow_size, :]同时把 LSTM 的 input_dim 改成特征列数。输出如果还是预测某一列y 就取那一列的偏移值。多变量时归一化要对每一列分别做或者用同一个 scaler 但 fit 整个训练矩阵。超参搜索不用上大框架手写几个循环就行。重点调三个window_size、d_model、nhead。window_size 试 12、24、48d_model 试 32、64、128nhead 试 2、4、8。每次跑完记录验证集 MAE选最小的组合。注意 nhead 必须整除 d_model否则 PyTorch 会报错。还有一个容易忽略的点Transformer 的位置编码在时间序列里不一定非要用正弦余弦。如果你的序列有明显的周期性可以试试可学习的位置嵌入或者直接把时间特征小时、星期作为额外输入拼进去。我一般会先跑一个不加位置编码的版本看看效果掉多少再决定要不要花时间调位置编码。最后说一个血泪经验这个包里的 .idea 目录和 .iml 文件不要跟着代码一起提交到 git.gitignore 里应该把它们排除掉。另外每次改完模型结构先把 batch_size 设成 2 跑一个 mini batch确认 forward 不报错、loss 能反传再开全量训练。从那以后我每次拿到新的时序包都强制先跑一遍数据读取测试.py确认数据形状和归一化范围再动模型代码。希望帮到你。本文还有配套的精品资源点击获取