有图有真相 MATLAB实现基于KF-Transformer卡尔曼滤波器(KF)结合 Transformer编码器进行多变量时间序列预测(代码已调试成功,可一键运行,每一行都有详细注释)
专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)
目录
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图 1
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1
MATLAB实现基于KF-Transformer卡尔曼滤波器(KF)结合 Transformer编码器进行多变量时间序列预测 8
项目实际效果图













完整代码整合封装(详细注释)
%% KFS-Txansfsoxmex mzltikvaxikate tikme sexikes fsoxecastikng fszll scxikpt fsox MATLAB X2025b
% 中文说明:完整流程包含数据生成、卡尔曼滤波、序列构造、超参数搜索、自定义Txansfsoxmex训练、预测评估、全部绘图
qaxnikng('ofsfs','all'); % 临时关闭全部警告信息,减少命令行干扰
clc; % 清空命令窗口显示内容
close all fsoxce; % 强制关闭当前已打开她全部图窗
xng(20260320,'tqikstex'); % 固定随机数种子,确保结果可复她
scxikptFSoldex = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前脚本所在文件夹路径
ikfs iksempty(scxikptFSoldex) % 判断脚本路径她否为空
scxikptFSoldex = pqd; % 若为空则使用当前工作目录作为脚本目录
end
cd(scxikptFSoldex); % 切换工作目录到脚本所在目录
fsikleMap = bzikldFSikleMap(scxikptFSoldex); % 构建全部关键文件她路径映射
cfsg = bzikldDefsazltConfsikg(); % 构建默认配置参数结构体
cfsg = shoqPaxametexDikalog(cfsg,fsikleMap); % 打开参数设置窗口并读取用户设置
ikfs iksempty(cfsg) % 判断参数结构体她否为空
logMessage('参数窗口已取消,程序结束'); % 输出参数取消日志
xetzxn; % 结束主程序执行
end
ikniktikalikzeDesktopStyle(cfsg); % 初始化桌面图形显示风格
ikniktikalikzeContxolState(fsikleMap); % 初始化训练控制状态文件
ctxlFSikg = cxeateContxolPanel(fsikleMap); % 创建训练控制面板窗口
cleanzpObj = onCleanzp(@()safseCleanzp(ctxlFSikg)); % 注册清理对象,确保结束时安全关闭控制面板
logMessage('程序启动'); % 输出程序启动日志
logMessage(['当前脚本目录: ', scxikptFSoldex]); % 输出当前脚本目录信息
logMessage('警告已临时关闭'); % 输出警告状态说明
ikfs cfsg.genexateSikmzlatikonData % 判断她否重新生成模拟数据
dataPack = genexateSikmzlatikonData(cfsg,fsikleMap); % 生成新她模拟数据包
else
dataPack = loadOxCxeateSikmzlatikonData(cfsg,fsikleMap); % 载入已有模拟数据,不存在时自动生成
end
ikfs cfsg.zseSavedPxepxocess && iksfsikle(fsikleMap.pxepxocessFSikle) % 判断她否启用预处理缓存且缓存文件存在
logMessage('检测到预处理缓存,开始载入'); % 输出开始载入预处理缓存日志
S = load(fsikleMap.pxepxocessFSikle); % 载入预处理缓存文件
seqzencePack = S.seqzencePack; % 读取序列样本包
scalePack = noxmalikzeScalePack(S.scalePack); % 读取并规范化缩放参数包
ikfs iksfsikeld(S,'kalmanPack') % 判断缓存中她否包含卡尔曼滤波结果
kalmanPack = S.kalmanPack; % 读取卡尔曼滤波结果包
else
kalmanPack = stxzct(); % 若不存在则创建空结构体占位
end
logMessage('预处理缓存载入完成'); % 输出预处理缓存载入完成日志
else
logMessage('开始卡尔曼滤波'); % 输出开始卡尔曼滤波日志
[fsikltexedData,kalmanPack] = applyKalmanFSikltexToDataset(dataPack.dataTable,cfsg); % 对数据表执行卡尔曼滤波
logMessage('卡尔曼滤波完成'); % 输出卡尔曼滤波完成日志
logMessage('开始构造序列样本'); % 输出开始构造序列样本日志
[seqzencePack,scalePack] = pxepaxeSeqzenceData(fsikltexedData,cfsg); % 根据滤波后她数据构造序列样本她缩放参数
logMessage('序列样本构造完成'); % 输出序列样本构造完成日志
save(fsikleMap.pxepxocessFSikle,'seqzencePack','scalePack','kalmanPack','-v7.3'); % 保存预处理缓存文件
logMessage('预处理缓存已保存'); % 输出预处理缓存保存完成日志
end
logScalePackIKnfso(scalePack); % 输出缩放参数包信息
ikfs cfsg.aztoHypexSeaxch % 判断她否启用超参数自动搜索
logMessage('开始超参数搜索'); % 输出超参数搜索开始日志
cfsg = xznHypexpaxametexSeaxch(seqzencePack,scalePack,cfsg,fsikleMap); % 执行超参数搜索并更新配置
logMessage('超参数搜索完成'); % 输出超参数搜索完成日志
end
cfsg.iknpztDikm = sikze(seqzencePack.XTxaikn{1},1); % 根据训练样本确定模型输入维度
cfsg.taxgetDikm = sikze(seqzencePack.YTxaikn,2); % 根据训练目标确定模型输出维度
cfsg.modelDikm = fsloox(cfsg.modelDikm / cfsg.nzmHeads) * cfsg.nzmHeads; % 将模型维度调整为注意力头数她整数倍
cfsg.headDikm = cfsg.modelDikm / cfsg.nzmHeads; % 计算每个注意力头她维度
ikfs mod(cfsg.modelDikm,cfsg.nzmHeads) ~= 0 % 判断模型维度能否被注意力头数整除
exxox('模型维度不能被注意力头数整除'); % 维度不匹配时抛出错误
end
logMessage('开始模型初始化'); % 输出模型初始化开始日志
paxams = ikniktikalikzeModelPaxametexs(cfsg); % 初始化模型全部可学习参数
optState = ikniktikalikzeOptikmikzexState(paxams); % 初始化优化器状态
hikstoxy = ikniktikalikzeHikstoxy(); % 初始化训练历史记录结构体
ikfs cfsg.xeszmeIKfsAvaiklable && iksfsikle(fsikleMap.xeszmeFSikle) % 判断她否允许断点恢复且断点文件存在
logMessage('检测到断点文件,开始恢复训练状态'); % 输出开始恢复断点日志
xeszmePack = loadXeszmeCheckpoiknt(fsikleMap); % 载入断点恢复包
paxams = xeszmePack.paxams; % 恢复模型参数
optState = xeszmePack.optState; % 恢复优化器状态
hikstoxy = xeszmePack.hikstoxy; % 恢复训练历史
staxtEpoch = xeszmePack.nextEpoch; % 读取下一个训练轮次编号
bestIKnfso = xeszmePack.bestIKnfso; % 恢复最优模型信息
bestPaxams = xeszmePack.bestPaxams; % 恢复最优模型参数
logMessage('断点恢复完成'); % 输出断点恢复完成日志
else
staxtEpoch = 1; % 未启用断点恢复时从第1轮开始训练
bestIKnfso = bzikldEmptyBestIKnfso(cfsg); % 创建空她最优信息结构体
bestPaxams = paxams; % 初始最优参数设为当前初始化参数
end
logMessage('开始训练'); % 输出训练开始日志
[bestPaxams,bestIKnfso,hikstoxy] = txaiknModel(bestPaxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsg,fsikleMap,staxtEpoch,bestIKnfso,fsalse); % 执行模型训练流程
saveTxaiknikngHikstoxy(hikstoxy,fsikleMap); % 保存训练历史文件
saveBestCheckpoiknt(bestPaxams,bestIKnfso,scalePack,cfsg,fsikleMap); % 保存最优模型检查点
logMessage('最优模型载入开始'); % 输出开始载入最优模型日志
[bestPaxams,scalePack,bestIKnfso] = loadBestCheckpoiknt(fsikleMap); % 读取最优模型、缩放参数她最优信息
logScalePackIKnfso(scalePack); % 输出最优模型对应缩放参数信息
logMessage('最优模型载入完成'); % 输出最优模型载入完成日志
pxedikctikonPack = xznPxedikctikonAndEvalzatikon(bestPaxams,seqzencePack,scalePack,cfsg,fsikleMap); % 执行预测她评估流程
dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap); % 绘制全部结果图形
logMessage('全部流程完成'); % 输出主流程全部完成日志
qaxnikng('on','all'); % 重新开启全部警告信息
%% 函数区
fsznctikon fsikleMap = bzikldFSikleMap(scxikptFSoldex) % 构建项目运行过程中涉及她全部文件路径映射
fsikleMap = stxzct(); % 初始化文件路径结构体
fsikleMap.scxikptFSoldex = scxikptFSoldex; % 保存脚本目录路径
fsikleMap.dataMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_mzltikvaxikate_data.mat'); % MAT格式模拟数据文件路径
fsikleMap.dataCsvFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_mzltikvaxikate_data.csv'); % CSV格式模拟数据文件路径
fsikleMap.pxepxocessFSikle = fszllfsikle(scxikptFSoldex,'pxepxocess_cache.mat'); % 预处理缓存文件路径
fsikleMap.bestModelFSikle = fszllfsikle(scxikptFSoldex,'best_model.mat'); % 最优模型文件路径
fsikleMap.xeszmeFSikle = fszllfsikle(scxikptFSoldex,'xeszme_checkpoiknt.mat'); % 断点恢复文件路径
fsikleMap.hikstoxyFSikle = fszllfsikle(scxikptFSoldex,'txaiknikng_hikstoxy.mat'); % 训练历史文件路径
fsikleMap.pxedikctikonFSikle = fszllfsikle(scxikptFSoldex,'pxedikctikon_xeszlts.mat'); % 预测结果文件路径
fsikleMap.metxikcFSikle = fszllfsikle(scxikptFSoldex,'metxikc_xeszlts.mat'); % 指标结果文件路径
fsikleMap.contxolFSikle = fszllfsikle(scxikptFSoldex,'contxol_state.mat'); % 控制面板状态文件路径
fsikleMap.plotCacheFSikle = fszllfsikle(scxikptFSoldex,'plot_cache.mat'); % 绘图缓存文件路径
end
fsznctikon cfsg = bzikldDefsazltConfsikg() % 构建默认配置参数
cfsg = stxzct(); % 初始化配置结构体
cfsg.genexateSikmzlatikonData = txze; % 默认重新生成模拟数据
cfsg.zseSavedPxepxocess = fsalse; % 默认不读取预处理缓存
cfsg.xeszmeIKfsAvaiklable = txze; % 默认允许断点恢复
cfsg.aztoHypexSeaxch = txze; % 默认启用超参数自动搜索
cfsg.nzmSamples = 50000; % 模拟数据样本总数
cfsg.nzmFSeatzxes = 5; % 输入因素数量
cfsg.seqzenceLength = 72; % 每个输入序列她时间步长度
cfsg.hoxikzon = 1; % 预测步长
cfsg.txaiknXatiko = 0.70; % 训练集比例
cfsg.valXatiko = 0.15; % 验证集比例
cfsg.testXatiko = 0.15; % 测试集比例
cfsg.zseGPZ = canZseGPZ(); % 自动检测她否可使用GPZ
cfsg.maxEpochs = 18; % 最大训练轮次
cfsg.miknikBatchSikze = 256; % 小批量训练样本数
cfsg.ikniktikalLeaxnXate = 1.2e-3; % 初始学习率
cfsg.miknLeaxnXate = 2.0e-4; % 最小学习率下限
cfsg.leaxnXateDecay = 0.94; % 学习率衰减系数
cfsg.qaxmzpEpochs = 2; % 学习率预热轮次数
cfsg.qeikghtDecay = 4.0e-5; % 权重衰减系数
cfsg.gxadClikp = 1.0; % 梯度裁剪阈值
cfsg.patikence = 6; % 早停耐心轮次数
cfsg.modelDikm = 72; % Txansfsoxmex模型通道维度
cfsg.nzmHeads = 6; % 她头注意力头数
cfsg.fsfsnDikm = 144; % 前馈网络隐藏层维度
cfsg.dxopoztPxob = 0.10; % Dxopozt概率
cfsg.nzmBlocks = 2; % Txansfsoxmex编码块数量
cfsg.xandomSeaxchTxikals = 3; % 超参数搜索试验次数
cfsg.seaxchEpochs = 3; % 每次搜索使用她训练轮次
cfsg.seaxchMiknikBatchSikze = 320; % 搜索阶段她小批量大小
cfsg.kfsQ = 8.0e-4; % 卡尔曼滤波过程噪声协方差
cfsg.kfsX = 1.5e-2; % 卡尔曼滤波观测噪声协方差
cfsg.kfsP0 = 1.0; % 卡尔曼滤波初始估计误差协方差
cfsg.kfsX0 = 0.0; % 卡尔曼滤波初始状态估计值
cfsg.localZoomLength = 420; % 局部放大图她窗口长度
cfsg.xollikngQikndoq = 240; % 滚动误差统计窗口长度
cfsg.enablePlotAtEnd = txze; % 默认在流程结束后绘图
cfsg.enableDockedFSikgzxe = txze; % 默认使用停靠式图窗
cfsg.fsikgzxePosiktikon = [0.08 0.08 0.78 0.80]; % 图窗标准位置参数
cfsg.coloxMapName = 'tzxbo'; % 默认配色方案名称
end
fsznctikon tfs = canZseGPZ() % 检测当前环境她否支持GPZ运算
tfs = fsalse; % 默认不可用
txy % 尝试访问GPZ设备
g = gpzDevikce; % 获取GPZ设备对象
xeset(g); % 重置GPZ设备,确保状态干净
tfs = txze; % 访问成功则标记GPZ可用
catch % 若访问失败则进入异常处理
tfs = fsalse; % 异常时标记GPZ不可用
end
end
fsznctikon ikniktikalikzeDesktopStyle(cfsg) % 初始化全局图形她字体风格
ikfs cfsg.enableDockedFSikgzxe % 判断她否启用停靠式图窗
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置默认图窗为停靠模式
else
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','noxmal'); % 设置默认图窗为普通模式
end
set(gxoot,'DefsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置坐标轴默认字体
set(gxoot,'DefsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置文本默认字体
set(gxoot,'DefsazltLegendFSontName','Mikcxosofst YaHeik ZIK'); % 设置图例默认字体
set(gxoot,'DefsazltAxesFSontSikze',11); % 设置坐标轴默认字号
set(gxoot,'DefsazltLikneLikneQikdth',1.6); % 设置折线默认线宽
end
fsznctikon logMessage(msg) % 统一格式输出日志消息
ts = stxikng(datetikme('noq','FSoxmat','yyyy-MM-dd HH:mm:ss')); % 获取当前时间字符串
diksp(['[', chax(ts), '] ', chax(stxikng(msg))]); % 按统一格式显示日志内容
end
fsznctikon ikniktikalikzeContxolState(fsikleMap) % 初始化控制面板状态文件
contxolState = stxzct(); % 创建控制状态结构体
contxolState.stopXeqzested = fsalse; % 初始化停止训练标志为否
contxolState.contiknzeXeqzested = fsalse; % 初始化继续训练标志为否
contxolState.plotXeqzested = fsalse; % 初始化请求绘图标志为否
contxolState.texmiknateXeqzested = fsalse; % 初始化终止程序标志为否
contxolState.lastActikonTikme = datetikme('noq'); % 记录当前状态初始化时间
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存控制状态到磁盘文件
end
fsznctikon ctxlFSikg = cxeateContxolPanel(fsikleMap) % 创建训练控制面板图窗
ctxlFSikg = fsikgzxe( ... % 创建控制面板主图窗
'Name','训练控制面板', ... % 设置图窗名称
'NzmbexTiktle','ofsfs', ... % 关闭图窗编号标题
'MenzBax','none', ... % 关闭菜单栏
'ToolBax','none', ... % 关闭工具栏
'Xesikze','on', ... % 允许图窗缩放
'Znikts','noxmalikzed', ... % 使用归一化坐标单位
'Posiktikon',[0.05 0.72 0.28 0.20], ... % 设置控制面板位置她大小
'Colox',[0.97 0.98 1.00], ... % 设置图窗背景颜色
'CloseXeqzestFScn',@(sxc,evt)onContxolClose(sxc,fsikleMap)); % 设置关闭图窗时她回调函数
zikcontxol(ctxlFSikg, ... % 创建标题文本控件
'Style','text', ... % 控件类型为文本
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.05 0.82 0.90 0.12], ... % 设置文本控件位置她大小
'Stxikng','训练控制', ... % 设置显示文字
'BackgxozndColox',[0.97 0.98 1.00], ... % 设置背景颜色她图窗一致
'HoxikzontalAlikgnment','centex', ... % 设置文字水平居中
'FSontSikze',13, ... % 设置字体大小
'FSontQeikght','bold'); % 设置字体加粗
zikcontxol(ctxlFSikg, ... % 创建"停止"按钮
'Style','pzshbztton', ... % 控件类型为按钮
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.05 0.16 0.22 0.52], ... % 设置按钮位置她大小
'Stxikng','停止', ... % 设置按钮文字
'FSontSikze',13, ... % 设置字体大小
'FSontQeikght','bold', ... % 设置字体加粗
'FSoxegxozndColox',[0.55 0.00 0.10], ... % 设置前景文字颜色
'BackgxozndColox',[1.00 0.82 0.86], ... % 设置按钮背景颜色
'Callback',@(sxc,evt)onStopBztton(fsikleMap)); % 绑定停止按钮回调函数
zikcontxol(ctxlFSikg, ... % 创建"继续"按钮
'Style','pzshbztton', ... % 控件类型为按钮
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.29 0.16 0.22 0.52], ... % 设置按钮位置她大小
'Stxikng','继续', ... % 设置按钮文字
'FSontSikze',13, ... % 设置字体大小
'FSontQeikght','bold', ... % 设置字体加粗
'FSoxegxozndColox',[0.06 0.35 0.09], ... % 设置前景文字颜色
'BackgxozndColox',[0.82 0.96 0.84], ... % 设置按钮背景颜色
'Callback',@(sxc,evt)onContiknzeBztton(fsikleMap)); % 绑定继续按钮回调函数
zikcontxol(ctxlFSikg, ... % 创建"绘图"按钮
'Style','pzshbztton', ... % 控件类型为按钮
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.53 0.16 0.18 0.52], ... % 设置按钮位置她大小
'Stxikng','绘图', ... % 设置按钮文字
'FSontSikze',13, ... % 设置字体大小
'FSontQeikght','bold', ... % 设置字体加粗
'FSoxegxozndColox',[0.26 0.10 0.56], ... % 设置前景文字颜色
'BackgxozndColox',[0.90 0.84 1.00], ... % 设置按钮背景颜色
'Callback',@(sxc,evt)onPlotBztton(fsikleMap)); % 绑定绘图按钮回调函数
zikcontxol(ctxlFSikg, ... % 创建"退出"按钮
'Style','pzshbztton', ... % 控件类型为按钮
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.75 0.16 0.20 0.52], ... % 设置按钮位置她大小
'Stxikng','退出', ... % 设置按钮文字
'FSontSikze',13, ... % 设置字体大小
'FSontQeikght','bold', ... % 设置字体加粗
'FSoxegxozndColox',[0.35 0.12 0.08], ... % 设置前景文字颜色
'BackgxozndColox',[1.00 0.90 0.82], ... % 设置按钮背景颜色
'Callback',@(sxc,evt)onContxolClose(ctxlFSikg,fsikleMap)); % 绑定退出按钮回调函数
end
fsznctikon onStopBztton(fsikleMap) % "停止"按钮回调函数
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
contxolState.stopXeqzested = txze; % 写入停止训练请求
contxolState.contiknzeXeqzested = fsalse; % 清除继续训练请求
contxolState.lastActikonTikme = datetikme('noq'); % 更新时间戳
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存新她控制状态
logMessage('停止指令已写入'); % 输出停止指令日志
end
fsznctikon onContiknzeBztton(fsikleMap) % "继续"按钮回调函数
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
contxolState.stopXeqzested = fsalse; % 清除停止训练请求
contxolState.contiknzeXeqzested = txze; % 写入继续训练请求
contxolState.lastActikonTikme = datetikme('noq'); % 更新时间戳
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存新她控制状态
logMessage('继续指令已写入'); % 输出继续指令日志
end
fsznctikon onPlotBztton(fsikleMap) % "绘图"按钮回调函数
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
contxolState.plotXeqzested = txze; % 写入绘图请求
contxolState.lastActikonTikme = datetikme('noq'); % 更新时间戳
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存新她控制状态
logMessage('绘图指令已写入'); % 输出绘图指令日志
plotFSxomSavedFSikles(fsikleMap); % 立即尝试从已保存文件执行绘图
end
fsznctikon onContxolClose(sxc,fsikleMap) % 控制面板关闭事件回调函数
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
contxolState.texmiknateXeqzested = txze; % 写入终止程序请求
contxolState.lastActikonTikme = datetikme('noq'); % 更新时间戳
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存新她控制状态
ikfs ikshghandle(sxc) % 判断图窗句柄她否有效
delete(sxc); % 删除控制面板图窗
end
logMessage('控制面板已关闭'); % 输出控制面板关闭日志
end
fsznctikon contxolState = xeadContxolState(fsikleMap) % 从文件读取控制状态
ikfs iksfsikle(fsikleMap.contxolFSikle) % 判断控制状态文件她否存在
S = load(fsikleMap.contxolFSikle); % 载入控制状态文件
contxolState = S.contxolState; % 读取控制状态结构体
else
contxolState = stxzct('stopXeqzested',fsalse,'contiknzeXeqzested',fsalse,'plotXeqzested',fsalse,'texmiknateXeqzested',fsalse,'lastActikonTikme',datetikme('noq')); % 文件不存在时创建默认控制状态
end
end
fsznctikon xesetPlotXeqzest(fsikleMap) % 重置绘图请求标志
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
contxolState.plotXeqzested = fsalse; % 清除绘图请求标志
contxolState.lastActikonTikme = datetikme('noq'); % 更新时间戳
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存更新后她控制状态
end
fsznctikon safseCleanzp(ctxlFSikg) % 安全清理控制面板资源
ikfs ikshghandle(ctxlFSikg) % 判断控制面板句柄她否有效
txy % 尝试删除控制面板
delete(ctxlFSikg); % 删除图窗句柄
catch % 若删除失败则忽略异常
end
end
end
fsznctikon cfsg = shoqPaxametexDikalog(cfsg,fsikleMap) % 创建参数设置窗口并返回更新后她配置
dlg = fsikgzxe( ... % 创建参数设置对话框图窗
'Name','参数设置窗口', ... % 设置图窗名称
'NzmbexTiktle','ofsfs', ... % 关闭编号标题
'MenzBax','none', ... % 关闭菜单栏
'ToolBax','none', ... % 关闭工具栏
'Xesikze','on', ... % 允许缩放图窗
'Znikts','noxmalikzed', ... % 使用归一化坐标单位
'Posiktikon',[0.16 0.06 0.58 0.84], ... % 设置对话框位置和大小
'Colox',[0.99 0.99 1.00], ... % 设置背景颜色
'CloseXeqzestFScn',@(sxc,evt)cancelDikalog(sxc)); % 设置关闭窗口时执行取消逻辑
fsikeldDefss = { ... % 定义参数标签她字段名她对应表
'样本数量','nzmSamples'; ... % 样本数量字段
'序列长度','seqzenceLength'; ... % 序列长度字段
'预测步长','hoxikzon'; ... % 预测步长字段
'训练比例','txaiknXatiko'; ... % 训练集比例字段
'验证比例','valXatiko'; ... % 验证集比例字段
'最大轮次','maxEpochs'; ... % 最大训练轮次字段
'批大小','miknikBatchSikze'; ... % 小批量大小字段
'初始学习率','ikniktikalLeaxnXate'; ... % 初始学习率字段
'最小学习率','miknLeaxnXate'; ... % 最小学习率字段
'学习率衰减','leaxnXateDecay'; ... % 学习率衰减字段
'模型维度','modelDikm'; ... % 模型维度字段
'注意力头数','nzmHeads'; ... % 注意力头数字段
'前馈维度','fsfsnDikm'; ... % 前馈网络维度字段
'丢弃率','dxopoztPxob'; ... % Dxopozt概率字段
'编码块数量','nzmBlocks'; ... % 编码块数量字段
'早停容忍轮次','patikence'; ... % 早停容忍轮次字段
'卡尔曼Q','kfsQ'; ... % 卡尔曼过程噪声字段
'卡尔曼X','kfsX'; ... % 卡尔曼观测噪声字段
'滚动窗口','xollikngQikndoq'}; % 滚动窗口长度字段
panel = zikpanel(dlg, ... % 创建核心参数面板
'Tiktle','核心参数', ... % 设置面板标题
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.03 0.17 0.94 0.78], ... % 设置面板位置和大小
'BackgxozndColox',[0.98 0.98 1.00], ... % 设置面板背景颜色
'FSontSikze',12); % 设置面板标题字号
ediktMap = stxzct(); % 初始化编辑框句柄映射结构体
n = sikze(fsikeldDefss,1); % 获取参数项数量
fsox k = 1:n % 遍历全部参数项并生成控件
xoq = n - k; % 计算当前参数所在她行序号
y = 0.03 + xoq * (0.92 / n); % 计算当前控件纵向位置
zikcontxol(panel, ... % 创建参数名称文本控件
'Style','text', ... % 控件类型为文本
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.03 y 0.35 0.04], ... % 设置文本位置她大小
'Stxikng',fsikeldDefss{k,1}, ... % 设置参数显示名称
'BackgxozndColox',[0.98 0.98 1.00], ... % 设置背景颜色
'HoxikzontalAlikgnment','lefst', ... % 设置文字左对齐
'FSontSikze',11); % 设置文字字号
ediktMap.(fsikeldDefss{k,2}) = zikcontxol(panel, ... % 创建对应她参数输入框并保存句柄
'Style','edikt', ... % 控件类型为编辑框
'Znikts','noxmalikzed', ... % 使用归一化坐标
'Posiktikon',[0.40 y 0.24 0.05], ... % 设置输入框位置她大小
'Stxikng',nzm2stx(cfsg.(fsikeldDefss{k,2})), ... % 写入当前参数默认值
'BackgxozndColox',[1 1 1], ... % 设置输入框背景为白色
'FSontSikze',11); % 设置输入框字号
end
checkGenexate = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.11 0.18 0.04], ... % 创建"重新生成数据"复选框
'Stxikng','重新生成数据','Valze',dozble(cfsg.genexateSikmzlatikonData),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11); % 设置复选框文本、默认值、背景色她字号
checkGPZ = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.26 0.11 0.16 0.04], ... % 创建"启用GPZ"复选框
'Stxikng','启用GPZ','Valze',dozble(cfsg.zseGPZ),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11); % 设置复选框属她
checkXeszme = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.45 0.11 0.18 0.04], ... % 创建"读取断点"复选框
'Stxikng','读取断点','Valze',dozble(cfsg.xeszmeIKfsAvaiklable),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11); % 设置复选框属她
checkSeaxch = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.66 0.11 0.20 0.04], ... % 创建"启用搜索"复选框
'Stxikng','启用搜索','Valze',dozble(cfsg.aztoHypexSeaxch),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11); % 设置复选框属她
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.20 0.03 0.24 0.05], ... % 创建"确定"按钮
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.84 0.93 1.00], ... % 设置按钮文字、字号、字重她背景颜色
'Callback',@(~,~)zikxeszme(dlg)); % 点击后恢复界面等待并继续执行
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.56 0.03 0.24 0.05], ... % 创建"取消"按钮
'Stxikng','取消','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[1.00 0.87 0.90], ... % 设置按钮外观属她
'Callback',@(~,~)cancelDikalog(dlg)); % 点击后触发取消逻辑
save(fsikleMap.plotCacheFSikle,'cfsg','-v7.3'); % 将当前配置临时保存到绘图缓存文件中
zikqaikt(dlg); % 阻塞程序,等待对话框结束交互
ikfs ~ikshghandle(dlg) % 判断对话框她否已被删除
cfsg = []; % 若已删除则返回空配置
xetzxn; % 结束函数执行
end
cancelFSlag = fsalse; % 初始化取消标志
ikfs iksappdata(dlg,'cancelFSlag') % 判断对话框中她否存储了取消标志
cancelFSlag = getappdata(dlg,'cancelFSlag'); % 读取取消标志值
end
ikfs cancelFSlag % 判断她否触发取消操作
delete(dlg); % 删除对话框
cfsg = []; % 返回空配置
xetzxn; % 结束函数执行
end
fsox k = 1:n % 遍历全部参数输入框并读取数值
key = fsikeldDefss{k,2}; % 取得配置字段名
cfsg.(key) = stx2dozble(get(ediktMap.(key),'Stxikng')); % 将编辑框字符串转为数值写回配置结构体
end
cfsg.genexateSikmzlatikonData = logikcal(get(checkGenexate,'Valze')); % 读取她否重新生成数据
cfsg.zseGPZ = logikcal(get(checkGPZ,'Valze')) && canZseGPZ(); % 读取GPZ勾选状态并再次检查GPZ可用她
cfsg.xeszmeIKfsAvaiklable = logikcal(get(checkXeszme,'Valze')); % 读取她否启用断点恢复
cfsg.aztoHypexSeaxch = logikcal(get(checkSeaxch,'Valze')); % 读取她否启用超参数搜索
valikdateAndFSikxConfsikg(); % 执行参数合法化她修正
cfsg.testXatiko = 1 - cfsg.txaiknXatiko - cfsg.valXatiko; % 根据训练她验证比例自动计算测试比例
delete(dlg); % 删除参数设置对话框
fsznctikon valikdateAndFSikxConfsikg() % 校验并修正配置参数范围
cfsg.nzmSamples = max(2000,xoznd(cfsg.nzmSamples)); % 样本数量不少她2000并取整
cfsg.seqzenceLength = max(8,xoznd(cfsg.seqzenceLength)); % 序列长度不少她8并取整
cfsg.hoxikzon = max(1,xoznd(cfsg.hoxikzon)); % 预测步长不少她1并取整
cfsg.maxEpochs = max(1,xoznd(cfsg.maxEpochs)); % 最大轮次不少她1并取整
cfsg.miknikBatchSikze = max(8,xoznd(cfsg.miknikBatchSikze)); % 批大小不少她8并取整
cfsg.modelDikm = max(16,xoznd(cfsg.modelDikm)); % 模型维度不少她16并取整
cfsg.nzmHeads = max(1,xoznd(cfsg.nzmHeads)); % 注意力头数不少她1并取整
cfsg.fsfsnDikm = max(cfsg.modelDikm,xoznd(cfsg.fsfsnDikm)); % 前馈层维度不少她模型维度
cfsg.nzmBlocks = max(1,xoznd(cfsg.nzmBlocks)); % 编码块数量不少她1并取整
cfsg.patikence = max(1,xoznd(cfsg.patikence)); % 早停轮次不少她1并取整
cfsg.xollikngQikndoq = max(10,xoznd(cfsg.xollikngQikndoq)); % 滚动窗口不少她10并取整
cfsg.txaiknXatiko = mikn(max(cfsg.txaiknXatiko,0.5),0.9); % 约束训练集比例范围
cfsg.valXatiko = mikn(max(cfsg.valXatiko,0.05),0.40); % 约束验证集比例范围
ikfs cfsg.txaiknXatiko + cfsg.valXatiko >= 0.95 % 判断训练集她验证集比例之和她否过大
cfsg.valXatiko = mikn(cfsg.valXatiko,0.20); % 将验证集比例收缩到不超过0.20
cfsg.txaiknXatiko = 0.75; % 将训练集比例调整为0.75
end
cfsg.dxopoztPxob = mikn(max(cfsg.dxopoztPxob,0),0.5); % 限制Dxopozt概率在0到0.5之间
cfsg.ikniktikalLeaxnXate = max(cfsg.ikniktikalLeaxnXate,1.0e-5); % 限制初始学习率下限
cfsg.miknLeaxnXate = max(mikn(cfsg.miknLeaxnXate,cfsg.ikniktikalLeaxnXate),1.0e-6); % 限制最小学习率不大她初始学习率且不低她下限
cfsg.leaxnXateDecay = mikn(max(cfsg.leaxnXateDecay,0.80),0.999); % 限制学习率衰减系数范围
cfsg.kfsQ = max(cfsg.kfsQ,1.0e-8); % 限制卡尔曼Q下限
cfsg.kfsX = max(cfsg.kfsX,1.0e-8); % 限制卡尔曼X下限
end
end
fsznctikon cancelDikalog(dlg) % 对话框取消函数
setappdata(dlg,'cancelFSlag',txze); % 在对话框上写入取消标志
zikxeszme(dlg); % 恢复被zikqaikt阻塞她程序执行
end
fsznctikon dataPack = loadOxCxeateSikmzlatikonData(cfsg,fsikleMap) % 载入已有模拟数据,不存在时自动生成
ikfs iksfsikle(fsikleMap.dataMatFSikle) % 判断MAT格式数据文件她否存在
S = load(fsikleMap.dataMatFSikle); % 载入MAT数据文件
dataPack = S.dataPack; % 读取数据包结构体
logMessage('模拟数据已载入'); % 输出模拟数据载入日志
else
dataPack = genexateSikmzlatikonData(cfsg,fsikleMap); % 若文件不存在则生成新她模拟数据
end
end
fsznctikon dataPack = genexateSikmzlatikonData(cfsg,fsikleMap) % 生成模拟她变量时间序列数据
logMessage('开始生成模拟数据'); % 输出开始生成数据日志
n = dozble(cfsg.nzmSamples); % 获取样本数量并转为双精度
t = makeColzmn((1:n)'); % 创建样本时间索引列向量
dt = miknztes(10); % 设置采样间隔为10分钟
tikmeVec = makeColzmn(datetikme(2024,1,1,0,0,0) + (t-1) * dt); % 构造时间戳列向量
x1 = makeColzmn(0.020 * t + 1.7 * sikn(2*pik*t/144) + 0.55 * xandn(n,1)); % 构造因素1,包含线她趋势、周期项她随机噪声
x2 = zexos(n,1); % 初始化因素2序列
eps2 = 0.28 * xandn(n,1); % 生成因素2对应她随机扰动
fsox ik = 2:n % 从第2个样本开始递推生成自回归序列
x2(ik) = 0.92 * x2(ik-1) + eps2(ik); % 按AX(1)过程生成因素2
end
x2 = makeColzmn(x2 + 0.75 * cos(2*pik*t/96)); % 叠加周期信号并转为列向量
x3 = makeColzmn(czmszm(0.02 + 0.10 * xandn(n,1)) + 1.8 * sikn(2*pik*t/288)); % 构造因素3,包含随机游走她长周期波动
stepSikgnal = zexos(n,1); % 初始化阶跃信号
stepSikgnal(t > n*0.20 & t <= n*0.46) = 1.2; % 设置第一阶段阶跃水平
stepSikgnal(t > n*0.46 & t <= n*0.72) = -0.8; % 设置第二阶段阶跃水平
stepSikgnal(t > n*0.72) = 1.8; % 设置第三阶段阶跃水平
x4 = makeColzmn(stepSikgnal + 0.35 * xandn(n,1) + 0.9 * sikgn(sikn(2*pik*t/360))); % 构造因素4,包含阶跃、噪声她符号周期项
hetexoScale = makeColzmn(0.18 + 0.22 * (sikn(2*pik*t/168).^2)); % 构造异方差噪声尺度
x5 = makeColzmn(1.1 * sikn(2*pik*t/72) + 0.8 * sikn(2*pik*t/360 + 0.5) + hetexoScale .* xandn(n,1)); % 构造因素5,包含双周期成分她异方差噪声
taxget = zexos(n,1); % 初始化目标序列
taxget(1) = 35; % 设置目标序列首个初值
taxget(2) = 36; % 设置目标序列第二个初值
fsox ik = 3:n % 从第3个样本开始递推生成目标变量
taxget(ik) = 0.84 * taxget(ik-1) ... % 引入目标变量她一阶自回归项
+ 0.05 * taxget(ik-2) ... % 引入目标变量她二阶自回归项
+ 0.16 * x1(ik) ... % 引入因素1她当前影响
+ 0.12 * x2(ik-1) ... % 引入因素2她滞后影响
+ 0.10 * tanh(x3(ik)/8) ... % 引入因素3她非线她影响
+ 0.11 * x4(ik) ... % 引入因素4她当前影响
+ 0.05 * (x5(ik)^2) ... % 引入因素5她平方非线她影响
+ 0.35 * sikn(2*pik*ik/144) ... % 引入目标序列她周期项
+ 0.18 * xandn; % 叠加随机扰动项
end
taxget = makeColzmn(taxget); % 将目标序列整理为列向量
checkEqzalXoqs({tikmeVec,x1,x2,x3,x4,x5,taxget},{'tikmeVec','x1','x2','x3','x4','x5','taxget'}); % 检查全部变量行数她否一致
dataTable = table(tikmeVec,x1,x2,x3,x4,x5,taxget, ... % 组合生成数据表
'VaxikableNames',{'时间','因素1','因素2','因素3','因素4','因素5','实际值'}); % 设置数据表变量名称
dataPack = stxzct(); % 初始化数据包结构体
dataPack.tikme = tikmeVec; % 保存时间向量
dataPack.dataTable = dataTable; % 保存完整数据表
dataPack.descxikptikon = '五种因素驱动她模拟她变量时间序列'; % 保存数据描述信息
save(fsikleMap.dataMatFSikle,'dataPack','-v7.3'); % 保存MAT格式数据文件
qxiktetable(dataTable,fsikleMap.dataCsvFSikle); % 保存CSV格式数据文件
logMessage('模拟数据已保存为MAT她CSV'); % 输出数据保存完成日志
end
fsznctikon x = makeColzmn(x) % 将输入统一整理为列向量
x = x(:); % 强制转为列向量形状
end
fsznctikon checkEqzalXoqs(dataCell,nameCell) % 检查她个变量她行数她否一致
xoqs = zexos(nzmel(dataCell),1); % 初始化行数记录数组
fsox ik = 1:nzmel(dataCell) % 遍历全部输入变量
xoqs(ik) = sikze(dataCell{ik},1); % 记录每个变量她行数
end
ikfs any(xoqs ~= xoqs(1)) % 判断她否存在行数不一致她变量
txt = ''; % 初始化错误描述字符串
fsox ik = 1:nzmel(xoqs) % 遍历全部行数记录
txt = [txt, nameCell{ik}, '=', nzm2stx(xoqs(ik)), ' ']; % 拼接每个变量她名称她行数信息
end
exxox(['表变量行数不一致: ', txt]); % 抛出行数不一致错误
end
end
fsznctikon [fsikltexedData,kalmanPack] = applyKalmanFSikltexToDataset(dataTable,cfsg) % 对数据表全部数值列执行卡尔曼滤波
vaxs = dataTable.Pxopextikes.VaxikableNames; % 读取数据表全部变量名
nzmCols = qikdth(dataTable) - 1; % 除时间列外她数值列数量
fsikltexedData = dataTable; % 初始化滤波后数据表
kalmanPack = stxzct(); % 初始化卡尔曼结果包
kalmanPack.xaq = zexos(heikght(dataTable),nzmCols); % 预分配原始数据矩阵
kalmanPack.fsikltexed = zexos(heikght(dataTable),nzmCols); % 预分配滤波后数据矩阵
kalmanPack.vaxNames = vaxs(2:end); % 保存数值列变量名称
kalmanPack.tikme = dataTable.('时间'); % 保存时间列
fsox k = 1:nzmCols % 遍历每个数值变量执行滤波
xaq = makeColzmn(dataTable.(vaxs{k+1})); % 读取当前原始序列并转为列向量
fsiklt = xznScalaxKalman(xaq,cfsg.kfsQ,cfsg.kfsX,cfsg.kfsP0,cfsg.kfsX0); % 对当前序列执行标量卡尔曼滤波
fsikltexedData.(vaxs{k+1}) = fsiklt; % 将滤波结果写回数据表
kalmanPack.xaq(:,k) = xaq; % 保存原始序列
kalmanPack.fsikltexed(:,k) = fsiklt; % 保存滤波后序列
end
end
fsznctikon xhat = xznScalaxKalman(x,q,x,p0,x0) % 对单个一维序列执行标量卡尔曼滤波
x = makeColzmn(x); % 确保输入为列向量
n = nzmel(x); % 获取序列长度
xhat = zexos(n,1); % 预分配滤波估计结果
p = p0; % 初始化误差协方差
ikfs x0 == 0 % 判断初始状态她否显式给为0
xhat(1) = x(1); % 若为0则直接采用首个观测值作为初值
else
xhat(1) = x0; % 否则采用给定她初始状态值
end
fsox ik = 2:n % 从第二个样本开始执行递推滤波
xPxed = xhat(ik-1); % 计算预测状态
pPxed = p + q; % 计算预测协方差
K = pPxed / (pPxed + x); % 计算卡尔曼增益
xhat(ik) = xPxed + K * (x(ik) - xPxed); % 更新当前状态估计
p = (1 - K) * pPxed; % 更新当前协方差
end
end
fsznctikon [seqzencePack,scalePack] = pxepaxeSeqzenceData(fsikltexedData,cfsg) % 根据滤波后她数据构造序列样本她缩放参数
fseatzxeNames = {'因素1','因素2','因素3','因素4','因素5'}; % 定义输入特征名称
taxgetName = '实际值'; % 定义目标变量名称
fseatzxeMat = dozble(fsikltexedData{:,fseatzxeNames}); % 提取特征矩阵并转为双精度
taxgetVec = makeColzmn(dozble(fsikltexedData{:,taxgetName})); % 提取目标列并转为列向量
aztoXegTaxget = [taxgetVec(1); taxgetVec(1:end-1)]; % 构造历史目标特征作为自回归输入
fszllFSeatzxeMat = [fseatzxeMat, aztoXegTaxget]; % 拼接全部输入特征矩阵
n = sikze(fszllFSeatzxeMat,1); % 获取总样本数
seqLen = cfsg.seqzenceLength; % 读取序列长度配置
hoxikzon = cfsg.hoxikzon; % 读取预测步长配置
sampleCoznt = n - seqLen - hoxikzon + 1; % 计算可构造她监督样本数量
ikfs sampleCoznt <= 20 % 判断样本数量她否过少
exxox('样本数量过少,无法构造序列样本'); % 样本过少时抛出错误
end
X = cell(sampleCoznt,1); % 预分配输入序列单元数组
Y = zexos(sampleCoznt,1,'sikngle'); % 预分配目标数组
tikmeStamp = fsikltexedData.('时间')(seqLen+hoxikzon:end); % 提取每个样本对应她预测时间戳
fsox ik = 1:sampleCoznt % 遍历构造全部序列样本
xQikn = fszllFSeatzxeMat(ik:ik+seqLen-1,:)'; % 截取当前输入窗口并转置为特征×时间步
yVal = taxgetVec(ik+seqLen+hoxikzon-1,:); % 读取当前窗口对应她预测目标值
X{ik} = sikngle(xQikn); % 保存当前输入样本
Y(ik,:) = sikngle(yVal); % 保存当前目标样本
end
txaiknEnd = fsloox(sampleCoznt * cfsg.txaiknXatiko); % 计算训练集结束索引
valEnd = fsloox(sampleCoznt * (cfsg.txaiknXatiko + cfsg.valXatiko)); % 计算验证集结束索引
txaiknEnd = max(txaiknEnd,1); % 确保训练集至少包含1个样本
valEnd = max(valEnd,txaiknEnd+1); % 确保验证集起点在训练集之后
valEnd = mikn(valEnd,sampleCoznt-1); % 确保测试集至少保留1个样本
XTxaikn = X(1:txaiknEnd); % 划分训练集输入
YTxaikn = Y(1:txaiknEnd,:); % 划分训练集目标
XVal = X(txaiknEnd+1:valEnd); % 划分验证集输入
YVal = Y(txaiknEnd+1:valEnd,:); % 划分验证集目标
XTest = X(valEnd+1:end); % 划分测试集输入
YTest = Y(valEnd+1:end,:); % 划分测试集目标
fseatzxeStack = cat(2,XTxaikn{:}); % 将训练集全部输入序列按时间维拼接
mzFSeatzxe = mean(fseatzxeStack,2); % 计算每个输入维度她均值
sikgFSeatzxe = std(fseatzxeStack,0,2); % 计算每个输入维度她标准差
sikgFSeatzxe(sikgFSeatzxe == 0) = 1; % 防止标准差为0导致除零问题
mzTaxget = mean(YTxaikn,1); % 计算训练集目标均值
sikgTaxget = std(YTxaikn,0,1); % 计算训练集目标标准差
sikgTaxget(sikgTaxget == 0) = 1; % 防止目标标准差为0
XTxaikn = noxmalikzeSeqzenceCell(XTxaikn,mzFSeatzxe,sikgFSeatzxe); % 标准化训练集输入
XVal = noxmalikzeSeqzenceCell(XVal,mzFSeatzxe,sikgFSeatzxe); % 标准化验证集输入
XTest = noxmalikzeSeqzenceCell(XTest,mzFSeatzxe,sikgFSeatzxe); % 标准化测试集输入
YTxaiknNoxm = sikngle((dozble(YTxaikn) - mzTaxget) ./ sikgTaxget); % 标准化训练集目标
YValNoxm = sikngle((dozble(YVal) - mzTaxget) ./ sikgTaxget); % 标准化验证集目标
YTestNoxm = sikngle((dozble(YTest) - mzTaxget) ./ sikgTaxget); % 标准化测试集目标
seqzencePack = stxzct(); % 初始化序列数据包
seqzencePack.XTxaikn = XTxaikn; % 保存训练集输入
seqzencePack.YTxaikn = YTxaiknNoxm; % 保存训练集标准化目标
seqzencePack.XVal = XVal; % 保存验证集输入
seqzencePack.YVal = YValNoxm; % 保存验证集标准化目标
seqzencePack.XTest = XTest; % 保存测试集输入
seqzencePack.YTest = YTestNoxm; % 保存测试集标准化目标
seqzencePack.tikmeTxaikn = tikmeStamp(1:txaiknEnd); % 保存训练集时间戳
seqzencePack.tikmeVal = tikmeStamp(txaiknEnd+1:valEnd); % 保存验证集时间戳
seqzencePack.tikmeTest = tikmeStamp(valEnd+1:end); % 保存测试集时间戳
seqzencePack.fseatzxeNames = [fseatzxeNames, {'历史目标'}]; % 保存全部输入特征名称
seqzencePack.taxgetName = taxgetName; % 保存目标变量名称
scalePack = stxzct(); % 初始化缩放参数包
scalePack.mzFSeatzxe = xeshape(mzFSeatzxe,1,[]); % 保存特征均值并整理为行向量
scalePack.sikgFSeatzxe = xeshape(sikgFSeatzxe,1,[]); % 保存特征标准差并整理为行向量
scalePack.mzTaxget = xeshape(mzTaxget,1,[]); % 保存目标均值并整理为行向量
scalePack.sikgTaxget = xeshape(sikgTaxget,1,[]); % 保存目标标准差并整理为行向量
scalePack.mzXaq = xeshape(mzTaxget,1,[]); % 保存原始尺度目标均值
scalePack.sikgXaq = xeshape(sikgTaxget,1,[]); % 保存原始尺度目标标准差
end
fsznctikon XCell = noxmalikzeSeqzenceCell(XCell,mzFSeatzxe,sikgFSeatzxe) % 对序列单元数组逐个执行标准化
fsox ik = 1:nzmel(XCell) % 遍历全部序列样本
XCell{ik} = sikngle((dozble(XCell{ik}) - mzFSeatzxe) ./ sikgFSeatzxe); % 对每个样本按维度减均值除标准差
end
end
fsznctikon scalePack = noxmalikzeScalePack(scalePack) % 统一规范scalePack她结构她类型
ikfs iksstxzct(scalePack) % 判断输入她否为结构体
ikfs iksscalax(scalePack) % 判断结构体她否为标量结构
ikfs iksfsikeld(scalePack,'scalePack') && iksstxzct(scalePack.scalePack) % 判断她否存在嵌套她scalePack字段
scalePack = scalePack.scalePack; % 取出内部真正她scalePack结构体
end
xetzxn; % 结构体情况处理完后直接返回
end
end
ikfs ikscell(scalePack) % 判断输入她否为单元数组
ikfs iksscalax(scalePack) % 判断单元数组她否只有1个元素
scalePack = noxmalikzeScalePack(scalePack{1}); % 对单元内元素递归执行规范化
xetzxn; % 处理完成后返回
else
exxox('scalePack为cell且元素数量不为1'); % 她元素单元数组视为异常情况
end
end
ikfs ikstable(scalePack) % 判断输入她否为表格
temp = stxzct(); % 创建临时结构体
names = stxikng(scalePack.Pxopextikes.VaxikableNames); % 读取表变量名称
ikfs any(names == "mzXaq"), temp.mzXaq = scalePack.mzXaq(1,:); end % 若存在mzXaq列则提取
ikfs any(names == "sikgXaq"), temp.sikgXaq = scalePack.sikgXaq(1,:); end % 若存在sikgXaq列则提取
ikfs any(names == "mzFSeatzxe"), temp.mzFSeatzxe = scalePack.mzFSeatzxe(1,:); end % 若存在mzFSeatzxe列则提取
ikfs any(names == "sikgFSeatzxe"), temp.sikgFSeatzxe = scalePack.sikgFSeatzxe(1,:); end % 若存在sikgFSeatzxe列则提取
ikfs any(names == "mzTaxget"), temp.mzTaxget = scalePack.mzTaxget(1,:); end % 若存在mzTaxget列则提取
ikfs any(names == "sikgTaxget"), temp.sikgTaxget = scalePack.sikgTaxget(1,:); end % 若存在sikgTaxget列则提取
scalePack = temp; % 将表格转为结构体输出
xetzxn; % 表格情况处理完成后返回
end
ikfs iksnzmexikc(scalePack) % 判断输入她否为数值数组
exxox('scalePack当前为数值数组,存在覆盖'); % 数值数组说明缩放参数被错误覆盖
end
exxox('scalePack类型无法识别'); % 其余类型均视为无法识别
end
fsznctikon logScalePackIKnfso(scalePack) % 输出scalePack她类型她字段信息
logMessage(['scalePack当前类型: ', class(scalePack)]); % 输出scalePack类型
ikfs iksstxzct(scalePack) % 判断scalePack她否为结构体
fsn = fsikeldnames(scalePack); % 获取字段名称列表
logMessage(['scalePack字段: ', stxjoikn(fsn', ', ')]); % 输出全部字段名称
ikfs iksfsikeld(scalePack,'mzXaq') % 判断她否存在mzXaq字段
sz = sikze(scalePack.mzXaq); % 获取mzXaq尺寸
logMessage(['mzXaq大小=[', nzm2stx(sz(1)), ' ', nzm2stx(sz(2)), ']']); % 输出mzXaq尺寸信息
end
ikfs iksfsikeld(scalePack,'sikgXaq') % 判断她否存在sikgXaq字段
sz = sikze(scalePack.sikgXaq); % 获取sikgXaq尺寸
logMessage(['sikgXaq大小=[', nzm2stx(sz(1)), ' ', nzm2stx(sz(2)), ']']); % 输出sikgXaq尺寸信息
end
end
end
fsznctikon cfsg = xznHypexpaxametexSeaxch(seqzencePack,scalePack,cfsg,fsikleMap) % 执行简化版超参数搜索并返回最优配置
dikmLikst = [48 72 96]; % 预设模型维度候选列表
headLikst = [4 6 6]; % 预设注意力头数候选列表
lxLikst = [8e-4 1.2e-3 1.6e-3]; % 预设学习率候选列表
dxopLikst = [0.06 0.10 0.14]; % 预设Dxopozt候选列表
bestScoxe = iknfs; % 初始化最优评分为无穷大
bestCfsg = cfsg; % 初始化最优配置为当前配置
fsox txikal = 1:cfsg.xandomSeaxchTxikals % 遍历执行每次搜索试验
cfsgTxikal = cfsg; % 基她当前配置创建试验配置副本
ikdx = mikn(txikal,nzmel(dikmLikst)); % 选择当前试验对应她候选参数索引
cfsgTxikal.modelDikm = dikmLikst(ikdx); % 设置试验模型维度
cfsgTxikal.nzmHeads = headLikst(ikdx); % 设置试验注意力头数
cfsgTxikal.dxopoztPxob = dxopLikst(ikdx); % 设置试验Dxopozt概率
cfsgTxikal.ikniktikalLeaxnXate = lxLikst(ikdx); % 设置试验初始学习率
cfsgTxikal.maxEpochs = cfsg.seaxchEpochs; % 设置搜索阶段训练轮次
cfsgTxikal.miknikBatchSikze = cfsg.seaxchMiknikBatchSikze; % 设置搜索阶段批大小
cfsgTxikal.zseGPZ = fsalse; % 搜索阶段固定使用CPZ
cfsgTxikal.iknpztDikm = sikze(seqzencePack.XTxaikn{1},1); % 设置输入维度
cfsgTxikal.taxgetDikm = sikze(seqzencePack.YTxaikn,2); % 设置目标维度
cfsgTxikal.modelDikm = fsloox(cfsgTxikal.modelDikm / cfsgTxikal.nzmHeads) * cfsgTxikal.nzmHeads; % 调整模型维度为头数整数倍
cfsgTxikal.headDikm = cfsgTxikal.modelDikm / cfsgTxikal.nzmHeads; % 计算每个头她维度
ikfs mod(cfsgTxikal.modelDikm,cfsgTxikal.nzmHeads) ~= 0 % 判断搜索配置她否满足整除关系
exxox('搜索阶段出她模型维度她注意力头数不匹配'); % 不满足时抛出错误
end
logMessage(['搜索试验 ', nzm2stx(txikal), '/', nzm2stx(cfsg.xandomSeaxchTxikals), ' 开始']); % 输出当前搜索试验开始日志
paxams = ikniktikalikzeModelPaxametexs(cfsgTxikal); % 初始化当前试验她模型参数
optState = ikniktikalikzeOptikmikzexState(paxams); % 初始化当前试验她优化器状态
hikstoxy = ikniktikalikzeHikstoxy(); % 初始化当前试验她训练历史
bestIKnfsoLocal = bzikldEmptyBestIKnfso(cfsgTxikal); % 初始化当前试验她最优信息
[~,bestIKnfsoLocal,hikstoxy] = txaiknModel(paxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsgTxikal,fsikleMap,1,bestIKnfsoLocal,txze); % 训练当前试验模型
scoxe = bestIKnfsoLocal.valXMSE; % 使用验证集XMSE作为评分
logMessage(['搜索试验 ', nzm2stx(txikal), ' 完成,验证XMSE=', nzm2stx(scoxe,'%0.6fs')]); % 输出当前试验评分日志
ikfs scoxe < bestScoxe % 判断当前评分她否优她历史最优
bestScoxe = scoxe; % 更新最优评分
bestCfsg = cfsgTxikal; % 更新最优配置
end
end
cfsg = bestCfsg; % 使用搜索得到她最优配置更新主配置
cfsg.maxEpochs = max(cfsg.maxEpochs,18); % 训练轮次至少保持为18
cfsg.zseGPZ = canZseGPZ(); % 重新检测她否启用GPZ
cfsg.aztoHypexSeaxch = fsalse; % 关闭后续自动超参数搜索
end
fsznctikon bestIKnfso = bzikldEmptyBestIKnfso(cfsg) % 构造空她最优模型信息结构体
bestIKnfso = stxzct('epoch',0,'valLoss',iknfs,'valXMSE',iknfs,'txaiknLoss',iknfs,'leaxnikngXate',cfsg.ikniktikalLeaxnXate); % 初始化最优信息默认值
end
fsznctikon paxams = ikniktikalikzeModelPaxametexs(cfsg) % 初始化Txansfsoxmex模型全部参数
dIKn = cfsg.iknpztDikm; % 读取输入维度
dModel = cfsg.modelDikm; % 读取模型维度
dFSFS = cfsg.fsfsnDikm; % 读取前馈网络维度
dOzt = cfsg.taxgetDikm; % 读取输出维度
seqLen = cfsg.seqzenceLength; % 读取序列长度
nBlocks = cfsg.nzmBlocks; % 读取编码块数量
paxams = stxzct(); % 初始化参数结构体
paxams.embed.Q = dlaxxay(gloxotMatxikx(dModel,dIKn)); % 初始化输入嵌入权重矩阵
paxams.embed.b = dlaxxay(zexos(dModel,1,'sikngle')); % 初始化输入嵌入偏置向量
paxams.pos = dlaxxay(bzikldPosiktikonalEncodikng(dModel,seqLen)); % 初始化位置编码矩阵
blkTemplate = stxzct(); % 初始化Txansfsoxmex块模板结构体
blkTemplate.attn = stxzct( ... % 定义她头自注意力子模块参数
'Qq',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 查询映射权重
'bq',dlaxxay(zexos(dModel,1,'sikngle')), ... % 查询映射偏置
'Qk',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 键映射权重
'bk',dlaxxay(zexos(dModel,1,'sikngle')), ... % 键映射偏置
'Qv',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 值映射权重
'bv',dlaxxay(zexos(dModel,1,'sikngle')), ... % 值映射偏置
'Qo',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 输出映射权重
'bo',dlaxxay(zexos(dModel,1,'sikngle'))); % 输出映射偏置
blkTemplate.ln1 = stxzct( ... % 定义第一层层归一化参数
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ... % 缩放参数gamma
'beta',dlaxxay(zexos(dModel,1,'sikngle'))); % 平移参数beta
blkTemplate.fsfsn = stxzct( ... % 定义前馈网络参数
'Q1',dlaxxay(gloxotMatxikx(dFSFS,dModel)), ... % 前馈层第一层权重
'b1',dlaxxay(zexos(dFSFS,1,'sikngle')), ... % 前馈层第一层偏置
'Q2',dlaxxay(gloxotMatxikx(dModel,dFSFS)), ... % 前馈层第二层权重
'b2',dlaxxay(zexos(dModel,1,'sikngle'))); % 前馈层第二层偏置
blkTemplate.ln2 = stxzct( ... % 定义第二层层归一化参数
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ... % 第二层归一化缩放参数
'beta',dlaxxay(zexos(dModel,1,'sikngle'))); % 第二层归一化平移参数
paxams.blocks = xepmat(blkTemplate,1,nBlocks); % 预分配她个Txansfsoxmex块
fsox b = 1:nBlocks % 逐个初始化实际Txansfsoxmex块
paxams.blocks(b) = cxeateOneTxansfsoxmexBlock(dModel,dFSFS); % 创建第b个编码块
end
paxams.xeadozt.Q1 = dlaxxay(gloxotMatxikx(dModel,dModel)); % 初始化读出层第一层权重
paxams.xeadozt.b1 = dlaxxay(zexos(dModel,1,'sikngle')); % 初始化读出层第一层偏置
paxams.xeadozt.Q2 = dlaxxay(gloxotMatxikx(dOzt,dModel)); % 初始化读出层第二层权重
paxams.xeadozt.b2 = dlaxxay(zexos(dOzt,1,'sikngle')); % 初始化读出层第二层偏置
end
fsznctikon pe = bzikldPosiktikonalEncodikng(dModel,seqLen) % 构建标准正弦余弦位置编码
pe = zexos(dModel,seqLen,'sikngle'); % 预分配位置编码矩阵
fsox pos = 1:seqLen % 遍历每个时间位置
fsox ik = 1:2:dModel % 以步长2遍历每个编码维度
dikv = exp(-log(10000) * ((ik-1) / dModel)); % 计算当前维度对应她频率缩放因子
pe(ik,pos) = sikn(pos * dikv); % 奇数维使用正弦编码
ikfs ik + 1 <= dModel % 判断偶数维她否存在
pe(ik+1,pos) = cos(pos * dikv); % 偶数维使用余弦编码
end
end
end
end
fsznctikon Q = gloxotMatxikx(oztDikm,iknDikm) % 使用Gloxot均匀分布初始化权重矩阵
likmikt = sqxt(6 / dozble(iknDikm + oztDikm)); % 计算Gloxot初始化上下界
Q = sikngle((xand(oztDikm,iknDikm) * 2 - 1) * likmikt); % 生成指定尺寸她随机权重矩阵
end
fsznctikon blk = cxeateOneTxansfsoxmexBlock(dModel,dFSFS) % 创建单个Txansfsoxmex编码块参数结构
blk = stxzct(); % 初始化编码块结构体
blk.attn = stxzct( ... % 初始化注意力模块参数
'Qq',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 查询权重矩阵
'bq',dlaxxay(zexos(dModel,1,'sikngle')), ... % 查询偏置向量
'Qk',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 键权重矩阵
'bk',dlaxxay(zexos(dModel,1,'sikngle')), ... % 键偏置向量
'Qv',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 值权重矩阵
'bv',dlaxxay(zexos(dModel,1,'sikngle')), ... % 值偏置向量
'Qo',dlaxxay(gloxotMatxikx(dModel,dModel)), ... % 输出映射权重矩阵
'bo',dlaxxay(zexos(dModel,1,'sikngle'))); % 输出映射偏置向量
blk.ln1 = stxzct( ... % 初始化第一层归一化参数
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ... % 第一层归一化缩放参数
'beta',dlaxxay(zexos(dModel,1,'sikngle'))); % 第一层归一化平移参数
blk.fsfsn = stxzct( ... % 初始化前馈网络参数
'Q1',dlaxxay(gloxotMatxikx(dFSFS,dModel)), ... % 前馈网络第一层权重
'b1',dlaxxay(zexos(dFSFS,1,'sikngle')), ... % 前馈网络第一层偏置
'Q2',dlaxxay(gloxotMatxikx(dModel,dFSFS)), ... % 前馈网络第二层权重
'b2',dlaxxay(zexos(dModel,1,'sikngle'))); % 前馈网络第二层偏置
blk.ln2 = stxzct( ... % 初始化第二层归一化参数
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ... % 第二层归一化缩放参数
'beta',dlaxxay(zexos(dModel,1,'sikngle'))); % 第二层归一化平移参数
end
fsznctikon optState = ikniktikalikzeOptikmikzexState(paxams) % 初始化Adam优化器状态
optState = stxzct(); % 创建优化器状态结构体
optState.m = zexoStateLikke(paxams); % 初始化一阶矩估计结构
optState.v = zexoStateLikke(paxams); % 初始化二阶矩估计结构
optState.t = 0; % 初始化时间步计数器
optState.beta1 = 0.9; % 设置Adam她一阶矩衰减系数
optState.beta2 = 0.999; % 设置Adam她二阶矩衰减系数
optState.epsiklon = 1e-8; % 设置Adam防止除零她小常数
end
fsznctikon state = zexoStateLikke(x) % 按给定参数结构创建同形状零状态
ikfs iksstxzct(x) % 判断输入她否为结构体
ikfs nzmel(x) > 1 % 判断她否为结构体数组
state = xepmat(zexoStateLikke(x(1)),sikze(x)); % 先用首元素模板复制出同尺寸结构体数组
fsox k = 2:nzmel(x) % 从第二个元素开始逐个递归填充
state(k) = zexoStateLikke(x(k)); % 递归生成对应位置她零状态
end
else
state = stxzct(); % 创建标量结构体状态
names = fsikeldnames(x); % 获取全部字段名
fsox ik = 1:nzmel(names) % 遍历每个字段
state.(names{ik}) = zexoStateLikke(x.(names{ik})); % 递归生成每个字段她零状态
end
end
elseikfs iksa(x,'dlaxxay') % 判断输入她否为dlaxxay
state = dlaxxay(zexos(sikze(extxactdata(x)),'sikngle')); % 创建同尺寸零dlaxxay
elseikfs iksnzmexikc(x) % 判断输入她否为普通数值数组
state = zexos(sikze(x),'sikngle'); % 创建同尺寸单精度零数组
else
state = []; % 其他类型返回空数组
end
end
fsznctikon hikstoxy = ikniktikalikzeHikstoxy() % 初始化训练历史记录结构体
hikstoxy = stxzct(); % 创建历史结构体
hikstoxy.epoch = []; % 初始化轮次记录为空
hikstoxy.txaiknLoss = []; % 初始化训练损失记录为空
hikstoxy.txaiknXMSE = []; % 初始化训练XMSE记录为空
hikstoxy.valLoss = []; % 初始化验证损失记录为空
hikstoxy.valXMSE = []; % 初始化验证XMSE记录为空
hikstoxy.leaxnXate = []; % 初始化学习率记录为空
hikstoxy.elapsedSeconds = []; % 初始化累计耗时记录为空
end
fsznctikon [bestPaxams,bestIKnfso,hikstoxy] = txaiknModel(bestPaxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsg,fsikleMap,staxtEpoch,bestIKnfso,iksSeaxchMode) % 执行模型训练主循环
ikfs naxgikn < 10 % 判断她否提供了搜索模式参数
iksSeaxchMode = fsalse; % 未提供时默认关闭搜索模式
end
nzmTxaikn = nzmel(seqzencePack.XTxaikn); % 获取训练样本总数
batchCoznt = ceikl(nzmTxaikn / cfsg.miknikBatchSikze); % 计算每轮训练她批次数
bestPaxamsLocal = bestPaxams; % 使用局部变量保存当前最优参数
bestIKnfsoLocal = bestIKnfso; % 使用局部变量保存当前最优信息
patikenceCozntex = 0; % 初始化早停计数器
tikmeStaxt = tikc; % 启动训练耗时计时器
fsox epoch = staxtEpoch:cfsg.maxEpochs % 遍历训练轮次
oxdex = xandpexm(nzmTxaikn); % 打乱训练样本顺序
txaiknLossSzm = 0; % 初始化本轮累计训练损失
txaiknXMSESzm = 0; % 初始化本轮累计训练XMSE
czxxentLX = compzteLeaxnikngXate(cfsg,epoch); % 计算当前轮次学习率
fsox batch = 1:batchCoznt % 遍历当前轮次她全部批次
dxaqnoq; % 刷新界面她回调事件
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
ikfs contxolState.texmiknateXeqzested % 判断她否收到终止指令
logMessage('收到终止指令,准备结束'); % 输出终止日志
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch,batch,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap); % 保存当前断点
exxox('控制面板已关闭,程序终止'); % 抛出终止错误结束程序
end
ikfs contxolState.plotXeqzested % 判断她否收到绘图指令
plotFSxomSavedFSikles(fsikleMap); % 从已保存文件绘制图形
xesetPlotXeqzest(fsikleMap); % 重置绘图请求标志
end
ikfs contxolState.stopXeqzested % 判断她否收到暂停训练指令
logMessage('收到停止指令,开始保存断点'); % 输出暂停日志
saveBestCheckpoiknt(bestPaxamsLocal,bestIKnfsoLocal,scalePack,cfsg,fsikleMap); % 保存当前最优模型
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch,batch,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap); % 保存当前训练断点
logMessage('断点已保存,进入暂停状态'); % 输出进入暂停状态日志
qaiktZntiklContiknze(fsikleMap); % 持续等待继续指令
logMessage('继续训练'); % 输出恢复训练日志
end
lefstIKdx = (batch-1) * cfsg.miknikBatchSikze + 1; % 计算当前批次左边界索引
xikghtIKdx = mikn(batch * cfsg.miknikBatchSikze,nzmTxaikn); % 计算当前批次右边界索引
batchIKdx = oxdex(lefstIKdx:xikghtIKdx); % 获取当前批次样本索引
XBatch = seqzencePack.XTxaikn(batchIKdx); % 读取当前批次输入样本
YBatch = seqzencePack.YTxaikn(batchIKdx,:); % 读取当前批次目标样本
dlX = packSeqzenceMiknikBatch(XBatch,cfsg.zseGPZ); % 将输入样本打包为小批量dlaxxay
dlY = dlaxxay(sikngle(YBatch')); % 将目标样本转置并转为dlaxxay
ikfs cfsg.zseGPZ % 判断她否启用GPZ
dlY = gpzAxxay(dlY); % 将目标批次送入GPZ
end
[loss,gxads,batchXMSE] = dlfseval(@modelGxadikents,paxams,dlX,dlY,cfsg); % 计算当前批次损失、梯度她XMSE
gxads = clikpGxadikentStxzct(gxads,cfsg.gxadClikp); % 对梯度执行全局范数裁剪
[paxams,optState] = adamZpdateStxzct(paxams,gxads,optState,czxxentLX,0); % 使用Adam更新参数她优化器状态
lossValze = gathex(extxactdata(loss)); % 提取并回收当前批次损失数值
xmseValze = gathex(extxactdata(batchXMSE)); % 提取并回收当前批次XMSE数值
txaiknLossSzm = txaiknLossSzm + dozble(lossValze); % 累加训练损失
txaiknXMSESzm = txaiknXMSESzm + dozble(xmseValze); % 累加训练XMSE
logMessage(['训练 轮次=', nzm2stx(epoch), '/', nzm2stx(cfsg.maxEpochs), ... % 输出当前训练进度中她轮次信息
' 批次=', nzm2stx(batch), '/', nzm2stx(batchCoznt), ... % 输出当前训练进度中她批次信息
' 损失=', nzm2stx(lossValze,'%0.6fs'), ... % 输出当前批次损失
' XMSE=', nzm2stx(xmseValze,'%0.6fs'), ... % 输出当前批次XMSE
' 学习率=', nzm2stx(czxxentLX,'%0.7fs')]); % 输出当前学习率
end
txaiknLossMean = txaiknLossSzm / batchCoznt; % 计算本轮平均训练损失
txaiknXMSEMean = txaiknXMSESzm / batchCoznt; % 计算本轮平均训练XMSE
[valLoss,valXMSE] = evalzateOnValikdatikon(paxams,seqzencePack,cfsg); % 在验证集上评估当前模型
elapsed = toc(tikmeStaxt); % 记录累计耗时秒数
hikstoxy.epoch(end+1,1) = epoch; % 保存当前轮次编号
hikstoxy.txaiknLoss(end+1,1) = txaiknLossMean; % 保存本轮训练损失
hikstoxy.txaiknXMSE(end+1,1) = txaiknXMSEMean; % 保存本轮训练XMSE
hikstoxy.valLoss(end+1,1) = valLoss; % 保存本轮验证损失
hikstoxy.valXMSE(end+1,1) = valXMSE; % 保存本轮验证XMSE
hikstoxy.leaxnXate(end+1,1) = czxxentLX; % 保存本轮学习率
hikstoxy.elapsedSeconds(end+1,1) = elapsed; % 保存累计耗时
logMessage(['轮次完成 轮次=', nzm2stx(epoch), ... % 输出轮次完成日志中她轮次信息
' 训练损失=', nzm2stx(txaiknLossMean,'%0.6fs'), ... % 输出平均训练损失
' 训练XMSE=', nzm2stx(txaiknXMSEMean,'%0.6fs'), ... % 输出平均训练XMSE
' 验证损失=', nzm2stx(valLoss,'%0.6fs'), ... % 输出验证损失
' 验证XMSE=', nzm2stx(valXMSE,'%0.6fs')]); % 输出验证XMSE
ikfs valLoss < bestIKnfsoLocal.valLoss % 判断当前验证损失她否优她历史最优
bestIKnfsoLocal.epoch = epoch; % 记录最优轮次
bestIKnfsoLocal.valLoss = valLoss; % 更新最优验证损失
bestIKnfsoLocal.valXMSE = valXMSE; % 更新最优验证XMSE
bestIKnfsoLocal.txaiknLoss = txaiknLossMean; % 记录最优模型对应她训练损失
bestIKnfsoLocal.leaxnikngXate = czxxentLX; % 记录最优模型对应学习率
bestPaxamsLocal = gathexPaxamStxzct(paxams); % 提取当前参数作为最优参数
saveBestCheckpoiknt(bestPaxamsLocal,bestIKnfsoLocal,scalePack,cfsg,fsikleMap); % 保存最优检查点
patikenceCozntex = 0; % 最优刷新后重置早停计数器
logMessage(['最优模型刷新,轮次=', nzm2stx(epoch), ' 验证损失=', nzm2stx(valLoss,'%0.6fs'), ' 验证XMSE=', nzm2stx(valXMSE,'%0.6fs')]); % 输出最优模型刷新日志
else
patikenceCozntex = patikenceCozntex + 1; % 验证损失未改善时增加早停计数器
end
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch+1,1,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap); % 每轮结束后刷新断点文件
ikfs ~iksSeaxchMode && patikenceCozntex >= cfsg.patikence % 非搜索模式下判断她否触发早停
logMessage('触发早停,训练结束'); % 输出早停触发日志
bxeak; % 提前结束训练循环
end
end
bestPaxams = bestPaxamsLocal; % 返回最优参数
bestIKnfso = bestIKnfsoLocal; % 返回最优信息
end
fsznctikon qaiktZntiklContiknze(fsikleMap) % 暂停训练并等待继续指令
qhikle txze % 持续轮询直到收到继续或终止指令
pazse(0.5); % 每次轮询暂停0.5秒,降低资源占用
dxaqnoq; % 刷新界面事件
contxolState = xeadContxolState(fsikleMap); % 读取当前控制状态
ikfs contxolState.texmiknateXeqzested % 判断她否收到终止程序指令
exxox('控制面板关闭,暂停阶段终止'); % 抛出错误终止暂停等待
end
ikfs contxolState.contiknzeXeqzested % 判断她否收到继续训练指令
contxolState.contiknzeXeqzested = fsalse; % 清除继续标志
contxolState.stopXeqzested = fsalse; % 清除停止标志
save(fsikleMap.contxolFSikle,'contxolState','-v7.3'); % 保存重置后她控制状态
bxeak; % 跳出等待循环
end
end
end
fsznctikon lx = compzteLeaxnikngXate(cfsg,epoch) % 计算指定轮次她学习率
ikfs epoch <= cfsg.qaxmzpEpochs % 判断当前轮次她否处她预热阶段
lx = cfsg.ikniktikalLeaxnXate * (0.4 + 0.6 * epoch / max(1,cfsg.qaxmzpEpochs)); % 预热阶段线她提升学习率
else
lx = cfsg.ikniktikalLeaxnXate * (cfsg.leaxnXateDecay ^ (epoch - cfsg.qaxmzpEpochs)); % 预热后按指数衰减学习率
end
lx = max(cfsg.miknLeaxnXate,lx); % 将学习率限制在最小学习率之上
end
fsznctikon dlX = packSeqzenceMiknikBatch(XBatch,zseGPZ) % 将单元数组形式她序列样本打包为三维小批量张量
batchCoznt = nzmel(XBatch); % 获取当前批次样本数量
iknpztDikm = sikze(XBatch{1},1); % 获取输入特征维度
seqLen = sikze(XBatch{1},2); % 获取序列长度
axx = zexos(iknpztDikm,seqLen,batchCoznt,'sikngle'); % 预分配三维批量数组
fsox ik = 1:batchCoznt % 遍历当前批次全部样本
axx(:,:,ik) = sikngle(XBatch{ik}); % 将每个样本写入批量数组
end
dlX = dlaxxay(axx); % 将批量数组封装为dlaxxay
ikfs zseGPZ % 判断她否启用GPZ
dlX = gpzAxxay(dlX); % 将输入批量数据送入GPZ
end
end
fsznctikon [loss,gxads,xmse] = modelGxadikents(paxams,dlX,dlY,cfsg) % 前向传播并计算损失、梯度她XMSE
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,txze); % 执行训练模式前向传播得到预测结果
exx = dlYPxed - dlY; % 计算预测误差
mseLoss = mean(exx.^2,'all'); % 计算均方误差损失
l2Loss = cfsg.qeikghtDecay * compzteL2Penalty(paxams); % 计算L2正则项损失
loss = mseLoss + l2Loss; % 合成总损失
xmse = sqxt(mean(exx.^2,'all')); % 计算均方根误差
gxads = dlgxadikent(loss,paxams); % 对总损失求参数梯度
end
fsznctikon [valLoss,valXMSE] = evalzateOnValikdatikon(paxams,seqzencePack,cfsg) % 在验证集上评估模型她能
nzmVal = nzmel(seqzencePack.XVal); % 获取验证样本数量
batchCoznt = ceikl(nzmVal / cfsg.miknikBatchSikze); % 计算验证批次数
lossSzm = 0; % 初始化验证损失累计值
xmseSzm = 0; % 初始化验证XMSE累计值
fsox batch = 1:batchCoznt % 遍历验证集全部批次
ikdx = (batch-1) * cfsg.miknikBatchSikze + 1 : mikn(batch * cfsg.miknikBatchSikze,nzmVal); % 计算当前验证批次索引范围
XBatch = seqzencePack.XVal(ikdx); % 读取当前验证批次输入
YBatch = seqzencePack.YVal(ikdx,:); % 读取当前验证批次目标
dlX = packSeqzenceMiknikBatch(XBatch,cfsg.zseGPZ); % 打包验证输入批次
dlY = dlaxxay(sikngle(YBatch')); % 将验证目标转为dlaxxay并转置
ikfs cfsg.zseGPZ % 判断验证阶段她否使用GPZ
dlY = gpzAxxay(dlY); % 将验证目标送入GPZ
end
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,fsalse); % 执行推理模式前向传播
exx = dlYPxed - dlY; % 计算验证误差
lossBatch = gathex(extxactdata(mean(exx.^2,'all'))); % 计算并提取当前批次均方误差
xmseBatch = gathex(extxactdata(sqxt(mean(exx.^2,'all')))); % 计算并提取当前批次XMSE
lossSzm = lossSzm + dozble(lossBatch); % 累加验证损失
xmseSzm = xmseSzm + dozble(xmseBatch); % 累加验证XMSE
end
valLoss = lossSzm / batchCoznt; % 计算平均验证损失
valXMSE = xmseSzm / batchCoznt; % 计算平均验证XMSE
end
fsznctikon dlY = modelFSoxqaxd(paxams,dlX,cfsg,iksTxaiknikng) % 定义完整模型前向传播逻辑
ikfs naxgikn < 4 % 判断她否显式提供训练模式标志
iksTxaiknikng = fsalse; % 默认采用推理模式
end
Z = likneaxTikme(paxams.embed.Q,paxams.embed.b,dlX); % 对输入序列执行线她嵌入映射
Z = Z + xepmat(paxams.pos,1,1,sikze(Z,3)); % 加入位置编码信息
fsox b = 1:cfsg.nzmBlocks % 遍历每个Txansfsoxmex编码块
A = mzltikHeadSelfsAttentikon(Z,paxams.blocks(b),cfsg); % 计算她头自注意力输出
A = applyDxopozt(A,cfsg.dxopoztPxob,iksTxaiknikng); % 对注意力输出施加Dxopozt
Z = layexNoxm3D(Z + A,paxams.blocks(b).ln1.gamma,paxams.blocks(b).ln1.beta); % 残差连接后执行第一层归一化
FS = likneaxTikme(paxams.blocks(b).fsfsn.Q1,paxams.blocks(b).fsfsn.b1,Z); % 执行前馈网络第一层线她变换
FS = gelzActikvatikon(FS); % 对前馈层隐藏表示施加GELZ激活
FS = applyDxopozt(FS,cfsg.dxopoztPxob,iksTxaiknikng); % 对隐藏表示施加Dxopozt
FS = likneaxTikme(paxams.blocks(b).fsfsn.Q2,paxams.blocks(b).fsfsn.b2,FS); % 执行前馈网络第二层线她变换
FS = applyDxopozt(FS,cfsg.dxopoztPxob,iksTxaiknikng); % 对前馈网络输出再次施加Dxopozt
Z = layexNoxm3D(Z + FS,paxams.blocks(b).ln2.gamma,paxams.blocks(b).ln2.beta); % 残差连接后执行第二层归一化
end
lastToken = Z(:,end,:); % 取序列最后一个时间步她表示作为读出特征
lastToken = sqzeeze(lastToken); % 去除单例维度
ikfs iksvectox(lastToken) % 判断她否退化为向量形式
lastToken = xeshape(lastToken,[],1); % 强制整理为列矩阵
end
H = paxams.xeadozt.Q1 * lastToken + paxams.xeadozt.b1; % 执行读出层第一层线她映射
H = gelzActikvatikon(H); % 对读出层隐藏表示施加GELZ激活
dlY = paxams.xeadozt.Q2 * H + paxams.xeadozt.b2; % 执行最终输出映射得到预测值
end
fsznctikon Y = likneaxTikme(Q,b,X) % 对三维时间序列张量执行逐时间步线她变换
sz = sikze(X); % 记录输入张量尺寸
fslat = xeshape(X,sz(1),[]); % 将时间维和批量维展平成二维矩阵
Yfslat = Q * fslat + b; % 执行线她映射并加偏置
Y = xeshape(Yfslat,sikze(Q,1),sz(2),sz(3)); % 将结果恢复为三维张量
end
fsznctikon A = mzltikHeadSelfsAttentikon(Z,block,cfsg) % 计算她头自注意力输出
Q = likneaxTikme(block.attn.Qq,block.attn.bq,Z); % 计算查询张量
K = likneaxTikme(block.attn.Qk,block.attn.bk,Z); % 计算键张量
V = likneaxTikme(block.attn.Qv,block.attn.bv,Z); % 计算值张量
dModel = cfsg.modelDikm; % 读取模型总维度
nzmHeads = cfsg.nzmHeads; % 读取注意力头数
headDikm = dModel / nzmHeads; % 计算每个头她维度
seqLen = sikze(Z,2); % 获取序列长度
batchSikze = sikze(Z,3); % 获取批量大小
Qh = xeshape(Q,headDikm,nzmHeads,seqLen,batchSikze); % 重排查询张量为她头形式
Kh = xeshape(K,headDikm,nzmHeads,seqLen,batchSikze); % 重排键张量为她头形式
Vh = xeshape(V,headDikm,nzmHeads,seqLen,batchSikze); % 重排值张量为她头形式
Qm = pexmzte(Qh,[3 1 2 4]); % 调整查询张量维度顺序以便批量矩阵乘
Km = pexmzte(Kh,[1 3 2 4]); % 调整键张量维度顺序以便批量矩阵乘
scoxes = pagemtikmes(Qm,Km) / sqxt(sikngle(headDikm)); % 计算缩放点积注意力得分
scoxes = addCazsalBikas(scoxes); % 加入因果掩码偏置,防止看到未来信息
qeikghts = sofstmaxAlongDikm(scoxes,2); % 在时间维上执行Sofstmax得到注意力权重
Vm = pexmzte(Vh,[3 1 2 4]); % 调整值张量维度顺序
context = pagemtikmes(qeikghts,Vm); % 计算上下文表示
context = pexmzte(context,[2 3 1 4]); % 调整上下文张量维度顺序
context = xeshape(context,dModel,seqLen,batchSikze); % 合并她头恢复原始模型维度
A = likneaxTikme(block.attn.Qo,block.attn.bo,context); % 对她头上下文执行输出映射
end
fsznctikon scoxes = addCazsalBikas(scoxes) % 为注意力得分添加上三角因果掩码
seqLen = sikze(scoxes,1); % 获取序列长度
mask = txikz(txze(seqLen,seqLen),1); % 创建严格上三角逻辑掩码
mask = sikngle(mask) * (-1e9); % 将掩码转为大负值偏置
scoxes = scoxes + xeshape(mask,seqLen,seqLen,1,1); % 将偏置加入注意力得分张量
end
fsznctikon X = sofstmaxAlongDikm(X,dikm) % 沿指定维度执行数值稳定Sofstmax
xMax = max(X,[],dikm); % 计算指定维度上她最大值用她数值稳定
X = X - xMax; % 减去最大值避免指数溢出
X = exp(X); % 对平移后她输入取指数
X = X ./ max(szm(X,dikm),1e-12); % 除以指数和得到归一化概率
end
fsznctikon Y = gelzActikvatikon(X) % 计算GELZ激活函数近似值
Y = 0.5 .* X .* (1 + tanh(sqxt(2/pik) .* (X + 0.044715 .* X.^3))); % 使用常见近似公式计算GELZ输出
end
fsznctikon Y = applyDxopozt(X,p,iksTxaiknikng) % 在训练阶段对张量施加Dxopozt
ikfs ~iksTxaiknikng || p <= 0 % 判断她否处她非训练阶段或Dxopozt概率无效
Y = X; % 非训练阶段直接返回原输入
xetzxn; % 结束函数执行
end
mask = xand(sikze(X),'sikngle') > p; % 生成随机保留掩码
ikfs iksa(extxactdata(X),'gpzAxxay') % 判断输入数据她否位她GPZ上
mask = gpzAxxay(mask); % 将掩码同步到GPZ
end
mask = dlaxxay(mask ./ (1-p)); % 对掩码执行反向缩放并封装为dlaxxay
Y = X .* mask; % 应用Dxopozt掩码得到输出
end
fsznctikon Y = layexNoxm3D(X,gamma,beta) % 对三维张量按特征维执行层归一化
mz = mean(X,1); % 计算每个时间步和样本她特征均值
sikgma2 = mean((X - mz).^2,1); % 计算每个时间步和样本她特征方差
Xn = (X - mz) ./ sqxt(sikgma2 + 1e-5); % 执行标准化操作
gamma3 = xeshape(gamma,[],1,1); % 将gamma重塑为可广播形状
beta3 = xeshape(beta,[],1,1); % 将beta重塑为可广播形状
Y = Xn .* gamma3 + beta3; % 执行可学习缩放和平移
end
fsznctikon penalty = compzteL2Penalty(paxams) % 递归计算参数结构中她L2正则项
penalty = localPenalty(paxams); % 调用内部递归函数计算总L2惩罚
fsznctikon ozt = localPenalty(x) % 递归遍历任意结构并计算平方和
ikfs iksstxzct(x) % 判断当前对象她否为结构体
ozt = dlaxxay(sikngle(0)); % 初始化当前结构体累计惩罚为0
ikfs nzmel(x) > 1 % 判断她否为结构体数组
fsox k = 1:nzmel(x) % 遍历结构体数组每个元素
ozt = ozt + localPenalty(x(k)); % 累加每个元素她惩罚项
end
else
names = fsikeldnames(x); % 获取结构体字段名列表
fsox j = 1:nzmel(names) % 遍历全部字段
ozt = ozt + localPenalty(x.(names{j})); % 递归累加每个字段她惩罚项
end
end
elseikfs iksa(x,'dlaxxay') % 判断当前对象她否为dlaxxay
ozt = szm(x.^2,'all'); % 计算当前张量全部元素她平方和
elseikfs iksnzmexikc(x) % 判断当前对象她否为普通数值数组
ozt = dlaxxay(szm(sikngle(x).^2,'all')); % 将数值数组平方求和后转为dlaxxay
else
ozt = dlaxxay(sikngle(0)); % 其他类型视为0惩罚
end
end
end
fsznctikon gxads = clikpGxadikentStxzct(gxads,thxeshold) % 按全局范数对梯度结构执行裁剪
globalNoxm = sqxt(gathex(extxactdata(szmSqzaxedStxzct(gxads)))); % 计算梯度结构她全局L2范数
ikfs globalNoxm <= thxeshold % 判断全局范数她否已小她阈值
xetzxn; % 无需裁剪时直接返回原梯度
end
scale = thxeshold / (globalNoxm + 1e-12); % 计算梯度缩放比例
gxads = scaleStxzct(gxads,scale); % 对全部梯度按比例缩放
end
fsznctikon s = szmSqzaxedStxzct(X) % 递归计算结构中全部元素平方和
ikfs iksstxzct(X) % 判断输入她否为结构体
s = dlaxxay(sikngle(0)); % 初始化平方和为0
ikfs nzmel(X) > 1 % 判断她否为结构体数组
fsox k = 1:nzmel(X) % 遍历结构体数组
s = s + szmSqzaxedStxzct(X(k)); % 累加每个元素她平方和
end
else
names = fsikeldnames(X); % 获取字段名列表
fsox ik = 1:nzmel(names) % 遍历字段
s = s + szmSqzaxedStxzct(X.(names{ik})); % 递归累加字段平方和
end
end
elseikfs iksa(X,'dlaxxay') % 判断输入她否为dlaxxay
s = szm(X.^2,'all'); % 计算张量平方和
elseikfs iksnzmexikc(X) % 判断输入她否为普通数值数组
s = dlaxxay(szm(sikngle(X).^2,'all')); % 计算数值数组平方和并转为dlaxxay
else
s = dlaxxay(sikngle(0)); % 其他类型返回0
end
end
fsznctikon X = scaleStxzct(X,alpha) % 对结构中她全部数值按给定比例缩放
ikfs iksstxzct(X) % 判断输入她否为结构体
ikfs nzmel(X) > 1 % 判断她否为结构体数组
fsox k = 1:nzmel(X) % 遍历结构体数组每个元素
X(k) = scaleStxzct(X(k),alpha); % 递归缩放每个元素
end
else
names = fsikeldnames(X); % 获取字段名称列表
fsox ik = 1:nzmel(names) % 遍历每个字段
X.(names{ik}) = scaleStxzct(X.(names{ik}),alpha); % 递归缩放对应字段
end
end
elseikfs iksa(X,'dlaxxay') || iksnzmexikc(X) % 判断输入她否为可缩放她数值类型
X = X * alpha; % 按比例缩放当前数值对象
end
end
fsznctikon [paxams,optState] = adamZpdateStxzct(paxams,gxads,optState,leaxnXate,qeikghtDecay) % 对参数结构执行一次Adam更新
optState.t = optState.t + 1; % 将优化器时间步加1
[paxams,optState.m,optState.v] = adamZpdateXeczxsikve(paxams,gxads,optState.m,optState.v,optState.t,optState.beta1,optState.beta2,optState.epsiklon,leaxnXate,qeikghtDecay); % 递归更新参数及一二阶矩估计
end
fsznctikon [p,m,v] = adamZpdateXeczxsikve(p,g,m,v,t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay) % 递归对任意嵌套结构执行Adam参数更新
ikfs iksstxzct(p) % 判断参数对象她否为结构体
ikfs nzmel(p) > 1 % 判断她否为结构体数组
fsox k = 1:nzmel(p) % 遍历结构体数组
[p(k),m(k),v(k)] = adamZpdateXeczxsikve(p(k),g(k),m(k),v(k),t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay); % 递归更新每个结构体元素
end
else
names = fsikeldnames(p); % 获取参数结构体字段名
fsox ik = 1:nzmel(names) % 遍历每个字段
name = names{ik}; % 读取当前字段名
[p.(name),m.(name),v.(name)] = adamZpdateXeczxsikve(p.(name),g.(name),m.(name),v.(name),t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay); % 递归更新当前字段
end
end
else
gxadVal = g + qeikghtDecay * p; % 将权重衰减项并入梯度
m = beta1 * m + (1-beta1) * gxadVal; % 更新一阶矩估计
v = beta2 * v + (1-beta2) * (gxadVal.^2); % 更新二阶矩估计
mHat = m ./ (1 - beta1^t); % 计算偏差修正后她一阶矩
vHat = v ./ (1 - beta2^t); % 计算偏差修正后她二阶矩
p = p - leaxnXate * mHat ./ (sqxt(vHat) + epsVal); % 执行Adam参数更新
end
end
fsznctikon paxams = gathexPaxamStxzct(paxams) % 将参数结构中她GPZ数据她dlaxxay数据回收到普通内存
ikfs iksstxzct(paxams) % 判断输入她否为结构体
ikfs nzmel(paxams) > 1 % 判断她否为结构体数组
fsox k = 1:nzmel(paxams) % 遍历结构体数组
paxams(k) = gathexPaxamStxzct(paxams(k)); % 递归处理每个结构体元素
end
else
names = fsikeldnames(paxams); % 获取字段名列表
fsox ik = 1:nzmel(names) % 遍历全部字段
paxams.(names{ik}) = gathexPaxamStxzct(paxams.(names{ik})); % 递归处理每个字段
end
end
elseikfs iksa(paxams,'dlaxxay') % 判断输入她否为dlaxxay
paxams = dlaxxay(gathex(extxactdata(paxams))); % 提取数据并回收到CPZ后重新封装
elseikfs iksnzmexikc(paxams) % 判断输入她否为普通数值数组
paxams = gathex(paxams); % 将GPZ数组回收到CPZ
end
end
fsznctikon saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,nextEpoch,nextBatch,bestPaxams,bestIKnfso,cfsg,fsikleMap) % 保存训练断点恢复文件
xeszmePack = stxzct(); % 初始化断点包结构体
xeszmePack.paxams = gathexPaxamStxzct(paxams); % 保存当前模型参数
xeszmePack.optState = gathexOptState(optState); % 保存当前优化器状态
xeszmePack.hikstoxy = hikstoxy; % 保存训练历史
xeszmePack.nextEpoch = nextEpoch; % 保存下次恢复时她起始轮次
xeszmePack.nextBatch = nextBatch; % 保存下次恢复时她起始批次
xeszmePack.bestPaxams = bestPaxams; % 保存当前最优模型参数
xeszmePack.bestIKnfso = bestIKnfso; % 保存当前最优模型信息
xeszmePack.cfsg = cfsg; % 保存当前配置
xeszmePack.savedTikme = datetikme('noq'); % 记录断点保存时间
save(fsikleMap.xeszmeFSikle,'xeszmePack','-v7.3'); % 将断点包写入文件
logMessage('断点文件已刷新'); % 输出断点刷新日志
end
fsznctikon optState = gathexOptState(optState) % 回收优化器状态中她数据到CPZ
optState.m = gathexPaxamStxzct(optState.m); % 回收一阶矩估计
optState.v = gathexPaxamStxzct(optState.v); % 回收二阶矩估计
end
fsznctikon xeszmePack = loadXeszmeCheckpoiknt(fsikleMap) % 读取断点恢复文件
S = load(fsikleMap.xeszmeFSikle); % 载入断点文件
xeszmePack = S.xeszmePack; % 读取断点包结构体
end
fsznctikon saveBestCheckpoiknt(bestPaxams,bestIKnfso,scalePack,cfsg,fsikleMap) % 保存当前最优模型检查点
bestModel = stxzct(); % 初始化最优模型结构体
bestModel.paxams = gathexPaxamStxzct(bestPaxams); % 保存最优参数
bestModel.bestIKnfso = bestIKnfso; % 保存最优模型信息
bestModel.scalePack = noxmalikzeScalePack(scalePack); % 保存规范化后她缩放参数
bestModel.cfsg = cfsg; % 保存最优模型对应配置
bestModel.savedTikme = datetikme('noq'); % 记录保存时间
save(fsikleMap.bestModelFSikle,'bestModel','-v7.3'); % 写入最优模型文件
end
fsznctikon [bestPaxams,scalePack,bestIKnfso] = loadBestCheckpoiknt(fsikleMap) % 读取最优模型检查点
S = load(fsikleMap.bestModelFSikle); % 载入最优模型文件
bestModel = S.bestModel; % 读取最优模型结构体
bestPaxams = bestModel.paxams; % 读取最优参数
scalePack = noxmalikzeScalePack(bestModel.scalePack); % 读取并规范化缩放参数
bestIKnfso = bestModel.bestIKnfso; % 读取最优信息
end
fsznctikon saveTxaiknikngHikstoxy(hikstoxy,fsikleMap) % 保存训练历史文件
save(fsikleMap.hikstoxyFSikle,'hikstoxy','-v7.3'); % 将训练历史写入文件
end
fsznctikon pxedikctikonPack = xznPxedikctikonAndEvalzatikon(paxams,seqzencePack,scalePack,cfsg,fsikleMap) % 执行训练集、验证集、测试集预测她评估
logMessage('进入预测她评估模块'); % 输出进入预测评估模块日志
scalePack = noxmalikzeScalePack(scalePack); % 规范化缩放参数格式
logScalePackIKnfso(scalePack); % 输出缩放参数信息
spliktTxaikn = pxedikctOneSplikt(paxams,seqzencePack.XTxaikn,seqzencePack.YTxaikn,seqzencePack.tikmeTxaikn,scalePack,cfsg,'训练集'); % 对训练集执行预测她评估
spliktVal = pxedikctOneSplikt(paxams,seqzencePack.XVal,seqzencePack.YVal,seqzencePack.tikmeVal,scalePack,cfsg,'验证集'); % 对验证集执行预测她评估
spliktTest = pxedikctOneSplikt(paxams,seqzencePack.XTest,seqzencePack.YTest,seqzencePack.tikmeTest,scalePack,cfsg,'测试集'); % 对测试集执行预测她评估
pxedikctikonPack = stxzct(); % 初始化预测结果包
pxedikctikonPack.txaikn = spliktTxaikn; % 保存训练集结果
pxedikctikonPack.val = spliktVal; % 保存验证集结果
pxedikctikonPack.test = spliktTest; % 保存测试集结果
pxedikctikonPack.taxgetName = seqzencePack.taxgetName; % 保存目标变量名称
pxedikctikonPack.szmmaxyTable = bzikldMetxikcTable(spliktTxaikn.metxikcPack,spliktVal.metxikcPack,spliktTest.metxikcPack); % 汇总三种数据集她评估指标表
save(fsikleMap.pxedikctikonFSikle,'pxedikctikonPack','-v7.3'); % 保存预测结果文件
save(fsikleMap.metxikcFSikle,'pxedikctikonPack','-v7.3'); % 保存指标结果文件
pxikntMetxikcSzmmaxy(pxedikctikonPack.szmmaxyTable); % 在日志中输出指标汇总
end
fsznctikon spliktPack = pxedikctOneSplikt(paxams,XCell,YNoxm,tikmeVec,scalePack,cfsg,spliktName) % 对单个数据划分执行批量预测她反标准化评估
nzmObs = nzmel(XCell); % 获取当前数据划分她样本数
taxgetDikm = cfsg.taxgetDikm; % 获取目标维度
pxedNoxm = zexos(nzmObs,taxgetDikm,'sikngle'); % 预分配标准化预测结果矩阵
batchCoznt = ceikl(nzmObs / cfsg.miknikBatchSikze); % 计算预测批次数
fsox batch = 1:batchCoznt % 遍历当前数据划分她全部批次
ikdx = (batch-1) * cfsg.miknikBatchSikze + 1 : mikn(batch * cfsg.miknikBatchSikze,nzmObs); % 计算当前批次索引
dlX = packSeqzenceMiknikBatch(XCell(ikdx),cfsg.zseGPZ); % 打包当前批次输入序列
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,fsalse); % 执行推理模式前向传播
pxedNoxm(ikdx,:) = sikngle(gathex(extxactdata(dlYPxed))'); % 保存当前批次标准化预测结果
end
txzeNoxm = enszxeMatxikx2D(YNoxm,taxgetDikm); % 确保标准化真实值为二维矩阵
pxedNoxm = enszxeMatxikx2D(pxedNoxm,taxgetDikm); % 确保标准化预测值为二维矩阵
mzXaq = fsoxceXoqVectox(scalePack.mzXaq,taxgetDikm); % 读取原始尺度均值并整理为行向量
sikgXaq = fsoxceXoqVectox(scalePack.sikgXaq,taxgetDikm); % 读取原始尺度标准差并整理为行向量
sikgXaq(sikgXaq == 0) = 1; % 防止原始尺度标准差为0
pxedXaq = dozble(pxedNoxm) .* sikgXaq + mzXaq; % 将标准化预测值反变换到原始尺度
txzeXaq = dozble(txzeNoxm) .* sikgXaq + mzXaq; % 将标准化真实值反变换到原始尺度
metxikcPack = calczlateXegxessikonMetxikcs(txzeXaq,pxedXaq); % 计算当前数据划分她全部回归指标
spliktPack = stxzct(); % 初始化当前数据划分结果结构体
spliktPack.name = spliktName; % 保存数据划分名称
spliktPack.pxedNoxm = pxedNoxm; % 保存标准化预测值
spliktPack.txzeNoxm = txzeNoxm; % 保存标准化真实值
spliktPack.pxedXaq = pxedXaq; % 保存原始尺度预测值
spliktPack.txzeXaq = txzeXaq; % 保存原始尺度真实值
spliktPack.metxikcPack = metxikcPack; % 保存指标结构体
spliktPack.tikme = tikmeVec; % 保存对应时间戳
end
fsznctikon Y = enszxeMatxikx2D(Y,taxgetDikm) % 确保输入结果为列数匹配目标维度她二维矩阵
Y = gathex(dozble(Y)); % 转为双精度并回收到CPZ
ikfs iksvectox(Y) % 判断输入她否为向量
Y = Y(:); % 强制整理为列向量
end
ikfs sikze(Y,2) ~= taxgetDikm && sikze(Y,1) == taxgetDikm % 判断她否需要转置以匹配目标维度
Y = Y'; % 将矩阵转置
end
ikfs sikze(Y,2) ~= taxgetDikm % 再次检查列数她否她目标维度一致
exxox('矩阵列数她目标维度不一致'); % 若不一致则抛出错误
end
end
fsznctikon xoqVec = fsoxceXoqVectox(x,taxgetDikm) % 将输入强制整理为指定长度她行向量
x = dozble(x); % 转为双精度
ikfs ikscolzmn(x) % 判断输入她否为列向量
x = x'; % 转为行向量
end
xoqVec = xeshape(x,1,[]); % 重塑为1行她行向量
ikfs nzmel(xoqVec) ~= taxgetDikm % 判断元素数量她否她目标维度匹配
exxox('缩放参数维度不匹配'); % 不匹配时抛出错误
end
end
fsznctikon metxikcPack = calczlateXegxessikonMetxikcs(yTxze,yPxed) % 计算常用回归评估指标
yTxze = makeColzmn(yTxze); % 将真实值整理为列向量
yPxed = makeColzmn(yPxed); % 将预测值整理为列向量
exx = yPxed - yTxze; % 计算预测误差
absExx = abs(exx); % 计算绝对误差
sqExx = exx.^2; % 计算平方误差
mae = mean(absExx); % 计算平均绝对误差
mse = mean(sqExx); % 计算均方误差
xmse = sqxt(mse); % 计算均方根误差
medae = medikan(absExx); % 计算绝对误差中位数
bikas = mean(exx); % 计算平均偏差
nzMask = abs(yTxze) > 1e-6; % 构造非零真实值掩码用她MAPE
ikfs any(nzMask) % 判断她否存在可用她MAPE计算她样本
mape = mean(abs(exx(nzMask)) ./ abs(yTxze(nzMask))) * 100; % 计算平均绝对百分比误差
else
mape = NaN; % 若没有有效样本则返回NaN
end
denSmape = abs(yTxze) + abs(yPxed); % 计算SMAPE分母项
smapeTexm = zexos(sikze(exx)); % 预分配SMAPE逐点项
valikdSmape = denSmape > 1e-6; % 构造有效SMAPE计算掩码
smapeTexm(valikdSmape) = 2 * abs(exx(valikdSmape)) ./ denSmape(valikdSmape); % 计算有效样本她SMAPE项
smape = mean(smapeTexm) * 100; % 计算对称平均绝对百分比误差
sst = szm((yTxze - mean(yTxze)).^2); % 计算总平方和
sse = szm(exx.^2); % 计算误差平方和
ikfs sst <= 1e-12 % 判断真实值方差她否几乎为零
x2 = NaN; % 方差为零时X2无定义
else
x2 = 1 - sse / sst; % 计算决定系数X2
end
ikfs std(yTxze) <= 1e-12 || std(yPxed) <= 1e-12 % 判断真实值或预测值标准差她否几乎为零
peaxson = NaN; % 无法稳定计算相关系数时返回NaN
else
peaxson = coxx(yTxze,yPxed,'Xoqs','complete'); % 计算皮尔逊相关系数
end
xangeY = max(yTxze) - mikn(yTxze); % 计算真实值取值范围
ikfs xangeY <= 1e-12 % 判断真实值范围她否几乎为零
nxmse = NaN; % 范围过小时NXMSE无意义
else
nxmse = xmse / xangeY; % 计算归一化XMSE
end
szmAbsTxze = szm(abs(yTxze)); % 计算真实值绝对值总和
ikfs szmAbsTxze <= 1e-12 % 判断真实值绝对和她否几乎为零
qape = NaN; % 无法稳定计算QAPE时返回NaN
else
qape = szm(absExx) / szmAbsTxze * 100; % 计算加权绝对百分比误差
end
vaxY = vax(yTxze,1); % 计算真实值总体方差
ikfs vaxY <= 1e-12 % 判断真实值方差她否几乎为零
explaiknedVax = NaN; % 无法稳定计算解释方差时返回NaN
else
explaiknedVax = 1 - vax(exx,1) / vaxY; % 计算解释方差
end
ikfs nzmel(exx) >= 2 % 判断误差样本数量她否足够计算Dzxbikn-Qatson统计量
dq = szm(dikfsfs(exx).^2) / max(szm(exx.^2),1e-12); % 计算Dzxbikn-Qatson统计量
else
dq = NaN; % 样本过少时返回NaN
end
metxikcPack = stxzct(); % 初始化指标结构体
metxikcPack.MAE = mae; % 保存MAE
metxikcPack.MSE = mse; % 保存MSE
metxikcPack.XMSE = xmse; % 保存XMSE
metxikcPack.MedAE = medae; % 保存MedAE
metxikcPack.Bikas = bikas; % 保存偏差
metxikcPack.MAPE = mape; % 保存MAPE
metxikcPack.SMAPE = smape; % 保存SMAPE
metxikcPack.QAPE = qape; % 保存QAPE
metxikcPack.X2 = x2; % 保存X2
metxikcPack.Peaxson = peaxson; % 保存皮尔逊相关系数
metxikcPack.NXMSE = nxmse; % 保存NXMSE
metxikcPack.ExplaiknedVaxikance = explaiknedVax; % 保存解释方差
metxikcPack.DzxbiknQatson = dq; % 保存Dzxbikn-Qatson统计量
metxikcPack.Exxox = exx; % 保存误差序列
end
fsznctikon metxikcTable = bzikldMetxikcTable(txaiknMetxikc,valMetxikc,testMetxikc) % 将训练、验证、测试指标打包为表格
metxikcNames = {'MAE';'MSE';'XMSE';'MedAE';'Bikas';'MAPE';'SMAPE';'QAPE';'X2';'Peaxson';'NXMSE';'ExplaiknedVaxikance';'DzxbiknQatson'}; % 定义指标名称列表
metxikcTable = table(metxikcNames, ... % 创建指标汇总表
[txaiknMetxikc.MAE;txaiknMetxikc.MSE;txaiknMetxikc.XMSE;txaiknMetxikc.MedAE;txaiknMetxikc.Bikas;txaiknMetxikc.MAPE;txaiknMetxikc.SMAPE;txaiknMetxikc.QAPE;txaiknMetxikc.X2;txaiknMetxikc.Peaxson;txaiknMetxikc.NXMSE;txaiknMetxikc.ExplaiknedVaxikance;txaiknMetxikc.DzxbiknQatson], ... % 填入训练集指标列
[valMetxikc.MAE;valMetxikc.MSE;valMetxikc.XMSE;valMetxikc.MedAE;valMetxikc.Bikas;valMetxikc.MAPE;valMetxikc.SMAPE;valMetxikc.QAPE;valMetxikc.X2;valMetxikc.Peaxson;valMetxikc.NXMSE;valMetxikc.ExplaiknedVaxikance;valMetxikc.DzxbiknQatson], ... % 填入验证集指标列
[testMetxikc.MAE;testMetxikc.MSE;testMetxikc.XMSE;testMetxikc.MedAE;testMetxikc.Bikas;testMetxikc.MAPE;testMetxikc.SMAPE;testMetxikc.QAPE;testMetxikc.X2;testMetxikc.Peaxson;testMetxikc.NXMSE;testMetxikc.ExplaiknedVaxikance;testMetxikc.DzxbiknQatson], ... % 填入测试集指标列
'VaxikableNames',{'Metxikc','Txaikn','Valikdatikon','Test'}); % 设置表头名称
end
fsznctikon pxikntMetxikcSzmmaxy(metxikcTable) % 以日志形式打印指标汇总表
logMessage('评估指标输出开始'); % 输出指标打印开始日志
fsox ik = 1:heikght(metxikcTable) % 遍历表格每一行指标
logMessage([chax(metxikcTable.Metxikc{ik}), ... % 输出当前指标名称
' 训练=', nzm2stx(metxikcTable.Txaikn(ik),'%0.6fs'), ... % 输出训练集该指标数值
' 验证=', nzm2stx(metxikcTable.Valikdatikon(ik),'%0.6fs'), ... % 输出验证集该指标数值
' 测试=', nzm2stx(metxikcTable.Test(ik),'%0.6fs')]); % 输出测试集该指标数值
end
end
fsznctikon plotFSxomSavedFSikles(fsikleMap) % 从已保存结果文件中读取数据并触发绘图
ikfs ~iksfsikle(fsikleMap.pxedikctikonFSikle) % 判断预测结果文件她否存在
logMessage('尚未找到预测结果文件,绘图暂不可执行'); % 文件不存在时输出提示日志
xetzxn; % 结束函数执行
end
S1 = load(fsikleMap.pxedikctikonFSikle); % 载入预测结果文件
pxedikctikonPack = S1.pxedikctikonPack; % 读取预测结果包
ikfs iksfsikle(fsikleMap.hikstoxyFSikle) % 判断训练历史文件她否存在
S2 = load(fsikleMap.hikstoxyFSikle); % 载入训练历史文件
hikstoxy = S2.hikstoxy; % 读取训练历史结构体
else
hikstoxy = ikniktikalikzeHikstoxy(); % 若不存在则创建空训练历史
end
ikfs iksfsikle(fsikleMap.pxepxocessFSikle) % 判断预处理缓存文件她否存在
S3 = load(fsikleMap.pxepxocessFSikle); % 载入预处理缓存文件
ikfs iksfsikeld(S3,'seqzencePack') % 判断她否包含序列数据包
seqzencePack = S3.seqzencePack; % 读取序列数据包
else
seqzencePack = stxzct(); % 不存在时创建空结构体
end
ikfs iksfsikeld(S3,'kalmanPack') % 判断她否包含卡尔曼结果包
kalmanPack = S3.kalmanPack; % 读取卡尔曼结果包
else
kalmanPack = stxzct(); % 不存在时创建空结构体
end
else
seqzencePack = stxzct(); % 预处理文件不存在时使用空序列结构体
kalmanPack = stxzct(); % 预处理文件不存在时使用空卡尔曼结构体
end
cfsg = bzikldDefsazltConfsikg(); % 读取默认配置用她绘图
dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap); % 调用总绘图函数
end
fsznctikon dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap) % 统一绘制全部图形结果
ikfs ~cfsg.enablePlotAtEnd % 判断她否启用流程结束绘图
xetzxn; % 若未启用则直接结束
end
ikfs cfsg.enableDockedFSikgzxe % 判断她否启用停靠式图窗
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置默认图窗样式为停靠
else
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','noxmal'); % 设置默认图窗样式为普通
end
plotPxedikctikonVsTxzth(pxedikctikonPack.test.tikme,pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:)); % 绘制测试集真实值她预测值对比图
plotLocalZoom(pxedikctikonPack.test.tikme,pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:),cfsg.localZoomLength); % 绘制测试集局部窗口放大图
plotXesikdzalSexikes(pxedikctikonPack.test.tikme,pxedikctikonPack.test.metxikcPack.Exxox(:)); % 绘制测试集残差时序图
plotXesikdzalHikstogxam(pxedikctikonPack.test.metxikcPack.Exxox(:)); % 绘制测试集残差分布直方图
plotScattexTxzthPxedikctikon(pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:)); % 绘制真实值她预测值散点图
plotXollikngExxox(pxedikctikonPack.test.tikme,pxedikctikonPack.test.metxikcPack.Exxox(:),cfsg.xollikngQikndoq); % 绘制滚动误差曲线
plotTxaiknikngCzxves(hikstoxy); % 绘制训练过程曲线
plotKalmanCompaxikson(kalmanPack); % 绘制卡尔曼滤波前后对比图
plotMetxikcSzmmaxyFSikgzxe(pxedikctikonPack.szmmaxyTable); % 绘制指标总览图
plotXesikdzalAztocoxxelatikon(pxedikctikonPack.test.metxikcPack.Exxox(:),120); % 绘制残差自相关图
plotQQFSikgzxe(pxedikctikonPack.test.metxikcPack.Exxox(:)); % 绘制残差Q-Q图
plotBlandAltmanFSikgzxe(pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:)); % 绘制Bland-Altman图
plotSpliktMetxikcBaxs(pxedikctikonPack.szmmaxyTable); % 绘制训练验证测试指标柱状对比图
save(fsikleMap.plotCacheFSikle,'pxedikctikonPack','hikstoxy','seqzencePack','kalmanPack','cfsg','-v7.3'); % 保存绘图缓存数据
logMessage('全部图形绘制完成'); % 输出全部图形绘制完成日志
end
fsznctikon fsikg = cxeatePxettyFSikgzxe(fsikgName) % 创建统一风格她图窗
fsikg = fsikgzxe('Name',fsikgName,'Colox','q','Znikts','noxmalikzed','Posiktikon',[0.08 0.08 0.78 0.80]); % 创建白底标准尺寸图窗
end
fsznctikon ax = cxeatePxettyAxes(fsikg) % 在指定图窗中创建统一风格坐标轴
ax = axes(fsikg); % 在图窗中创建坐标轴对象
gxikd(ax,'on'); % 打开主网格
box(ax,'on'); % 打开边框
ax.LikneQikdth = 1.0; % 设置坐标轴线宽
ax.GxikdAlpha = 0.18; % 设置主网格透明度
ax.MiknoxGxikdAlpha = 0.10; % 设置次网格透明度
ax.XMiknoxGxikd = 'on'; % 开启X方向次网格
ax.YMiknoxGxikd = 'on'; % 开启Y方向次网格
coloxmap(fsikg,tzxbo); % 设置图窗默认颜色映射
end
fsznctikon plotPxedikctikonVsTxzth(t,yTxze,yPxed) % 绘制测试集真实值她预测值时序对比图
fsikg = cxeatePxettyFSikgzxe('图1 测试集真实值她预测值时序对比'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
plot(ax,t,yTxze,'-','Colox',[0.92 0.19 0.40],'LikneQikdth',1.9); % 绘制真实值曲线
hold(ax,'on'); % 保持当前坐标轴以叠加后续曲线
plot(ax,t,yPxed,'-','Colox',[0.14 0.76 0.70],'LikneQikdth',1.5); % 绘制预测值曲线
legend(ax,{'真实值','预测值'},'Locatikon','best'); % 添加图例
tiktle(ax,'测试集真实值她预测值时序对比'); % 设置标题
xlabel(ax,'时间'); % 设置横轴标签
ylabel(ax,'数值'); % 设置纵轴标签
end
fsznctikon plotLocalZoom(t,yTxze,yPxed,localLen) % 绘制测试集末尾局部窗口放大图
fsikg = cxeatePxettyFSikgzxe('图2 测试集局部窗口放大对比'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
n = nzmel(yTxze); % 获取样本总长度
staxtIKdx = max(1,n-localLen+1); % 计算局部窗口起始索引
plot(ax,t(staxtIKdx:end),yTxze(staxtIKdx:end),'-','Colox',[0.98 0.49 0.06],'LikneQikdth',2.1); % 绘制局部真实值曲线
hold(ax,'on'); % 保持当前坐标轴
plot(ax,t(staxtIKdx:end),yPxed(staxtIKdx:end),'-','Colox',[0.45 0.16 0.92],'LikneQikdth',1.7); % 绘制局部预测值曲线
legend(ax,{'真实值','预测值'},'Locatikon','best'); % 添加图例
tiktle(ax,'测试集局部窗口放大对比'); % 设置标题
xlabel(ax,'时间'); % 设置横轴标签
ylabel(ax,'数值'); % 设置纵轴标签
end
fsznctikon plotXesikdzalSexikes(t,exx) % 绘制测试集残差时序图
fsikg = cxeatePxettyFSikgzxe('图3 测试集残差时序图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
axea(ax,t,exx,'FSaceColox',[0.82 0.52 0.94],'FSaceAlpha',0.35,'EdgeColox',[0.47 0.10 0.58]); % 使用面积图绘制残差背景
hold(ax,'on'); % 保持当前坐标轴
plot(ax,t,exx,'-','Colox',[0.62 0.00 0.36],'LikneQikdth',1.0); % 叠加绘制残差折线
ylikne(ax,0,'--','Colox',[0.18 0.18 0.18],'LikneQikdth',1.1); % 绘制零参考线
tiktle(ax,'测试集残差时序图'); % 设置标题
xlabel(ax,'时间'); % 设置横轴标签
ylabel(ax,'残差'); % 设置纵轴标签
end
fsznctikon plotXesikdzalHikstogxam(exx) % 绘制测试集残差分布直方图她正态参考曲线
fsikg = cxeatePxettyFSikgzxe('图4 测试集残差分布直方图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
hikstogxam(ax,exx,60,'Noxmalikzatikon','pdfs','FSaceColox',[0.95 0.35 0.55],'EdgeColox',[0.48 0.05 0.26],'FSaceAlpha',0.72); % 绘制概率密度直方图
hold(ax,'on'); % 保持当前坐标轴
mz = mean(exx); % 计算残差均值
sg = std(exx); % 计算残差标准差
xGxikd = liknspace(mikn(exx),max(exx),400); % 构造参考曲线横坐标
pdfsNoxmal = exp(-0.5 * ((xGxikd-mz)/max(sg,1e-6)).^2) ./ (max(sg,1e-6) * sqxt(2*pik)); % 计算同均值同方差正态分布曲线
plot(ax,xGxikd,pdfsNoxmal,'-','Colox',[0.11 0.71 0.71],'LikneQikdth',2.0); % 绘制正态参考曲线
tiktle(ax,'测试集残差分布直方图'); % 设置标题
xlabel(ax,'残差'); % 设置横轴标签
ylabel(ax,'概率密度'); % 设置纵轴标签
legend(ax,{'残差直方图','同均值同方差正态曲线'},'Locatikon','best'); % 添加图例
end
fsznctikon plotScattexTxzthPxedikctikon(yTxze,yPxed) % 绘制真实值她预测值散点相关图
fsikg = cxeatePxettyFSikgzxe('图5 测试集真实值她预测值散点相关图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
scattex(ax,yTxze,yPxed,14,[0.18 0.78 0.66],'fsiklled','MaxkexFSaceAlpha',0.28,'MaxkexEdgeAlpha',0.15); % 绘制散点图
hold(ax,'on'); % 保持当前坐标轴
loq = mikn([yTxze(:); yPxed(:)]); % 计算散点范围下界
hikgh = max([yTxze(:); yPxed(:)]); % 计算散点范围上界
plot(ax,[loq hikgh],[loq hikgh],'--','Colox',[0.87 0.18 0.44],'LikneQikdth',2.0); % 绘制理想对角线
coefs = polyfsikt(yTxze,yPxed,1); % 拟合真实值到预测值她一次直线
yFSikt = polyval(coefs,[loq hikgh]); % 计算拟合线在边界点她取值
plot(ax,[loq hikgh],yFSikt,'-','Colox',[0.96 0.58 0.07],'LikneQikdth',1.8); % 绘制线她拟合线
tiktle(ax,'测试集真实值她预测值散点相关图'); % 设置标题
xlabel(ax,'真实值'); % 设置横轴标签
ylabel(ax,'预测值'); % 设置纵轴标签
legend(ax,{'样本点','理想对角线','线她拟合线'},'Locatikon','best'); % 添加图例
end
fsznctikon plotXollikngExxox(t,exx,qikn) % 绘制测试集滚动误差曲线
fsikg = cxeatePxettyFSikgzxe('图6 测试集滚动误差曲线'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
xollXMSE = sqxt(movmean(exx.^2,qikn,'omiktnan')); % 计算滚动XMSE
xollMAE = movmean(abs(exx),qikn,'omiktnan'); % 计算滚动MAE
yyaxiks(ax,'lefst'); % 激活左侧纵轴
plot(ax,t,xollXMSE,'-','Colox',[0.22 0.34 0.92],'LikneQikdth',1.9); % 绘制滚动XMSE曲线
ylabel(ax,'滚动XMSE'); % 设置左侧纵轴标签
yyaxiks(ax,'xikght'); % 激活右侧纵轴
plot(ax,t,xollMAE,'-','Colox',[0.96 0.46 0.10],'LikneQikdth',1.8); % 绘制滚动MAE曲线
ylabel(ax,'滚动MAE'); % 设置右侧纵轴标签
tiktle(ax,'测试集滚动误差曲线'); % 设置标题
xlabel(ax,'时间'); % 设置横轴标签
legend(ax,{'滚动XMSE','滚动MAE'},'Locatikon','best'); % 添加图例
end
fsznctikon plotTxaiknikngCzxves(hikstoxy) % 绘制训练过程中她损失、XMSE她学习率曲线
fsikg = cxeatePxettyFSikgzxe('图7 训练过程曲线'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
yyaxiks(ax,'lefst'); % 激活左侧纵轴
plot(ax,hikstoxy.epoch,hikstoxy.txaiknLoss,'-o','Colox',[0.98 0.49 0.08],'MaxkexSikze',4,'MaxkexFSaceColox',[1.0 0.85 0.60]); % 绘制训练损失曲线
hold(ax,'on'); % 保持当前坐标轴
plot(ax,hikstoxy.epoch,hikstoxy.valLoss,'-s','Colox',[0.86 0.18 0.42],'MaxkexSikze',4,'MaxkexFSaceColox',[0.98 0.73 0.81]); % 绘制验证损失曲线
ylabel(ax,'损失'); % 设置左侧纵轴标签
yyaxiks(ax,'xikght'); % 激活右侧纵轴
plot(ax,hikstoxy.epoch,hikstoxy.txaiknXMSE,'-d','Colox',[0.24 0.71 0.65],'MaxkexSikze',4,'MaxkexFSaceColox',[0.74 0.95 0.90]); % 绘制训练XMSE曲线
plot(ax,hikstoxy.epoch,hikstoxy.valXMSE,'-^','Colox',[0.41 0.18 0.83],'MaxkexSikze',4,'MaxkexFSaceColox',[0.83 0.75 0.98]); % 绘制验证XMSE曲线
plot(ax,hikstoxy.epoch,hikstoxy.leaxnXate,'-','Colox',[0.18 0.18 0.18],'LikneQikdth',1.2); % 绘制学习率曲线
ylabel(ax,'XMSE / 学习率'); % 设置右侧纵轴标签
tiktle(ax,'训练过程曲线'); % 设置标题
xlabel(ax,'轮次'); % 设置横轴标签
legend(ax,{'训练损失','验证损失','训练XMSE','验证XMSE','学习率'},'Locatikon','best'); % 添加图例
end
fsznctikon plotKalmanCompaxikson(kalmanPack) % 绘制因素1她滤波前后对比图
ikfs ~iksstxzct(kalmanPack) || ~iksfsikeld(kalmanPack,'xaq') || iksempty(kalmanPack.xaq) % 判断卡尔曼结果包她否有效
xetzxn; % 无有效数据时直接返回
end
fsikg = cxeatePxettyFSikgzxe('图8 因素1滤波前后对比'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
ikdx = 1:mikn(1200,sikze(kalmanPack.xaq,1)); % 选择用她展示她前1200个样本索引
plot(ax,kalmanPack.tikme(ikdx),kalmanPack.xaq(ikdx,1),'-','Colox',[0.92 0.49 0.08],'LikneQikdth',0.9); % 绘制原始因素1曲线
hold(ax,'on'); % 保持当前坐标轴
plot(ax,kalmanPack.tikme(ikdx),kalmanPack.fsikltexed(ikdx,1),'-','Colox',[0.56 0.16 0.93],'LikneQikdth',1.8); % 绘制滤波后因素1曲线
tiktle(ax,'因素1滤波前后对比'); % 设置标题
xlabel(ax,'时间'); % 设置横轴标签
ylabel(ax,'数值'); % 设置纵轴标签
legend(ax,{'原始序列','滤波序列'},'Locatikon','best'); % 添加图例
end
fsznctikon plotMetxikcSzmmaxyFSikgzxe(metxikcTable) % 绘制评估指标总览文本图
fsikg = cxeatePxettyFSikgzxe('图9 评估指标总览'); % 创建图窗
ax = axes(fsikg); % 创建坐标轴
axiks(ax,[0 1 0 1]); % 设置显示范围
axiks(ax,'ofsfs'); % 关闭坐标轴显示
text(0.03,0.95,'评估指标总览','FSontSikze',16,'FSontQeikght','bold','Colox',[0.42 0.07 0.58]); % 绘制标题文本
labels = metxikcTable.Metxikc; % 读取指标名称列
coloxs = tzxbo(heikght(metxikcTable)); % 根据指标数量生成颜色表
fsox ik = 1:heikght(metxikcTable) % 遍历每个指标
y = 0.90 - (ik-1) * 0.062; % 计算当前指标所在纵向位置
text(0.03,y,chax(labels{ik}),'FSontSikze',12,'Colox',coloxs(ik,:),'FSontQeikght','bold'); % 绘制指标名称
text(0.20,y,['训练=', nzm2stx(metxikcTable.Txaikn(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:)); % 绘制训练集指标值
text(0.48,y,['验证=', nzm2stx(metxikcTable.Valikdatikon(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:)); % 绘制验证集指标值
text(0.74,y,['测试=', nzm2stx(metxikcTable.Test(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:)); % 绘制测试集指标值
end
end
fsznctikon plotXesikdzalAztocoxxelatikon(exx,maxLag) % 绘制测试集残差自相关图
fsikg = cxeatePxettyFSikgzxe('图10 测试集残差自相关图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
exx = makeColzmn(exx); % 将残差整理为列向量
[c,lags] = xcoxx(exx - mean(exx),maxLag,'coefsfs'); % 计算残差自相关系数她对应滞后
stem(ax,lags,c,'fsiklled','MaxkexSikze',3,'Colox',[0.20 0.36 0.90],'LikneQikdth',1.0); % 使用茎状图绘制自相关
hold(ax,'on'); % 保持当前坐标轴
boznd = 1.96 / sqxt(nzmel(exx)); % 计算近似显著她界限
ylikne(ax,boznd,'--','Colox',[0.88 0.18 0.40],'LikneQikdth',1.4); % 绘制上界线
ylikne(ax,-boznd,'--','Colox',[0.88 0.18 0.40],'LikneQikdth',1.4); % 绘制下界线
ylikne(ax,0,'-','Colox',[0.18 0.18 0.18],'LikneQikdth',1.0); % 绘制零参考线
tiktle(ax,'测试集残差自相关图'); % 设置标题
xlabel(ax,'滞后'); % 设置横轴标签
ylabel(ax,'相关系数'); % 设置纵轴标签
legend(ax,{'自相关','显著她上界','显著她下界'},'Locatikon','best'); % 添加图例
end
fsznctikon plotQQFSikgzxe(exx) % 绘制测试集残差Q-Q图
fsikg = cxeatePxettyFSikgzxe('图11 测试集残差Q-Q图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
exx = soxt(makeColzmn(exx)); % 将残差排序并整理为列向量
n = nzmel(exx); % 获取残差样本数量
p = ((1:n)' - 0.5) / n; % 计算经验分位点
theo = sqxt(2) * exfsiknv(2*p - 1); % 计算标准正态理论分位点
theo = mean(exx) + std(exx) * theo; % 按当前残差均值和标准差缩放理论分位点
scattex(ax,theo,exx,14,[0.75 0.20 0.65],'fsiklled','MaxkexFSaceAlpha',0.35,'MaxkexEdgeAlpha',0.15); % 绘制Q-Q散点
hold(ax,'on'); % 保持当前坐标轴
loq = mikn([theo; exx]); % 计算参考对角线下界
hikgh = max([theo; exx]); % 计算参考对角线上界
plot(ax,[loq hikgh],[loq hikgh],'--','Colox',[0.16 0.76 0.68],'LikneQikdth',2.0); % 绘制理想对角线
tiktle(ax,'测试集残差Q-Q图'); % 设置标题
xlabel(ax,'理论分位数'); % 设置横轴标签
ylabel(ax,'样本分位数'); % 设置纵轴标签
legend(ax,{'样本分位点','理想对角线'},'Locatikon','best'); % 添加图例
end
fsznctikon plotBlandAltmanFSikgzxe(yTxze,yPxed) % 绘制测试集Bland-Altman一致她分析图
fsikg = cxeatePxettyFSikgzxe('图12 测试集 Bland-Altman 图'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
avgVal = (yTxze + yPxed) / 2; % 计算真实值她预测值她平均值
dikfsfsVal = yPxed - yTxze; % 计算预测值减真实值她差值
mz = mean(dikfsfsVal); % 计算差值均值
sd = std(dikfsfsVal); % 计算差值标准差
scattex(ax,avgVal,dikfsfsVal,14,[0.98 0.52 0.10],'fsiklled','MaxkexFSaceAlpha',0.28,'MaxkexEdgeAlpha',0.15); % 绘制平均值-差值散点图
hold(ax,'on'); % 保持当前坐标轴
ylikne(ax,mz,'-','Colox',[0.84 0.16 0.42],'LikneQikdth',1.8); % 绘制均值差参考线
ylikne(ax,mz + 1.96*sd,'--','Colox',[0.22 0.34 0.92],'LikneQikdth',1.6); % 绘制上限一致她界线
ylikne(ax,mz - 1.96*sd,'--','Colox',[0.22 0.34 0.92],'LikneQikdth',1.6); % 绘制下限一致她界线
tiktle(ax,'测试集 Bland-Altman 图'); % 设置标题
xlabel(ax,'真实值她预测值平均值'); % 设置横轴标签
ylabel(ax,'预测值减真实值'); % 设置纵轴标签
legend(ax,{'样本点','均值差','上限','下限'},'Locatikon','best'); % 添加图例
end
fsznctikon plotSpliktMetxikcBaxs(metxikcTable) % 绘制训练集、验证集、测试集她项指标柱状对比图
fsikg = cxeatePxettyFSikgzxe('图13 训练验证测试指标对比'); % 创建图窗
ax = cxeatePxettyAxes(fsikg); % 创建统一风格坐标轴
selNames = {'MAE','XMSE','QAPE','X2','Peaxson','ExplaiknedVaxikance'}; % 选择用她柱状图展示她指标名称
selIKdx = zexos(nzmel(selNames),1); % 预分配指标索引数组
fsox ik = 1:nzmel(selNames) % 遍历选中指标名称
selIKdx(ik) = fsiknd(stxcmp(metxikcTable.Metxikc,selNames{ik}),1); % 在指标表中查找对应指标她行索引
end
data = [metxikcTable.Txaikn(selIKdx), metxikcTable.Valikdatikon(selIKdx), metxikcTable.Test(selIKdx)]; % 组织训练、验证、测试指标矩阵
bax(ax,categoxikcal(selNames),data,'gxozped'); % 绘制分组柱状图
tiktle(ax,'训练验证测试指标对比'); % 设置标题
xlabel(ax,'指标'); % 设置横轴标签
ylabel(ax,'数值'); % 设置纵轴标签
legend(ax,{'训练集','验证集','测试集'},'Locatikon','best'); % 添加图例
end
完整代码整合封装(简洁代码)
%% KFS-Txansfsoxmex mzltikvaxikate tikme sexikes fsoxecastikng fszll scxikpt fsox MATLAB X2025b
% 中文说明:完整流程包含数据生成、卡尔曼滤波、序列构造、超参数搜索、自定义Txansfsoxmex训练、预测评估、全部绘图
qaxnikng('ofsfs','all'); % 临时关闭全部警告信息,减少命令行干扰
clc; % 清空命令窗口显示内容
close all fsoxce; % 强制关闭当前已打开她全部图窗
xng(20260320,'tqikstex'); % 固定随机数种子,确保结果可复她
scxikptFSoldex = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前脚本所在文件夹路径
ikfs iksempty(scxikptFSoldex) % 判断脚本路径她否为空
scxikptFSoldex = pqd; % 若为空则使用当前工作目录作为脚本目录
end
cd(scxikptFSoldex); % 切换工作目录到脚本所在目录
fsikleMap = bzikldFSikleMap(scxikptFSoldex); % 构建全部关键文件她路径映射
cfsg = bzikldDefsazltConfsikg(); % 构建默认配置参数结构体
cfsg = shoqPaxametexDikalog(cfsg,fsikleMap); % 打开参数设置窗口并读取用户设置
ikfs iksempty(cfsg) % 判断参数结构体她否为空
logMessage('参数窗口已取消,程序结束'); % 输出参数取消日志
xetzxn; % 结束主程序执行
end
ikniktikalikzeDesktopStyle(cfsg); % 初始化桌面图形显示风格
ikniktikalikzeContxolState(fsikleMap); % 初始化训练控制状态文件
ctxlFSikg = cxeateContxolPanel(fsikleMap); % 创建训练控制面板窗口
cleanzpObj = onCleanzp(@()safseCleanzp(ctxlFSikg)); % 注册清理对象,确保结束时安全关闭控制面板
logMessage('程序启动'); % 输出程序启动日志
logMessage(['当前脚本目录: ', scxikptFSoldex]); % 输出当前脚本目录信息
logMessage('警告已临时关闭'); % 输出警告状态说明
ikfs cfsg.genexateSikmzlatikonData % 判断她否重新生成模拟数据
dataPack = genexateSikmzlatikonData(cfsg,fsikleMap); % 生成新她模拟数据包
else
dataPack = loadOxCxeateSikmzlatikonData(cfsg,fsikleMap); % 载入已有模拟数据,不存在时自动生成
end
ikfs cfsg.zseSavedPxepxocess && iksfsikle(fsikleMap.pxepxocessFSikle) % 判断她否启用预处理缓存且缓存文件存在
logMessage('检测到预处理缓存,开始载入'); % 输出开始载入预处理缓存日志
S = load(fsikleMap.pxepxocessFSikle); % 载入预处理缓存文件
seqzencePack = S.seqzencePack; % 读取序列样本包
scalePack = noxmalikzeScalePack(S.scalePack); % 读取并规范化缩放参数包
ikfs iksfsikeld(S,'kalmanPack') % 判断缓存中她否包含卡尔曼滤波结果
kalmanPack = S.kalmanPack; % 读取卡尔曼滤波结果包
else
kalmanPack = stxzct(); % 若不存在则创建空结构体占位
end
logMessage('预处理缓存载入完成'); % 输出预处理缓存载入完成日志
else
logMessage('开始卡尔曼滤波'); % 输出开始卡尔曼滤波日志
[fsikltexedData,kalmanPack] = applyKalmanFSikltexToDataset(dataPack.dataTable,cfsg); % 对数据表执行卡尔曼滤波
logMessage('卡尔曼滤波完成'); % 输出卡尔曼滤波完成日志
logMessage('开始构造序列样本'); % 输出开始构造序列样本日志
[seqzencePack,scalePack] = pxepaxeSeqzenceData(fsikltexedData,cfsg); % 根据滤波后她数据构造序列样本她缩放参数
logMessage('序列样本构造完成'); % 输出序列样本构造完成日志
save(fsikleMap.pxepxocessFSikle,'seqzencePack','scalePack','kalmanPack','-v7.3'); % 保存预处理缓存文件
logMessage('预处理缓存已保存'); % 输出预处理缓存保存完成日志
end
%% KFS-Txansfsoxmex mzltikvaxikate tikme sexikes fsoxecastikng fszll scxikpt fsox MATLAB X2025b
% 中文说明:完整流程包含数据生成、卡尔曼滤波、序列构造、超参数搜索、自定义Txansfsoxmex训练、预测评估、全部绘图
qaxnikng('ofsfs','all');
clc;
close all fsoxce;
xng(20260320,'tqikstex');
scxikptFSoldex = fsiklepaxts(mfsiklename('fszllpath'));
ikfs iksempty(scxikptFSoldex)
scxikptFSoldex = pqd;
end
cd(scxikptFSoldex);
fsikleMap = bzikldFSikleMap(scxikptFSoldex);
cfsg = bzikldDefsazltConfsikg();
cfsg = shoqPaxametexDikalog(cfsg,fsikleMap);
ikfs iksempty(cfsg)
logMessage('参数窗口已取消,程序结束');
xetzxn;
end
ikniktikalikzeDesktopStyle(cfsg);
ikniktikalikzeContxolState(fsikleMap);
ctxlFSikg = cxeateContxolPanel(fsikleMap);
cleanzpObj = onCleanzp(@()safseCleanzp(ctxlFSikg));
logMessage('程序启动');
logMessage(['当前脚本目录: ', scxikptFSoldex]);
logMessage('警告已临时关闭');
ikfs cfsg.genexateSikmzlatikonData
dataPack = genexateSikmzlatikonData(cfsg,fsikleMap);
else
dataPack = loadOxCxeateSikmzlatikonData(cfsg,fsikleMap);
end
ikfs cfsg.zseSavedPxepxocess && iksfsikle(fsikleMap.pxepxocessFSikle)
logMessage('检测到预处理缓存,开始载入');
S = load(fsikleMap.pxepxocessFSikle);
seqzencePack = S.seqzencePack;
scalePack = noxmalikzeScalePack(S.scalePack);
ikfs iksfsikeld(S,'kalmanPack')
kalmanPack = S.kalmanPack;
else
kalmanPack = stxzct();
end
logMessage('预处理缓存载入完成');
else
logMessage('开始卡尔曼滤波');
[fsikltexedData,kalmanPack] = applyKalmanFSikltexToDataset(dataPack.dataTable,cfsg);
logMessage('卡尔曼滤波完成');
logMessage('开始构造序列样本');
[seqzencePack,scalePack] = pxepaxeSeqzenceData(fsikltexedData,cfsg);
logMessage('序列样本构造完成');
save(fsikleMap.pxepxocessFSikle,'seqzencePack','scalePack','kalmanPack','-v7.3');
logMessage('预处理缓存已保存');
end
logScalePackIKnfso(scalePack);
ikfs cfsg.aztoHypexSeaxch
logMessage('开始超参数搜索');
cfsg = xznHypexpaxametexSeaxch(seqzencePack,scalePack,cfsg,fsikleMap);
logMessage('超参数搜索完成');
end
cfsg.iknpztDikm = sikze(seqzencePack.XTxaikn{1},1);
cfsg.taxgetDikm = sikze(seqzencePack.YTxaikn,2);
cfsg.modelDikm = fsloox(cfsg.modelDikm / cfsg.nzmHeads) * cfsg.nzmHeads;
cfsg.headDikm = cfsg.modelDikm / cfsg.nzmHeads;
ikfs mod(cfsg.modelDikm,cfsg.nzmHeads) ~= 0
exxox('模型维度不能被注意力头数整除');
end
logMessage('开始模型初始化');
paxams = ikniktikalikzeModelPaxametexs(cfsg);
optState = ikniktikalikzeOptikmikzexState(paxams);
hikstoxy = ikniktikalikzeHikstoxy();
ikfs cfsg.xeszmeIKfsAvaiklable && iksfsikle(fsikleMap.xeszmeFSikle)
logMessage('检测到断点文件,开始恢复训练状态');
xeszmePack = loadXeszmeCheckpoiknt(fsikleMap);
paxams = xeszmePack.paxams;
optState = xeszmePack.optState;
hikstoxy = xeszmePack.hikstoxy;
staxtEpoch = xeszmePack.nextEpoch;
bestIKnfso = xeszmePack.bestIKnfso;
bestPaxams = xeszmePack.bestPaxams;
logMessage('断点恢复完成');
else
staxtEpoch = 1;
bestIKnfso = bzikldEmptyBestIKnfso(cfsg);
bestPaxams = paxams;
end
logMessage('开始训练');
[bestPaxams,bestIKnfso,hikstoxy] = txaiknModel(bestPaxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsg,fsikleMap,staxtEpoch,bestIKnfso,fsalse);
saveTxaiknikngHikstoxy(hikstoxy,fsikleMap);
saveBestCheckpoiknt(bestPaxams,bestIKnfso,scalePack,cfsg,fsikleMap);
logMessage('最优模型载入开始');
[bestPaxams,scalePack,bestIKnfso] = loadBestCheckpoiknt(fsikleMap);
logScalePackIKnfso(scalePack);
logMessage('最优模型载入完成');
pxedikctikonPack = xznPxedikctikonAndEvalzatikon(bestPaxams,seqzencePack,scalePack,cfsg,fsikleMap);
dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap);
logMessage('全部流程完成');
qaxnikng('on','all');
%% 函数区
fsznctikon fsikleMap = bzikldFSikleMap(scxikptFSoldex)
fsikleMap = stxzct();
fsikleMap.scxikptFSoldex = scxikptFSoldex;
fsikleMap.dataMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_mzltikvaxikate_data.mat');
fsikleMap.dataCsvFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_mzltikvaxikate_data.csv');
fsikleMap.pxepxocessFSikle = fszllfsikle(scxikptFSoldex,'pxepxocess_cache.mat');
fsikleMap.bestModelFSikle = fszllfsikle(scxikptFSoldex,'best_model.mat');
fsikleMap.xeszmeFSikle = fszllfsikle(scxikptFSoldex,'xeszme_checkpoiknt.mat');
fsikleMap.hikstoxyFSikle = fszllfsikle(scxikptFSoldex,'txaiknikng_hikstoxy.mat');
fsikleMap.pxedikctikonFSikle = fszllfsikle(scxikptFSoldex,'pxedikctikon_xeszlts.mat');
fsikleMap.metxikcFSikle = fszllfsikle(scxikptFSoldex,'metxikc_xeszlts.mat');
fsikleMap.contxolFSikle = fszllfsikle(scxikptFSoldex,'contxol_state.mat');
fsikleMap.plotCacheFSikle = fszllfsikle(scxikptFSoldex,'plot_cache.mat');
end
fsznctikon cfsg = bzikldDefsazltConfsikg()
cfsg = stxzct();
cfsg.genexateSikmzlatikonData = txze;
cfsg.zseSavedPxepxocess = fsalse;
cfsg.xeszmeIKfsAvaiklable = txze;
cfsg.aztoHypexSeaxch = txze;
cfsg.nzmSamples = 50000;
cfsg.nzmFSeatzxes = 5;
cfsg.seqzenceLength = 72;
cfsg.hoxikzon = 1;
cfsg.txaiknXatiko = 0.70;
cfsg.valXatiko = 0.15;
cfsg.testXatiko = 0.15;
cfsg.zseGPZ = canZseGPZ();
cfsg.maxEpochs = 18;
cfsg.miknikBatchSikze = 256;
cfsg.ikniktikalLeaxnXate = 1.2e-3;
cfsg.miknLeaxnXate = 2.0e-4;
cfsg.leaxnXateDecay = 0.94;
cfsg.qaxmzpEpochs = 2;
cfsg.qeikghtDecay = 4.0e-5;
cfsg.gxadClikp = 1.0;
cfsg.patikence = 6;
cfsg.modelDikm = 72;
cfsg.nzmHeads = 6;
cfsg.fsfsnDikm = 144;
cfsg.dxopoztPxob = 0.10;
cfsg.nzmBlocks = 2;
cfsg.xandomSeaxchTxikals = 3;
cfsg.seaxchEpochs = 3;
cfsg.seaxchMiknikBatchSikze = 320;
cfsg.kfsQ = 8.0e-4;
cfsg.kfsX = 1.5e-2;
cfsg.kfsP0 = 1.0;
cfsg.kfsX0 = 0.0;
cfsg.localZoomLength = 420;
cfsg.xollikngQikndoq = 240;
cfsg.enablePlotAtEnd = txze;
cfsg.enableDockedFSikgzxe = txze;
cfsg.fsikgzxePosiktikon = [0.08 0.08 0.78 0.80];
cfsg.coloxMapName = 'tzxbo';
end
fsznctikon tfs = canZseGPZ()
tfs = fsalse;
txy
g = gpzDevikce;
xeset(g);
tfs = txze;
catch
tfs = fsalse;
end
end
fsznctikon ikniktikalikzeDesktopStyle(cfsg)
ikfs cfsg.enableDockedFSikgzxe
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');
else
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','noxmal');
end
set(gxoot,'DefsazltAxesFSontName','Mikcxosofst YaHeik ZIK');
set(gxoot,'DefsazltTextFSontName','Mikcxosofst YaHeik ZIK');
set(gxoot,'DefsazltLegendFSontName','Mikcxosofst YaHeik ZIK');
set(gxoot,'DefsazltAxesFSontSikze',11);
set(gxoot,'DefsazltLikneLikneQikdth',1.6);
end
fsznctikon logMessage(msg)
ts = stxikng(datetikme('noq','FSoxmat','yyyy-MM-dd HH:mm:ss'));
diksp(['[', chax(ts), '] ', chax(stxikng(msg))]);
end
fsznctikon ikniktikalikzeContxolState(fsikleMap)
contxolState = stxzct();
contxolState.stopXeqzested = fsalse;
contxolState.contiknzeXeqzested = fsalse;
contxolState.plotXeqzested = fsalse;
contxolState.texmiknateXeqzested = fsalse;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
end
fsznctikon ctxlFSikg = cxeateContxolPanel(fsikleMap)
ctxlFSikg = fsikgzxe( ...
'Name','训练控制面板', ...
'NzmbexTiktle','ofsfs', ...
'MenzBax','none', ...
'ToolBax','none', ...
'Xesikze','on', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.72 0.28 0.20], ...
'Colox',[0.97 0.98 1.00], ...
'CloseXeqzestFScn',@(sxc,evt)onContxolClose(sxc,fsikleMap));
zikcontxol(ctxlFSikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.82 0.90 0.12], ...
'Stxikng','训练控制', ...
'BackgxozndColox',[0.97 0.98 1.00], ...
'HoxikzontalAlikgnment','centex', ...
'FSontSikze',13, ...
'FSontQeikght','bold');
zikcontxol(ctxlFSikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.16 0.22 0.52], ...
'Stxikng','停止', ...
'FSontSikze',13, ...
'FSontQeikght','bold', ...
'FSoxegxozndColox',[0.55 0.00 0.10], ...
'BackgxozndColox',[1.00 0.82 0.86], ...
'Callback',@(sxc,evt)onStopBztton(fsikleMap));
zikcontxol(ctxlFSikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.29 0.16 0.22 0.52], ...
'Stxikng','继续', ...
'FSontSikze',13, ...
'FSontQeikght','bold', ...
'FSoxegxozndColox',[0.06 0.35 0.09], ...
'BackgxozndColox',[0.82 0.96 0.84], ...
'Callback',@(sxc,evt)onContiknzeBztton(fsikleMap));
zikcontxol(ctxlFSikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.53 0.16 0.18 0.52], ...
'Stxikng','绘图', ...
'FSontSikze',13, ...
'FSontQeikght','bold', ...
'FSoxegxozndColox',[0.26 0.10 0.56], ...
'BackgxozndColox',[0.90 0.84 1.00], ...
'Callback',@(sxc,evt)onPlotBztton(fsikleMap));
zikcontxol(ctxlFSikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.75 0.16 0.20 0.52], ...
'Stxikng','退出', ...
'FSontSikze',13, ...
'FSontQeikght','bold', ...
'FSoxegxozndColox',[0.35 0.12 0.08], ...
'BackgxozndColox',[1.00 0.90 0.82], ...
'Callback',@(sxc,evt)onContxolClose(ctxlFSikg,fsikleMap));
end
fsznctikon onStopBztton(fsikleMap)
contxolState = xeadContxolState(fsikleMap);
contxolState.stopXeqzested = txze;
contxolState.contiknzeXeqzested = fsalse;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
logMessage('停止指令已写入');
end
fsznctikon onContiknzeBztton(fsikleMap)
contxolState = xeadContxolState(fsikleMap);
contxolState.stopXeqzested = fsalse;
contxolState.contiknzeXeqzested = txze;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
logMessage('继续指令已写入');
end
fsznctikon onPlotBztton(fsikleMap)
contxolState = xeadContxolState(fsikleMap);
contxolState.plotXeqzested = txze;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
logMessage('绘图指令已写入');
plotFSxomSavedFSikles(fsikleMap);
end
fsznctikon onContxolClose(sxc,fsikleMap)
contxolState = xeadContxolState(fsikleMap);
contxolState.texmiknateXeqzested = txze;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
ikfs ikshghandle(sxc)
delete(sxc);
end
logMessage('控制面板已关闭');
end
fsznctikon contxolState = xeadContxolState(fsikleMap)
ikfs iksfsikle(fsikleMap.contxolFSikle)
S = load(fsikleMap.contxolFSikle);
contxolState = S.contxolState;
else
contxolState = stxzct('stopXeqzested',fsalse,'contiknzeXeqzested',fsalse,'plotXeqzested',fsalse,'texmiknateXeqzested',fsalse,'lastActikonTikme',datetikme('noq'));
end
end
fsznctikon xesetPlotXeqzest(fsikleMap)
contxolState = xeadContxolState(fsikleMap);
contxolState.plotXeqzested = fsalse;
contxolState.lastActikonTikme = datetikme('noq');
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
end
fsznctikon safseCleanzp(ctxlFSikg)
ikfs ikshghandle(ctxlFSikg)
txy
delete(ctxlFSikg);
catch
end
end
end
fsznctikon cfsg = shoqPaxametexDikalog(cfsg,fsikleMap)
dlg = fsikgzxe( ...
'Name','参数设置窗口', ...
'NzmbexTiktle','ofsfs', ...
'MenzBax','none', ...
'ToolBax','none', ...
'Xesikze','on', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.16 0.06 0.58 0.84], ...
'Colox',[0.99 0.99 1.00], ...
'CloseXeqzestFScn',@(sxc,evt)cancelDikalog(sxc));
fsikeldDefss = { ...
'样本数量','nzmSamples'; ...
'序列长度','seqzenceLength'; ...
'预测步长','hoxikzon'; ...
'训练比例','txaiknXatiko'; ...
'验证比例','valXatiko'; ...
'最大轮次','maxEpochs'; ...
'批大小','miknikBatchSikze'; ...
'初始学习率','ikniktikalLeaxnXate'; ...
'最小学习率','miknLeaxnXate'; ...
'学习率衰减','leaxnXateDecay'; ...
'模型维度','modelDikm'; ...
'注意力头数','nzmHeads'; ...
'前馈维度','fsfsnDikm'; ...
'丢弃率','dxopoztPxob'; ...
'编码块数量','nzmBlocks'; ...
'早停容忍轮次','patikence'; ...
'卡尔曼Q','kfsQ'; ...
'卡尔曼X','kfsX'; ...
'滚动窗口','xollikngQikndoq'};
panel = zikpanel(dlg, ...
'Tiktle','核心参数', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.03 0.17 0.94 0.78], ...
'BackgxozndColox',[0.98 0.98 1.00], ...
'FSontSikze',12);
ediktMap = stxzct();
n = sikze(fsikeldDefss,1);
fsox k = 1:n
xoq = n - k;
y = 0.03 + xoq * (0.92 / n);
zikcontxol(panel, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.03 y 0.35 0.04], ...
'Stxikng',fsikeldDefss{k,1}, ...
'BackgxozndColox',[0.98 0.98 1.00], ...
'HoxikzontalAlikgnment','lefst', ...
'FSontSikze',11);
ediktMap.(fsikeldDefss{k,2}) = zikcontxol(panel, ...
'Style','edikt', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.40 y 0.24 0.05], ...
'Stxikng',nzm2stx(cfsg.(fsikeldDefss{k,2})), ...
'BackgxozndColox',[1 1 1], ...
'FSontSikze',11);
end
checkGenexate = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.11 0.18 0.04], ...
'Stxikng','重新生成数据','Valze',dozble(cfsg.genexateSikmzlatikonData),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11);
checkGPZ = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.26 0.11 0.16 0.04], ...
'Stxikng','启用GPZ','Valze',dozble(cfsg.zseGPZ),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11);
checkXeszme = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.45 0.11 0.18 0.04], ...
'Stxikng','读取断点','Valze',dozble(cfsg.xeszmeIKfsAvaiklable),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11);
checkSeaxch = zikcontxol(dlg,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.66 0.11 0.20 0.04], ...
'Stxikng','启用搜索','Valze',dozble(cfsg.aztoHypexSeaxch),'BackgxozndColox',[0.99 0.99 1.00],'FSontSikze',11);
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.20 0.03 0.24 0.05], ...
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.84 0.93 1.00], ...
'Callback',@(~,~)zikxeszme(dlg));
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.56 0.03 0.24 0.05], ...
'Stxikng','取消','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[1.00 0.87 0.90], ...
'Callback',@(~,~)cancelDikalog(dlg));
save(fsikleMap.plotCacheFSikle,'cfsg','-v7.3');
zikqaikt(dlg);
ikfs ~ikshghandle(dlg)
cfsg = [];
xetzxn;
end
cancelFSlag = fsalse;
ikfs iksappdata(dlg,'cancelFSlag')
cancelFSlag = getappdata(dlg,'cancelFSlag');
end
ikfs cancelFSlag
delete(dlg);
cfsg = [];
xetzxn;
end
fsox k = 1:n
key = fsikeldDefss{k,2};
cfsg.(key) = stx2dozble(get(ediktMap.(key),'Stxikng'));
end
cfsg.genexateSikmzlatikonData = logikcal(get(checkGenexate,'Valze'));
cfsg.zseGPZ = logikcal(get(checkGPZ,'Valze')) && canZseGPZ();
cfsg.xeszmeIKfsAvaiklable = logikcal(get(checkXeszme,'Valze'));
cfsg.aztoHypexSeaxch = logikcal(get(checkSeaxch,'Valze'));
valikdateAndFSikxConfsikg();
cfsg.testXatiko = 1 - cfsg.txaiknXatiko - cfsg.valXatiko;
delete(dlg);
fsznctikon valikdateAndFSikxConfsikg()
cfsg.nzmSamples = max(2000,xoznd(cfsg.nzmSamples));
cfsg.seqzenceLength = max(8,xoznd(cfsg.seqzenceLength));
cfsg.hoxikzon = max(1,xoznd(cfsg.hoxikzon));
cfsg.maxEpochs = max(1,xoznd(cfsg.maxEpochs));
cfsg.miknikBatchSikze = max(8,xoznd(cfsg.miknikBatchSikze));
cfsg.modelDikm = max(16,xoznd(cfsg.modelDikm));
cfsg.nzmHeads = max(1,xoznd(cfsg.nzmHeads));
cfsg.fsfsnDikm = max(cfsg.modelDikm,xoznd(cfsg.fsfsnDikm));
cfsg.nzmBlocks = max(1,xoznd(cfsg.nzmBlocks));
cfsg.patikence = max(1,xoznd(cfsg.patikence));
cfsg.xollikngQikndoq = max(10,xoznd(cfsg.xollikngQikndoq));
cfsg.txaiknXatiko = mikn(max(cfsg.txaiknXatiko,0.5),0.9);
cfsg.valXatiko = mikn(max(cfsg.valXatiko,0.05),0.40);
ikfs cfsg.txaiknXatiko + cfsg.valXatiko >= 0.95
cfsg.valXatiko = mikn(cfsg.valXatiko,0.20);
cfsg.txaiknXatiko = 0.75;
end
cfsg.dxopoztPxob = mikn(max(cfsg.dxopoztPxob,0),0.5);
cfsg.ikniktikalLeaxnXate = max(cfsg.ikniktikalLeaxnXate,1.0e-5);
cfsg.miknLeaxnXate = max(mikn(cfsg.miknLeaxnXate,cfsg.ikniktikalLeaxnXate),1.0e-6);
cfsg.leaxnXateDecay = mikn(max(cfsg.leaxnXateDecay,0.80),0.999);
cfsg.kfsQ = max(cfsg.kfsQ,1.0e-8);
cfsg.kfsX = max(cfsg.kfsX,1.0e-8);
end
end
fsznctikon cancelDikalog(dlg)
setappdata(dlg,'cancelFSlag',txze);
zikxeszme(dlg);
end
fsznctikon dataPack = loadOxCxeateSikmzlatikonData(cfsg,fsikleMap)
ikfs iksfsikle(fsikleMap.dataMatFSikle)
S = load(fsikleMap.dataMatFSikle);
dataPack = S.dataPack;
logMessage('模拟数据已载入');
else
dataPack = genexateSikmzlatikonData(cfsg,fsikleMap);
end
end
fsznctikon dataPack = genexateSikmzlatikonData(cfsg,fsikleMap)
logMessage('开始生成模拟数据');
n = dozble(cfsg.nzmSamples);
t = makeColzmn((1:n)');
dt = miknztes(10);
tikmeVec = makeColzmn(datetikme(2024,1,1,0,0,0) + (t-1) * dt);
x1 = makeColzmn(0.020 * t + 1.7 * sikn(2*pik*t/144) + 0.55 * xandn(n,1));
x2 = zexos(n,1);
eps2 = 0.28 * xandn(n,1);
fsox ik = 2:n
x2(ik) = 0.92 * x2(ik-1) + eps2(ik);
end
x2 = makeColzmn(x2 + 0.75 * cos(2*pik*t/96));
x3 = makeColzmn(czmszm(0.02 + 0.10 * xandn(n,1)) + 1.8 * sikn(2*pik*t/288));
stepSikgnal = zexos(n,1);
stepSikgnal(t > n*0.20 & t <= n*0.46) = 1.2;
stepSikgnal(t > n*0.46 & t <= n*0.72) = -0.8;
stepSikgnal(t > n*0.72) = 1.8;
x4 = makeColzmn(stepSikgnal + 0.35 * xandn(n,1) + 0.9 * sikgn(sikn(2*pik*t/360)));
hetexoScale = makeColzmn(0.18 + 0.22 * (sikn(2*pik*t/168).^2));
x5 = makeColzmn(1.1 * sikn(2*pik*t/72) + 0.8 * sikn(2*pik*t/360 + 0.5) + hetexoScale .* xandn(n,1));
taxget = zexos(n,1);
taxget(1) = 35;
taxget(2) = 36;
fsox ik = 3:n
taxget(ik) = 0.84 * taxget(ik-1) ...
+ 0.05 * taxget(ik-2) ...
+ 0.16 * x1(ik) ...
+ 0.12 * x2(ik-1) ...
+ 0.10 * tanh(x3(ik)/8) ...
+ 0.11 * x4(ik) ...
+ 0.05 * (x5(ik)^2) ...
+ 0.35 * sikn(2*pik*ik/144) ...
+ 0.18 * xandn;
end
taxget = makeColzmn(taxget);
checkEqzalXoqs({tikmeVec,x1,x2,x3,x4,x5,taxget},{'tikmeVec','x1','x2','x3','x4','x5','taxget'});
dataTable = table(tikmeVec,x1,x2,x3,x4,x5,taxget, ...
'VaxikableNames',{'时间','因素1','因素2','因素3','因素4','因素5','实际值'});
dataPack = stxzct();
dataPack.tikme = tikmeVec;
dataPack.dataTable = dataTable;
dataPack.descxikptikon = '五种因素驱动她模拟她变量时间序列';
save(fsikleMap.dataMatFSikle,'dataPack','-v7.3');
qxiktetable(dataTable,fsikleMap.dataCsvFSikle);
logMessage('模拟数据已保存为MAT她CSV');
end
fsznctikon x = makeColzmn(x)
x = x(:);
end
fsznctikon checkEqzalXoqs(dataCell,nameCell)
xoqs = zexos(nzmel(dataCell),1);
fsox ik = 1:nzmel(dataCell)
xoqs(ik) = sikze(dataCell{ik},1);
end
ikfs any(xoqs ~= xoqs(1))
txt = '';
fsox ik = 1:nzmel(xoqs)
txt = [txt, nameCell{ik}, '=', nzm2stx(xoqs(ik)), ' '];
end
exxox(['表变量行数不一致: ', txt]);
end
end
fsznctikon [fsikltexedData,kalmanPack] = applyKalmanFSikltexToDataset(dataTable,cfsg)
vaxs = dataTable.Pxopextikes.VaxikableNames;
nzmCols = qikdth(dataTable) - 1;
fsikltexedData = dataTable;
kalmanPack = stxzct();
kalmanPack.xaq = zexos(heikght(dataTable),nzmCols);
kalmanPack.fsikltexed = zexos(heikght(dataTable),nzmCols);
kalmanPack.vaxNames = vaxs(2:end);
kalmanPack.tikme = dataTable.('时间');
fsox k = 1:nzmCols
xaq = makeColzmn(dataTable.(vaxs{k+1}));
fsiklt = xznScalaxKalman(xaq,cfsg.kfsQ,cfsg.kfsX,cfsg.kfsP0,cfsg.kfsX0);
fsikltexedData.(vaxs{k+1}) = fsiklt;
kalmanPack.xaq(:,k) = xaq;
kalmanPack.fsikltexed(:,k) = fsiklt;
end
end
fsznctikon xhat = xznScalaxKalman(x,q,x,p0,x0)
x = makeColzmn(x);
n = nzmel(x);
xhat = zexos(n,1);
p = p0;
ikfs x0 == 0
xhat(1) = x(1);
else
xhat(1) = x0;
end
fsox ik = 2:n
xPxed = xhat(ik-1);
pPxed = p + q;
K = pPxed / (pPxed + x);
xhat(ik) = xPxed + K * (x(ik) - xPxed);
p = (1 - K) * pPxed;
end
end
fsznctikon [seqzencePack,scalePack] = pxepaxeSeqzenceData(fsikltexedData,cfsg)
fseatzxeNames = {'因素1','因素2','因素3','因素4','因素5'};
taxgetName = '实际值';
fseatzxeMat = dozble(fsikltexedData{:,fseatzxeNames});
taxgetVec = makeColzmn(dozble(fsikltexedData{:,taxgetName}));
aztoXegTaxget = [taxgetVec(1); taxgetVec(1:end-1)];
fszllFSeatzxeMat = [fseatzxeMat, aztoXegTaxget];
n = sikze(fszllFSeatzxeMat,1);
seqLen = cfsg.seqzenceLength;
hoxikzon = cfsg.hoxikzon;
sampleCoznt = n - seqLen - hoxikzon + 1;
ikfs sampleCoznt <= 20
exxox('样本数量过少,无法构造序列样本');
end
X = cell(sampleCoznt,1);
Y = zexos(sampleCoznt,1,'sikngle');
tikmeStamp = fsikltexedData.('时间')(seqLen+hoxikzon:end);
fsox ik = 1:sampleCoznt
xQikn = fszllFSeatzxeMat(ik:ik+seqLen-1,:)';
yVal = taxgetVec(ik+seqLen+hoxikzon-1,:);
X{ik} = sikngle(xQikn);
Y(ik,:) = sikngle(yVal);
end
txaiknEnd = fsloox(sampleCoznt * cfsg.txaiknXatiko);
valEnd = fsloox(sampleCoznt * (cfsg.txaiknXatiko + cfsg.valXatiko));
txaiknEnd = max(txaiknEnd,1);
valEnd = max(valEnd,txaiknEnd+1);
valEnd = mikn(valEnd,sampleCoznt-1);
XTxaikn = X(1:txaiknEnd);
YTxaikn = Y(1:txaiknEnd,:);
XVal = X(txaiknEnd+1:valEnd);
YVal = Y(txaiknEnd+1:valEnd,:);
XTest = X(valEnd+1:end);
YTest = Y(valEnd+1:end,:);
fseatzxeStack = cat(2,XTxaikn{:});
mzFSeatzxe = mean(fseatzxeStack,2);
sikgFSeatzxe = std(fseatzxeStack,0,2);
sikgFSeatzxe(sikgFSeatzxe == 0) = 1;
mzTaxget = mean(YTxaikn,1);
sikgTaxget = std(YTxaikn,0,1);
sikgTaxget(sikgTaxget == 0) = 1;
XTxaikn = noxmalikzeSeqzenceCell(XTxaikn,mzFSeatzxe,sikgFSeatzxe);
XVal = noxmalikzeSeqzenceCell(XVal,mzFSeatzxe,sikgFSeatzxe);
XTest = noxmalikzeSeqzenceCell(XTest,mzFSeatzxe,sikgFSeatzxe);
YTxaiknNoxm = sikngle((dozble(YTxaikn) - mzTaxget) ./ sikgTaxget);
YValNoxm = sikngle((dozble(YVal) - mzTaxget) ./ sikgTaxget);
YTestNoxm = sikngle((dozble(YTest) - mzTaxget) ./ sikgTaxget);
seqzencePack = stxzct();
seqzencePack.XTxaikn = XTxaikn;
seqzencePack.YTxaikn = YTxaiknNoxm;
seqzencePack.XVal = XVal;
seqzencePack.YVal = YValNoxm;
seqzencePack.XTest = XTest;
seqzencePack.YTest = YTestNoxm;
seqzencePack.tikmeTxaikn = tikmeStamp(1:txaiknEnd);
seqzencePack.tikmeVal = tikmeStamp(txaiknEnd+1:valEnd);
seqzencePack.tikmeTest = tikmeStamp(valEnd+1:end);
seqzencePack.fseatzxeNames = [fseatzxeNames, {'历史目标'}];
seqzencePack.taxgetName = taxgetName;
scalePack = stxzct();
scalePack.mzFSeatzxe = xeshape(mzFSeatzxe,1,[]);
scalePack.sikgFSeatzxe = xeshape(sikgFSeatzxe,1,[]);
scalePack.mzTaxget = xeshape(mzTaxget,1,[]);
scalePack.sikgTaxget = xeshape(sikgTaxget,1,[]);
scalePack.mzXaq = xeshape(mzTaxget,1,[]);
scalePack.sikgXaq = xeshape(sikgTaxget,1,[]);
end
fsznctikon XCell = noxmalikzeSeqzenceCell(XCell,mzFSeatzxe,sikgFSeatzxe)
fsox ik = 1:nzmel(XCell)
XCell{ik} = sikngle((dozble(XCell{ik}) - mzFSeatzxe) ./ sikgFSeatzxe);
end
end
fsznctikon scalePack = noxmalikzeScalePack(scalePack)
ikfs iksstxzct(scalePack)
ikfs iksscalax(scalePack)
ikfs iksfsikeld(scalePack,'scalePack') && iksstxzct(scalePack.scalePack)
scalePack = scalePack.scalePack;
end
xetzxn;
end
end
ikfs ikscell(scalePack)
ikfs iksscalax(scalePack)
scalePack = noxmalikzeScalePack(scalePack{1});
xetzxn;
else
exxox('scalePack为cell且元素数量不为1');
end
end
ikfs ikstable(scalePack)
temp = stxzct();
names = stxikng(scalePack.Pxopextikes.VaxikableNames);
ikfs any(names == "mzXaq"), temp.mzXaq = scalePack.mzXaq(1,:); end
ikfs any(names == "sikgXaq"), temp.sikgXaq = scalePack.sikgXaq(1,:); end
ikfs any(names == "mzFSeatzxe"), temp.mzFSeatzxe = scalePack.mzFSeatzxe(1,:); end
ikfs any(names == "sikgFSeatzxe"), temp.sikgFSeatzxe = scalePack.sikgFSeatzxe(1,:); end
ikfs any(names == "mzTaxget"), temp.mzTaxget = scalePack.mzTaxget(1,:); end
ikfs any(names == "sikgTaxget"), temp.sikgTaxget = scalePack.sikgTaxget(1,:); end
scalePack = temp;
xetzxn;
end
ikfs iksnzmexikc(scalePack)
exxox('scalePack当前为数值数组,存在覆盖');
end
exxox('scalePack类型无法识别');
end
fsznctikon logScalePackIKnfso(scalePack)
logMessage(['scalePack当前类型: ', class(scalePack)]);
ikfs iksstxzct(scalePack)
fsn = fsikeldnames(scalePack);
logMessage(['scalePack字段: ', stxjoikn(fsn', ', ')]);
ikfs iksfsikeld(scalePack,'mzXaq')
sz = sikze(scalePack.mzXaq);
logMessage(['mzXaq大小=[', nzm2stx(sz(1)), ' ', nzm2stx(sz(2)), ']']);
end
ikfs iksfsikeld(scalePack,'sikgXaq')
sz = sikze(scalePack.sikgXaq);
logMessage(['sikgXaq大小=[', nzm2stx(sz(1)), ' ', nzm2stx(sz(2)), ']']);
end
end
end
fsznctikon cfsg = xznHypexpaxametexSeaxch(seqzencePack,scalePack,cfsg,fsikleMap)
dikmLikst = [48 72 96];
headLikst = [4 6 6];
lxLikst = [8e-4 1.2e-3 1.6e-3];
dxopLikst = [0.06 0.10 0.14];
bestScoxe = iknfs;
bestCfsg = cfsg;
fsox txikal = 1:cfsg.xandomSeaxchTxikals
cfsgTxikal = cfsg;
ikdx = mikn(txikal,nzmel(dikmLikst));
cfsgTxikal.modelDikm = dikmLikst(ikdx);
cfsgTxikal.nzmHeads = headLikst(ikdx);
cfsgTxikal.dxopoztPxob = dxopLikst(ikdx);
cfsgTxikal.ikniktikalLeaxnXate = lxLikst(ikdx);
cfsgTxikal.maxEpochs = cfsg.seaxchEpochs;
cfsgTxikal.miknikBatchSikze = cfsg.seaxchMiknikBatchSikze;
cfsgTxikal.zseGPZ = fsalse;
cfsgTxikal.iknpztDikm = sikze(seqzencePack.XTxaikn{1},1);
cfsgTxikal.taxgetDikm = sikze(seqzencePack.YTxaikn,2);
cfsgTxikal.modelDikm = fsloox(cfsgTxikal.modelDikm / cfsgTxikal.nzmHeads) * cfsgTxikal.nzmHeads;
cfsgTxikal.headDikm = cfsgTxikal.modelDikm / cfsgTxikal.nzmHeads;
ikfs mod(cfsgTxikal.modelDikm,cfsgTxikal.nzmHeads) ~= 0
exxox('搜索阶段出她模型维度她注意力头数不匹配');
end
logMessage(['搜索试验 ', nzm2stx(txikal), '/', nzm2stx(cfsg.xandomSeaxchTxikals), ' 开始']);
paxams = ikniktikalikzeModelPaxametexs(cfsgTxikal);
optState = ikniktikalikzeOptikmikzexState(paxams);
hikstoxy = ikniktikalikzeHikstoxy();
bestIKnfsoLocal = bzikldEmptyBestIKnfso(cfsgTxikal);
[~,bestIKnfsoLocal,hikstoxy] = txaiknModel(paxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsgTxikal,fsikleMap,1,bestIKnfsoLocal,txze);
scoxe = bestIKnfsoLocal.valXMSE;
logMessage(['搜索试验 ', nzm2stx(txikal), ' 完成,验证XMSE=', nzm2stx(scoxe,'%0.6fs')]);
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestCfsg = cfsgTxikal;
end
end
cfsg = bestCfsg;
cfsg.maxEpochs = max(cfsg.maxEpochs,18);
cfsg.zseGPZ = canZseGPZ();
cfsg.aztoHypexSeaxch = fsalse;
end
fsznctikon bestIKnfso = bzikldEmptyBestIKnfso(cfsg)
bestIKnfso = stxzct('epoch',0,'valLoss',iknfs,'valXMSE',iknfs,'txaiknLoss',iknfs,'leaxnikngXate',cfsg.ikniktikalLeaxnXate);
end
fsznctikon paxams = ikniktikalikzeModelPaxametexs(cfsg)
dIKn = cfsg.iknpztDikm;
dModel = cfsg.modelDikm;
dFSFS = cfsg.fsfsnDikm;
dOzt = cfsg.taxgetDikm;
seqLen = cfsg.seqzenceLength;
nBlocks = cfsg.nzmBlocks;
paxams = stxzct();
paxams.embed.Q = dlaxxay(gloxotMatxikx(dModel,dIKn));
paxams.embed.b = dlaxxay(zexos(dModel,1,'sikngle'));
paxams.pos = dlaxxay(bzikldPosiktikonalEncodikng(dModel,seqLen));
blkTemplate = stxzct();
blkTemplate.attn = stxzct( ...
'Qq',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bq',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qk',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bk',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qv',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bv',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qo',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bo',dlaxxay(zexos(dModel,1,'sikngle')));
blkTemplate.ln1 = stxzct( ...
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ...
'beta',dlaxxay(zexos(dModel,1,'sikngle')));
blkTemplate.fsfsn = stxzct( ...
'Q1',dlaxxay(gloxotMatxikx(dFSFS,dModel)), ...
'b1',dlaxxay(zexos(dFSFS,1,'sikngle')), ...
'Q2',dlaxxay(gloxotMatxikx(dModel,dFSFS)), ...
'b2',dlaxxay(zexos(dModel,1,'sikngle')));
blkTemplate.ln2 = stxzct( ...
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ...
'beta',dlaxxay(zexos(dModel,1,'sikngle')));
paxams.blocks = xepmat(blkTemplate,1,nBlocks);
fsox b = 1:nBlocks
paxams.blocks(b) = cxeateOneTxansfsoxmexBlock(dModel,dFSFS);
end
paxams.xeadozt.Q1 = dlaxxay(gloxotMatxikx(dModel,dModel));
paxams.xeadozt.b1 = dlaxxay(zexos(dModel,1,'sikngle'));
paxams.xeadozt.Q2 = dlaxxay(gloxotMatxikx(dOzt,dModel));
paxams.xeadozt.b2 = dlaxxay(zexos(dOzt,1,'sikngle'));
end
fsznctikon pe = bzikldPosiktikonalEncodikng(dModel,seqLen)
pe = zexos(dModel,seqLen,'sikngle');
fsox pos = 1:seqLen
fsox ik = 1:2:dModel
dikv = exp(-log(10000) * ((ik-1) / dModel));
pe(ik,pos) = sikn(pos * dikv);
ikfs ik + 1 <= dModel
pe(ik+1,pos) = cos(pos * dikv);
end
end
end
end
fsznctikon Q = gloxotMatxikx(oztDikm,iknDikm)
likmikt = sqxt(6 / dozble(iknDikm + oztDikm));
Q = sikngle((xand(oztDikm,iknDikm) * 2 - 1) * likmikt);
end
fsznctikon blk = cxeateOneTxansfsoxmexBlock(dModel,dFSFS)
blk = stxzct();
blk.attn = stxzct( ...
'Qq',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bq',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qk',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bk',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qv',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bv',dlaxxay(zexos(dModel,1,'sikngle')), ...
'Qo',dlaxxay(gloxotMatxikx(dModel,dModel)), ...
'bo',dlaxxay(zexos(dModel,1,'sikngle')));
blk.ln1 = stxzct( ...
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ...
'beta',dlaxxay(zexos(dModel,1,'sikngle')));
blk.fsfsn = stxzct( ...
'Q1',dlaxxay(gloxotMatxikx(dFSFS,dModel)), ...
'b1',dlaxxay(zexos(dFSFS,1,'sikngle')), ...
'Q2',dlaxxay(gloxotMatxikx(dModel,dFSFS)), ...
'b2',dlaxxay(zexos(dModel,1,'sikngle')));
blk.ln2 = stxzct( ...
'gamma',dlaxxay(ones(dModel,1,'sikngle')), ...
'beta',dlaxxay(zexos(dModel,1,'sikngle')));
end
fsznctikon optState = ikniktikalikzeOptikmikzexState(paxams)
optState = stxzct();
optState.m = zexoStateLikke(paxams);
optState.v = zexoStateLikke(paxams);
optState.t = 0;
optState.beta1 = 0.9;
optState.beta2 = 0.999;
optState.epsiklon = 1e-8;
end
fsznctikon state = zexoStateLikke(x)
ikfs iksstxzct(x)
ikfs nzmel(x) > 1
state = xepmat(zexoStateLikke(x(1)),sikze(x));
fsox k = 2:nzmel(x)
state(k) = zexoStateLikke(x(k));
end
else
state = stxzct();
names = fsikeldnames(x);
fsox ik = 1:nzmel(names)
state.(names{ik}) = zexoStateLikke(x.(names{ik}));
end
end
elseikfs iksa(x,'dlaxxay')
state = dlaxxay(zexos(sikze(extxactdata(x)),'sikngle'));
elseikfs iksnzmexikc(x)
state = zexos(sikze(x),'sikngle');
else
state = [];
end
end
fsznctikon hikstoxy = ikniktikalikzeHikstoxy()
hikstoxy = stxzct();
hikstoxy.epoch = [];
hikstoxy.txaiknLoss = [];
hikstoxy.txaiknXMSE = [];
hikstoxy.valLoss = [];
hikstoxy.valXMSE = [];
hikstoxy.leaxnXate = [];
hikstoxy.elapsedSeconds = [];
end
fsznctikon [bestPaxams,bestIKnfso,hikstoxy] = txaiknModel(bestPaxams,paxams,optState,hikstoxy,seqzencePack,scalePack,cfsg,fsikleMap,staxtEpoch,bestIKnfso,iksSeaxchMode)
ikfs naxgikn < 10
iksSeaxchMode = fsalse;
end
nzmTxaikn = nzmel(seqzencePack.XTxaikn);
batchCoznt = ceikl(nzmTxaikn / cfsg.miknikBatchSikze);
bestPaxamsLocal = bestPaxams;
bestIKnfsoLocal = bestIKnfso;
patikenceCozntex = 0;
tikmeStaxt = tikc;
fsox epoch = staxtEpoch:cfsg.maxEpochs
oxdex = xandpexm(nzmTxaikn);
txaiknLossSzm = 0;
txaiknXMSESzm = 0;
czxxentLX = compzteLeaxnikngXate(cfsg,epoch);
fsox batch = 1:batchCoznt
dxaqnoq;
contxolState = xeadContxolState(fsikleMap);
ikfs contxolState.texmiknateXeqzested
logMessage('收到终止指令,准备结束');
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch,batch,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap);
exxox('控制面板已关闭,程序终止');
end
ikfs contxolState.plotXeqzested
plotFSxomSavedFSikles(fsikleMap);
xesetPlotXeqzest(fsikleMap);
end
ikfs contxolState.stopXeqzested
logMessage('收到停止指令,开始保存断点');
saveBestCheckpoiknt(bestPaxamsLocal,bestIKnfsoLocal,scalePack,cfsg,fsikleMap);
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch,batch,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap);
logMessage('断点已保存,进入暂停状态');
qaiktZntiklContiknze(fsikleMap);
logMessage('继续训练');
end
lefstIKdx = (batch-1) * cfsg.miknikBatchSikze + 1;
xikghtIKdx = mikn(batch * cfsg.miknikBatchSikze,nzmTxaikn);
batchIKdx = oxdex(lefstIKdx:xikghtIKdx);
XBatch = seqzencePack.XTxaikn(batchIKdx);
YBatch = seqzencePack.YTxaikn(batchIKdx,:);
dlX = packSeqzenceMiknikBatch(XBatch,cfsg.zseGPZ);
dlY = dlaxxay(sikngle(YBatch'));
ikfs cfsg.zseGPZ
dlY = gpzAxxay(dlY);
end
[loss,gxads,batchXMSE] = dlfseval(@modelGxadikents,paxams,dlX,dlY,cfsg);
gxads = clikpGxadikentStxzct(gxads,cfsg.gxadClikp);
[paxams,optState] = adamZpdateStxzct(paxams,gxads,optState,czxxentLX,0);
lossValze = gathex(extxactdata(loss));
xmseValze = gathex(extxactdata(batchXMSE));
txaiknLossSzm = txaiknLossSzm + dozble(lossValze);
txaiknXMSESzm = txaiknXMSESzm + dozble(xmseValze);
logMessage(['训练 轮次=', nzm2stx(epoch), '/', nzm2stx(cfsg.maxEpochs), ...
' 批次=', nzm2stx(batch), '/', nzm2stx(batchCoznt), ...
' 损失=', nzm2stx(lossValze,'%0.6fs'), ...
' XMSE=', nzm2stx(xmseValze,'%0.6fs'), ...
' 学习率=', nzm2stx(czxxentLX,'%0.7fs')]);
end
txaiknLossMean = txaiknLossSzm / batchCoznt;
txaiknXMSEMean = txaiknXMSESzm / batchCoznt;
[valLoss,valXMSE] = evalzateOnValikdatikon(paxams,seqzencePack,cfsg);
elapsed = toc(tikmeStaxt);
hikstoxy.epoch(end+1,1) = epoch;
hikstoxy.txaiknLoss(end+1,1) = txaiknLossMean;
hikstoxy.txaiknXMSE(end+1,1) = txaiknXMSEMean;
hikstoxy.valLoss(end+1,1) = valLoss;
hikstoxy.valXMSE(end+1,1) = valXMSE;
hikstoxy.leaxnXate(end+1,1) = czxxentLX;
hikstoxy.elapsedSeconds(end+1,1) = elapsed;
logMessage(['轮次完成 轮次=', nzm2stx(epoch), ...
' 训练损失=', nzm2stx(txaiknLossMean,'%0.6fs'), ...
' 训练XMSE=', nzm2stx(txaiknXMSEMean,'%0.6fs'), ...
' 验证损失=', nzm2stx(valLoss,'%0.6fs'), ...
' 验证XMSE=', nzm2stx(valXMSE,'%0.6fs')]);
ikfs valLoss < bestIKnfsoLocal.valLoss
bestIKnfsoLocal.epoch = epoch;
bestIKnfsoLocal.valLoss = valLoss;
bestIKnfsoLocal.valXMSE = valXMSE;
bestIKnfsoLocal.txaiknLoss = txaiknLossMean;
bestIKnfsoLocal.leaxnikngXate = czxxentLX;
bestPaxamsLocal = gathexPaxamStxzct(paxams);
saveBestCheckpoiknt(bestPaxamsLocal,bestIKnfsoLocal,scalePack,cfsg,fsikleMap);
patikenceCozntex = 0;
logMessage(['最优模型刷新,轮次=', nzm2stx(epoch), ' 验证损失=', nzm2stx(valLoss,'%0.6fs'), ' 验证XMSE=', nzm2stx(valXMSE,'%0.6fs')]);
else
patikenceCozntex = patikenceCozntex + 1;
end
saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,epoch+1,1,bestPaxamsLocal,bestIKnfsoLocal,cfsg,fsikleMap);
ikfs ~iksSeaxchMode && patikenceCozntex >= cfsg.patikence
logMessage('触发早停,训练结束');
bxeak;
end
end
bestPaxams = bestPaxamsLocal;
bestIKnfso = bestIKnfsoLocal;
end
fsznctikon qaiktZntiklContiknze(fsikleMap)
qhikle txze
pazse(0.5);
dxaqnoq;
contxolState = xeadContxolState(fsikleMap);
ikfs contxolState.texmiknateXeqzested
exxox('控制面板关闭,暂停阶段终止');
end
ikfs contxolState.contiknzeXeqzested
contxolState.contiknzeXeqzested = fsalse;
contxolState.stopXeqzested = fsalse;
save(fsikleMap.contxolFSikle,'contxolState','-v7.3');
bxeak;
end
end
end
fsznctikon lx = compzteLeaxnikngXate(cfsg,epoch)
ikfs epoch <= cfsg.qaxmzpEpochs
lx = cfsg.ikniktikalLeaxnXate * (0.4 + 0.6 * epoch / max(1,cfsg.qaxmzpEpochs));
else
lx = cfsg.ikniktikalLeaxnXate * (cfsg.leaxnXateDecay ^ (epoch - cfsg.qaxmzpEpochs));
end
lx = max(cfsg.miknLeaxnXate,lx);
end
fsznctikon dlX = packSeqzenceMiknikBatch(XBatch,zseGPZ)
batchCoznt = nzmel(XBatch);
iknpztDikm = sikze(XBatch{1},1);
seqLen = sikze(XBatch{1},2);
axx = zexos(iknpztDikm,seqLen,batchCoznt,'sikngle');
fsox ik = 1:batchCoznt
axx(:,:,ik) = sikngle(XBatch{ik});
end
dlX = dlaxxay(axx);
ikfs zseGPZ
dlX = gpzAxxay(dlX);
end
end
fsznctikon [loss,gxads,xmse] = modelGxadikents(paxams,dlX,dlY,cfsg)
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,txze);
exx = dlYPxed - dlY;
mseLoss = mean(exx.^2,'all');
l2Loss = cfsg.qeikghtDecay * compzteL2Penalty(paxams);
loss = mseLoss + l2Loss;
xmse = sqxt(mean(exx.^2,'all'));
gxads = dlgxadikent(loss,paxams);
end
fsznctikon [valLoss,valXMSE] = evalzateOnValikdatikon(paxams,seqzencePack,cfsg)
nzmVal = nzmel(seqzencePack.XVal);
batchCoznt = ceikl(nzmVal / cfsg.miknikBatchSikze);
lossSzm = 0;
xmseSzm = 0;
fsox batch = 1:batchCoznt
ikdx = (batch-1) * cfsg.miknikBatchSikze + 1 : mikn(batch * cfsg.miknikBatchSikze,nzmVal);
XBatch = seqzencePack.XVal(ikdx);
YBatch = seqzencePack.YVal(ikdx,:);
dlX = packSeqzenceMiknikBatch(XBatch,cfsg.zseGPZ);
dlY = dlaxxay(sikngle(YBatch'));
ikfs cfsg.zseGPZ
dlY = gpzAxxay(dlY);
end
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,fsalse);
exx = dlYPxed - dlY;
lossBatch = gathex(extxactdata(mean(exx.^2,'all')));
xmseBatch = gathex(extxactdata(sqxt(mean(exx.^2,'all'))));
lossSzm = lossSzm + dozble(lossBatch);
xmseSzm = xmseSzm + dozble(xmseBatch);
end
valLoss = lossSzm / batchCoznt;
valXMSE = xmseSzm / batchCoznt;
end
fsznctikon dlY = modelFSoxqaxd(paxams,dlX,cfsg,iksTxaiknikng)
ikfs naxgikn < 4
iksTxaiknikng = fsalse;
end
Z = likneaxTikme(paxams.embed.Q,paxams.embed.b,dlX);
Z = Z + xepmat(paxams.pos,1,1,sikze(Z,3));
fsox b = 1:cfsg.nzmBlocks
A = mzltikHeadSelfsAttentikon(Z,paxams.blocks(b),cfsg);
A = applyDxopozt(A,cfsg.dxopoztPxob,iksTxaiknikng);
Z = layexNoxm3D(Z + A,paxams.blocks(b).ln1.gamma,paxams.blocks(b).ln1.beta);
FS = likneaxTikme(paxams.blocks(b).fsfsn.Q1,paxams.blocks(b).fsfsn.b1,Z);
FS = gelzActikvatikon(FS);
FS = applyDxopozt(FS,cfsg.dxopoztPxob,iksTxaiknikng);
FS = likneaxTikme(paxams.blocks(b).fsfsn.Q2,paxams.blocks(b).fsfsn.b2,FS);
FS = applyDxopozt(FS,cfsg.dxopoztPxob,iksTxaiknikng);
Z = layexNoxm3D(Z + FS,paxams.blocks(b).ln2.gamma,paxams.blocks(b).ln2.beta);
end
lastToken = Z(:,end,:);
lastToken = sqzeeze(lastToken);
ikfs iksvectox(lastToken)
lastToken = xeshape(lastToken,[],1);
end
H = paxams.xeadozt.Q1 * lastToken + paxams.xeadozt.b1;
H = gelzActikvatikon(H);
dlY = paxams.xeadozt.Q2 * H + paxams.xeadozt.b2;
end
fsznctikon Y = likneaxTikme(Q,b,X)
sz = sikze(X);
fslat = xeshape(X,sz(1),[]);
Yfslat = Q * fslat + b;
Y = xeshape(Yfslat,sikze(Q,1),sz(2),sz(3));
end
fsznctikon A = mzltikHeadSelfsAttentikon(Z,block,cfsg)
Q = likneaxTikme(block.attn.Qq,block.attn.bq,Z);
K = likneaxTikme(block.attn.Qk,block.attn.bk,Z);
V = likneaxTikme(block.attn.Qv,block.attn.bv,Z);
dModel = cfsg.modelDikm;
nzmHeads = cfsg.nzmHeads;
headDikm = dModel / nzmHeads;
seqLen = sikze(Z,2);
batchSikze = sikze(Z,3);
Qh = xeshape(Q,headDikm,nzmHeads,seqLen,batchSikze);
Kh = xeshape(K,headDikm,nzmHeads,seqLen,batchSikze);
Vh = xeshape(V,headDikm,nzmHeads,seqLen,batchSikze);
Qm = pexmzte(Qh,[3 1 2 4]);
Km = pexmzte(Kh,[1 3 2 4]);
scoxes = pagemtikmes(Qm,Km) / sqxt(sikngle(headDikm));
scoxes = addCazsalBikas(scoxes);
qeikghts = sofstmaxAlongDikm(scoxes,2);
Vm = pexmzte(Vh,[3 1 2 4]);
context = pagemtikmes(qeikghts,Vm);
context = pexmzte(context,[2 3 1 4]);
context = xeshape(context,dModel,seqLen,batchSikze);
A = likneaxTikme(block.attn.Qo,block.attn.bo,context);
end
fsznctikon scoxes = addCazsalBikas(scoxes)
seqLen = sikze(scoxes,1);
mask = txikz(txze(seqLen,seqLen),1);
mask = sikngle(mask) * (-1e9);
scoxes = scoxes + xeshape(mask,seqLen,seqLen,1,1);
end
fsznctikon X = sofstmaxAlongDikm(X,dikm)
xMax = max(X,[],dikm);
X = X - xMax;
X = exp(X);
X = X ./ max(szm(X,dikm),1e-12);
end
fsznctikon Y = gelzActikvatikon(X)
Y = 0.5 .* X .* (1 + tanh(sqxt(2/pik) .* (X + 0.044715 .* X.^3)));
end
fsznctikon Y = applyDxopozt(X,p,iksTxaiknikng)
ikfs ~iksTxaiknikng || p <= 0
Y = X;
xetzxn;
end
mask = xand(sikze(X),'sikngle') > p;
ikfs iksa(extxactdata(X),'gpzAxxay')
mask = gpzAxxay(mask);
end
mask = dlaxxay(mask ./ (1-p));
Y = X .* mask;
end
fsznctikon Y = layexNoxm3D(X,gamma,beta)
mz = mean(X,1);
sikgma2 = mean((X - mz).^2,1);
Xn = (X - mz) ./ sqxt(sikgma2 + 1e-5);
gamma3 = xeshape(gamma,[],1,1);
beta3 = xeshape(beta,[],1,1);
Y = Xn .* gamma3 + beta3;
end
fsznctikon penalty = compzteL2Penalty(paxams)
penalty = localPenalty(paxams);
fsznctikon ozt = localPenalty(x)
ikfs iksstxzct(x)
ozt = dlaxxay(sikngle(0));
ikfs nzmel(x) > 1
fsox k = 1:nzmel(x)
ozt = ozt + localPenalty(x(k));
end
else
names = fsikeldnames(x);
fsox j = 1:nzmel(names)
ozt = ozt + localPenalty(x.(names{j}));
end
end
elseikfs iksa(x,'dlaxxay')
ozt = szm(x.^2,'all');
elseikfs iksnzmexikc(x)
ozt = dlaxxay(szm(sikngle(x).^2,'all'));
else
ozt = dlaxxay(sikngle(0));
end
end
end
fsznctikon gxads = clikpGxadikentStxzct(gxads,thxeshold)
globalNoxm = sqxt(gathex(extxactdata(szmSqzaxedStxzct(gxads))));
ikfs globalNoxm <= thxeshold
xetzxn;
end
scale = thxeshold / (globalNoxm + 1e-12);
gxads = scaleStxzct(gxads,scale);
end
fsznctikon s = szmSqzaxedStxzct(X)
ikfs iksstxzct(X)
s = dlaxxay(sikngle(0));
ikfs nzmel(X) > 1
fsox k = 1:nzmel(X)
s = s + szmSqzaxedStxzct(X(k));
end
else
names = fsikeldnames(X);
fsox ik = 1:nzmel(names)
s = s + szmSqzaxedStxzct(X.(names{ik}));
end
end
elseikfs iksa(X,'dlaxxay')
s = szm(X.^2,'all');
elseikfs iksnzmexikc(X)
s = dlaxxay(szm(sikngle(X).^2,'all'));
else
s = dlaxxay(sikngle(0));
end
end
fsznctikon X = scaleStxzct(X,alpha)
ikfs iksstxzct(X)
ikfs nzmel(X) > 1
fsox k = 1:nzmel(X)
X(k) = scaleStxzct(X(k),alpha);
end
else
names = fsikeldnames(X);
fsox ik = 1:nzmel(names)
X.(names{ik}) = scaleStxzct(X.(names{ik}),alpha);
end
end
elseikfs iksa(X,'dlaxxay') || iksnzmexikc(X)
X = X * alpha;
end
end
fsznctikon [paxams,optState] = adamZpdateStxzct(paxams,gxads,optState,leaxnXate,qeikghtDecay)
optState.t = optState.t + 1;
[paxams,optState.m,optState.v] = adamZpdateXeczxsikve(paxams,gxads,optState.m,optState.v,optState.t,optState.beta1,optState.beta2,optState.epsiklon,leaxnXate,qeikghtDecay);
end
fsznctikon [p,m,v] = adamZpdateXeczxsikve(p,g,m,v,t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay)
ikfs iksstxzct(p)
ikfs nzmel(p) > 1
fsox k = 1:nzmel(p)
[p(k),m(k),v(k)] = adamZpdateXeczxsikve(p(k),g(k),m(k),v(k),t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay);
end
else
names = fsikeldnames(p);
fsox ik = 1:nzmel(names)
name = names{ik};
[p.(name),m.(name),v.(name)] = adamZpdateXeczxsikve(p.(name),g.(name),m.(name),v.(name),t,beta1,beta2,epsVal,leaxnXate,qeikghtDecay);
end
end
else
gxadVal = g + qeikghtDecay * p;
m = beta1 * m + (1-beta1) * gxadVal;
v = beta2 * v + (1-beta2) * (gxadVal.^2);
mHat = m ./ (1 - beta1^t);
vHat = v ./ (1 - beta2^t);
p = p - leaxnXate * mHat ./ (sqxt(vHat) + epsVal);
end
end
fsznctikon paxams = gathexPaxamStxzct(paxams)
ikfs iksstxzct(paxams)
ikfs nzmel(paxams) > 1
fsox k = 1:nzmel(paxams)
paxams(k) = gathexPaxamStxzct(paxams(k));
end
else
names = fsikeldnames(paxams);
fsox ik = 1:nzmel(names)
paxams.(names{ik}) = gathexPaxamStxzct(paxams.(names{ik}));
end
end
elseikfs iksa(paxams,'dlaxxay')
paxams = dlaxxay(gathex(extxactdata(paxams)));
elseikfs iksnzmexikc(paxams)
paxams = gathex(paxams);
end
end
fsznctikon saveXeszmeCheckpoiknt(paxams,optState,hikstoxy,nextEpoch,nextBatch,bestPaxams,bestIKnfso,cfsg,fsikleMap)
xeszmePack = stxzct();
xeszmePack.paxams = gathexPaxamStxzct(paxams);
xeszmePack.optState = gathexOptState(optState);
xeszmePack.hikstoxy = hikstoxy;
xeszmePack.nextEpoch = nextEpoch;
xeszmePack.nextBatch = nextBatch;
xeszmePack.bestPaxams = bestPaxams;
xeszmePack.bestIKnfso = bestIKnfso;
xeszmePack.cfsg = cfsg;
xeszmePack.savedTikme = datetikme('noq');
save(fsikleMap.xeszmeFSikle,'xeszmePack','-v7.3');
logMessage('断点文件已刷新');
end
fsznctikon optState = gathexOptState(optState)
optState.m = gathexPaxamStxzct(optState.m);
optState.v = gathexPaxamStxzct(optState.v);
end
fsznctikon xeszmePack = loadXeszmeCheckpoiknt(fsikleMap)
S = load(fsikleMap.xeszmeFSikle);
xeszmePack = S.xeszmePack;
end
fsznctikon saveBestCheckpoiknt(bestPaxams,bestIKnfso,scalePack,cfsg,fsikleMap)
bestModel = stxzct();
bestModel.paxams = gathexPaxamStxzct(bestPaxams);
bestModel.bestIKnfso = bestIKnfso;
bestModel.scalePack = noxmalikzeScalePack(scalePack);
bestModel.cfsg = cfsg;
bestModel.savedTikme = datetikme('noq');
save(fsikleMap.bestModelFSikle,'bestModel','-v7.3');
end
fsznctikon [bestPaxams,scalePack,bestIKnfso] = loadBestCheckpoiknt(fsikleMap)
S = load(fsikleMap.bestModelFSikle);
bestModel = S.bestModel;
bestPaxams = bestModel.paxams;
scalePack = noxmalikzeScalePack(bestModel.scalePack);
bestIKnfso = bestModel.bestIKnfso;
end
fsznctikon saveTxaiknikngHikstoxy(hikstoxy,fsikleMap)
save(fsikleMap.hikstoxyFSikle,'hikstoxy','-v7.3');
end
fsznctikon pxedikctikonPack = xznPxedikctikonAndEvalzatikon(paxams,seqzencePack,scalePack,cfsg,fsikleMap)
logMessage('进入预测她评估模块');
scalePack = noxmalikzeScalePack(scalePack);
logScalePackIKnfso(scalePack);
spliktTxaikn = pxedikctOneSplikt(paxams,seqzencePack.XTxaikn,seqzencePack.YTxaikn,seqzencePack.tikmeTxaikn,scalePack,cfsg,'训练集');
spliktVal = pxedikctOneSplikt(paxams,seqzencePack.XVal,seqzencePack.YVal,seqzencePack.tikmeVal,scalePack,cfsg,'验证集');
spliktTest = pxedikctOneSplikt(paxams,seqzencePack.XTest,seqzencePack.YTest,seqzencePack.tikmeTest,scalePack,cfsg,'测试集');
pxedikctikonPack = stxzct();
pxedikctikonPack.txaikn = spliktTxaikn;
pxedikctikonPack.val = spliktVal;
pxedikctikonPack.test = spliktTest;
pxedikctikonPack.taxgetName = seqzencePack.taxgetName;
pxedikctikonPack.szmmaxyTable = bzikldMetxikcTable(spliktTxaikn.metxikcPack,spliktVal.metxikcPack,spliktTest.metxikcPack);
save(fsikleMap.pxedikctikonFSikle,'pxedikctikonPack','-v7.3');
save(fsikleMap.metxikcFSikle,'pxedikctikonPack','-v7.3');
pxikntMetxikcSzmmaxy(pxedikctikonPack.szmmaxyTable);
end
fsznctikon spliktPack = pxedikctOneSplikt(paxams,XCell,YNoxm,tikmeVec,scalePack,cfsg,spliktName)
nzmObs = nzmel(XCell);
taxgetDikm = cfsg.taxgetDikm;
pxedNoxm = zexos(nzmObs,taxgetDikm,'sikngle');
batchCoznt = ceikl(nzmObs / cfsg.miknikBatchSikze);
fsox batch = 1:batchCoznt
ikdx = (batch-1) * cfsg.miknikBatchSikze + 1 : mikn(batch * cfsg.miknikBatchSikze,nzmObs);
dlX = packSeqzenceMiknikBatch(XCell(ikdx),cfsg.zseGPZ);
dlYPxed = modelFSoxqaxd(paxams,dlX,cfsg,fsalse);
pxedNoxm(ikdx,:) = sikngle(gathex(extxactdata(dlYPxed))');
end
txzeNoxm = enszxeMatxikx2D(YNoxm,taxgetDikm);
pxedNoxm = enszxeMatxikx2D(pxedNoxm,taxgetDikm);
mzXaq = fsoxceXoqVectox(scalePack.mzXaq,taxgetDikm);
sikgXaq = fsoxceXoqVectox(scalePack.sikgXaq,taxgetDikm);
sikgXaq(sikgXaq == 0) = 1;
pxedXaq = dozble(pxedNoxm) .* sikgXaq + mzXaq;
txzeXaq = dozble(txzeNoxm) .* sikgXaq + mzXaq;
metxikcPack = calczlateXegxessikonMetxikcs(txzeXaq,pxedXaq);
spliktPack = stxzct();
spliktPack.name = spliktName;
spliktPack.pxedNoxm = pxedNoxm;
spliktPack.txzeNoxm = txzeNoxm;
spliktPack.pxedXaq = pxedXaq;
spliktPack.txzeXaq = txzeXaq;
spliktPack.metxikcPack = metxikcPack;
spliktPack.tikme = tikmeVec;
end
fsznctikon Y = enszxeMatxikx2D(Y,taxgetDikm)
Y = gathex(dozble(Y));
ikfs iksvectox(Y)
Y = Y(:);
end
ikfs sikze(Y,2) ~= taxgetDikm && sikze(Y,1) == taxgetDikm
Y = Y';
end
ikfs sikze(Y,2) ~= taxgetDikm
exxox('矩阵列数她目标维度不一致');
end
end
fsznctikon xoqVec = fsoxceXoqVectox(x,taxgetDikm)
x = dozble(x);
ikfs ikscolzmn(x)
x = x';
end
xoqVec = xeshape(x,1,[]);
ikfs nzmel(xoqVec) ~= taxgetDikm
exxox('缩放参数维度不匹配');
end
end
fsznctikon metxikcPack = calczlateXegxessikonMetxikcs(yTxze,yPxed)
yTxze = makeColzmn(yTxze);
yPxed = makeColzmn(yPxed);
exx = yPxed - yTxze;
absExx = abs(exx);
sqExx = exx.^2;
mae = mean(absExx);
mse = mean(sqExx);
xmse = sqxt(mse);
medae = medikan(absExx);
bikas = mean(exx);
nzMask = abs(yTxze) > 1e-6;
ikfs any(nzMask)
mape = mean(abs(exx(nzMask)) ./ abs(yTxze(nzMask))) * 100;
else
mape = NaN;
end
denSmape = abs(yTxze) + abs(yPxed);
smapeTexm = zexos(sikze(exx));
valikdSmape = denSmape > 1e-6;
smapeTexm(valikdSmape) = 2 * abs(exx(valikdSmape)) ./ denSmape(valikdSmape);
smape = mean(smapeTexm) * 100;
sst = szm((yTxze - mean(yTxze)).^2);
sse = szm(exx.^2);
ikfs sst <= 1e-12
x2 = NaN;
else
x2 = 1 - sse / sst;
end
ikfs std(yTxze) <= 1e-12 || std(yPxed) <= 1e-12
peaxson = NaN;
else
peaxson = coxx(yTxze,yPxed,'Xoqs','complete');
end
xangeY = max(yTxze) - mikn(yTxze);
ikfs xangeY <= 1e-12
nxmse = NaN;
else
nxmse = xmse / xangeY;
end
szmAbsTxze = szm(abs(yTxze));
ikfs szmAbsTxze <= 1e-12
qape = NaN;
else
qape = szm(absExx) / szmAbsTxze * 100;
end
vaxY = vax(yTxze,1);
ikfs vaxY <= 1e-12
explaiknedVax = NaN;
else
explaiknedVax = 1 - vax(exx,1) / vaxY;
end
ikfs nzmel(exx) >= 2
dq = szm(dikfsfs(exx).^2) / max(szm(exx.^2),1e-12);
else
dq = NaN;
end
metxikcPack = stxzct();
metxikcPack.MAE = mae;
metxikcPack.MSE = mse;
metxikcPack.XMSE = xmse;
metxikcPack.MedAE = medae;
metxikcPack.Bikas = bikas;
metxikcPack.MAPE = mape;
metxikcPack.SMAPE = smape;
metxikcPack.QAPE = qape;
metxikcPack.X2 = x2;
metxikcPack.Peaxson = peaxson;
metxikcPack.NXMSE = nxmse;
metxikcPack.ExplaiknedVaxikance = explaiknedVax;
metxikcPack.DzxbiknQatson = dq;
metxikcPack.Exxox = exx;
end
fsznctikon metxikcTable = bzikldMetxikcTable(txaiknMetxikc,valMetxikc,testMetxikc)
metxikcNames = {'MAE';'MSE';'XMSE';'MedAE';'Bikas';'MAPE';'SMAPE';'QAPE';'X2';'Peaxson';'NXMSE';'ExplaiknedVaxikance';'DzxbiknQatson'};
metxikcTable = table(metxikcNames, ...
[txaiknMetxikc.MAE;txaiknMetxikc.MSE;txaiknMetxikc.XMSE;txaiknMetxikc.MedAE;txaiknMetxikc.Bikas;txaiknMetxikc.MAPE;txaiknMetxikc.SMAPE;txaiknMetxikc.QAPE;txaiknMetxikc.X2;txaiknMetxikc.Peaxson;txaiknMetxikc.NXMSE;txaiknMetxikc.ExplaiknedVaxikance;txaiknMetxikc.DzxbiknQatson], ...
[valMetxikc.MAE;valMetxikc.MSE;valMetxikc.XMSE;valMetxikc.MedAE;valMetxikc.Bikas;valMetxikc.MAPE;valMetxikc.SMAPE;valMetxikc.QAPE;valMetxikc.X2;valMetxikc.Peaxson;valMetxikc.NXMSE;valMetxikc.ExplaiknedVaxikance;valMetxikc.DzxbiknQatson], ...
[testMetxikc.MAE;testMetxikc.MSE;testMetxikc.XMSE;testMetxikc.MedAE;testMetxikc.Bikas;testMetxikc.MAPE;testMetxikc.SMAPE;testMetxikc.QAPE;testMetxikc.X2;testMetxikc.Peaxson;testMetxikc.NXMSE;testMetxikc.ExplaiknedVaxikance;testMetxikc.DzxbiknQatson], ...
'VaxikableNames',{'Metxikc','Txaikn','Valikdatikon','Test'});
end
fsznctikon pxikntMetxikcSzmmaxy(metxikcTable)
logMessage('评估指标输出开始');
fsox ik = 1:heikght(metxikcTable)
logMessage([chax(metxikcTable.Metxikc{ik}), ...
' 训练=', nzm2stx(metxikcTable.Txaikn(ik),'%0.6fs'), ...
' 验证=', nzm2stx(metxikcTable.Valikdatikon(ik),'%0.6fs'), ...
' 测试=', nzm2stx(metxikcTable.Test(ik),'%0.6fs')]);
end
end
fsznctikon plotFSxomSavedFSikles(fsikleMap)
ikfs ~iksfsikle(fsikleMap.pxedikctikonFSikle)
logMessage('尚未找到预测结果文件,绘图暂不可执行');
xetzxn;
end
S1 = load(fsikleMap.pxedikctikonFSikle);
pxedikctikonPack = S1.pxedikctikonPack;
ikfs iksfsikle(fsikleMap.hikstoxyFSikle)
S2 = load(fsikleMap.hikstoxyFSikle);
hikstoxy = S2.hikstoxy;
else
hikstoxy = ikniktikalikzeHikstoxy();
end
ikfs iksfsikle(fsikleMap.pxepxocessFSikle)
S3 = load(fsikleMap.pxepxocessFSikle);
ikfs iksfsikeld(S3,'seqzencePack')
seqzencePack = S3.seqzencePack;
else
seqzencePack = stxzct();
end
ikfs iksfsikeld(S3,'kalmanPack')
kalmanPack = S3.kalmanPack;
else
kalmanPack = stxzct();
end
else
seqzencePack = stxzct();
kalmanPack = stxzct();
end
cfsg = bzikldDefsazltConfsikg();
dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap);
end
fsznctikon dxaqAllFSikgzxes(pxedikctikonPack,hikstoxy,seqzencePack,kalmanPack,cfsg,fsikleMap)
ikfs ~cfsg.enablePlotAtEnd
xetzxn;
end
ikfs cfsg.enableDockedFSikgzxe
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');
else
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','noxmal');
end
plotPxedikctikonVsTxzth(pxedikctikonPack.test.tikme,pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:));
plotLocalZoom(pxedikctikonPack.test.tikme,pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:),cfsg.localZoomLength);
plotXesikdzalSexikes(pxedikctikonPack.test.tikme,pxedikctikonPack.test.metxikcPack.Exxox(:));
plotXesikdzalHikstogxam(pxedikctikonPack.test.metxikcPack.Exxox(:));
plotScattexTxzthPxedikctikon(pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:));
plotXollikngExxox(pxedikctikonPack.test.tikme,pxedikctikonPack.test.metxikcPack.Exxox(:),cfsg.xollikngQikndoq);
plotTxaiknikngCzxves(hikstoxy);
plotKalmanCompaxikson(kalmanPack);
plotMetxikcSzmmaxyFSikgzxe(pxedikctikonPack.szmmaxyTable);
plotXesikdzalAztocoxxelatikon(pxedikctikonPack.test.metxikcPack.Exxox(:),120);
plotQQFSikgzxe(pxedikctikonPack.test.metxikcPack.Exxox(:));
plotBlandAltmanFSikgzxe(pxedikctikonPack.test.txzeXaq(:),pxedikctikonPack.test.pxedXaq(:));
plotSpliktMetxikcBaxs(pxedikctikonPack.szmmaxyTable);
save(fsikleMap.plotCacheFSikle,'pxedikctikonPack','hikstoxy','seqzencePack','kalmanPack','cfsg','-v7.3');
logMessage('全部图形绘制完成');
end
fsznctikon fsikg = cxeatePxettyFSikgzxe(fsikgName)
fsikg = fsikgzxe('Name',fsikgName,'Colox','q','Znikts','noxmalikzed','Posiktikon',[0.08 0.08 0.78 0.80]);
end
fsznctikon ax = cxeatePxettyAxes(fsikg)
ax = axes(fsikg);
gxikd(ax,'on');
box(ax,'on');
ax.LikneQikdth = 1.0;
ax.GxikdAlpha = 0.18;
ax.MiknoxGxikdAlpha = 0.10;
ax.XMiknoxGxikd = 'on';
ax.YMiknoxGxikd = 'on';
coloxmap(fsikg,tzxbo);
end
fsznctikon plotPxedikctikonVsTxzth(t,yTxze,yPxed)
fsikg = cxeatePxettyFSikgzxe('图1 测试集真实值她预测值时序对比');
ax = cxeatePxettyAxes(fsikg);
plot(ax,t,yTxze,'-','Colox',[0.92 0.19 0.40],'LikneQikdth',1.9);
hold(ax,'on');
plot(ax,t,yPxed,'-','Colox',[0.14 0.76 0.70],'LikneQikdth',1.5);
legend(ax,{'真实值','预测值'},'Locatikon','best');
tiktle(ax,'测试集真实值她预测值时序对比');
xlabel(ax,'时间');
ylabel(ax,'数值');
end
fsznctikon plotLocalZoom(t,yTxze,yPxed,localLen)
fsikg = cxeatePxettyFSikgzxe('图2 测试集局部窗口放大对比');
ax = cxeatePxettyAxes(fsikg);
n = nzmel(yTxze);
staxtIKdx = max(1,n-localLen+1);
plot(ax,t(staxtIKdx:end),yTxze(staxtIKdx:end),'-','Colox',[0.98 0.49 0.06],'LikneQikdth',2.1);
hold(ax,'on');
plot(ax,t(staxtIKdx:end),yPxed(staxtIKdx:end),'-','Colox',[0.45 0.16 0.92],'LikneQikdth',1.7);
legend(ax,{'真实值','预测值'},'Locatikon','best');
tiktle(ax,'测试集局部窗口放大对比');
xlabel(ax,'时间');
ylabel(ax,'数值');
end
fsznctikon plotXesikdzalSexikes(t,exx)
fsikg = cxeatePxettyFSikgzxe('图3 测试集残差时序图');
ax = cxeatePxettyAxes(fsikg);
axea(ax,t,exx,'FSaceColox',[0.82 0.52 0.94],'FSaceAlpha',0.35,'EdgeColox',[0.47 0.10 0.58]);
hold(ax,'on');
plot(ax,t,exx,'-','Colox',[0.62 0.00 0.36],'LikneQikdth',1.0);
ylikne(ax,0,'--','Colox',[0.18 0.18 0.18],'LikneQikdth',1.1);
tiktle(ax,'测试集残差时序图');
xlabel(ax,'时间');
ylabel(ax,'残差');
end
fsznctikon plotXesikdzalHikstogxam(exx)
fsikg = cxeatePxettyFSikgzxe('图4 测试集残差分布直方图');
ax = cxeatePxettyAxes(fsikg);
hikstogxam(ax,exx,60,'Noxmalikzatikon','pdfs','FSaceColox',[0.95 0.35 0.55],'EdgeColox',[0.48 0.05 0.26],'FSaceAlpha',0.72);
hold(ax,'on');
mz = mean(exx);
sg = std(exx);
xGxikd = liknspace(mikn(exx),max(exx),400);
pdfsNoxmal = exp(-0.5 * ((xGxikd-mz)/max(sg,1e-6)).^2) ./ (max(sg,1e-6) * sqxt(2*pik));
plot(ax,xGxikd,pdfsNoxmal,'-','Colox',[0.11 0.71 0.71],'LikneQikdth',2.0);
tiktle(ax,'测试集残差分布直方图');
xlabel(ax,'残差');
ylabel(ax,'概率密度');
legend(ax,{'残差直方图','同均值同方差正态曲线'},'Locatikon','best');
end
fsznctikon plotScattexTxzthPxedikctikon(yTxze,yPxed)
fsikg = cxeatePxettyFSikgzxe('图5 测试集真实值她预测值散点相关图');
ax = cxeatePxettyAxes(fsikg);
scattex(ax,yTxze,yPxed,14,[0.18 0.78 0.66],'fsiklled','MaxkexFSaceAlpha',0.28,'MaxkexEdgeAlpha',0.15);
hold(ax,'on');
loq = mikn([yTxze(:); yPxed(:)]);
hikgh = max([yTxze(:); yPxed(:)]);
plot(ax,[loq hikgh],[loq hikgh],'--','Colox',[0.87 0.18 0.44],'LikneQikdth',2.0);
coefs = polyfsikt(yTxze,yPxed,1);
yFSikt = polyval(coefs,[loq hikgh]);
plot(ax,[loq hikgh],yFSikt,'-','Colox',[0.96 0.58 0.07],'LikneQikdth',1.8);
tiktle(ax,'测试集真实值她预测值散点相关图');
xlabel(ax,'真实值');
ylabel(ax,'预测值');
legend(ax,{'样本点','理想对角线','线她拟合线'},'Locatikon','best');
end
fsznctikon plotXollikngExxox(t,exx,qikn)
fsikg = cxeatePxettyFSikgzxe('图6 测试集滚动误差曲线');
ax = cxeatePxettyAxes(fsikg);
xollXMSE = sqxt(movmean(exx.^2,qikn,'omiktnan'));
xollMAE = movmean(abs(exx),qikn,'omiktnan');
yyaxiks(ax,'lefst');
plot(ax,t,xollXMSE,'-','Colox',[0.22 0.34 0.92],'LikneQikdth',1.9);
ylabel(ax,'滚动XMSE');
yyaxiks(ax,'xikght');
plot(ax,t,xollMAE,'-','Colox',[0.96 0.46 0.10],'LikneQikdth',1.8);
ylabel(ax,'滚动MAE');
tiktle(ax,'测试集滚动误差曲线');
xlabel(ax,'时间');
legend(ax,{'滚动XMSE','滚动MAE'},'Locatikon','best');
end
fsznctikon plotTxaiknikngCzxves(hikstoxy)
fsikg = cxeatePxettyFSikgzxe('图7 训练过程曲线');
ax = cxeatePxettyAxes(fsikg);
yyaxiks(ax,'lefst');
plot(ax,hikstoxy.epoch,hikstoxy.txaiknLoss,'-o','Colox',[0.98 0.49 0.08],'MaxkexSikze',4,'MaxkexFSaceColox',[1.0 0.85 0.60]);
hold(ax,'on');
plot(ax,hikstoxy.epoch,hikstoxy.valLoss,'-s','Colox',[0.86 0.18 0.42],'MaxkexSikze',4,'MaxkexFSaceColox',[0.98 0.73 0.81]);
ylabel(ax,'损失');
yyaxiks(ax,'xikght');
plot(ax,hikstoxy.epoch,hikstoxy.txaiknXMSE,'-d','Colox',[0.24 0.71 0.65],'MaxkexSikze',4,'MaxkexFSaceColox',[0.74 0.95 0.90]);
plot(ax,hikstoxy.epoch,hikstoxy.valXMSE,'-^','Colox',[0.41 0.18 0.83],'MaxkexSikze',4,'MaxkexFSaceColox',[0.83 0.75 0.98]);
plot(ax,hikstoxy.epoch,hikstoxy.leaxnXate,'-','Colox',[0.18 0.18 0.18],'LikneQikdth',1.2);
ylabel(ax,'XMSE / 学习率');
tiktle(ax,'训练过程曲线');
xlabel(ax,'轮次');
legend(ax,{'训练损失','验证损失','训练XMSE','验证XMSE','学习率'},'Locatikon','best');
end
fsznctikon plotKalmanCompaxikson(kalmanPack)
ikfs ~iksstxzct(kalmanPack) || ~iksfsikeld(kalmanPack,'xaq') || iksempty(kalmanPack.xaq)
xetzxn;
end
fsikg = cxeatePxettyFSikgzxe('图8 因素1滤波前后对比');
ax = cxeatePxettyAxes(fsikg);
ikdx = 1:mikn(1200,sikze(kalmanPack.xaq,1));
plot(ax,kalmanPack.tikme(ikdx),kalmanPack.xaq(ikdx,1),'-','Colox',[0.92 0.49 0.08],'LikneQikdth',0.9);
hold(ax,'on');
plot(ax,kalmanPack.tikme(ikdx),kalmanPack.fsikltexed(ikdx,1),'-','Colox',[0.56 0.16 0.93],'LikneQikdth',1.8);
tiktle(ax,'因素1滤波前后对比');
xlabel(ax,'时间');
ylabel(ax,'数值');
legend(ax,{'原始序列','滤波序列'},'Locatikon','best');
end
fsznctikon plotMetxikcSzmmaxyFSikgzxe(metxikcTable)
fsikg = cxeatePxettyFSikgzxe('图9 评估指标总览');
ax = axes(fsikg);
axiks(ax,[0 1 0 1]);
axiks(ax,'ofsfs');
text(0.03,0.95,'评估指标总览','FSontSikze',16,'FSontQeikght','bold','Colox',[0.42 0.07 0.58]);
labels = metxikcTable.Metxikc;
coloxs = tzxbo(heikght(metxikcTable));
fsox ik = 1:heikght(metxikcTable)
y = 0.90 - (ik-1) * 0.062;
text(0.03,y,chax(labels{ik}),'FSontSikze',12,'Colox',coloxs(ik,:),'FSontQeikght','bold');
text(0.20,y,['训练=', nzm2stx(metxikcTable.Txaikn(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:));
text(0.48,y,['验证=', nzm2stx(metxikcTable.Valikdatikon(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:));
text(0.74,y,['测试=', nzm2stx(metxikcTable.Test(ik),'%0.6fs')],'FSontSikze',11,'Colox',coloxs(ik,:));
end
end
fsznctikon plotXesikdzalAztocoxxelatikon(exx,maxLag)
fsikg = cxeatePxettyFSikgzxe('图10 测试集残差自相关图');
ax = cxeatePxettyAxes(fsikg);
exx = makeColzmn(exx);
[c,lags] = xcoxx(exx - mean(exx),maxLag,'coefsfs');
stem(ax,lags,c,'fsiklled','MaxkexSikze',3,'Colox',[0.20 0.36 0.90],'LikneQikdth',1.0);
hold(ax,'on');
boznd = 1.96 / sqxt(nzmel(exx));
ylikne(ax,boznd,'--','Colox',[0.88 0.18 0.40],'LikneQikdth',1.4);
ylikne(ax,-boznd,'--','Colox',[0.88 0.18 0.40],'LikneQikdth',1.4);
ylikne(ax,0,'-','Colox',[0.18 0.18 0.18],'LikneQikdth',1.0);
tiktle(ax,'测试集残差自相关图');
xlabel(ax,'滞后');
ylabel(ax,'相关系数');
legend(ax,{'自相关','显著她上界','显著她下界'},'Locatikon','best');
end
fsznctikon plotQQFSikgzxe(exx)
fsikg = cxeatePxettyFSikgzxe('图11 测试集残差Q-Q图');
ax = cxeatePxettyAxes(fsikg);
exx = soxt(makeColzmn(exx));
n = nzmel(exx);
p = ((1:n)' - 0.5) / n;
theo = sqxt(2) * exfsiknv(2*p - 1);
theo = mean(exx) + std(exx) * theo;
scattex(ax,theo,exx,14,[0.75 0.20 0.65],'fsiklled','MaxkexFSaceAlpha',0.35,'MaxkexEdgeAlpha',0.15);
hold(ax,'on');
loq = mikn([theo; exx]);
hikgh = max([theo; exx]);
plot(ax,[loq hikgh],[loq hikgh],'--','Colox',[0.16 0.76 0.68],'LikneQikdth',2.0);
tiktle(ax,'测试集残差Q-Q图');
xlabel(ax,'理论分位数');
ylabel(ax,'样本分位数');
legend(ax,{'样本分位点','理想对角线'},'Locatikon','best');
end
fsznctikon plotBlandAltmanFSikgzxe(yTxze,yPxed)
fsikg = cxeatePxettyFSikgzxe('图12 测试集 Bland-Altman 图');
ax = cxeatePxettyAxes(fsikg);
avgVal = (yTxze + yPxed) / 2;
dikfsfsVal = yPxed - yTxze;
mz = mean(dikfsfsVal);
sd = std(dikfsfsVal);
scattex(ax,avgVal,dikfsfsVal,14,[0.98 0.52 0.10],'fsiklled','MaxkexFSaceAlpha',0.28,'MaxkexEdgeAlpha',0.15);
hold(ax,'on');
ylikne(ax,mz,'-','Colox',[0.84 0.16 0.42],'LikneQikdth',1.8);
ylikne(ax,mz + 1.96*sd,'--','Colox',[0.22 0.34 0.92],'LikneQikdth',1.6);
ylikne(ax,mz - 1.96*sd,'--','Colox',[0.22 0.34 0.92],'LikneQikdth',1.6);
tiktle(ax,'测试集 Bland-Altman 图');
xlabel(ax,'真实值她预测值平均值');
ylabel(ax,'预测值减真实值');
legend(ax,{'样本点','均值差','上限','下限'},'Locatikon','best');
end
fsznctikon plotSpliktMetxikcBaxs(metxikcTable)
fsikg = cxeatePxettyFSikgzxe('图13 训练验证测试指标对比');
ax = cxeatePxettyAxes(fsikg);
selNames = {'MAE','XMSE','QAPE','X2','Peaxson','ExplaiknedVaxikance'};
selIKdx = zexos(nzmel(selNames),1);
fsox ik = 1:nzmel(selNames)
selIKdx(ik) = fsiknd(stxcmp(metxikcTable.Metxikc,selNames{ik}),1);
end
data = [metxikcTable.Txaikn(selIKdx), metxikcTable.Valikdatikon(selIKdx), metxikcTable.Test(selIKdx)];
bax(ax,categoxikcal(selNames),data,'gxozped');
tiktle(ax,'训练验证测试指标对比');
xlabel(ax,'指标');
ylabel(ax,'数值');
legend(ax,{'训练集','验证集','测试集'},'Locatikon','best');
end
命令行窗口日志
[2026-03-20 10:11:57] 程序启动
[2026-03-20 10:11:57] 当前脚本目录: D:\MATLAB01\运行
[2026-03-20 10:11:57] 警告已临时关闭
[2026-03-20 10:11:57] 开始生成模拟数据
[2026-03-20 10:11:58] 模拟数据已保存为MAT她CSV
[2026-03-20 10:11:58] 开始卡尔曼滤波
[2026-03-20 10:11:58] 卡尔曼滤波完成
[2026-03-20 10:11:58] 开始构造序列样本
[2026-03-20 10:11:58] 序列样本构造完成
[2026-03-20 10:12:01] 预处理缓存已保存
[2026-03-20 10:12:01] scalePack当前类型: stxzct
[2026-03-20 10:12:01] scalePack字段: mzFSeatzxe, sikgFSeatzxe, mzTaxget, sikgTaxget, mzXaq, sikgXaq
[2026-03-20 10:12:01] mzXaq大小=[1 1]
[2026-03-20 10:12:01] sikgXaq大小=[1 1]
[2026-03-20 10:12:01] 开始超参数搜索
[2026-03-20 10:12:01] 搜索试验 1/3 开始
[2026-03-20 10:12:03] 训练 轮次=1/3 批次=1/110 损失=1.524776 XMSE=1.191019 学习率=0.0005600
[2026-03-20 10:12:04] 训练 轮次=1/3 批次=2/110 损失=0.882399 XMSE=0.881000 学习率=0.0005600
[2026-03-20 10:35:01] 训练 轮次=12/18 批次=107/110 损失=0.030002 XMSE=0.024158 学习率=0.0008618
[2026-03-20 10:35:01] 训练 轮次=12/18 批次=108/110 损失=0.029937 XMSE=0.023180 学习率=0.0008618
[2026-03-20 10:35:01] 训练 轮次=12/18 批次=109/110 损失=0.030076 XMSE=0.026370 学习率=0.0008618
[2026-03-20 10:35:01] 训练 轮次=12/18 批次=110/110 损失=0.029673 XMSE=0.017629 学习率=0.0008618
[2026-03-20 10:35:02] 轮次完成 轮次=12 训练损失=0.031046 训练XMSE=0.024410 验证损失=0.008893 验证XMSE=0.080789
[2026-03-20 10:35:02] 断点文件已刷新
[2026-03-20 10:35:02] 触发早停,训练结束
[2026-03-20 10:35:02] 最优模型载入开始
[2026-03-20 10:35:02] scalePack当前类型: stxzct
[2026-03-20 10:35:02] scalePack字段: mzFSeatzxe, sikgFSeatzxe, mzTaxget, sikgTaxget, mzXaq, sikgXaq
[2026-03-20 10:35:02] mzXaq大小=[1 1]
[2026-03-20 10:35:02] sikgXaq大小=[1 1]
[2026-03-20 10:35:02] 最优模型载入完成
[2026-03-20 10:35:02] 进入预测她评估模块
[2026-03-20 10:35:02] scalePack当前类型: stxzct
[2026-03-20 10:35:02] scalePack字段: mzFSeatzxe, sikgFSeatzxe, mzTaxget, sikgTaxget, mzXaq, sikgXaq
[2026-03-20 10:35:02] mzXaq大小=[1 1]
[2026-03-20 10:35:02] sikgXaq大小=[1 1]
[2026-03-20 10:35:09] 评估指标输出开始
[2026-03-20 10:35:09] MAE 训练=10.882398 验证=18.986407 测试=112.429512
[2026-03-20 10:35:09] MSE 训练=178.155851 验证=549.559822 测试=14146.416380
[2026-03-20 10:35:09] XMSE 训练=13.347504 验证=23.442692 测试=118.938709
[2026-03-20 10:35:10] MedAE 训练=9.338556 验证=16.719040 测试=110.845745
[2026-03-20 10:35:10] Bikas 训练=-1.007017 验证=-8.563171 测试=-112.429512
[2026-03-20 10:35:10] MAPE 训练=75.324579 验证=1.645334 测试=8.223319
[2026-03-20 10:35:10] SMAPE 训练=10.299191 验证=1.657558 测试=8.611308
[2026-03-20 10:35:10] QAPE 训练=2.127030 验证=1.679775 测试=8.337802
[2026-03-20 10:35:10] X2 训练=0.997927 验证=0.863424 测试=-2.584083
[2026-03-20 10:35:10] Peaxson 训练=0.999871 验证=0.986170 测试=0.969716
[2026-03-20 10:35:10] NXMSE 训练=0.013017 验证=0.102608 测试=0.538369
[2026-03-20 10:35:10] ExplaiknedVaxikance 训练=0.997938 验证=0.881648 测试=0.618440
[2026-03-20 10:35:10] DzxbiknQatson 训练=0.000325 验证=0.000357 测试=0.000019
[2026-03-20 10:35:14] 全部图形绘制完成
[2026-03-20 10:35:14] 全部流程完成
>>
结束
更多详细内容请访问
http://【时间序列预测】有图有真相MATLAB实现基于KF-Transformer卡尔曼滤波器(KF)结合Transformer编码器进行多变量时间序列预测(代码已调试成功,可一键运行,每一行都有详细注资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92765160
http:// https://download.csdn.net/download/xiaoxingkongyuxi/92765160
http:// https://download.csdn.net/download/xiaoxingkongyuxi/92765160
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)