项目介绍 MATLAB实现基于MSGNet- Transformer多尺度时序关系捕捉(MSGNet)结合Transformer编码器进行多变量时间序列预测(含模型描述及部分示例代码)专栏近期有大量优
MATLAB实现基于MSGNet- Transformer多尺度时序关系捕捉(MSGNet)结合Transformer编码器进行多变量时间序列预测的详细项目实例
项目背景介绍
多变量时间序列预测属于工业智能、能源管理、交通调度、金融分析、环境监测等领域的核心任务,核心难点在于多个变量之间并非独立变化,而是存在显著的时空耦合关系、尺度差异和长短期共同作用特征。传统统计模型例如 AR、MA、ARIMA、VAR 等,能够描述线性平稳过程,但在面对多源传感器数据、复杂周期叠加、突发扰动以及非线性演化时,往往会出现建模能力不足的问题。随着深度学习的发展,循环神经网络、卷积神经网络、注意力机制等方法逐步用于时序建模,其中 LSTM、GRU 在短期依赖捕捉方面表现较好,Transformer 则因其全局依赖建模能力和并行计算优势,逐步成为长序列预测的重要基础结构。然而,单纯依赖 Transformer 往往会面临两个突出问题:一是对局部细粒度时序模式的刻画不够充分,二是对多尺度变化的敏感性不足,尤其在多变量序列中,不同变量具有不同采样噪声、不同响应滞后和不同变化频率时,统一尺度的特征提取容易导致关键信息被淹没。
MSGNet 的核心思想正是针对多尺度时序关系捕捉这一痛点而提出。该类方法通常强调通过不同时间感受野、不同卷积核尺寸、不同频带或不同图结构构造方式,去挖掘短期波动、中期趋势、长期周期之间的互补信息。多尺度机制能够将原本在单一尺度下难以识别的结构拆分出来,再通过融合策略形成更具表达力的时间特征表示。与此同时,Transformer 编码器在序列中构建全局依赖关系方面具有优势,尤其适合建模变量之间的远距离交互、跨时间步的信息传递以及长期趋势演化。将 MSGNet 与 Transformer 编码器组合,可以形成一种兼顾局部精细模式和全局长程依赖的混合架构,使模型既能看到“局部波动”,也能把握“整体走势”,从而在复杂多变量预测场景中获得更稳健的性能。
在实际项目中,多变量时间序列通常存在缺失值、异常值、尺度不一致、变量相关性非静态、分布漂移等问题。以工业设备预测性维护为例,振动、电流、温度、压力等指标会在设备老化、工况切换、负载变化时产生显著联动;在电力负荷预测中,温度、湿度、节假日、历史用电曲线和行业行为模式共同影响结果;在交通流量预测中,早晚高峰、天气、事故和道路拓扑关系会导致明显的周期与突发共存现象。面对这些场景,仅依赖单尺度特征或单一注意力机制容易出现预测滞后、峰值跟踪不准确、长期滚动误差累积等问题。因此,一个结合 MSGNet 和 Transformer 编码器的多变量时间序列预测系统,不仅是算法上的升级,更是面向真实复杂数据环境的工程化解决路径。
MATLAB 在该类任务中的优势体现在三个层面。第一,MATLAB 对矩阵运算、信号处理、时间序列分析、可视化和工程原型验证非常成熟,适合快速构建从数据清洗、特征构造、模型训练到结果评估的完整流程。第二,MATLAB 的深度学习工具箱与自定义层机制支持灵活搭建网络结构,适合实现多尺度卷积、注意力模块、位置编码和编码器堆叠。第三,MATLAB 的交互式分析环境有利于对模型进行误差分析、注意力可视化、超参数对比、滑窗策略测试等工作,从而帮助项目从研究原型走向可落地实现。
基于 MSGNet 与 Transformer 编码器的多变量时间序列预测项目,通常需要同时兼顾数据层、特征层、网络层和评价层四个层面的完整设计。数据层需要完成缺失值处理、异常值修正、归一化、滑动窗口构造与标签对齐;特征层需要对原始变量进行多尺度表示;网络层需要将局部多尺度特征与全局序列依赖融合;评价层需要使用 MAE、RMSE、MAPE、R2 等指标,并结合误差分布和预测曲线对模型稳定性进行分析。整个方案的价值不只在于提升预测精度,还在于增强模型对真实业务波动的适应能力,使其在复杂环境中具备较强的泛化性和解释性。
项目目标与意义
提升多变量序列的长期预测精度
该项目的首要目标是提高多变量时间序列在中长期预测任务中的准确率,尤其是对趋势、周期和突发波动的综合建模能力。传统方法在短期预测中可能表现尚可,但当预测跨度延长时,误差会随着递推过程逐步放大,导致曲线偏移和峰谷失真。MSGNet 通过多尺度路径提取不同时间范围内的局部与全局模式,再交由 Transformer 编码器统一建模,可以增强对长时间跨度内复杂依赖关系的感知能力。此目标的意义在于让模型不仅能“跟上变化”,还能够“提前识别变化”,在电力、交通、库存、气象等场景中提升决策提前量,减少滞后响应带来的损失。
强化多源变量之间的关联建模能力
多变量序列预测并非单纯对每个变量独立做回归,而是需要揭示变量之间隐藏的协同关系、滞后关系和驱动关系。例如,温度变化可能先于负荷变化,压力变化可能与设备振动同步上升,交通速度与流量之间存在动态耦合。该项目的重要目标之一,就是将变量间交互纳入统一表示空间,通过编码器中的自注意力机制和多尺度特征融合机制,实现跨变量、跨时间步的信息传递。其意义在于能够更全面地利用数据本身蕴含的信息结构,避免只依赖单个特征造成的信息损失,同时提升模型对复杂系统状态变化的敏感性。
提高复杂场景下的鲁棒性与泛化能力
真实业务数据常伴随噪声、异常点、缺失片段、分布漂移和工况切换。单一结构的模型在训练集上可能有效,但到了新场景或新时间段就会明显退化。采用 MSGNet 与 Transformer 编码器结合的方式,可以从多尺度角度降低噪声对局部表示的干扰,同时借助全局注意力机制保持对长期规律的稳定识别。该目标的意义在于增强模型跨时段、跨工况、跨区域的可迁移能力,使预测系统更适合部署到长期运行环境中。尤其在工业监测和能源调度中,稳定性往往比一次性的精度更重要,鲁棒模型更能支撑连续运行。
形成可复用、可扩展的MATLAB实现方案
项目不仅追求单次实验的指标提升,还追求形成一套可重复、可扩展、可调试的 MATLAB 工程实现路径。通过明确的数据预处理流程、窗口构造方式、网络模块划分、训练参数设置和评估流程,可以构建适用于不同数据集的通用模板。该目标的意义在于降低后续迁移和二次开发成本,使同一框架可快速应用于能源、医疗、金融、制造等多个领域。对于研究与工程结合的场景而言,这种可复用性直接决定了方案的落地价值,也为后续引入更多模块,例如概率预测、不确定性估计和在线更新,预留了接口空间。
项目挑战及解决方案
多尺度特征提取与融合的结构设计难点
多变量时间序列中,短周期变化、趋势变化和突发事件往往在不同时间尺度上出现,如果只用单一卷积核或单一注意力结构,容易只捕捉一种粒度的信息。多尺度结构设计的难点在于如何让不同尺度既保持独立表达能力,又能在融合时不发生信息冲突。解决思路是构建并行多尺度分支,例如使用不同卷积核尺寸、不同扩张率或不同池化步长提取局部模式,再通过拼接、加权求和或门控融合方式统一表示。这样能够在同一层中同时观察短期噪声抖动、中期趋势转折和长期周期轮廓。对于 MSGNet 与 Transformer 的结合,前端多尺度模块负责“提取”,后端编码器负责“组织”,两者职责分明,可显著减少结构冗余并提升表示质量。
长序列建模中的计算复杂度与信息衰减问题
Transformer 虽然具有优秀的全局依赖建模能力,但其自注意力机制在长序列上会带来较高的计算和存储开销;同时,过长序列容易出现注意力稀释,导致局部关键信号被平均化。该挑战的解决方式包括三类:一是通过滑动窗口切片控制输入长度,使模型专注于最有用的历史范围;二是先用多尺度卷积或局部编码器压缩序列信息,减少后续 Transformer 的处理负担;三是在编码器中加入位置编码与残差连接,保持位置信息和梯度流稳定。这样既保留长程依赖,又避免模型在长序列上因复杂度过高而难以训练。对于 MATLAB 实现而言,还需要注意内存管理、mini-batch 尺寸选择和数据格式统一,防止训练过程中出现显存或内存压力过大的问题。
训练稳定性、参数敏感性与泛化控制问题
深度时序模型的训练常受学习率、批量大小、归一化方式、窗口长度和预测步长等因素影响,稍有不当就可能出现收敛缓慢、震荡、过拟合或欠拟合。特别是多变量预测任务中,变量尺度差异较大,若归一化不充分,训练会被大幅度变量主导;若正则化过强,又会抑制模型对复杂模式的拟合能力。解决方案包括:在数据进入网络前进行统一标准化或区间缩放;训练中使用早停、梯度裁剪和学习率衰减;在模型中适当引入 dropout 与残差连接;在验证集上以多指标而非单指标选择最佳模型。通过这些方式,可在保证训练稳定性的同时提升泛化性能,使模型在未见数据上保持较好的预测能力。
项目模型架构
数据输入与滑动窗口构造模块
该模块负责把原始多变量时间序列转化为适合监督学习的样本对。具体做法是从连续历史序列中截取固定长度的输入窗口,并将窗口后若干步作为预测目标。对于多变量场景,输入张量通常形成为“时间步数 × 变量数”的矩阵,经过滑窗后得到多个样本,每个样本对应一段历史轨迹和一段未来标签。该机制的基本原理在于把时间依赖学习问题转化为标准监督回归问题,从而使网络可以通过批量训练学习输入到输出的映射。该模块还需要处理缺失值、异常值与尺度差异,常见方式包括线性插值、均值填充、移动中位数修正和 z-score 标准化。良好的输入构造是整个系统性能的基础,因为后续网络只能在输入信息质量足够高的前提下发挥作用。
多尺度时序关系捕捉模块
MSGNet 的核心价值体现在多尺度建模。该模块可采用多个并行卷积分支分别提取不同感受野下的时间特征,例如小卷积核用于捕捉短期局部波动,大卷积核用于识别中期趋势,扩张卷积用于覆盖更长的历史依赖。其基本原理是通过不同尺度下的滤波器对序列进行变换,使模型从多个时间分辨率观察同一条序列,从而获得更全面的表达。多尺度结构的优点在于可以兼顾细节和趋势,不会像单尺度模型那样只关注某一层面的变化。融合时可采用拼接后线性映射,也可采用注意力门控权重进行自适应组合。对于多变量数据,还可以在通道维度上进行特征交互,使不同变量在不同尺度下形成联合表示,从而为后续 Transformer 编码器提供更丰富的输入。
Transformer 编码器模块
Transformer 编码器负责从多尺度特征中学习全局依赖关系和变量间交互关系。其关键组成部分包括位置编码、自注意力机制、前馈网络、残差连接和层归一化。位置编码的基本原理是向网络显式注入时间顺序信息,因为自注意力机制本身对顺序不敏感。自注意力通过计算序列中任意两个位置之间的相关性,实现信息从全局范围传播,特别适合捕捉远距离依赖和跨变量关联。前馈网络则进一步对每个时间位置上的表示进行非线性变换,提高特征表达能力。残差连接有助于缓解深层网络训练中的梯度消失问题,层归一化则使每层输入分布更加稳定。将多尺度输出送入编码器后,网络能够同时建模局部模式与全局结构,使最终特征具备更强的预测判别力。
预测头与输出映射模块
编码器输出通常需要经过预测头映射到最终的预测空间。对于单步预测,常用全连接层直接输出目标变量值;对于多步预测,可采用序列到序列映射方式,逐步或一次性输出未来多个时间点的结果。该模块的基本原理是把高维时序表示压缩为任务所需的目标维度,确保网络输出与真实标签一致。若任务对象是多个变量,则输出层可设置为与目标变量数量相同的维度;若任务需要同时预测多个未来时刻,则输出张量需按时间步展开。预测头还可加入 dropout 或线性投影层,提高输出的泛化性和数值稳定性。该部分虽结构简单,但决定了任务形式是否与网络表达一致,是从特征空间回到业务空间的关键桥梁。
损失函数、优化器与评估模块
该模块负责指导模型训练方向并衡量模型效果。回归任务常用均方误差、平均绝对误差或其组合形式作为损失函数,其中均方误差对大偏差更敏感,适合训练阶段推动模型更快收敛;平均绝对误差对异常值更稳健,适合评估阶段衡量平均偏差。优化器通常选择 Adam 或其变体,因为其具有自适应学习率调整能力,适合复杂非凸目标。评估模块则常使用 MAE、RMSE、MAPE、R2 等多指标综合判断:MAE反映平均误差水平,RMSE强调大误差惩罚,MAPE体现相对误差,R2衡量拟合程度。该模块的原理在于通过可量化指标监控训练过程、筛选最优模型并分析误差来源,最终形成完整的实验闭环。
项目模型描述及代码示例
多变量时间序列数据构造与归一化
rng(42); % 固定随机种子,保证结果可复现
T = 2400; % 构造总时间步长度
t = (1:T)'; % 生成时间索引列向量
x1 = sin(2*pi*t/48) + 0.15*sin(2*pi*t/12) + 0.05*randn(T,1); % 变量1:多周期叠加并加入高斯噪声
x2 = 0.7*cos(2*pi*t/72) + 0.2*sin(2*pi*t/24) + 0.08*randn(T,1); % 变量2:不同周期响应并加入扰动
x3 = 0.4*x1 + 0.3*x2 + 0.1*randn(T,1); % 变量3:体现变量间耦合关系
X = [x1 x2 x3]; % 组合为多变量时间序列矩阵
X = fillmissing(X,'linear'); % 线性插值补齐潜在缺失值
mu = mean(X,1); % 计算每个变量的均值
sigma = std(X,0,1); % 计算每个变量的标准差
Xn = (X - mu) ./ sigma; % 进行z-score标准化,统一尺度
lookBack = 48; % 输入窗口长度,覆盖两个日周期
horizon = 1; % 预测步长设置为单步
numObs = T - lookBack - horizon + 1; % 可构造样本数量
XCell = cell(numObs,1); % 创建输入样本单元数组
Y = zeros(numObs,3); % 创建输出标签矩阵
for i = 1:numObs % 遍历所有可用窗口
XCell{i} = Xn(i:i+lookBack-1,:)'; % 每个样本组织为“变量数×时间步数”
Y(i,:) = Xn(i+lookBack+horizon-1,:); % 取窗口后对应时刻作为监督标签
end % 完成滑动窗口构造
splitIdx = floor(0.7*numObs); % 划分训练集边界
XTrain = XCell(1:splitIdx); % 训练输入
YTrain = Y(1:splitIdx,:); % 训练标签
XTest = XCell(splitIdx+1:end); % 测试输入
YTest = Y(splitIdx+1:end,:); % 测试标签
多尺度特征提取分支
inputSize = 3; % 输入变量数
numFilters = 32; % 每个卷积分支输出通道数
XInput = sequenceInputLayer(inputSize,"Name","input"); % 序列输入层接收多变量时间序列
conv3 = convolution1dLayer(3,numFilters,"Padding","same","Name","conv_k3"); % 小卷积核提取短期局部模式
bn3 = batchNormalizationLayer("Name","bn_k3"); % 对分支特征做归一化稳定训练
relu3 = reluLayer("Name","relu_k3"); % 非线性激活增强表达
conv5 = convolution1dLayer(5,numFilters,"Padding","same","Name","conv_k5"); % 中等卷积核提取中期变化
bn5 = batchNormalizationLayer("Name","bn_k5"); % 中期分支归一化
relu5 = reluLayer("Name","relu_k5"); % 中期分支激活
conv9 = convolution1dLayer(9,numFilters,"Padding","same","Name","conv_k9"); % 大卷积核提取更长感受野特征
bn9 = batchNormalizationLayer("Name","bn_k9"); % 长感受野分支归一化
relu9 = reluLayer("Name","relu_k9"); % 长感受野分支激活
concat = depthConcatenationLayer(3,"Name","multi_scale_concat"); % 将三个尺度特征在通道维拼接
fusion = convolution1dLayer(1,64,"Padding","same","Name","fusion_1x1"); % 用1×1卷积压缩并融合多尺度信息
fusionBn = batchNormalizationLayer("Name","fusion_bn"); % 融合后再次归一化
fusionRelu = reluLayer("Name","fusion_relu"); % 激活后得到紧凑表示
Transformer编码器核心搭建
embed = fullyConnectedLayer(64,"Name","embed_proj"); % 将多尺度特征投影到统一嵌入维度
pos = positionEmbeddingLayer(lookBack,64,"Name","pos_embed"); % 添加位置编码保留时间顺序信息
addPos = additionLayer(2,"Name","add_pos"); % 将特征表示与位置编码相加
attn = selfAttentionLayer(4,64,"Name","self_attn"); % 四头自注意力学习全局依赖关系
ff1 = fullyConnectedLayer(128,"Name","ffn_fc1"); % 前馈网络第一层扩大表示维度
ffRelu = reluLayer("Name","ffn_relu"); % 非线性映射增强特征组合能力
ff2 = fullyConnectedLayer(64,"Name","ffn_fc2"); % 前馈网络第二层回到原维度
addFFN = additionLayer(2,"Name","add_ffn"); % 残差连接稳定深层训练
norm1 = layerNormalizationLayer("Name","ln1"); % 第一层归一化
norm2 = layerNormalizationLayer("Name","ln2"); % 第二层归一化
gap = globalAveragePooling1dLayer("Name","gap"); % 对时间维聚合得到全局表示
fcOut = fullyConnectedLayer(3,"Name","fc_out"); % 输出三个变量的一步预测结果
regOut = regressionLayer("Name","regression_output"); % 回归损失输出层
网络连线与结构组合
layers = layerGraph(); % 创建空的层图
layers = addLayers(layers,XInput); % 添加输入层
layers = addLayers(layers,conv3); % 添加3核卷积分支
layers = addLayers(layers,bn3); % 添加3核分支批归一化
layers = addLayers(layers,relu3); % 添加3核分支激活
layers = addLayers(layers,conv5); % 添加5核卷积分支
layers = addLayers(layers,bn5); % 添加5核分支批归一化
layers = addLayers(layers,relu5); % 添加5核分支激活
layers = addLayers(layers,conv9); % 添加9核卷积分支
layers = addLayers(layers,bn9); % 添加9核分支批归一化
layers = addLayers(layers,relu9); % 添加9核分支激活
layers = addLayers(layers,concat); % 添加多尺度拼接层
layers = addLayers(layers,fusion); % 添加融合卷积层
layers = addLayers(layers,fusionBn); % 添加融合后归一化
layers = addLayers(layers,fusionRelu); % 添加融合后激活
layers = addLayers(layers,embed); % 添加嵌入投影层
layers = addLayers(layers,pos); % 添加位置编码层
layers = addLayers(layers,addPos); % 添加位置相加层
layers = addLayers(layers,attn); % 添加自注意力层
layers = addLayers(layers,norm1); % 添加第一层归一化
layers = addLayers(layers,ff1); % 添加FFN第一层
layers = addLayers(layers,ffRelu); % 添加FFN激活
layers = addLayers(layers,ff2); % 添加FFN第二层
layers = addLayers(layers,addFFN); % 添加FFN残差层
layers = addLayers(layers,norm2); % 添加第二层归一化
layers = addLayers(layers,gap); % 添加全局池化层
layers = addLayers(layers,fcOut); % 添加输出全连接层
layers = addLayers(layers,regOut); % 添加回归输出层
layers = connectLayers(layers,"input","conv_k3"); % 输入连接到3核分支
layers = connectLayers(layers,"input","conv_k5"); % 输入连接到5核分支
layers = connectLayers(layers,"input","conv_k9"); % 输入连接到9核分支
layers = connectLayers(layers,"conv_k3","bn_k3"); % 3核卷积到归一化
layers = connectLayers(layers,"bn_k3","relu_k3"); % 3核归一化到激活
layers = connectLayers(layers,"conv_k5","bn_k5"); % 5核卷积到归一化
layers = connectLayers(layers,"bn_k5","relu_k5"); % 5核归一化到激活
layers = connectLayers(layers,"conv_k9","bn_k9"); % 9核卷积到归一化
layers = connectLayers(layers,"bn_k9","relu_k9"); % 9核归一化到激活
layers = connectLayers(layers,"relu_k3","multi_scale_concat/in1"); % 第一路特征进入拼接层
layers = connectLayers(layers,"relu_k5","multi_scale_concat/in2"); % 第二路特征进入拼接层
layers = connectLayers(layers,"relu_k9","multi_scale_concat/in3"); % 第三路特征进入拼接层
layers = connectLayers(layers,"multi_scale_concat","fusion_1x1"); % 拼接后进入融合卷积
layers = connectLayers(layers,"fusion_1x1","fusion_bn"); % 融合卷积到归一化
layers = connectLayers(layers,"fusion_bn","fusion_relu"); % 归一化到激活
layers = connectLayers(layers,"fusion_relu","embed_proj"); % 多尺度特征投影到嵌入空间
layers = connectLayers(layers,"embed_proj","add_pos/in1"); % 投影特征送入相加层
layers = connectLayers(layers,"pos_embed","add_pos/in2"); % 位置编码送入相加层
layers = connectLayers(layers,"add_pos","self_attn"); % 加位置编码后进入自注意力
layers = connectLayers(layers,"self_attn","ln1"); % 注意力输出进入归一化
layers = connectLayers(layers,"ln1","ffn_fc1"); % 归一化后进入前馈网络
layers = connectLayers(layers,"ffn_fc1","ffn_relu"); % 前馈第一层到激活
layers = connectLayers(layers,"ffn_relu","ffn_fc2"); % 激活后进入前馈第二层
layers = connectLayers(layers,"ln1","add_ffn/in1"); % 残差支路一:注意力归一化输出
layers = connectLayers(layers,"ffn_fc2","add_ffn/in2"); % 残差支路二:FFN输出
layers = connectLayers(layers,"add_ffn","ln2"); % 残差相加后做第二次归一化
layers = connectLayers(layers,"ln2","gap"); % 对时间维做全局平均池化
layers = connectLayers(layers,"gap","fc_out"); % 池化结果送入输出层
layers = connectLayers(layers,"fc_out","regression_output"); % 输出层计算回归损失
训练参数与模型训练
options = trainingOptions("adam"); % 选择Adam优化器
options.MaxEpochs = 80; % 最大训练轮数
options.MiniBatchSize = 64; % 批量大小
options.InitialLearnRate = 1e-3; % 初始学习率
options.Shuffle = "every-epoch"; % 每轮打乱训练样本
options.ValidationData = {XTest,YTest}; % 设置验证数据
options.ValidationFrequency = 30; % 验证频率
options.ExecutionEnvironment = "auto"; % 自动选择CPU或GPU
options.Plots = "training-progress"; % 显示训练过程
options.Verbose = false; % 关闭命令行冗余输出
net = trainNetwork(XTrain,YTrain,layers,options); % 开始训练完整模型
预测、反归一化与误差评估
YPred = predict(net,XTest,"MiniBatchSize",64); % 对测试集进行预测
YPredRaw = YPred .* sigma + mu; % 将预测值反归一化回原始尺度
YTestRaw = YTest .* sigma + mu; % 将真实值反归一化回原始尺度
mae = mean(abs(YPredRaw - YTestRaw),1); % 计算每个变量的平均绝对误差
rmse = sqrt(mean((YPredRaw - YTestRaw).^2,1)); % 计算每个变量的均方根误差
r2 = 1 - sum((YPredRaw - YTestRaw).^2,1) ./ sum((YTestRaw - mean(YTestRaw,1)).^2,1); % 计算决定系数
disp(mae); % 输出MAE结果
disp(rmse); % 输出RMSE结果
disp(r2); % 输出R2结果
多变量时间序列数据构造与归一化
rng(42); % 固定随机种子,保证结果可复现
T = 2400; % 构造总时间步长度
t = (1:T)'; % 生成时间索引列向量
x1 = sin(2*pi*t/48) + 0.15*sin(2*pi*t/12) + 0.05*randn(T,1); % 变量1:多周期叠加并加入高斯噪声
x2 = 0.7*cos(2*pi*t/72) + 0.2*sin(2*pi*t/24) + 0.08*randn(T,1); % 变量2:不同周期响应并加入扰动
x3 = 0.4*x1 + 0.3*x2 + 0.1*randn(T,1); % 变量3:体现变量间耦合关系
X = [x1 x2 x3]; % 组合为多变量时间序列矩阵
X = fillmissing(X,'linear'); % 线性插值补齐潜在缺失值
mu = mean(X,1); % 计算每个变量的均值
sigma = std(X,0,1); % 计算每个变量的标准差
Xn = (X - mu) ./ sigma; % 进行z-score标准化,统一尺度
lookBack = 48; % 输入窗口长度,覆盖两个日周期
horizon = 1; % 预测步长设置为单步
numObs = T - lookBack - horizon + 1; % 可构造样本数量
XCell = cell(numObs,1); % 创建输入样本单元数组
Y = zeros(numObs,3); % 创建输出标签矩阵
for i = 1:numObs % 遍历所有可用窗口
XCell{i} = Xn(i:i+lookBack-1,:)'; % 每个样本组织为“变量数×时间步数”
Y(i,:) = Xn(i+lookBack+horizon-1,:); % 取窗口后对应时刻作为监督标签
end % 完成滑动窗口构造
splitIdx = floor(0.7*numObs); % 划分训练集边界
XTrain = XCell(1:splitIdx); % 训练输入
YTrain = Y(1:splitIdx,:); % 训练标签
XTest = XCell(splitIdx+1:end); % 测试输入
YTest = Y(splitIdx+1:end,:); % 测试标签
多尺度特征提取分支
inputSize = 3; % 输入变量数
numFilters = 32; % 每个卷积分支输出通道数
XInput = sequenceInputLayer(inputSize,"Name","input"); % 序列输入层接收多变量时间序列
conv3 = convolution1dLayer(3,numFilters,"Padding","same","Name","conv_k3"); % 小卷积核提取短期局部模式
bn3 = batchNormalizationLayer("Name","bn_k3"); % 对分支特征做归一化稳定训练
relu3 = reluLayer("Name","relu_k3"); % 非线性激活增强表达
conv5 = convolution1dLayer(5,numFilters,"Padding","same","Name","conv_k5"); % 中等卷积核提取中期变化
bn5 = batchNormalizationLayer("Name","bn_k5"); % 中期分支归一化
relu5 = reluLayer("Name","relu_k5"); % 中期分支激活
conv9 = convolution1dLayer(9,numFilters,"Padding","same","Name","conv_k9"); % 大卷积核提取更长感受野特征
bn9 = batchNormalizationLayer("Name","bn_k9"); % 长感受野分支归一化
relu9 = reluLayer("Name","relu_k9"); % 长感受野分支激活
concat = depthConcatenationLayer(3,"Name","multi_scale_concat"); % 将三个尺度特征在通道维拼接
fusion = convolution1dLayer(1,64,"Padding","same","Name","fusion_1x1"); % 用1×1卷积压缩并融合多尺度信息
fusionBn = batchNormalizationLayer("Name","fusion_bn"); % 融合后再次归一化
fusionRelu = reluLayer("Name","fusion_relu"); % 激活后得到紧凑表示
Transformer编码器核心搭建
embed = fullyConnectedLayer(64,"Name","embed_proj"); % 将多尺度特征投影到统一嵌入维度
pos = positionEmbeddingLayer(lookBack,64,"Name","pos_embed"); % 添加位置编码保留时间顺序信息
addPos = additionLayer(2,"Name","add_pos"); % 将特征表示与位置编码相加
attn = selfAttentionLayer(4,64,"Name","self_attn"); % 四头自注意力学习全局依赖关系
ff1 = fullyConnectedLayer(128,"Name","ffn_fc1"); % 前馈网络第一层扩大表示维度
ffRelu = reluLayer("Name","ffn_relu"); % 非线性映射增强特征组合能力
ff2 = fullyConnectedLayer(64,"Name","ffn_fc2"); % 前馈网络第二层回到原维度
addFFN = additionLayer(2,"Name","add_ffn"); % 残差连接稳定深层训练
norm1 = layerNormalizationLayer("Name","ln1"); % 第一层归一化
norm2 = layerNormalizationLayer("Name","ln2"); % 第二层归一化
gap = globalAveragePooling1dLayer("Name","gap"); % 对时间维聚合得到全局表示
fcOut = fullyConnectedLayer(3,"Name","fc_out"); % 输出三个变量的一步预测结果
regOut = regressionLayer("Name","regression_output"); % 回归损失输出层
网络连线与结构组合
layers = layerGraph(); % 创建空的层图
layers = addLayers(layers,XInput); % 添加输入层
layers = addLayers(layers,conv3); % 添加3核卷积分支
layers = addLayers(layers,bn3); % 添加3核分支批归一化
layers = addLayers(layers,relu3); % 添加3核分支激活
layers = addLayers(layers,conv5); % 添加5核卷积分支
layers = addLayers(layers,bn5); % 添加5核分支批归一化
layers = addLayers(layers,relu5); % 添加5核分支激活
layers = addLayers(layers,conv9); % 添加9核卷积分支
layers = addLayers(layers,bn9); % 添加9核分支批归一化
layers = addLayers(layers,relu9); % 添加9核分支激活
layers = addLayers(layers,concat); % 添加多尺度拼接层
layers = addLayers(layers,fusion); % 添加融合卷积层
layers = addLayers(layers,fusionBn); % 添加融合后归一化
layers = addLayers(layers,fusionRelu); % 添加融合后激活
layers = addLayers(layers,embed); % 添加嵌入投影层
layers = addLayers(layers,pos); % 添加位置编码层
layers = addLayers(layers,addPos); % 添加位置相加层
layers = addLayers(layers,attn); % 添加自注意力层
layers = addLayers(layers,norm1); % 添加第一层归一化
layers = addLayers(layers,ff1); % 添加FFN第一层
layers = addLayers(layers,ffRelu); % 添加FFN激活
layers = addLayers(layers,ff2); % 添加FFN第二层
layers = addLayers(layers,addFFN); % 添加FFN残差层
layers = addLayers(layers,norm2); % 添加第二层归一化
layers = addLayers(layers,gap); % 添加全局池化层
layers = addLayers(layers,fcOut); % 添加输出全连接层
layers = addLayers(layers,regOut); % 添加回归输出层
layers = connectLayers(layers,"input","conv_k3"); % 输入连接到3核分支
layers = connectLayers(layers,"input","conv_k5"); % 输入连接到5核分支
layers = connectLayers(layers,"input","conv_k9"); % 输入连接到9核分支
layers = connectLayers(layers,"conv_k3","bn_k3"); % 3核卷积到归一化
layers = connectLayers(layers,"bn_k3","relu_k3"); % 3核归一化到激活
layers = connectLayers(layers,"conv_k5","bn_k5"); % 5核卷积到归一化
layers = connectLayers(layers,"bn_k5","relu_k5"); % 5核归一化到激活
layers = connectLayers(layers,"conv_k9","bn_k9"); % 9核卷积到归一化
layers = connectLayers(layers,"bn_k9","relu_k9"); % 9核归一化到激活
layers = connectLayers(layers,"relu_k3","multi_scale_concat/in1"); % 第一路特征进入拼接层
layers = connectLayers(layers,"relu_k5","multi_scale_concat/in2"); % 第二路特征进入拼接层
layers = connectLayers(layers,"relu_k9","multi_scale_concat/in3"); % 第三路特征进入拼接层
layers = connectLayers(layers,"multi_scale_concat","fusion_1x1"); % 拼接后进入融合卷积
layers = connectLayers(layers,"fusion_1x1","fusion_bn"); % 融合卷积到归一化
layers = connectLayers(layers,"fusion_bn","fusion_relu"); % 归一化到激活
layers = connectLayers(layers,"fusion_relu","embed_proj"); % 多尺度特征投影到嵌入空间
layers = connectLayers(layers,"embed_proj","add_pos/in1"); % 投影特征送入相加层
layers = connectLayers(layers,"pos_embed","add_pos/in2"); % 位置编码送入相加层
layers = connectLayers(layers,"add_pos","self_attn"); % 加位置编码后进入自注意力
layers = connectLayers(layers,"self_attn","ln1"); % 注意力输出进入归一化
layers = connectLayers(layers,"ln1","ffn_fc1"); % 归一化后进入前馈网络
layers = connectLayers(layers,"ffn_fc1","ffn_relu"); % 前馈第一层到激活
layers = connectLayers(layers,"ffn_relu","ffn_fc2"); % 激活后进入前馈第二层
layers = connectLayers(layers,"ln1","add_ffn/in1"); % 残差支路一:注意力归一化输出
layers = connectLayers(layers,"ffn_fc2","add_ffn/in2"); % 残差支路二:FFN输出
layers = connectLayers(layers,"add_ffn","ln2"); % 残差相加后做第二次归一化
layers = connectLayers(layers,"ln2","gap"); % 对时间维做全局平均池化
layers = connectLayers(layers,"gap","fc_out"); % 池化结果送入输出层
layers = connectLayers(layers,"fc_out","regression_output"); % 输出层计算回归损失
训练参数与模型训练
options = trainingOptions("adam"); % 选择Adam优化器
options.MaxEpochs = 80; % 最大训练轮数
options.MiniBatchSize = 64; % 批量大小
options.InitialLearnRate = 1e-3; % 初始学习率
options.Shuffle = "every-epoch"; % 每轮打乱训练样本
options.ValidationData = {XTest,YTest}; % 设置验证数据
options.ValidationFrequency = 30; % 验证频率
options.ExecutionEnvironment = "auto"; % 自动选择CPU或GPU
options.Plots = "training-progress"; % 显示训练过程
options.Verbose = false; % 关闭命令行冗余输出
net = trainNetwork(XTrain,YTrain,layers,options); % 开始训练完整模型
预测、反归一化与误差评估
YPred = predict(net,XTest,"MiniBatchSize",64); % 对测试集进行预测
YPredRaw = YPred .* sigma + mu; % 将预测值反归一化回原始尺度
YTestRaw = YTest .* sigma + mu; % 将真实值反归一化回原始尺度
mae = mean(abs(YPredRaw - YTestRaw),1); % 计算每个变量的平均绝对误差
rmse = sqrt(mean((YPredRaw - YTestRaw).^2,1)); % 计算每个变量的均方根误差
r2 = 1 - sum((YPredRaw - YTestRaw).^2,1) ./ sum((YTestRaw - mean(YTestRaw,1)).^2,1); % 计算决定系数
disp(mae); % 输出MAE结果
disp(rmse); % 输出RMSE结果
disp(r2); % 输出R2结果
更多详细内容请访问
http://【多变量时间序列预测】MATLAB实现基于MSGNet-Transformer多尺度时序关系捕捉(MSGNet)结合Transformer编码器进行多变量时间序列预测的详细项目实例(含完整的程序_sdp对称点模式资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/90395676
https://download.csdn.net/download/xiaoxingkongyuxi/90395676
https://download.csdn.net/download/xiaoxingkongyuxi/90395676
更多推荐








所有评论(0)