1. 项目概述
时序预测是机器学习领域一个经典而重要的研究方向,在金融、气象、工业控制等领域都有广泛应用。最近我在做一个比较有意思的实验:用五种不同的深度学习模型(Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM和CNN)在Matlab环境下进行时序预测的对比研究。
这个实验的初衷很简单:在实际项目中,我们经常需要选择最适合的模型来解决时序预测问题。不同模型各有特点,但很少有系统的横向对比。于是我决定自己动手,用相同的实验条件和数据集,对这五种主流模型进行全面测试。
2. 模型选型与架构解析
2.1 Transformer模型
Transformer模型最初是为自然语言处理设计的,但其自注意力机制特别适合捕捉时序数据中的长距离依赖关系。在Matlab中实现Transformer需要注意几个关键点:
- 位置编码:时序数据中位置信息至关重要。我使用了正弦位置编码:
function pe = positionalEncoding(d_model, max_len) position = 0:max_len-1; div_term = exp((0:2:d_model-1) * -(log(10000.0)/d_model)); pe = zeros(max_len, d_model); pe(:,1:2:end) = sin(position' * div_term); pe(:,2:2:end) = cos(position' * div_term); end- 多头注意力:我设置了8个头,每个头的维度为64,这样总维度保持512与原始论文一致。
2.2 BiLSTM模型
双向LSTM是处理时序数据的经典选择。它通过前向和后向两个LSTM层同时处理序列,能更好地理解上下文关系。在Matlab中的关键实现:
layers = [ sequenceInputLayer(inputSize) bilstmLayer(numHiddenUnits,'OutputMode','sequence') fullyConnectedLayer(numResponses) regressionLayer];注意:BiLSTM对超参数非常敏感,特别是隐藏单元数和学习率。经过多次实验,我发现128个隐藏单元配合0.001的学习率在大多数时序数据上表现稳定。
2.3 CNN模型
虽然CNN主要用于图像处理,但一维CNN也能有效提取时序数据的局部特征。我的实现采用了三层卷积:
layers = [ sequenceInputLayer(inputSize) convolution1dLayer(3,64,'Padding','same') reluLayer convolution1dLayer(3,128,'Padding','same') reluLayer convolution1dLayer(3,256,'Padding','same') reluLayer globalAveragePooling1dLayer fullyConnectedLayer(numResponses) regressionLayer];2.4 混合模型架构
混合模型结合了不同架构的优势:
- Transformer-BiLSTM:先用Transformer提取全局依赖,再用BiLSTM处理序列
- CNN-BiLSTM:先用CNN提取局部特征,再用BiLSTM处理序列关系
以Transformer-BiLSTM为例的关键代码结构:
% Transformer部分 transformerLayers = [ sequenceInputLayer(inputSize) transformerLayer(d_model,numHeads) % 其他transformer层... ]; % BiLSTM部分 bilstmLayers = [ bilstmLayer(numHiddenUnits) fullyConnectedLayer(numResponses) regressionLayer ]; % 组合模型 lgraph = layerGraph(transformerLayers); lgraph = addLayers(lgraph, bilstmLayers); lgraph = connectLayers(lgraph,'transformerOut','bilstmIn');3. 实验设计与实现细节
3.1 数据集准备
我使用了三个公开时序数据集进行测试:
- 电力负荷数据(每15分钟采样)
- 股票价格数据(每日收盘价)
- 气象数据(每小时温度记录)
数据预处理流程:
% 标准化 [dataTrain,mu,sigma] = zscore(dataTrain); dataTest = (dataTest-mu)./sigma; % 创建序列窗口 XTrain = {}; YTrain = {}; for i = 1:numel(dataTrain)-sequenceLength-responseLength XTrain{end+1} = dataTrain(i:i+sequenceLength-1); YTrain{end+1} = dataTrain(i+sequenceLength:i+sequenceLength+responseLength-1); end3.2 训练配置
统一训练配置保证公平比较:
options = trainingOptions('adam', ... 'MaxEpochs',100, ... 'MiniBatchSize',64, ... 'InitialLearnRate',0.001, ... 'LearnRateSchedule','piecewise', ... 'LearnRateDropFactor',0.5, ... 'LearnRateDropPeriod',20, ... 'GradientThreshold',1, ... 'Shuffle','every-epoch', ... 'Plots','training-progress', ... 'Verbose',0);3.3 评估指标
使用四种指标评估模型性能:
- 均方根误差(RMSE)
- 平均绝对误差(MAE)
- 平均绝对百分比误差(MAPE)
- 决定系数(R²)
计算函数示例:
function [rmse, mae, mape, r2] = evaluateMetrics(YTrue, YPredict) rmse = sqrt(mean((YTrue-YPredict).^2)); mae = mean(abs(YTrue-YPredict)); mape = mean(abs((YTrue-YPredict)./YTrue))*100; r2 = 1 - sum((YTrue-YPredict).^2)/sum((YTrue-mean(YTrue)).^2); end4. 实验结果与分析
4.1 性能对比
在电力负荷数据集上的表现(数值越小越好):
| 模型 | RMSE | MAE | MAPE | R² |
|---|---|---|---|---|
| Transformer-BiLSTM | 0.48 | 0.35 | 2.1% | 0.97 |
| Transformer | 0.52 | 0.39 | 2.4% | 0.96 |
| CNN-BiLSTM | 0.51 | 0.38 | 2.3% | 0.96 |
| BiLSTM | 0.55 | 0.42 | 2.6% | 0.95 |
| CNN | 0.63 | 0.49 | 3.1% | 0.93 |
4.2 训练时间对比
| 模型 | 训练时间(秒/epoch) | 收敛epoch数 |
|---|---|---|
| Transformer-BiLSTM | 3.2 | 75 |
| Transformer | 2.8 | 80 |
| CNN-BiLSTM | 2.1 | 65 |
| BiLSTM | 1.8 | 70 |
| CNN | 1.2 | 50 |
4.3 结果分析
混合模型优势:Transformer-BiLSTM在各项指标上表现最好,说明结合全局注意力和序列建模确实能提升预测精度。
计算成本:性能提升的代价是更长的训练时间,Transformer类模型比传统CNN/LSTM慢约50%。
数据依赖性:在周期性强的数据(如电力负荷)上,所有模型表现都较好;而在随机性强的股票数据上,性能差距会缩小。
5. 关键问题与解决方案
5.1 过拟合问题
现象:模型在训练集上表现很好,但测试集误差大。
解决方案:
- 增加Dropout层
- 使用早停策略
- 数据增强(添加噪声、时间扭曲)
% 在模型中添加Dropout layers = [ ... dropoutLayer(0.2) ... ];5.2 训练不稳定
现象:损失函数波动大,难以收敛。
解决方案:
- 梯度裁剪
- 学习率预热
- 批量归一化
options = trainingOptions(... 'GradientThreshold',1, ... % 梯度裁剪 'InitialLearnRate',0.0001, ... % 初始小学习率 'LearnRateSchedule','piecewise', ... 'LearnRateDropPeriod',10);5.3 长期预测衰减
现象:预测步长增加时,预测质量明显下降。
解决方案:
- 使用递归预测策略
- 引入注意力机制
- 多尺度建模
6. Matlab实现技巧
6.1 加速训练
- 使用GPU加速:
options = trainingOptions(..., 'ExecutionEnvironment','gpu');- 预分配内存:
XTrain = cell(1,numSequences); % 预分配6.2 调试技巧
- 可视化中间结果:
analyzeNetwork(lgraph);- 检查梯度:
options = trainingOptions(..., 'CheckpointPath',checkpointDir);6.3 模型部署
- 导出为ONNX格式:
exportONNXNetwork(net,'model.onnx');- 生成C代码:
cfg = coder.config('lib'); codegen -config cfg predictFunction -args {coder.typeof(single(0),[sequenceLength 1])}7. 实际应用建议
根据实验结果,我总结出以下模型选择策略:
精度优先:选择Transformer-BiLSTM,适合对预测精度要求高的场景,如金融预测。
速度优先:选择CNN或BiLSTM,适合实时性要求高的场景,如工业控制。
平衡选择:CNN-BiLSTM在精度和速度间取得了较好平衡。
小数据量:传统BiLSTM可能更合适,因为Transformer需要大量数据才能发挥优势。
在具体实现时,建议先从小模型开始,逐步增加复杂度。同时要注意,不同数据集可能需要不同的超参数调优策略。