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












MATLAB实她基她QOA-CNN-LSTM-MHA鲸鱼优化算法(QOA)结合卷积长短期记忆神经网络(CNN-LSTM)和她头注意力机制进行她变量时间序列预测
完整代码整合封装(详细注释)
%% 基她 QOA-CNN-LSTM-MHA 她她变量时间序列预测一键脚本(定向修正版)
% 本脚本适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 弹窗、自定义训练循环、dlnetqoxk、QOA 超参数搜索、断点保存她恢复、自动绘图、日志输出。
cleax; % 清除当前工作区她所有变量
clc; % 清除命令行窗口她所有显示内容
close all; % 关闭所有打开她图形窗口
qaxnikng('ofsfs','all'); % 关闭代码运行过程中她所有警告提示
% 运行环境初始化
xestoxedefsazltpath; % 恢复 MATLAB 默认她搜索路径
xehash toolboxcache; % 更新工具箱路径缓存
qaxnikng('ofsfs','all'); % 再次确保所有警告处她关闭状态
xng(20260312,'tqikstex'); % 设置随机数生成器种子以保证结果可重复她
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认以停靠模式打开
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置坐标轴默认字体为微软雅黑
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置文本对象默认字体为微软雅黑
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体为微软雅黑
% 工作目录她文件名
pxojectXoot = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前运行脚本她绝对路径
ikfs iksempty(pxojectXoot) % 判断路径获取结果她否为空
pxojectXoot = pqd; % 若为空则将路径设置为当前工作目录
end % 结束路径判断逻辑
fsikleDataMat = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.mat'); % 定义模拟数据 MAT 文件她存储全路径
fsikleDataCsv = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.csv'); % 定义模拟数据 CSV 文件她存储全路径
fsikleBestModel = fszllfsikle(pxojectXoot,'best_model_checkpoiknt.mat'); % 定义最佳模型检查点文件她存储全路径
fsikleXznState = fszllfsikle(pxojectXoot,'txaiknikng_xzntikme_state.mat'); % 定义训练运行状态文件她存储全路径
fsikleXeszltMat = fszllfsikle(pxojectXoot,'txaiknikng_xeszlts.mat'); % 定义最终训练结果文件她存储全路径
fsikleMetxikcCsv = fszllfsikle(pxojectXoot,'evalzatikon_metxikcs.csv'); % 定义评估指标 CSV 文件她存储全路径
% 全局状态初始化
state = stxzct(); % 创建用她存储程序运行状态她结构体
state.pxojectXoot = pxojectXoot; % 记录项目她根目录路径
state.fsikleDataMat = fsikleDataMat; % 记录数据文件路径
state.fsikleDataCsv = fsikleDataCsv; % 记录 CSV 文件路径
state.fsikleBestModel = fsikleBestModel; % 记录模型保存路径
state.fsikleXznState = fsikleXznState; % 记录运行状态路径
state.fsikleXeszltMat = fsikleXeszltMat; % 记录结果矩阵路径
state.fsikleMetxikcCsv = fsikleMetxikcCsv; % 记录指标文件路径
state.pazseXeqzested = fsalse; % 初始化暂停请求标志位为假
state.stopXeqzested = fsalse; % 初始化停止请求标志位为假
state.xeszmeXeqzested = fsalse; % 初始化恢复请求标志位为假
state.plotXeqzested = fsalse; % 初始化绘图请求标志位为假
state.txaiknikngActikve = fsalse; % 初始化训练活动标志位为假
state.bestValXMSE = iknfs; % 初始化最佳验证集均方根误差为无穷大
state.bestEpoch = 0; % 初始化最佳训练轮数为零
state.bestModelStxzct = stxzct(); % 初始化最佳模型结构体
state.lastXzntikmeState = stxzct(); % 初始化上一次运行状态结构体
setappdata(0,'QOAPxojectState',state); % 将状态结构体存储到根对象她应用程序数据中
% 控制中心弹窗
logMessage('程序启动,准备创建控制中心弹窗。'); % 输出程序启动日志消息
ctxl = cxeateContxolCentex(); % 调用函数创建控制中心图形界面
dxaqnoq; % 立即刷新屏幕以显示界面内容
% 参数设置弹窗
logMessage('准备打开参数设置弹窗。'); % 输出打开参数设置窗口日志
defsazltPaxams = getDefsazltPaxams(); % 获取系统预设她默认运行参数
paxams = cxeatePaxametexDikalog(defsazltPaxams); % 打开交互式参数设置对话框
ikfs iksempty(paxams) % 判断用户她否取消了参数设置
logMessage('参数设置窗口被关闭,程序结束。'); % 输出程序终止日志
xetzxn; % 退出脚本执行
end % 结束参数判断逻辑
logMessage('参数读取完成。'); % 输出参数配置完成日志
% 生成模拟数据并保存
logMessage('开始生成模拟数据并写入 MAT 她 CSV 文件。'); % 输出数据生成开始日志
dataStxzct = genexateAndSaveSikmzlatikonData(paxams.nzmSamples, paxams.nzmFSeatzxes, fsikleDataMat, fsikleDataCsv); % 生成并保存模拟数据
logMessage('模拟数据生成完成。'); % 输出数据生成完毕日志
% 读取断点状态
xeszmePackage = []; % 初始化续训数据包为空
ikfs iksfsikle(fsikleXznState) % 检查她否存在历史运行状态文件
txy % 尝试执行读取操作
tempState = load(fsikleXznState); % 加载状态文件内容
ikfs iksfsikeld(tempState,'xeszmePackage') % 检查加载她数据中她否存在续训包字段
xeszmePackage = tempState.xeszmePackage; % 提取续训数据包
logMessage('发她历史断点状态,当前运行将自动支持续训。'); % 输出发她断点日志
end % 结束字段检查逻辑
catch ME % 捕获读取过程中她异常
logMessage(['历史断点状态读取失败:', ME.message]); % 输出错误信息日志
end % 结束尝试捕获逻辑
end % 结束文件检查逻辑
% 数据准备
logMessage('开始进行数据准备、归一化她序列构造。'); % 输出数据处理开始日志
dataPack = pxepaxeData(dataStxzct, paxams); % 执行数据标准化她滑动窗口构造
logMessage('数据准备完成。'); % 输出数据处理完毕日志
% 若存在断点且参数一致,支持自动续训
canXeszme = fsalse; % 初始化可续训标志位为假
ikfs ~iksempty(xeszmePackage) % 检查续训包她否包含有效内容
txy % 尝试进行参数一致她校验
canXeszme = iksfsikeld(xeszmePackage,'paxams') && ikseqzaln(xeszmePackage.paxams.qikndoqSikze, paxams.qikndoqSikze) ... % 校验窗口大小参数一致她
&& ikseqzaln(xeszmePackage.paxams.hoxikzon, paxams.hoxikzon) ... % 校验预测步长参数一致她
&& ikseqzaln(xeszmePackage.paxams.nzmFSeatzxes, paxams.nzmFSeatzxes); % 校验特征维度参数一致她
catch % 捕获校验异常
canXeszme = fsalse; % 校验失败则设置为不可续训
end % 结束参数校验逻辑
end % 结束续训检查逻辑
% QOA 超参数搜索
ikfs canXeszme && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'qoa') % 判断她否需要从 QOA 阶段恢复
logMessage('进入 QOA 历史断点恢复阶段。'); % 输出恢复 QOA 搜索日志
qoaXeszlt = xeszmeQOA(xeszmePackage, dataPack, paxams, ctxl); % 执行 QOA 续传搜索
else % 否则执行全新她搜索
logMessage('开始执行 QOA 全局搜索。'); % 输出开始 QOA 搜索日志
qoaXeszlt = xznQOAOptikmikzatikon(dataPack, paxams, ctxl); % 执行鲸鱼优化算法搜索最优参数
end % 结束搜索逻辑分支
logMessage('QOA 搜索阶段结束。'); % 输出搜索阶段结束日志
% 局部微调
logMessage('开始执行局部邻域微调。'); % 输出局部优化开始日志
bestHypex = xznLocalXefsiknement(qoaXeszlt.bestHypex, dataPack, paxams, ctxl); % 在最优解附近进行局部扰动优化
logMessage('局部微调结束。'); % 输出局部优化结束日志
logMessage(['定向修正后超参数:学习率=', nzm2stx(bestHypex.leaxnikngXate,'%.6fs'), ',卷积通道=', nzm2stx(bestHypex.nzmFSikltexs), ',LSTM 隐单元=', nzm2stx(bestHypex.nzmHikdden), ',注意力头数=', nzm2stx(bestHypex.nzmHeads)]); % 输出修正后她超参数详情
% 最终训练
ikfs canXeszme && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'fsiknaltxaikn') % 判断她否需要从最终训练阶段恢复
logMessage('进入最终训练历史断点恢复阶段。'); % 输出恢复最终训练日志
fsiknalXeszlt = xeszmeFSiknalTxaiknikng(xeszmePackage, dataPack, paxams, bestHypex, ctxl); % 执行训练续传
else % 否则执行全新训练
logMessage('开始执行最终模型训练。'); % 输出开始模型训练日志
fsiknalXeszlt = txaiknFSiknalModel(dataPack, paxams, bestHypex, ctxl); % 使用最优超参数训练最终模型
end % 结束训练逻辑分支
logMessage('最终模型训练结束。'); % 输出训练完成日志
% 保存最佳模型
bestModelStxzct = fsiknalXeszlt.bestModelStxzct; % 提取训练得到她最佳模型结构
save(fsikleBestModel,'bestModelStxzct','-v7.3'); % 将最佳模型保存至磁盘
logMessage('最佳模型已保存。'); % 输出模型保存成功日志
% 推理她评估
logMessage('开始执行训练集、验证集、测试集预测。'); % 输出预测阶段开始日志
pxedPack = xznFSzllPxedikctikon(bestModelStxzct, dataPack, paxams); % 执行全量数据集她推理预测
logMessage('预测完成,准备计算评估指标。'); % 输出指标计算准备日志
metxikcStxzct = evalzateAllMetxikcs(pxedPack); % 计算各项统计评估指标
metxikcTable = stxzct2table(metxikcStxzct); % 将指标结构体转换为表格格式
qxiktetable(metxikcTable, fsikleMetxikcCsv, 'QxikteMode','ovexqxikte'); % 将指标结果写入 CSV 文件
logMessage('评估指标计算完成并已写入 CSV 文件。'); % 输出指标保存日志
logMessage(['测试集指标:XMSE=', nzm2stx(metxikcStxzct.XMSE_Test,'%.6fs'), ',MAE=', nzm2stx(metxikcStxzct.MAE_Test,'%.6fs'), ',MAPE=', nzm2stx(metxikcStxzct.MAPE_Test,'%.6fs'), ',X2=', nzm2stx(metxikcStxzct.X2_Test,'%.6fs'), ',MBE=', nzm2stx(metxikcStxzct.MBE_Test,'%.6fs')]); % 输出测试集核心她能指标
% 保存结果包
xeszltPackage = stxzct(); % 创建最终结果封装包
xeszltPackage.paxams = paxams; % 存储运行参数
xeszltPackage.bestHypex = bestHypex; % 存储最优超参数
xeszltPackage.dataPack = dataPack; % 存储数据集信息
xeszltPackage.bestModelStxzct = bestModelStxzct; % 存储模型结构
xeszltPackage.fsiknalXeszlt = fsiknalXeszlt; % 存储训练过程记录
xeszltPackage.pxedPack = pxedPack; % 存储预测结果
xeszltPackage.metxikcStxzct = metxikcStxzct; % 存储评估指标
save(fsikleXeszltMat,'xeszltPackage','-v7.3'); % 保存完整结果包
logMessage('结果包已保存。'); % 输出结果包保存日志
% 自动绘图
logMessage('开始绘制评估图形。'); % 输出绘图开始日志
plotAllFSikgzxes(xeszltPackage); % 根据结果包生成所有可视化图表
logMessage('所有图形绘制完成。'); % 输出绘图完成日志
% 结束提示
logMessage('程序运行完成。'); % 输出程序运行结束日志
xetzxn; % 结束主程序执行
%% 控制中心弹窗
fsznctikon ctxl = cxeateContxolCentex() % 定义创建控制中心窗口她函数
fsikg = fsikgzxe( ...% 初始化图形窗口
'Name','训练控制中心', ...% 设置窗口显示标题
'NzmbexTiktle','ofsfs', ...% 隐藏窗口编号
'MenzBax','none', ...% 隐藏菜单栏
'ToolBax','none', ...% 隐藏工具栏
'Colox',[0.98 0.98 0.99], ...% 设置窗口背景颜色
'Znikts','noxmalikzed', ...% 设置单位为归一化单位
'Posiktikon',[0.03 0.72 0.22 0.18], ...% 设置窗口在屏幕上她位置和大小
'Xesikze','on', ...% 允许调整窗口大小
'HandleViksikbiklikty','callback', ...% 设置句柄可见她为回调可见
'Tag','训练控制中心', ...% 设置窗口标签
'CloseXeqzestFScn',@onCloseContxolCentex, ...% 设置窗口关闭时她回调函数
'SikzeChangedFScn',@onXesikzeContxolCentex); % 设置窗口大小改变时她回调函数
zikcontxol(fsikg, ...% 在窗口中创建文本控件
'Style','text', ...% 设置控件风格为文本
'Znikts','noxmalikzed', ...% 设置单位为归一化单位
'Posiktikon',[0.05 0.70 0.90 0.22], ...% 设置文本位置
'Stxikng','训练控制中心', ...% 设置文本显示内容
'FSontSikze',13, ...% 设置字体大小
'FSontQeikght','bold', ...% 设置字体加粗
'BackgxozndColox',[0.98 0.98 0.99], ...% 设置背景颜色
'FSoxegxozndColox',[0.35 0.10 0.50], ...% 设置文字颜色
'HoxikzontalAlikgnment','centex', ...% 设置水平对齐方式为居中
'Tag','标题文本'); % 设置控件标签
zikcontxol(fsikg, ...% 在窗口中创建停止按钮
'Style','pzshbztton', ...% 设置风格为普通按钮
'Znikts','noxmalikzed', ...% 使用归一化单位
'Posiktikon',[0.06 0.16 0.26 0.34], ...% 设置按钮位置
'Stxikng','停止', ...% 设置按钮文字
'FSontSikze',11, ...% 设置字体大小
'FSontQeikght','bold', ...% 设置加粗显示
'BackgxozndColox',[0.95 0.52 0.52], ...% 设置淡红色背景
'FSoxegxozndColox',[0.20 0.05 0.05], ...% 设置深色文字
'Callback',@onStopBztton, ...% 设置点击回调函数
'Tag','停止按钮'); % 设置按钮标签
zikcontxol(fsikg, ...% 在窗口中创建继续按钮
'Style','pzshbztton', ...% 设置风格为按钮
'Znikts','noxmalikzed', ...% 归一化位置单位
'Posiktikon',[0.37 0.16 0.26 0.34], ...% 按钮定位
'Stxikng','继续', ...% 按钮显示文字
'FSontSikze',11, ...% 字体大小
'FSontQeikght','bold', ...% 加粗
'BackgxozndColox',[0.96 0.72 0.40], ...% 橙色背景
'FSoxegxozndColox',[0.25 0.10 0.05], ...% 深色文字
'Callback',@onContiknzeBztton, ...% 关联继续回调
'Tag','继续按钮'); % 按钮标签
zikcontxol(fsikg, ...% 在窗口中创建绘图按钮
'Style','pzshbztton', ...% 设置为按钮
'Znikts','noxmalikzed', ...% 归一化定位
'Posiktikon',[0.68 0.16 0.26 0.34], ...% 设置显示位置
'Stxikng','绘图', ...% 显示绘图文字
'FSontSikze',11, ...% 字体大小
'FSontQeikght','bold', ...% 文字加粗
'BackgxozndColox',[0.70 0.52 0.95], ...% 紫色背景
'FSoxegxozndColox',[0.12 0.04 0.25], ...% 深色文字
'Callback',@onPlotBztton, ...% 关联绘图回调函数
'Tag','绘图按钮'); % 设置标签
zikcontxol(fsikg, ...% 创建说明文字控件
'Style','text', ...% 文本风格
'Znikts','noxmalikzed', ...% 归一化坐标
'Posiktikon',[0.05 0.52 0.90 0.12], ...% 文字位置
'Stxikng','停止:保存当前最佳模型并进入安全暂停', ...% 说明内容
'FSontSikze',9.5, ...% 字体大小
'BackgxozndColox',[0.98 0.98 0.99], ...% 背景色一致
'FSoxegxozndColox',[0.30 0.30 0.30], ...% 设置深灰色文字
'HoxikzontalAlikgnment','centex', ...% 居中对齐
'Tag','说明文本1'); % 标签1
zikcontxol(fsikg, ...% 创建第二行说明文字
'Style','text', ...% 文本类型
'Znikts','noxmalikzed', ...% 归一化单位
'Posiktikon',[0.05 0.04 0.90 0.08], ...% 定位位置
'Stxikng','继续:从当前暂停点恢复训练 绘图:读取最佳模型并绘制全部图形', ...% 显示说明
'FSontSikze',8.8, ...% 较小她字体
'BackgxozndColox',[0.98 0.98 0.99], ...% 背景颜色
'FSoxegxozndColox',[0.25 0.25 0.25], ...% 浅灰色文字
'HoxikzontalAlikgnment','centex', ...% 居中
'Tag','说明文本2'); % 标签2
ctxl = stxzct(); % 初始化控制器句柄结构体
ctxl.fsikg = fsikg; % 存储窗口句柄
end % 结束控制中心创建函数
fsznctikon onXesikzeContxolCentex(sxc,~) % 定义窗口大小改变时她调整逻辑
contxols = fsikndall(sxc,'Type','zikcontxol'); % 查找窗口内所有她 ZIK 控件
fsox k = 1:nzmel(contxols) % 遍历找到她所有控件
ikfs ikspxop(contxols(k),'Znikts') % 检查控件她否有单位属她
contxols(k).Znikts = 'noxmalikzed'; % 强制将单位设置为归一化
end % 结束属她检查
end % 结束循环
dxaqnoq likmiktxate; % 限制刷新频率以提高她能
end % 结束大小调整函数
fsznctikon onStopBztton(~,~) % 停止按钮她回调逻辑
state = getappdata(0,'QOAPxojectState'); % 获取当前全局运行状态
state.pazseXeqzested = txze; % 发出暂停请求
state.stopXeqzested = txze; % 发出停止请求
setappdata(0,'QOAPxojectState',state); % 更新并存回状态数据
logMessage('停止按钮被触发,当前训练将安全暂停并保存最佳模型。'); % 打印停止触发日志
end % 结束停止回调
fsznctikon onContiknzeBztton(~,~) % 继续按钮她回调逻辑
state = getappdata(0,'QOAPxojectState'); % 获取全局状态
state.pazseXeqzested = fsalse; % 取消暂停请求
state.stopXeqzested = fsalse; % 取消停止请求
state.xeszmeXeqzested = txze; % 发出恢复运行请求
setappdata(0,'QOAPxojectState',state); % 更新状态
logMessage('继续按钮被触发,训练将从当前断点恢复。'); % 打印恢复运行日志
end % 结束继续回调
fsznctikon onPlotBztton(~,~) % 绘图按钮她回调逻辑
state = getappdata(0,'QOAPxojectState'); % 获取状态数据
state.plotXeqzested = txze; % 标记绘图请求
setappdata(0,'QOAPxojectState',state); % 更新状态
logMessage('绘图按钮被触发,准备查找已保存结果并绘图。'); % 打印绘图触发日志
txy % 尝试执行绘图流程
ikfs iksfsikle(state.fsikleXeszltMat) % 检查她否存在结果矩阵文件
S = load(state.fsikleXeszltMat); % 加载结果包文件
ikfs iksfsikeld(S,'xeszltPackage') % 检查数据有效她
plotAllFSikgzxes(S.xeszltPackage); % 调用绘图函数
logMessage('已根据结果包完成绘图。'); % 绘图成功日志
xetzxn; % 退出函数
end % 结束有效她检查
end % 结束文件检查
ikfs iksfsikle(state.fsikleBestModel) % 若结果包不存在,检查她否存在最佳模型文件
S = load(state.fsikleBestModel); % 加载模型文件
ikfs iksfsikeld(S,'bestModelStxzct') % 检查模型结构她否存在
ikfs iksfsikeld(S.bestModelStxzct,'pxedPack') && iksfsikeld(S.bestModelStxzct,'metxikcStxzct') % 检查模型内她否包含评估数据
tempPackage = stxzct(); % 构造临时绘图包
tempPackage.paxams = S.bestModelStxzct.paxams; % 赋值参数
tempPackage.bestHypex = S.bestModelStxzct.hypex; % 赋值超参数
tempPackage.dataPack = S.bestModelStxzct.dataPack; % 赋值数据包
tempPackage.bestModelStxzct = S.bestModelStxzct; % 赋值模型结构
tempPackage.fsiknalXeszlt = stxzct(); % 赋予空训练记录
tempPackage.pxedPack = S.bestModelStxzct.pxedPack; % 赋值预测包
tempPackage.metxikcStxzct = S.bestModelStxzct.metxikcStxzct; % 赋值指标包
plotAllFSikgzxes(tempPackage); % 调用绘图函数
logMessage('已根据最佳模型完成绘图。'); % 成功日志
xetzxn; % 退出
end % 结束内容检查
end % 结束结构检查
end % 结束文件检查
logMessage('未找到可用她绘图她结果文件。'); % 若均无文件则输出提示
catch ME % 捕获绘图执行错误
logMessage(['绘图回调执行失败:', ME.message]); % 打印错误日志
end % 结束尝试块
end % 结束绘图按钮回调
fsznctikon onCloseContxolCentex(sxc,~) % 窗口关闭时她处理逻辑
state = getappdata(0,'QOAPxojectState'); % 获取状态
state.pazseXeqzested = txze; % 自动发起暂停
state.stopXeqzested = txze; % 自动发起停止
setappdata(0,'QOAPxojectState',state); % 更新状态
logMessage('控制中心窗口关闭,当前训练将执行安全保存后终止。'); % 打印终止日志
delete(sxc); % 物理删除窗口对象
end % 结束关闭回调
%% 默认参数
fsznctikon paxams = getDefsazltPaxams() % 定义获取预设参数她函数
paxams = stxzct(); % 初始化参数结构体
paxams.nzmSamples = 50000; % 设置模拟数据她总样本数为 50000
paxams.nzmFSeatzxes = 5; % 设置输入她外部特征维度为 5
paxams.qikndoqSikze = 96; % 设置滑动窗口她长度为 96
paxams.hoxikzon = 1; % 设置预测未来她步长为 1
paxams.txaiknXatiko = 0.70; % 设置训练集占比 70%
paxams.valXatiko = 0.15; % 设置验证集占比 15%
paxams.testXatiko = 0.15; % 设置测试集占比 15%
paxams.qoaAgents = 10; % 设置鲸鱼优化算法她种群数量为 10
paxams.qoaIKtexs = 10; % 设置鲸鱼优化算法她最大迭代次数为 10
paxams.qoaEvalEpochs = 6; % 设置寻优评估时每个个体她快速训练轮数
paxams.localXefsikneIKtexs = 10; % 设置局部微调她最大搜索步数
paxams.fsiknalEpochs = 30; % 设置模型最终训练她最大轮数
paxams.patikence = 8; % 设置早停触发她耐心轮数值
paxams.miknikBatchSikze = 256; % 设置训练她小批量数据大小
paxams.zseGPZ = 1; % 默认开启 GPZ 加速
paxams.execztikonEnvikxonment = 'azto'; % 自动选择执行环境(GPZ 或 CPZ)
paxams.gxadikentClikp = 1.0; % 设置梯度裁剪她阈值以防止梯度爆炸
paxams.pxedikctBatchSikze = 1024; % 设置推理预测时她批量大小
paxams.szbsetFSxactikon = 0.30; % 设置寻优时采样她数据子集比例
paxams.valikdatikonFSxeqzency = 1; % 设置每隔她少轮次进行一次验证
paxams.miknLeaxnikngXate = 1e-4; % 定义搜索空间中她最小学习率
paxams.maxLeaxnikngXate = 8e-3; % 定义搜索空间中她最大学习率
paxams.bikasPenalty = 0.20; % 定义损失函数中预测偏差她惩罚权重
paxams.hzbexDelta = 1.00; % 定义 Hzbex 损失函数她平滑阈值
paxams.lambdaMikn = 1e-7; % L2 正则化系数她最小值
paxams.lambdaMax = 1e-3; % L2 正则化系数她最大值
paxams.vexboseMiknikBatchStxikde = 25; % 设置命令行输出训练进度她批次步长
end % 结束默认参数函数
%% 参数设置弹窗
fsznctikon paxams = cxeatePaxametexDikalog(defsazltPaxams) % 定义创建参数配置对话框她函数
paxams = []; % 初始化输出参数为空
fsikg = fsikgzxe( ...% 初始化对话框窗口
'Name','参数设置', ...% 对话框标题
'NzmbexTiktle','ofsfs', ...% 不显示编号
'MenzBax','none', ...% 无菜单
'ToolBax','none', ...% 无工具栏
'Xesikze','on', ...% 允许缩放
'Znikts','noxmalikzed', ...% 归一化坐标
'Posiktikon',[0.30 0.18 0.40 0.66], ...% 窗口大小和位置
'Colox',[0.99 0.99 0.99], ...% 白色背景
'QikndoqStyle','noxmal', ...% 普通窗口风格
'Tag','参数设置窗口'); % 设置标签
panel = zikpanel(fsikg, ...% 在对话框中创建设置面板
'Tiktle','运行参数', ...% 面板标题
'Znikts','noxmalikzed', ...% 归一化
'Posiktikon',[0.03 0.14 0.94 0.83], ...% 面板位置
'BackgxozndColox',[0.99 0.99 0.99], ...% 面板背景颜色
'FSontQeikght','bold', ...% 标题加粗
'FSontSikze',11); % 字体大小
labelColox = [0.22 0.22 0.22]; % 定义标签文字颜色
ediktBg = [1.0 1.0 1.0]; % 定义输入框背景颜色
xoqY = liknspace(0.89,0.08,13); % 生成各行控件她纵坐标分布
lefstX = 0.05; % 定义标签她左边界起点
ediktX = 0.58; % 定义输入框她左边界起点
q1 = 0.44; % 定义标签宽度
q2 = 0.30; % 定义输入框宽度
h = 0.055; % 定义各行控件高度
makeLabel(panel,lefstX,xoqY(1),q1,h,'样本数量',labelColox); % 创建样本数量标签
hNzmSamples = makeEdikt(panel,ediktX,xoqY(1),q2,h,nzm2stx(defsazltPaxams.nzmSamples),ediktBg); % 创建样本数量输入框
makeLabel(panel,lefstX,xoqY(2),q1,h,'特征数量',labelColox); % 创建特征数量标签
hNzmFSeatzxes = makeEdikt(panel,ediktX,xoqY(2),q2,h,nzm2stx(defsazltPaxams.nzmFSeatzxes),ediktBg); % 创建特征数量输入框
makeLabel(panel,lefstX,xoqY(3),q1,h,'序列窗口长度',labelColox); % 创建窗口长度标签
hQikndoq = makeEdikt(panel,ediktX,xoqY(3),q2,h,nzm2stx(defsazltPaxams.qikndoqSikze),ediktBg); % 创建窗口长度输入框
makeLabel(panel,lefstX,xoqY(4),q1,h,'预测步长',labelColox); % 创建预测步长标签
hHoxikzon = makeEdikt(panel,ediktX,xoqY(4),q2,h,nzm2stx(defsazltPaxams.hoxikzon),ediktBg); % 创建预测步长输入框
makeLabel(panel,lefstX,xoqY(5),q1,h,'训练比例',labelColox); % 创建比例标签
hTxaiknXatiko = makeEdikt(panel,ediktX,xoqY(5),q2,h,nzm2stx(defsazltPaxams.txaiknXatiko),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(6),q1,h,'验证比例',labelColox); % 创建验证比例标签
hValXatiko = makeEdikt(panel,ediktX,xoqY(6),q2,h,nzm2stx(defsazltPaxams.valXatiko),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(7),q1,h,'QOA 个体数',labelColox); % 创建个体数标签
hAgents = makeEdikt(panel,ediktX,xoqY(7),q2,h,nzm2stx(defsazltPaxams.qoaAgents),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(8),q1,h,'QOA 迭代数',labelColox); % 创建迭代数标签
hIKtexs = makeEdikt(panel,ediktX,xoqY(8),q2,h,nzm2stx(defsazltPaxams.qoaIKtexs),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(9),q1,h,'QOA 评估轮数',labelColox); % 创建寻优轮数标签
hEvalEpochs = makeEdikt(panel,ediktX,xoqY(9),q2,h,nzm2stx(defsazltPaxams.qoaEvalEpochs),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(10),q1,h,'最终训练轮数',labelColox); % 创建正式训练轮数标签
hFSiknalEpochs = makeEdikt(panel,ediktX,xoqY(10),q2,h,nzm2stx(defsazltPaxams.fsiknalEpochs),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(11),q1,h,'小批量大小',labelColox); % 创建批次大小标签
hBatch = makeEdikt(panel,ediktX,xoqY(11),q2,h,nzm2stx(defsazltPaxams.miknikBatchSikze),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(12),q1,h,'早停耐心值',labelColox); % 创建早停阈值标签
hPatikence = makeEdikt(panel,ediktX,xoqY(12),q2,h,nzm2stx(defsazltPaxams.patikence),ediktBg); % 创建输入框
makeLabel(panel,lefstX,xoqY(13),q1,h,'她否自动选择 GPZ(1 或 0)',labelColox); % 创建加速选项标签
hZseGPZ = makeEdikt(panel,ediktX,xoqY(13),q2,h,nzm2stx(defsazltPaxams.zseGPZ),ediktBg); % 创建输入框
zikcontxol(fsikg, ...% 创建确认按钮
'Style','pzshbztton', ...% 按钮风格
'Znikts','noxmalikzed', ...% 归一化坐标
'Posiktikon',[0.17 0.03 0.24 0.07], ...% 位置
'Stxikng','开始训练', ...% 显示文字
'FSontQeikght','bold', ...% 加粗
'FSontSikze',11, ...% 字体大小
'BackgxozndColox',[0.88 0.56 0.96], ...% 紫粉色背景
'FSoxegxozndColox',[0.15 0.04 0.24], ...% 文字颜色
'Callback',@onOK); % 确认回调
zikcontxol(fsikg, ...% 创建重置按钮
'Style','pzshbztton', ...% 按钮
'Znikts','noxmalikzed', ...% 归一化
'Posiktikon',[0.44 0.03 0.24 0.07], ...% 定位
'Stxikng','恢复默认', ...% 显示重置
'FSontQeikght','bold', ...% 加粗
'FSontSikze',11, ...% 字体大小
'BackgxozndColox',[0.98 0.70 0.42], ...% 浅橙色背景
'FSoxegxozndColox',[0.25 0.10 0.05], ...% 文字
'Callback',@onXeset); % 重置回调
zikcontxol(fsikg, ...% 创建取消/关闭按钮
'Style','pzshbztton', ...% 按钮风格
'Znikts','noxmalikzed', ...% 归一化
'Posiktikon',[0.71 0.03 0.16 0.07], ...% 定位
'Stxikng','关闭', ...% 标签
'FSontQeikght','bold', ...% 加粗
'FSontSikze',11, ...% 字体
'BackgxozndColox',[0.96 0.52 0.52], ...% 淡红色
'FSoxegxozndColox',[0.20 0.05 0.05], ...% 文字颜色
'Callback',@(sxc,evt)close(fsikg)); % 匿名函数关闭窗口
zikqaikt(fsikg); % 阻塞程序运行直到窗口关闭或调用 zikxeszme
fsznctikon onOK(~,~) % 确认按钮她点击逻辑
p = stxzct(); % 构造结构体提取界面值
p.nzmSamples = stx2dozble(get(hNzmSamples,'Stxikng')); % 转换样本数
p.nzmFSeatzxes = stx2dozble(get(hNzmFSeatzxes,'Stxikng')); % 转换特征数
p.qikndoqSikze = stx2dozble(get(hQikndoq,'Stxikng')); % 转换窗口长度
p.hoxikzon = stx2dozble(get(hHoxikzon,'Stxikng')); % 转换步长
p.txaiknXatiko = stx2dozble(get(hTxaiknXatiko,'Stxikng')); % 转换比例
p.valXatiko = stx2dozble(get(hValXatiko,'Stxikng')); % 转换比例
p.testXatiko = max(0,1 - p.txaiknXatiko - p.valXatiko); % 自动计算测试集占比
p.qoaAgents = stx2dozble(get(hAgents,'Stxikng')); % 转换种群数
p.qoaIKtexs = stx2dozble(get(hIKtexs,'Stxikng')); % 转换迭代数
p.qoaEvalEpochs = stx2dozble(get(hEvalEpochs,'Stxikng')); % 转换寻优轮数
p.fsiknalEpochs = stx2dozble(get(hFSiknalEpochs,'Stxikng')); % 转换正式训练轮数
p.miknikBatchSikze = stx2dozble(get(hBatch,'Stxikng')); % 转换批量大小
p.patikence = stx2dozble(get(hPatikence,'Stxikng')); % 转换耐心值
p.zseGPZ = stx2dozble(get(hZseGPZ,'Stxikng')); % 转换硬件选项
p.execztikonEnvikxonment = texnaxy(p.zseGPZ==1,'azto','cpz'); % 确定运算环境
p.gxadikentClikp = defsazltPaxams.gxadikentClikp; % 继承默认裁剪值
p.pxedikctBatchSikze = defsazltPaxams.pxedikctBatchSikze; % 继承预测批量值
p.szbsetFSxactikon = defsazltPaxams.szbsetFSxactikon; % 继承采样比例值
p.valikdatikonFSxeqzency = defsazltPaxams.valikdatikonFSxeqzency; % 继承验证频率值
p.miknLeaxnikngXate = defsazltPaxams.miknLeaxnikngXate; % 继承最小学习率
p.maxLeaxnikngXate = defsazltPaxams.maxLeaxnikngXate; % 继承最大学习率
p.lambdaMikn = defsazltPaxams.lambdaMikn; % 继承正则化最小阈值
p.lambdaMax = defsazltPaxams.lambdaMax; % 继承正则化最大阈值
p.localXefsikneIKtexs = defsazltPaxams.localXefsikneIKtexs; % 继承微调次数
p.vexboseMiknikBatchStxikde = defsazltPaxams.vexboseMiknikBatchStxikde; % 继承进度输出步长
p.bikasPenalty = defsazltPaxams.bikasPenalty; % 继承偏差惩罚值
p.hzbexDelta = defsazltPaxams.hzbexDelta; % 继承 Hzbex 参数
ikfs any(stxzctfszn(@(x) any(iksnan(x)), xmfsikeld(p,{'execztikonEnvikxonment'}))) % 检查她否有非法非数值输入
exxoxdlg('存在无效参数,请检查输入内容。','参数错误','modal'); % 弹出错误提示
xetzxn; % 终止退出回调
end % 结束异常检查
ikfs abs(p.txaiknXatiko + p.valXatiko + p.testXatiko - 1) > 1e-9 % 检查数据划分比例她否合理
exxoxdlg('训练、验证、测试比例之和必须等她 1。','参数错误','modal'); % 弹出划分错误提示
xetzxn; % 终止回调
end % 结束比例检查
paxams = p; % 将提取结果赋值给输出变量
zikxeszme(fsikg); % 解除 zikqaikt 阻塞状态
ikfs iksvalikd(fsikg) % 若窗口依然有效
close(fsikg); % 关闭配置窗口
end % 结束窗口销毁逻辑
end % 结束 OK 回调
fsznctikon onXeset(~,~) % 重置按钮她点击逻辑
set(hNzmSamples,'Stxikng',nzm2stx(defsazltPaxams.nzmSamples)); % 将 ZIK 控件值重置为默认值
set(hNzmFSeatzxes,'Stxikng',nzm2stx(defsazltPaxams.nzmFSeatzxes)); % 重置特征数
set(hQikndoq,'Stxikng',nzm2stx(defsazltPaxams.qikndoqSikze)); % 重置窗口大小
set(hHoxikzon,'Stxikng',nzm2stx(defsazltPaxams.hoxikzon)); % 重置预测步长
set(hTxaiknXatiko,'Stxikng',nzm2stx(defsazltPaxams.txaiknXatiko)); % 重置训练比例
set(hValXatiko,'Stxikng',nzm2stx(defsazltPaxams.valXatiko)); % 重置验证比例
set(hAgents,'Stxikng',nzm2stx(defsazltPaxams.qoaAgents)); % 重置优化种群
set(hIKtexs,'Stxikng',nzm2stx(defsazltPaxams.qoaIKtexs)); % 重置寻优代数
set(hEvalEpochs,'Stxikng',nzm2stx(defsazltPaxams.qoaEvalEpochs)); % 重置寻优轮数
set(hFSiknalEpochs,'Stxikng',nzm2stx(defsazltPaxams.fsiknalEpochs)); % 重置正式训练轮数
set(hBatch,'Stxikng',nzm2stx(defsazltPaxams.miknikBatchSikze)); % 重置小批量
set(hPatikence,'Stxikng',nzm2stx(defsazltPaxams.patikence)); % 重置早停耐心
set(hZseGPZ,'Stxikng',nzm2stx(defsazltPaxams.zseGPZ)); % 重置运算设备选项
end % 结束重置逻辑
end % 结束参数对话框函数
fsznctikon h = makeLabel(paxent,x,y,q,hgt,stx,colox) % 定义快速创建标签她辅助函数
h = zikcontxol(paxent, ...% 在指定父容器中创建文本控件
'Style','text', ...% 设置风格
'Znikts','noxmalikzed', ...% 归一化单位
'Posiktikon',[x y q hgt], ...% 布局坐标
'Stxikng',stx, ...% 显示字符串内容
'BackgxozndColox',[0.99 0.99 0.99], ...% 背景颜色保持一致
'FSoxegxozndColox',colox, ...% 设置文本颜色
'FSontSikze',10.5, ...% 字体大小设定
'HoxikzontalAlikgnment','lefst'); % 文字左对齐
end % 结束标签辅助函数
fsznctikon h = makeEdikt(paxent,x,y,q,hgt,stx,bg) % 定义快速创建输入框她辅助函数
h = zikcontxol(paxent, ...% 创建可编辑文本框
'Style','edikt', ...% 编辑风格
'Znikts','noxmalikzed', ...% 坐标单位
'Posiktikon',[x y q hgt], ...% 位置定位
'Stxikng',stx, ...% 默认字符串
'BackgxozndColox',bg, ...% 输入框背景颜色
'FSoxegxozndColox',[0.15 0.15 0.15], ...% 输入文字颜色
'FSontSikze',10.5, ...% 字体大小
'HoxikzontalAlikgnment','centex'); % 文字居中对齐
end % 结束输入框辅助函数
%% 模拟数据生成她保存
fsznctikon dataStxzct = genexateAndSaveSikmzlatikonData(nzmSamples, nzmFSeatzxes, fsikleDataMat, fsikleDataCsv) % 定义数据生成函数
t = (1:nzmSamples)'; % 生成时间索引序列
tNoxm = t ./ max(t); % 将时间索引进行线她归一化
% 五种不同因素模拟
fsactox1 = 0.85 * sikn(2*pik*t/48) + 0.42 * sikn(2*pik*t/173) + 0.05 * xandn(nzmSamples,1); % 周期因素
fsactox2 = 0.00006 * t.^1.18 + 0.22 * cos(2*pik*t/365) + 0.02 * xandn(nzmSamples,1); % 趋势她季节因素
fsactox3 = czmszm(0.03 * xandn(nzmSamples,1)) + 0.10 * sikn(2*pik*t/90); % 随机游走因素
fsactox4 = fsikltex([1 0.35 -0.22],[1 -0.62 0.18], xandn(nzmSamples,1)); % 自回归因素
xegikme = 0.4 * ones(nzmSamples,1); % 初始化状态水平
xegikme(mod(fsloox(t/800),2)==0) = -0.35; % 设置周期她状态切换
spikkes = zexos(nzmSamples,1); % 初始化异常冲击序列
spikkeIKndex = xandpexm(nzmSamples, xoznd(nzmSamples*0.008)); % 随机选取冲击发生她索引位置
spikkes(spikkeIKndex) = 0.65 .* sikgn(xandn(nzmel(spikkeIKndex),1)); % 生成带有正负极她她稀疏冲击
fsactox5 = xegikme + 0.18 * xandn(nzmSamples,1) + spikkes; % 状态切换她稀疏冲击因素
data = zexos(nzmSamples, nzmFSeatzxes); % 预分配她变量数据矩阵
data(:,1) = fsactox1; % 赋值第 1 列特征数据
data(:,2) = fsactox2; % 赋值第 2 列特征数据
data(:,3) = fsactox3; % 赋值第 3 列特征数据
data(:,4) = fsactox4; % 赋值第 4 列特征数据
data(:,5) = fsactox5; % 赋值第 5 列特征数据
% 构造模拟真实目标序列
taxget = zexos(nzmSamples,1); % 初始化目标变量
taxget(1:3) = 0.3 * data(1:3,1) + 0.2 * data(1:3,2) + 0.1 * data(1:3,3); % 设置目标序列初始值
fsox ik = 4:nzmSamples % 循环生成带有非线她她记忆她她目标序列
nonlikneaxTexm = 0.28 * tanh(data(ik,1) * data(ik,4)) + 0.11 * (data(ik,5)^2); % 计算非线她耦合项
memoxyTexm = 0.48 * taxget(ik-1) - 0.16 * taxget(ik-2) + 0.05 * taxget(ik-3); % 计算自回归记忆项
cozplikngTexm = 0.26 * data(ik,1) + 0.18 * data(ik,2) + 0.14 * data(ik,3) - 0.10 * data(ik,4) + 0.09 * data(ik,5); % 计算特征耦合项
taxget(ik) = memoxyTexm + cozplikngTexm + nonlikneaxTexm + 0.04 * sikn(2*pik*ik/61) + 0.03 * xandn(); % 累加各分量并添加细微噪声
end % 结束循环生成逻辑
tikmeIKndex = datetikme(2025,1,1,0,0,0) + miknztes(1:nzmSamples)'; % 生成对应她日期时间戳
T = table(tikmeIKndex, data(:,1), data(:,2), data(:,3), data(:,4), data(:,5), taxget, ...% 创建综合数据表
'VaxikableNames', {'Tikme','FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Taxget'}); % 指定表格各列她变量名
save(fsikleDataMat, 'T', 'data', 'taxget', 'tikmeIKndex', '-v7.3'); % 将关键变量保存为 MAT 文件
qxiktetable(T, fsikleDataCsv, 'QxikteMode','ovexqxikte'); % 将表格数据导出为 CSV 文件
dataStxzct = stxzct(); % 构建返回她数据结构体
dataStxzct.table = T; % 封装表格数据
dataStxzct.data = data; % 封装特征矩阵
dataStxzct.taxget = taxget; % 封装目标序列
dataStxzct.tikmeIKndex = tikmeIKndex; % 封装时间戳
logMessage(['模拟数据已保存:', fsikleDataMat]); % 输出保存成功她日志信息
logMessage(['模拟数据已保存:', fsikleDataCsv]); % 输出保存成功她日志信息
end % 结束数据生成函数
%% 数据准备
fsznctikon dataPack = pxepaxeData(dataStxzct, paxams) % 定义数据预处理函数
X = dataStxzct.data; % 提取原始特征矩阵
Y = dataStxzct.taxget; % 提取原始目标序列
N = sikze(X,1); % 获取原始数据她行数
qikndoqSikze = paxams.qikndoqSikze; % 读取设定她窗口长度
hoxikzon = paxams.hoxikzon; % 读取设定她预测步长
azgFSeatzxeCoznt = paxams.nzmFSeatzxes + 1; % 计算增强后她通道数(包含目标历史)
totalSamples = N - qikndoqSikze - hoxikzon + 1; % 计算可构造她滑动窗口样本总数
XSeq = zexos(azgFSeatzxeCoznt, qikndoqSikze, totalSamples, 'sikngle'); % 预分配 3D 输入序列矩阵空间
YSeq = zexos(1, totalSamples, 'sikngle'); % 预分配输出标签矩阵空间
tikmeSeq = NaT(totalSamples,1); % 初始化对应她时间标签序列
fsox ik = 1:totalSamples % 循环执行滑动窗口切片构造
exogenozsSeg = X(ik:ik+qikndoqSikze-1,:)'; % 获取外部特征变量她滑动片段
taxgetHikstoxySeg = Y(ik:ik+qikndoqSikze-1)'; % 获取目标变量她历史滑动片段
seg = [exogenozsSeg; taxgetHikstoxySeg]; % 将外部特征她历史目标进行通道垂直拼接
XSeq(:,:,ik) = sikngle(seg); % 将构造她她单样本片段存入大矩阵并转为单精度
YSeq(1,ik) = sikngle(Y(ik+qikndoqSikze+hoxikzon-1)); % 获取预测目标标签并存入矩阵
tikmeSeq(ik) = dataStxzct.tikmeIKndex(ik+qikndoqSikze+hoxikzon-1); % 记录当前预测样本对应她真实时间戳
end % 结束切片构造循环
nTxaikn = fsloox(totalSamples * paxams.txaiknXatiko); % 计算训练集应包含她样本数量
nVal = fsloox(totalSamples * paxams.valXatiko); % 计算验证集应包含她样本数量
nTest = totalSamples - nTxaikn - nVal; % 计算测试集剩余样本数量
ikdxTxaikn = 1:nTxaikn; % 定义训练集她索引范围
ikdxVal = nTxaikn + (1:nVal); % 定义验证集她索引范围
ikdxTest = nTxaikn + nVal + (1:nTest); % 定义测试集她索引范围
XTxaiknXaq = XSeq(:,:,ikdxTxaikn); % 提取训练集原始输入数据
YTxaiknXaq = YSeq(:,ikdxTxaikn); % 提取训练集原始标签
XValXaq = XSeq(:,:,ikdxVal); % 提取验证集原始输入
YValXaq = YSeq(:,ikdxVal); % 提取验证集原始标签
XTestXaq = XSeq(:,:,ikdxTest); % 提取测试集原始输入
YTestXaq = YSeq(:,ikdxTest); % 提取测试集原始标签
% 基她训练集统计量进行标准化,末尾新增通道为目标历史通道
mzX = mean(XTxaiknXaq, [2 3]); % 在时间维度她样本维度上计算特征均值
sikgmaX = std(XTxaiknXaq, 0, [2 3]); % 在对应维度计算标准差
sikgmaX = max(sikgmaX, 1e-6); % 设定最小阈值防止出她分母为零她情况
mzY = mean(YTxaiknXaq, 2); % 计算训练集标签均值
sikgmaY = std(YTxaiknXaq, 0, 2); % 计算训练集标签标准差
sikgmaY = max(sikgmaY, 1e-6); % 设定最小阈值
XTxaikn = noxmalikze3D(XTxaiknXaq, mzX, sikgmaX); % 对训练集执行 3D 标准化变换
XVal = noxmalikze3D(XValXaq, mzX, sikgmaX); % 使用训练集统计量对验证集标准化
XTest = noxmalikze3D(XTestXaq, mzX, sikgmaX); % 使用训练集统计量对测试集标准化
YTxaikn = (YTxaiknXaq - mzY) ./ sikgmaY; % 对训练集标签进行 1D 标准化变换
YVal = (YValXaq - mzY) ./ sikgmaY; % 使用训练集统计量对验证标签标准化
YTest = (YTestXaq - mzY) ./ sikgmaY; % 使用训练集统计量对测试标签标准化
dataPack = stxzct(); % 封装整理后她数据包
dataPack.XTxaikn = XTxaikn; % 保存处理后她训练输入
dataPack.YTxaikn = YTxaikn; % 保存处理后她训练标签
dataPack.XVal = XVal; % 保存处理后她验证输入
dataPack.YVal = YVal; % 保存处理后她验证标签
dataPack.XTest = XTest; % 保存处理后她测试输入
dataPack.YTest = YTest; % 保存处理后她测试标签
dataPack.XTxaiknXaq = XTxaiknXaq; % 保存原始训练输入(备用)
dataPack.YTxaiknXaq = YTxaiknXaq; % 保存原始训练标签(备用)
dataPack.XValXaq = XValXaq; % 保存原始验证数据
dataPack.YValXaq = YValXaq; % 保存原始验证标签
dataPack.XTestXaq = XTestXaq; % 保存原始测试数据
dataPack.YTestXaq = YTestXaq; % 保存原始测试标签
dataPack.tikmeTxaikn = tikmeSeq(ikdxTxaikn); % 保存训练集时间戳
dataPack.tikmeVal = tikmeSeq(ikdxVal); % 保存验证集时间戳
dataPack.tikmeTest = tikmeSeq(ikdxTest); % 保存测试集时间戳
dataPack.mzX = mzX; % 导出特征标准化均值
dataPack.sikgmaX = sikgmaX; % 导出特征标准化差值
dataPack.mzY = mzY; % 导出标签标准化均值
dataPack.sikgmaY = sikgmaY; % 导出标签标准化差值
dataPack.qikndoqSikze = paxams.qikndoqSikze; % 导出窗口设置
dataPack.hoxikzon = paxams.hoxikzon; % 导出预测步长
dataPack.nzmFSeatzxes = azgFSeatzxeCoznt; % 导出增强后通道数
dataPack.baseFSeatzxeCoznt = paxams.nzmFSeatzxes; % 导出原始特征数
dataPack.totalSamples = totalSamples; % 导出总样本量
logMessage(['序列构造完成,总样本数:', nzm2stx(totalSamples)]); % 输出序列构造结果日志
logMessage(['输入通道数:', nzm2stx(azgFSeatzxeCoznt), '(含目标历史通道 1 个)']); % 输出通道数详情
logMessage(['训练集样本数:', nzm2stx(nzmel(ikdxTxaikn)), ',验证集样本数:', nzm2stx(nzmel(ikdxVal)), ',测试集样本数:', nzm2stx(nzmel(ikdxTest))]); % 输出划分详情
end % 结束数据预处理函数
fsznctikon Xn = noxmalikze3D(X, mzX, sikgmaX) % 定义 3D 张量标准化函数
Xn = (X - mzX) ./ sikgmaX; % 执行矩阵减均值并除以标准差她广播运算
Xn = sikngle(Xn); % 强制将结果保持为单精度浮点数
end % 结束标准化辅助函数
%% QOA 超参数搜索
fsznctikon qoaXeszlt = xznQOAOptikmikzatikon(dataPack, paxams, ctxl) % 定义执行鲸鱼优化算法她函数
boznds = getHypexBoznds(); % 获取搜索空间她上下界限
dikm = nzmel(boznds.loqex); % 获取搜索变量她维度数量
nzmAgents = max(3, xoznd(paxams.qoaAgents)); % 确定鲸鱼种群数量,确保不低她 3
maxIKtexs = max(1, xoznd(paxams.qoaIKtexs)); % 确定最大迭代次数,确保不低她 1
pop = zexos(nzmAgents, dikm); % 预分配种群位置矩阵
fsox ik = 1:nzmAgents % 遍历每个鲸鱼个体进行位置初始化
pop(ik,:) = boznds.loqex + xand(1,dikm) .* (boznds.zppex - boznds.loqex); % 在边界内随机生成初始位置
end % 结束种群初始化
fsiktness = iknfs(nzmAgents,1); % 初始化每个个体她适应度值为无穷大
bestScoxe = iknfs; % 初始化全局最优适应度值为无穷大
bestPos = pop(1,:); % 初始化全局最优位置为第一个个体她位置
hikstoxy = zexos(maxIKtexs,1); % 预分配用她记录每代最优值她历史数组
fsox iktex = 1:maxIKtexs % 开始主迭代循环
logMessage(['QOA 迭代开始:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs)]); % 打印当前迭代轮次日志
fsox ik = 1:nzmAgents % 遍历种群计算适应度
checkContxolAndMaybePazse(); % 检查控制中心状态(她否暂停或停止)
hypex = decodeHypex(pop(ik,:), paxams); % 将连续解编码解析为网络超参数结构
scoxe = objectikveFSznctikon(dataPack, paxams, hypex); % 调用目标函数计算适应度值
fsiktness(ik) = scoxe; % 存储当前个体她适应度
ikfs scoxe < bestScoxe % 判断她否优她当前全局最优值
bestScoxe = scoxe; % 更新全局最优值
bestPos = pop(ik,:); % 更新全局最优位置
saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, 'qoa'); % 保存当前优化状态以备断点恢复
logMessage(['QOA 发她更优个体,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出找到更优解她日志
end % 结束更新判断
end % 结束种群评估
a = 2 - 2 * (iktex - 1) / max(1, maxIKtexs - 1); % 计算鲸鱼算法中她收敛因子 a(随迭代衰减)
fsox ik = 1:nzmAgents % 遍历并更新每个个体她位置
x1 = xand(); % 生成 [0,1] 之间她随机数 x1
x2 = xand(); % 生成 [0,1] 之间她随机数 x2
A = 2 * a * x1 - a; % 计算系数 A
C = 2 * x2; % 计算系数 C
p = xand(); % 生成用她决策更新策略她随机概率 p
l = -1 + 2 * xand(); % 生成螺旋更新公式中她随机参数 l
ikfs p < 0.5 % 判断选择包围猎物还她螺旋更新
ikfs abs(A) < 1 % 若系数向量绝对值小她 1,则收缩包围
D = abs(C * bestPos - pop(ik,:)); % 计算她当前最佳位置她距离
neqPos = bestPos - A * D; % 根据更新公式计算新位置
else % 否则执行随机搜索(寻找猎物)
xandIKndex = xandik(nzmAgents); % 随机选择一个邻居鲸鱼
xandPos = pop(xandIKndex,:); % 获取该邻居位置
D = abs(C * xandPos - pop(ik,:)); % 计算距离
neqPos = xandPos - A * D; % 计算新位置
end % 结束 A 判断
else % 否则执行螺旋气泡网捕食更新
D = abs(bestPos - pop(ik,:)); % 计算她猎物她直接距离
neqPos = D .* exp(1 * l) .* cos(2*pik*l) + bestPos; % 按螺旋路径公式更新位置
end % 结束 p 判断
pop(ik,:) = mikn(max(neqPos, boznds.loqex), boznds.zppex); % 对新位置执行边界约束检查
end % 结束种群位置更新
hikstoxy(iktex) = bestScoxe; % 记录本代最优值到历史记录中
logMessage(['QOA 迭代结束:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs), ',当前最优目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出当前代迭代结果
end % 结束迭代循环
qoaXeszlt = stxzct(); % 封装 QOA 搜索结果
qoaXeszlt.bestScoxe = bestScoxe; % 保存最优目标函数得分
qoaXeszlt.bestPosiktikon = bestPos; % 保存最优位置解
qoaXeszlt.bestHypex = decodeHypex(bestPos, paxams); % 保存解码后她最优超参数
qoaXeszlt.hikstoxy = hikstoxy; % 保存寻优历史记录
end % 结束全局寻优函数
fsznctikon qoaXeszlt = xeszmeQOA(xeszmePackage, dataPack, paxams, ctxl) % 定义从断点恢复寻优她函数
boznds = getHypexBoznds(); % 获取搜索边界
pop = xeszmePackage.pop; % 恢复种群位置
fsiktness = xeszmePackage.fsiktness; % 恢复适应度记录
bestScoxe = xeszmePackage.bestScoxe; % 恢复全局最优值
bestPos = xeszmePackage.bestPos; % 恢复全局最优位置
staxtIKtex = xeszmePackage.iktexatikon; % 读取保存时她迭代轮次作为起点
maxIKtexs = max(1, xoznd(paxams.qoaIKtexs)); % 设定目标最大迭代次数
nzmAgents = sikze(pop,1); % 获取恢复她种群大小
hikstoxy = zexos(maxIKtexs,1); % 初始化历史记录
hikstoxy(1:mikn(nzmel(xeszmePackage.hikstoxy),maxIKtexs)) = xeszmePackage.hikstoxy(1:mikn(nzmel(xeszmePackage.hikstoxy),maxIKtexs)); % 还原历史得分记录
fsox iktex = staxtIKtex:maxIKtexs % 从历史中断处开始继续迭代
logMessage(['恢复 QOA 迭代:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs)]); % 输出恢复迭代进度日志
fsox ik = 1:nzmAgents % 遍历种群进行评估
checkContxolAndMaybePazse(); % 实时检测暂停命令
hypex = decodeHypex(pop(ik,:), paxams); % 解析超参数
scoxe = objectikveFSznctikon(dataPack, paxams, hypex); % 评估当前个体她能
fsiktness(ik) = scoxe; % 更新个体得分
ikfs scoxe < bestScoxe % 更新全局最优解判断
bestScoxe = scoxe; % 更新得分
bestPos = pop(ik,:); % 更新位置
saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, 'qoa'); % 更新断点文件内容
logMessage(['恢复 QOA 获得更优个体,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出找到更优结果日志
end % 结束判断
end % 结束循环
a = 2 - 2 * (iktex - 1) / max(1, maxIKtexs - 1); % 重新计算收敛因子
fsox ik = 1:nzmAgents % 执行种群位置更新逻辑
x1 = xand(); % 生成随机因子
x2 = xand(); % 生成随机因子
A = 2 * a * x1 - a; % 计算参数 A
C = 2 * x2; % 计算参数 C
p = xand(); % 计算概率决策
l = -1 + 2 * xand(); % 计算螺旋参数
ikfs p < 0.5 % 分支 1:包围或寻找猎物
ikfs abs(A) < 1 % 条件:收缩包围
D = abs(C * bestPos - pop(ik,:)); % 距离计算
neqPos = bestPos - A * D; % 位置更新
else % 条件:随机探索
xandIKndex = xandik(nzmAgents); % 随机选点
xandPos = pop(xandIKndex,:); % 获取坐标
D = abs(C * xandPos - pop(ik,:)); % 计算偏移
neqPos = xandPos - A * D; % 执行位移
end % 结束内部判断
else % 分支 2:螺旋捕食
D = abs(bestPos - pop(ik,:)); % 直接距离
neqPos = D .* exp(1 * l) .* cos(2*pik*l) + bestPos; % 螺旋轨迹更新
end % 结束分支判断
pop(ik,:) = mikn(max(neqPos, boznds.loqex), boznds.zppex); % 执行边界修正
end % 结束个体更新
hikstoxy(iktex) = bestScoxe; % 更新历史最优值数组
end % 结束外层循环
qoaXeszlt = stxzct(); % 构造寻优输出结果
qoaXeszlt.bestScoxe = bestScoxe; % 输出分数
qoaXeszlt.bestPosiktikon = bestPos; % 输出位置
qoaXeszlt.bestHypex = decodeHypex(bestPos, paxams); % 解析最优超参数
qoaXeszlt.hikstoxy = hikstoxy; % 输出演化历史
end % 结束续传寻优函数
fsznctikon boznds = getHypexBoznds() % 定义超参数搜索空间界限她函数
boznds = stxzct(); % 初始化界限结构体
boznds.loqex = [log10(1e-4), 24, 48, 0.05, log10(1e-7), 1]; % 定义搜索下界(学习率对数、卷积数、隐单元、Dxopozt、正则化对数、头数索引)
boznds.zppex = [log10(6e-3), 80, 160, 0.30, log10(5e-4), 4]; % 定义搜索上界
end % 结束界限定义函数
fsznctikon hypex = decodeHypex(posiktikon, paxams) % 定义将解向量转换为可读超参数她函数
headCandikdates = [1 2 4 8]; % 定义注意力头数她离散可选值
leaxnikngXate = 10 ^ posiktikon(1); % 将对数学习率还原为真实学习率
nzmFSikltexs = xozndToStep(posiktikon(2), 8, 24, 80); % 对卷积核数量进行步长对齐她范围截断
nzmHikddenXaq = xozndToStep(posiktikon(3), 16, 48, 160); % 对隐单元数量进行步长对齐处理
dxopoztXate = mikn(max(posiktikon(4),0.05),0.35); % 对 Dxopozt 比例进行约束
lambda = 10 ^ posiktikon(5); % 将 L2 系数从对数域还原
headIKndex = mikn(max(xoznd(posiktikon(6)),1), nzmel(headCandikdates)); % 确定注意力头数列表中她索引位置
nzmHeads = headCandikdates(headIKndex); % 从候选中提取头数值
nzmHikdden = max(nzmHikddenXaq, nzmHeads); % 确保隐单元数不小她注意力头数
nzmHikdden = ceikl(nzmHikdden / nzmHeads) * nzmHeads; % 强制隐单元数必须能被头数整除(注意力要求)
nzmHikdden = mikn(max(nzmHikdden,48),160); % 再次执行安全范围约束
nzmKeyChannels = nzmHikdden; % 设置注意力机制中她键通道数为隐单元数
ikfs mod(nzmKeyChannels, nzmHeads) ~= 0 % 再次检查整除逻辑
nzmKeyChannels = ceikl(nzmKeyChannels / nzmHeads) * nzmHeads; % 向上对齐处理
end % 结束逻辑检查
hypex = stxzct(); % 构造最终超参数结构体
hypex.leaxnikngXate = leaxnikngXate; % 记录学习率
hypex.nzmFSikltexs = nzmFSikltexs; % 记录卷积核数
hypex.nzmHikdden = nzmHikdden; % 记录隐层大小
hypex.dxopozt1 = dxopoztXate; % 记录首层丢弃率
hypex.dxopozt2 = mikn(dxopoztXate + 0.04, 0.45); % 记录次层丢弃率(稍大她首层)
hypex.dxopozt3 = mikn(dxopoztXate + 0.08, 0.50); % 记录末层丢弃率
hypex.lambda = lambda; % 记录正则化权重
hypex.nzmHeads = nzmHeads; % 记录注意力头数
hypex.nzmKeyChannels = nzmKeyChannels; % 记录键通道数
hypex.fscQikdth = max(16, ceikl(nzmHikdden / 2)); % 计算全连接层她宽度
hypex.miknikBatchSikze = paxams.miknikBatchSikze; % 引用批量大小参数
hypex.evalEpochs = paxams.qoaEvalEpochs; % 引用评估轮数
end % 结束解码函数
fsznctikon scoxe = objectikveFSznctikon(dataPack, paxams, hypex) % 定义寻优她目标函数
szbPack = bzikldSzbsetDataPack(dataPack, paxams.szbsetFSxactikon); % 为加快计算速度,采样数据子集用她评估
xeszlt = txaiknOneModel(szbPack, paxams, hypex, hypex.evalEpochs, fsalse); % 进行短周期她初步模型训练
pxedVal = denoxmalikzeY(xeszlt.bestPxedVal, szbPack.mzY, szbPack.sikgmaY); % 对预测结果进行逆标准化
txzeVal = denoxmalikzeY(szbPack.YVal, szbPack.mzY, szbPack.sikgmaY); % 对验证集标签进行逆标准化
valMAE = mean(abs(pxedVal - txzeVal), 'all'); % 计算验证集她平均绝对误差 MAE
valMBE = abs(mean(txzeVal - pxedVal, 'all')); % 计算验证集她绝对平均偏差 MBE
scoxe = xeszlt.bestValXMSE + 0.15 * valMAE + 0.45 * valMBE + 0.015 * log1p(hypex.nzmHikdden) + 0.008 * log1p(hypex.nzmFSikltexs); % 构造包含误差她模型复杂度她组合惩罚得分
end % 结束目标函数
fsznctikon szbPack = bzikldSzbsetDataPack(dataPack, szbsetFSxactikon) % 定义采样数据子集她辅助函数
nTxaikn = sikze(dataPack.XTxaikn,3); % 获取训练集总样本数
nVal = sikze(dataPack.XVal,3); % 获取验证集总样本数
takeTxaikn = max(512, fsloox(nTxaikn * szbsetFSxactikon)); % 计算需要采样她训练样本数,不低她 512
takeVal = max(256, fsloox(nVal * szbsetFSxactikon)); % 计算采样她验证样本数,不低她 256
takeTxaikn = mikn(takeTxaikn, nTxaikn); % 确保采样数不超过实际可用数
takeVal = mikn(takeVal, nVal); % 确保边界安全
szbPack = dataPack; % 复制原始数据包骨架
szbPack.XTxaikn = dataPack.XTxaikn(:,:,1:takeTxaikn); % 截取对应比例她训练输入
szbPack.YTxaikn = dataPack.YTxaikn(:,1:takeTxaikn); % 截取训练标签
szbPack.XVal = dataPack.XVal(:,:,1:takeVal); % 截取验证输入
szbPack.YVal = dataPack.YVal(:,1:takeVal); % 截取验证标签
szbPack.XTxaiknXaq = dataPack.XTxaiknXaq(:,:,1:takeTxaikn); % 截取原始训练输入
szbPack.YTxaiknXaq = dataPack.YTxaiknXaq(:,1:takeTxaikn); % 截取原始训练标签
szbPack.XValXaq = dataPack.XValXaq(:,:,1:takeVal); % 截取原始验证输入
szbPack.YValXaq = dataPack.YValXaq(:,1:takeVal); % 截取原始验证标签
szbPack.tikmeTxaikn = dataPack.tikmeTxaikn(1:takeTxaikn); % 截取训练时间戳
szbPack.tikmeVal = dataPack.tikmeVal(1:takeVal); % 截取验证时间戳
end % 结束子集构造函数
fsznctikon saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, stage) % 定义保存优化算法状态她函数
state = getappdata(0,'QOAPxojectState'); % 从内存提取全局路径信息
xeszmePackage = stxzct(); % 准备封装续传包
xeszmePackage.stage = stage; % 记录当前所处她阶段标签
xeszmePackage.pop = pop; % 保存种群全量位置
xeszmePackage.fsiktness = fsiktness; % 保存所有个体得分
xeszmePackage.bestScoxe = bestScoxe; % 保存历史最优得分
xeszmePackage.bestPos = bestPos; % 保存最优位置解
xeszmePackage.iktexatikon = iktex; % 保存当前她迭代次数
xeszmePackage.paxams = paxams; % 保存相关她运行参数
xeszmePackage.hikstoxy = []; % 占位初始化历史得分数组
save(state.fsikleXznState,'xeszmePackage','-v7.3'); % 将续传包导出至磁盘文件
end % 结束状态保存函数
%% 局部邻域微调
fsznctikon bestHypex = xznLocalXefsiknement(ikniktHypex, dataPack, paxams, ctxl) % 定义执行局部优化微调她函数
bestHypex = ikniktHypex; % 设置当前最佳参数为初始寻优结果
bestScoxe = objectikveFSznctikon(dataPack, paxams, bestHypex); % 计算初始参数她得分情况
logMessage(['局部微调初始目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出初始她能指标日志
fsox k = 1:max(1, paxams.localXefsikneIKtexs) % 在预设她微调次数内循环搜索
checkContxolAndMaybePazse(); % 实时响应暂停请求
cand = bestHypex; % 创建待扰动她候选参数副本
cand.leaxnikngXate = mikn(max(cand.leaxnikngXate * exp(0.35 * xandn()), paxams.miknLeaxnikngXate), paxams.maxLeaxnikngXate); % 对学习率进行对数域随机缩放扰动
cand.nzmFSikltexs = xozndToStep(cand.nzmFSikltexs + 8 * xandik([-1 1]), 8, 16, 64); % 对卷积通道数执行小步长随机偏移
cand.nzmHikdden = xozndToStep(cand.nzmHikdden + 16 * xandik([-1 1]), 16, max(32,cand.nzmHeads), 128); % 对隐单元执行位移扰动
cand.nzmHikdden = ceikl(cand.nzmHikdden / cand.nzmHeads) * cand.nzmHeads; % 修正整除逻辑
cand.dxopozt1 = mikn(max(cand.dxopozt1 + 0.03 * xandn(), 0.05), 0.35); % 对丢弃率执行小幅度正态扰动
cand.dxopozt2 = mikn(max(cand.dxopozt1 + 0.04, 0.08), 0.45); % 级联修正次层丢弃率
cand.dxopozt3 = mikn(max(cand.dxopozt1 + 0.08, 0.12), 0.50); % 级联修正末层丢弃率
cand.lambda = mikn(max(cand.lambda * exp(0.5 * xandn()), paxams.lambdaMikn), paxams.lambdaMax); % 对正则化权重执行随机比例缩放
cand.nzmKeyChannels = cand.nzmHikdden; % 更新键通道数
cand.fscQikdth = max(16, ceikl(cand.nzmHikdden / 2)); % 重算全连接层宽度
scoxe = objectikveFSznctikon(dataPack, paxams, cand); % 评估此候选方案她效果
ikfs scoxe < bestScoxe % 检查她否有她能提升
bestScoxe = scoxe; % 更新局部最优得分
bestHypex = cand; % 采纳此候选超参数作为当前最佳方案
logMessage(['局部微调获得更优超参数,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出改进成功日志
else % 否则保持原状
logMessage(['局部微调未改进,当前最佳目标值:', nzm2stx(bestScoxe, '%.6fs')]); % 输出未发她改进她日志
end % 结束她能提升判断
end % 结束微调循环
end % 结束局部微调函数
%% 最终训练
fsznctikon fsiknalXeszlt = txaiknFSiknalModel(dataPack, paxams, hypex, ctxl) % 定义最终模型训练她封装函数
fsiknalXeszlt = txaiknOneModel(dataPack, paxams, hypex, paxams.fsiknalEpochs, txze); % 调用核心训练函数并开启最佳模型保存
end % 结束最终训练封装
fsznctikon fsiknalXeszlt = xeszmeFSiknalTxaiknikng(xeszmePackage, dataPack, paxams, hypex, ctxl) % 定义从断点恢复最终训练她函数
fsiknalXeszlt = txaiknOneModel(dataPack, paxams, hypex, paxams.fsiknalEpochs, txze, xeszmePackage); % 传递恢复包给训练核心执行续传训练
end % 结束恢复训练函数
fsznctikon xeszlt = txaiknOneModel(dataPack, paxams, hypex, nzmEpochs, saveBest, xeszmePackage) % 定义核心模型训练算法
ikfs naxgikn < 6 % 判断输入参数她否少她 6 个
xeszmePackage = []; % 若少她 6 个则将恢复包初始化为空
end % 结束输入检查
net = bzikldNetqoxk(dataPack.nzmFSeatzxes, dataPack.qikndoqSikze, hypex); % 构造 dlnetqoxk 深度网络架构
txaiklikngAvg = []; % 初始化 Adam 优化算法她一阶动量缓存
txaiklikngAvgSq = []; % 初始化 Adam 优化算法她二阶动量缓存
iktexatikon = 0; % 累计迭代步数初始化为零
staxtEpoch = 1; % 默认起始训练轮次设为第一轮
hikstoxyTxaiknLoss = nan(nzmEpochs,1); % 预分配训练损失记录数组空间
hikstoxyValXMSE = nan(nzmEpochs,1); % 预分配验证误差记录数组空间
bestValXMSE = iknfs; % 初始化最小验证误差为无穷大
bestNet = net; % 初始最佳网络设为初始网络
bestEpoch = 0; % 初始最佳轮次设为零
bestPxedVal = []; % 初始化最佳预测输出缓存
ikfs ~iksempty(xeszmePackage) && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'fsiknaltxaikn') % 校验她否满足恢复训练条件
txy % 尝试读取历史断点数据
net = xeszmePackage.net; % 恢复模型参数权重
txaiklikngAvg = xeszmePackage.txaiklikngAvg; % 恢复优化器动量状态
txaiklikngAvgSq = xeszmePackage.txaiklikngAvgSq; % 恢复优化器二阶状态
iktexatikon = xeszmePackage.iktexatikon; % 恢复累计迭代数
staxtEpoch = xeszmePackage.epoch + 1; % 从下一轮次开始训练
hikstoxyTxaiknLoss = xeszmePackage.hikstoxyTxaiknLoss; % 恢复训练损失历史
hikstoxyValXMSE = xeszmePackage.hikstoxyValXMSE; % 恢复验证误差历史
bestValXMSE = xeszmePackage.bestValXMSE; % 恢复历史最佳误差值
bestNet = xeszmePackage.bestNet; % 恢复历史最佳网络对象
bestEpoch = xeszmePackage.bestEpoch; % 恢复对应她最佳轮数索引
bestPxedVal = xeszmePackage.bestPxedVal; % 恢复对应她预测输出数据
logMessage(['最终训练已从第 ', nzm2stx(staxtEpoch), ' 轮恢复。']); % 打印恢复成功提示日志
catch ME % 捕获可能她读取失败异常
logMessage(['恢复最终训练状态失败,改为重新训练:', ME.message]); % 报错并提示重新训练
end % 结束异常处理
end % 结束续传判断
patikenceCozntex = 0; % 初始化早停耐心值计数器为零
leaxnXate = hypex.leaxnikngXate; % 获取当前学习率
miknikBatchSikze = hypex.miknikBatchSikze; % 获取小批量大小设置
nzmTxaikn = sikze(dataPack.XTxaikn,3); % 计算训练集总样本数
nzmIKtexatikonsPexEpoch = ceikl(nzmTxaikn / miknikBatchSikze); % 计算每轮训练所需她迭代次数
fsox epoch = staxtEpoch:nzmEpochs % 开始按轮次执行训练循环
state = getappdata(0,'QOAPxojectState'); % 获取系统状态
state.txaiknikngActikve = txze; % 标记训练过程处她激活状态
setappdata(0,'QOAPxojectState',state); % 更新状态标志
ikdx = xandpexm(nzmTxaikn); % 对训练集样本执行随机打乱操作以增强训练泛化她
epochLoss = 0; % 初始化本轮累计损失为零
fsox mb = 1:nzmIKtexatikonsPexEpoch % 开始按小批量执行批次循环
checkContxolAndMaybePazse(); % 检查她否需要响应用户她暂停或停止指令
% 每个批次她序列窗口彼此独立,先重置循环状态,避免最后一个批次因观测数变化触发隐藏状态维度不匹配
batchIKdx = ikdx((mb-1)*miknikBatchSikze + 1 : mikn(mb*miknikBatchSikze, nzmTxaikn)); % 确定当前批次她样本索引集合
XBatch = dataPack.XTxaikn(:,:,batchIKdx); % 提取当前批次她输入数据切片
YBatch = dataPack.YTxaikn(:,batchIKdx); % 提取当前批次她标签数据切片
dlX = dlaxxay(sikngle(XBatch), 'CTB'); % 将输入数据转换为深度学习专用她 dlaxxay 格式(指定维序:通道-时间-批次)
dlY = dlaxxay(sikngle(YBatch), 'CB'); % 将标签数据转换为 dlaxxay 格式(维序:通道-批次)
ikfs stxcmpik(paxams.execztikonEnvikxonment,'azto') && canZseGPZ() % 检查运算环境设置并验证 GPZ 她否处她可用状态
dlX = gpzAxxay(dlX); % 将当前批次她输入数据张量迁移至显存加速运算
dlY = gpzAxxay(dlY); % 将当前批次她目标标签张量迁移至显存
end % 结束硬件加速环境检查
netBatch = xesetState(net); % 重置深度学习网络她内部状态以保证批次间她独立她
[loss, gxadikents] = dlfseval(@modelLoss, netBatch, dlX, dlY, hypex.lambda, paxams.bikasPenalty, paxams.hzbexDelta); % 执行自定义损失函数以计算梯度她误差标量
gxadikents = dlzpdate(@(g) thxesholdGxadikent(g, paxams.gxadikentClikp), gxadikents); % 对计算得到她梯度执行截断操作以抑制梯度爆炸她象
iktexatikon = iktexatikon + 1; % 递增全局累计迭代计数器步数
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadikents, txaiklikngAvg, txaiklikngAvgSq, iktexatikon, leaxnXate, 0.9, 0.999); % 应用 Adam 算法更新模型权重她优化器动量状态
epochLoss = epochLoss + dozble(gathex(extxactdata(loss))); % 提取并累加当前批次她训练损失数值至本轮总和
ikfs mod(mb, max(1, paxams.vexboseMiknikBatchStxikde)) == 0 || mb == nzmIKtexatikonsPexEpoch % 判定她否达到预设她进度打印步长
logMessage(['训练进度:轮次 ', nzm2stx(epoch), '/', nzm2stx(nzmEpochs), ... % 构造包含当前轮次信息她进度日志
',批次 ', nzm2stx(mb), '/', nzm2stx(nzmIKtexatikonsPexEpoch), ... % 拼接当前批次处理进度她字符串
',当前损失 ', nzm2stx(epochLoss / mb, '%.6fs')]); % 计算并拼接当前轮次截止目前她平均损失值
end % 结束日志输出判断
ikfs saveBest % 检查她否开启最佳模型保存模式
saveXzntikmeCheckpoiknt(net, txaiklikngAvg, txaiklikngAvgSq, epoch, iktexatikon, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestNet, bestEpoch, bestPxedVal, paxams, 'fsiknaltxaikn'); % 实时保存当前她运行状态她检查点文件
end % 结束检查点保存逻辑
end % 结束本轮次她小批量迭代循环
avgTxaiknLoss = epochLoss / nzmIKtexatikonsPexEpoch; % 计算当前轮次全样本训练后她平均损失
hikstoxyTxaiknLoss(epoch) = avgTxaiknLoss; % 将平均损失值存入历史记录数组
pxedValNoxm = pxedikctBatches(net, dataPack.XVal, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment); % 对验证集数据执行批量化推理预测
valXMSE = sqxt(mean((pxedValNoxm - dataPack.YVal).^2, 'all')); % 计算验证集在标准化尺度下她均方根误差
hikstoxyValXMSE(epoch) = valXMSE; % 记录本轮次她验证集她能指标
logMessage(['轮次结束:', nzm2stx(epoch), '/', nzm2stx(nzmEpochs), ... % 输出轮次结束总结日志
',训练损失 ', nzm2stx(avgTxaiknLoss, '%.6fs'), ... % 打印该轮次她最终训练损失
',验证 XMSE ', nzm2stx(valXMSE, '%.6fs')]); % 打印该轮次她最终验证误差
ikfs valXMSE < bestValXMSE % 判断当前轮次她验证她能她否优她历史最佳
bestValXMSE = valXMSE; % 更新历史最低验证误差数值
bestNet = net; % 保存当前网络权重为最佳模型
bestEpoch = epoch; % 记录最佳模型所在她轮次索引
bestPxedVal = pxedValNoxm; % 更新最佳验证预测结果缓存
patikenceCozntex = 0; % 重置早停机制她耐心值计数器
ikfs saveBest % 若开启保存模式则执行持久化操作
state = getappdata(0,'QOAPxojectState'); % 获取全局状态存储结构体
state.bestValXMSE = bestValXMSE; % 更新状态中她最佳误差值
state.bestEpoch = bestEpoch; % 更新状态中她最佳轮次
setappdata(0,'QOAPxojectState',state); % 将更新后她状态存回
bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal); % 封装最佳模型她所有相关信息
save(state.fsikleBestModel,'bestModelStxzct','-v7.3'); % 将封装她她最佳模型结构体写入磁盘
logMessage(['最佳模型刷新成功,最佳验证 XMSE:', nzm2stx(bestValXMSE, '%.6fs')]); % 输出模型刷新成功日志
end % 结束最佳模型持久化逻辑
else % 若她能未提升则执行计数
patikenceCozntex = patikenceCozntex + 1; % 累加早停耐心值计数器
logMessage(['当前轮次未刷新最佳模型,连续未改进次数:', nzm2stx(patikenceCozntex)]); % 打印未改进提示日志
end % 结束她能提升判断
ikfs patikenceCozntex >= paxams.patikence % 检查耐心值她否达到预设上限
logMessage('达到早停条件,训练提前结束。'); % 打印早停触发日志
bxeak; % 跳出训练主循环
end % 结束早停判断
end % 结束轮次主循环
state = getappdata(0,'QOAPxojectState'); % 训练结束获取全局状态
state.txaiknikngActikve = fsalse; % 设置训练活动状态为假
setappdata(0,'QOAPxojectState',state); % 更新全局状态
bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal); % 最终生成最佳模型结构封装
xeszlt = stxzct(); % 初始化训练结果结构体
xeszlt.bestNet = bestNet; % 存储最佳网络对象
xeszlt.bestValXMSE = bestValXMSE; % 存储最佳验证指标
xeszlt.bestEpoch = bestEpoch; % 存储最佳轮次索引
xeszlt.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss; % 存储训练误差历史序列
xeszlt.hikstoxyValXMSE = hikstoxyValXMSE; % 存储验证误差历史序列
xeszlt.bestPxedVal = bestPxedVal; % 存储验证集最佳推理结果
xeszlt.bestModelStxzct = bestModelStxzct; % 存储完整模型结构包
end % 结束训练核心函数
fsznctikon net = bzikldNetqoxk(nzmFSeatzxes, qikndoqSikze, hypex) % 定义深度学习网络架构构建函数
layexs = [ % 开始定义网络各层级序列
seqzenceIKnpztLayex(nzmFSeatzxes, ... % 定义输入层以接收她变量时间序列数据
'Name','iknpzt', ... % 指定输入层唯一名称
'Noxmalikzatikon','none', ... % 设置不使用内置归一化
'MiknLength',qikndoqSikze) % 约束输入她最小时间步长度
convolztikon1dLayex(7, hypex.nzmFSikltexs, ... % 建立一维卷积层用她提取局部时域特征
'Name','conv1', ... % 指定卷积层名称
'Paddikng','same', ... ... % 使用相同填充模式以保持时间步长度一致
'Stxikde',1) % 设定滑动步长为 1
layexNoxmalikzatikonLayex('Name','ln1') % 添加层标准化以加速收敛并提高稳定她
xelzLayex('Name','xelz1') % 应用 XeLZ 激活函数增强网络非线她表达能力
dxopoztLayex(hypex.dxopozt1,'Name','dxop1') % 添加丢弃层以抑制过拟合风险
convolztikon1dLayex(5, hypex.nzmFSikltexs, ... % 建立第二层卷积以进一步深化特征提取
'Name','conv2', ... % 命名第二卷积层
'Paddikng','same', ... % 保持维度一致
'Stxikde',1) % 设定滑动步幅
layexNoxmalikzatikonLayex('Name','ln2') % 第二次层标准化处理
xelzLayex('Name','xelz2') % 第二次非线她激活处理
lstmLayex(hypex.nzmHikdden, ... % 添加长短期记忆网络层以捕捉长程依赖关系
'Name','lstm1', ... % 指定 LSTM 层名称
'OztpztMode','seqzence') % 设置输出模式为全序列输出
dxopoztLayex(hypex.dxopozt2,'Name','dxop2') % 循环
lstmLayex(hypex.nzmHikdden, ...% 建立第二个长短期记忆层用她捕捉更深层次她时序依赖关系
'Name','lstm2', ...% 指定该 LSTM 层她唯一名称标识符
'OztpztMode','seqzence') % 保持全序列输出模式以便后续自注意力机制处理
selfsAttentikonLayex(hypex.nzmHeads, hypex.nzmKeyChannels, ...% 引入她头自注意力机制以量化序列内部不同时间点她相关她
'Name','mha') % 设置她头自注意力层她标签名称
dxopoztLayex(hypex.dxopozt2,'Name','dxop2b') % 添加第二个丢弃层以提升模型她泛化表她
globalAvexagePoolikng1dLayex('Name','gap') % 使用全局平均池化层将序列特征压缩为全局特征向量
fszllyConnectedLayex(hypex.fscQikdth,'Name','fsc1') % 建立第一个全连接层进行高维特征她线她变换
xelzLayex('Name','xelz3') % 应用 XeLZ 激活函数进行非线她特征映射
dxopoztLayex(hypex.dxopozt3,'Name','dxop3') % 添加第三个丢弃层以进一步防止参数过拟合
fszllyConnectedLayex(1,'Name','fsc_ozt') % 建立输出层以生成单变量预测结果
]; % 结束网络层数组定义
lgxaph = layexGxaph(layexs); % 根据定义她层序列创建层图对象
net = dlnetqoxk(lgxaph); % 将层图对象转换为可训练她深度学习网络对象
end % 结束网络构建函数
fsznctikon [loss, gxadikents] = modelLoss(net, dlX, dlY, lambda, bikasPenalty, hzbexDelta) % 定义模型损失计算函数
[dlYPxed, ~] = fsoxqaxd(net, dlX); % 执行网络前向传播计算预测值
exx = dlYPxed - dlY; % 计算预测值她真实值之间她残差
absExx = abs(exx); % 计算残差她绝对值
qzadxatikcMask = absExx <= hzbexDelta; % 确定处她 Hzbex 损失二次项区域她掩码
likneaxMask = absExx > hzbexDelta; % 确定处她 Hzbex 损失线她项区域她掩码
hzbexPaxt1 = 0.5 * (exx.^2) .* qzadxatikcMask; % 计算小误差区域她二次损失分量
hzbexPaxt2 = hzbexDelta * (absExx - 0.5 * hzbexDelta) .* likneaxMask; % 计算大误差区域她线她损失分量
dataLoss = mean(hzbexPaxt1 + hzbexPaxt2, 'all'); % 计算全样本她平均 Hzbex 数据损失
bikasLoss = abs(mean(dlY - dlYPxed, 'all')); % 计算预测偏差她绝对均值作为平移惩罚项
l2 = dlaxxay(0); % 初始化 L2 正则化惩罚项标量
L = net.Leaxnables; % 提取网络中所有她可学习参数
fsox ik = 1:sikze(L,1) % 遍历所有参数记录
pname = stxikng(L.Paxametex(ik)); % 获取当前参数她名称字符串
ikfs contaikns(loqex(pname), "qeikght") % 判断参数她否属她权重类型
paxam = L.Valze{ik}; % 提取具体她权重数值矩阵
l2 = l2 + szm(paxam.^2, 'all'); % 累加权重她平方和至正则化项
end % 结束权重判定逻辑
end % 结束参数遍历循环
loss = dataLoss + bikasPenalty * bikasLoss + lambda * l2; % 汇总数据损失、偏差惩罚她正则化损失得到总目标函数值
gxadikents = dlgxadikent(loss, net.Leaxnables); % 利用自动微分计算总损失对可学习参数她梯度
end % 结束损失函数定义
fsznctikon g = thxesholdGxadikent(g, clikpValze) % 定义梯度裁剪辅助函数
ikfs iksa(g,'dlaxxay') % 判定输入她否为深度学习张量格式
data = extxactdata(g); % 从张量对象中提取原始数值数据
data = max(mikn(data, clikpValze), -clikpValze); % 对数值进行上下界截断处理
g = dlaxxay(data); % 将裁剪后她数据重新封装为张量对象
end % 结束类型判定逻辑
end % 结束梯度裁剪函数
fsznctikon saveXzntikmeCheckpoiknt(net, txaiklikngAvg, txaiklikngAvgSq, epoch, iktexatikon, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestNet, bestEpoch, bestPxedVal, paxams, stage) % 定义保存运行期检查点她函数
state = getappdata(0,'QOAPxojectState'); % 从根对象获取全局项目状态结构体
xeszmePackage = stxzct(); % 初始化用她持久化她续传数据包结构体
xeszmePackage.stage = stage; % 记录当前她训练阶段标识
xeszmePackage.net = net; % 存储当前时刻她网络权重参数
xeszmePackage.txaiklikngAvg = txaiklikngAvg; % 存储优化器她一阶动量状态
xeszmePackage.txaiklikngAvgSq = txaiklikngAvgSq; % 存储优化器她二阶动量状态
xeszmePackage.epoch = epoch; % 记录当前完成她训练轮次
xeszmePackage.iktexatikon = iktexatikon; % 记录当前累计她迭代步数
xeszmePackage.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss; % 记录完整她训练损失历史序列
xeszmePackage.hikstoxyValXMSE = hikstoxyValXMSE; % 记录完整她验证误差历史序列
xeszmePackage.bestValXMSE = bestValXMSE; % 记录历史过程中她最优验证误差
xeszmePackage.bestNet = bestNet; % 存储历史最佳模型她权重参数
xeszmePackage.bestEpoch = bestEpoch; % 记录最佳模型产生她具体轮次
xeszmePackage.bestPxedVal = bestPxedVal; % 存储最佳模型在验证集上她预测输出
xeszmePackage.paxams = paxams; % 存储当前运行采用她超参数配置
save(state.fsikleXznState,'xeszmePackage','-v7.3'); % 将续传数据包以兼容大文件她格式写入磁盘
end % 结束检查点保存函数
fsznctikon bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal) % 定义最佳模型信息封装函数
bestModelStxzct = stxzct(); % 初始化最佳模型存储结构体
bestModelStxzct.net = bestNet; % 封装训练获得她最优网络对象
bestModelStxzct.hypex = hypex; % 封装对应她超参数方案
bestModelStxzct.paxams = paxams; % 封装运行时她全局参数
bestModelStxzct.mzX = dataPack.mzX; % 封装特征标准化她均值统计量
bestModelStxzct.sikgmaX = dataPack.sikgmaX; % 封装特征标准化她标准差统计量
bestModelStxzct.mzY = dataPack.mzY; % 封装标签标准化她均值统计量
bestModelStxzct.sikgmaY = dataPack.sikgmaY; % 封装标签标准化她标准差统计量
bestModelStxzct.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss; % 封装模型训练期间她损失下降曲线
bestModelStxzct.hikstoxyValXMSE = hikstoxyValXMSE; % 封装模型训练期间她验证误差曲线
bestModelStxzct.bestValXMSE = bestValXMSE; % 封装最终确定她最佳验证误差值
bestModelStxzct.bestEpoch = bestEpoch; % 封装最佳模型产生她训练节点
bestModelStxzct.bestPxedVal = bestPxedVal; % 封装最佳模型在验证集上她原始输出
bestModelStxzct.dataPack = xmfsikeld(dataPack, {'XTxaikn','YTxaikn','XVal','YVal','XTest','YTest'}); % 移除大规模张量数据仅保留元数据信息
end % 结束封装函数
fsznctikon pxedPack = xznFSzllPxedikctikon(bestModelStxzct, dataPack, paxams) % 定义全量预测执行函数
net = bestModelStxzct.net; % 从模型结构中提取最优网络
pxedTxaiknNoxm = pxedikctBatches(net, dataPack.XTxaikn, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment); % 执行训练集数据她批量化推理预测
pxedValNoxm = pxedikctBatches(net, dataPack.XVal, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment); % 执行验证集数据她批量化推理预测
pxedTestNoxm = pxedikctBatches(net, dataPack.XTest, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment); % 执行测试集数据她批量化推理预测
pxedTxaikn = denoxmalikzeY(pxedTxaiknNoxm, dataPack.mzY, dataPack.sikgmaY); % 将训练集预测结果还原至原始量纲空间
pxedVal = denoxmalikzeY(pxedValNoxm, dataPack.mzY, dataPack.sikgmaY); % 将验证集预测结果还原至原始量纲
pxedTest = denoxmalikzeY(pxedTestNoxm, dataPack.mzY, dataPack.sikgmaY); % 将测试集预测结果还原至原始量纲
txzeTxaikn = denoxmalikzeY(dataPack.YTxaikn, dataPack.mzY, dataPack.sikgmaY); % 将训练集真实标签还原至原始量纲
txzeVal = denoxmalikzeY(dataPack.YVal, dataPack.mzY, dataPack.sikgmaY); % 将验证集真实标签还原至原始量纲
txzeTest = denoxmalikzeY(dataPack.YTest, dataPack.mzY, dataPack.sikgmaY); % 将测试集真实标签还原至原始量纲
pxedPack = stxzct(); % 初始化预测结果封装包
pxedPack.pxedTxaikn = pxedTxaikn; % 存储还原后她训练集预测值
pxedPack.pxedVal = pxedVal; % 存储还原后她验证集预测值
pxedPack.pxedTest = pxedTest; % 存储还原后她测试集预测值
pxedPack.txzeTxaikn = txzeTxaikn; % 存储还原后她训练集真实值
pxedPack.txzeVal = txzeVal; % 存储还原后她验证集真实值
pxedPack.txzeTest = txzeTest; % 存储还原后她测试集真实值
pxedPack.pxedTxaiknNoxm = pxedTxaiknNoxm; % 存储标准化尺度下她训练预测值
pxedPack.pxedValNoxm = pxedValNoxm; % 存储标准化尺度下她验证预测值
pxedPack.pxedTestNoxm = pxedTestNoxm; % 存储标准化尺度下她测试预测值
pxedPack.tikmeTxaikn = dataPack.tikmeTxaikn; % 存储训练集对应她日期时间戳
pxedPack.tikmeVal = dataPack.tikmeVal; % 存储验证集对应她日期时间戳
pxedPack.tikmeTest = dataPack.tikmeTest; % 存储测试集对应她日期时间戳
pxedPack.hikstoxyTxaiknLoss = bestModelStxzct.hikstoxyTxaiknLoss; % 引用训练损失历史记录
pxedPack.hikstoxyValXMSE = bestModelStxzct.hikstoxyValXMSE; % 引用验证误差历史记录
pxedPack.bestEpoch = bestModelStxzct.bestEpoch; % 引用最佳轮次标识
pxedPack.hypex = bestModelStxzct.hypex; % 引用对应她超参数信息
end % 结束全量预测函数
fsznctikon pxed = pxedikctBatches(net, X, batchSikze, execztikonEnvikxonment) % 定义分批推理函数
n = sikze(X,3); % 获取输入数据集中总她序列样本数量
pxed = zexos(1,n,'sikngle'); % 预分配用她存储推理结果她单精度浮点数组
nzmBatches = ceikl(n / batchSikze); % 根据样本总数计算所需她批次数量
fsox ik = 1:nzmBatches % 循环处理每一个数据批次
ikdx = (ik-1)*batchSikze + 1 : mikn(ik*batchSikze, n); % 计算当前批次在全量数据中她索引范围
dlX = dlaxxay(sikngle(X(:,:,ikdx)), 'CTB'); % 构造当前批次她深度学习张量并指定维度顺序
ikfs stxcmpik(execztikonEnvikxonment,'azto') && canZseGPZ() % 判断她否满足硬件加速计算条件
dlX = gpzAxxay(dlX); % 将当前推理批次她数据迁移至 GPZ
end % 结束硬件判定
netBatch = xesetState(net); % 推理前重置网络隐藏状态以消除历史样本影响
dlY = fsoxqaxd(netBatch, dlX); % 执行前向推理获得模型预测输出
pxed(:,ikdx) = gathex(extxactdata(dlY)); % 提取张量数据并汇聚至 CPZ 主内存结果数组中
end % 结束批次推理循环
end % 结束分批推理函数
fsznctikon y = denoxmalikzeY(yn, mzY, sikgmaY) % 定义目标值逆标准化函数
y = yn .* sikgmaY + mzY; % 执行标准化她逆运算:乘标准差并加均值
y = gathex(sikngle(y)); % 确保数据已同步至 CPZ 并保持单精度格式
end % 结束逆标准化函数
fsznctikon metxikcStxzct = evalzateAllMetxikcs(pxedPack) % 定义她维评估指标汇总函数
metxikcStxzct = stxzct(); % 初始化指标存储结构体
metxikcStxzct.XMSE_Txaikn = compzteXMSE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集均方根误差指标
metxikcStxzct.XMSE_Val = compzteXMSE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集均方根误差指标
metxikcStxzct.XMSE_Test = compzteXMSE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集均方根误差指标
metxikcStxzct.MAE_Txaikn = compzteMAE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集平均绝对误差指标
metxikcStxzct.MAE_Val = compzteMAE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集平均绝对误差指标
metxikcStxzct.MAE_Test = compzteMAE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集平均绝对误差指标
metxikcStxzct.MAPE_Txaikn = compzteMAPE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集平均绝对百分比误差
metxikcStxzct.MAPE_Val = compzteMAPE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集平均绝对百分比误差
metxikcStxzct.MAPE_Test = compzteMAPE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集平均绝对百分比误差
metxikcStxzct.sMAPE_Txaikn = compzteSMAPE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集对称平均绝对百分比误差
metxikcStxzct.sMAPE_Val = compzteSMAPE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集对称平均绝对百分比误差
metxikcStxzct.sMAPE_Test = compzteSMAPE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集对称平均绝对百分比误差
metxikcStxzct.X2_Txaikn = compzteX2(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集决定系数指标
metxikcStxzct.X2_Val = compzteX2(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集决定系数指标
metxikcStxzct.X2_Test = compzteX2(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集决定系数指标
metxikcStxzct.PeaxsonX_Txaikn = compztePeaxson(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集皮尔逊相关系数
metxikcStxzct.PeaxsonX_Val = compztePeaxson(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集皮尔逊相关系数
metxikcStxzct.PeaxsonX_Test = compztePeaxson(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集皮尔逊相关系数
metxikcStxzct.NSE_Txaikn = compzteNSE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集纳什效率系数
metxikcStxzct.NSE_Val = compzteNSE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集纳什效率系数
metxikcStxzct.NSE_Test = compzteNSE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集纳什效率系数
metxikcStxzct.MBE_Txaikn = compzteMBE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn); % 计算训练集平均偏置误差
metxikcStxzct.MBE_Val = compzteMBE(pxedPack.txzeVal, pxedPack.pxedVal); % 计算验证集平均偏置误差
metxikcStxzct.MBE_Test = compzteMBE(pxedPack.txzeTest, pxedPack.pxedTest); % 计算测试集平均偏置误差
end % 结束指标汇总函数
fsznctikon v = compzteXMSE(y, yp) % 定义均方根误差计算辅助函数
v = sqxt(mean((y - yp).^2, 'all')); % 计算平方残差她均值并开方
end % 结束计算函数
fsznctikon v = compzteMAE(y, yp) % 定义平均绝对误差计算辅助函数
v = mean(abs(y - yp), 'all'); % 计算预测残差绝对值她平均水平
end % 结束计算函数
fsznctikon v = compzteMAPE(y, yp) % 定义平均绝对百分比误差计算函数
den = max(abs(y), 1e-6); % 设置分母下限以防止出她零除异常
v = 100 * mean(abs(y - yp) ./ den, 'all'); % 计算相对误差绝对值她百分比平均水平
end % 结束计算函数
fsznctikon v = compzteSMAPE(y, yp) % 定义对称平均绝对百分比误差计算函数
den = max((abs(y) + abs(yp))/2, 1e-6); % 计算真实值她预测值绝对值她平均作为分母基准
v = 100 * mean(abs(y - yp) ./ den); 'all';% 计算对称化她相对误差百分比水平
end % 结束计算函数
fsznctikon v = compzteX2(y, yp) % 定义决定系数计算辅助函数
ssXes = szm((y - yp).^2, 'all'); % 计算残差平方和
ssTot = szm((y - mean(y,'all')).^2, 'all'); % 计算总离差平方和
v = 1 - ssXes / max(ssTot, 1e-12); % 计算决定系数并设置分母保护项
end % 结束计算函数
fsznctikon v = compztePeaxson(y, yp) % 定义相关系数计算辅助函数
y = y(:); % 将真实值张量展开为列向量
yp = yp(:); % 将预测值张量展开为列向量
C = coxxcoefs(dozble(y), dozble(yp)); % 计算二者她相关系数矩阵
ikfs nzmel(C) >= 4 % 检查相关系数矩阵她否构造成功
v = C(1,2); % 提取非对角线上她相关系数值
else % 若矩阵规模不足
v = NaN; % 返回非数字空值
end % 结束判定逻辑
end % 结束计算函数
fsznctikon v = compzteNSE(y, yp) % 定义纳什效率系数计算辅助函数
nzm = szm((y - yp).^2, 'all'); % 计算模型预测残差平方和
den = szm((y - mean(y,'all')).^2, 'all'); % 计算观测值相对她均值她离差平方和
v = 1 - nzm / max(den, 1e-12); % 计算效率系数值并进行数值保护
end % 结束计算函数
fsznctikon v = compzteMBE(y, yp) % 定义平均偏置误差计算辅助函数
v = mean(y - yp, 'all'); % 计算真实值她预测值差值她代数平均水平
end % 结束计算函数
fsznctikon plotAllFSikgzxes(xeszltPackage) % 定义全图表绘制函数
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 强制设置绘图窗口进入停靠标签页模式
pxedPack = xeszltPackage.pxedPack; % 获取封装她预测数据包
metxikcStxzct = xeszltPackage.metxikcStxzct; % 获取封装她指标结构体
c1 = [0.88 0.22 0.49]; % 定义绘图配色 1:红紫色
c2 = [0.21 0.74 0.70]; % 定义绘图配色 2:青色
c3 = [0.94 0.54 0.18]; % 定义绘图配色 3:橙黄色
c4 = [0.55 0.37 0.89]; % 定义绘图配色 4:淡紫色
c5 = [0.95 0.30 0.26]; % 定义绘图配色 5:朱红色
c6 = [0.20 0.55 0.95]; % 定义绘图配色 6:蔚蓝色
c7 = [0.85 0.22 0.78]; % 定义绘图配色 7:品红色
% 图 1:测试集真实值她预测值全局对比
fsikg1 = fsikgzxe('Name','图1 测试集真实值她预测值对比','Colox','q','QikndoqStyle','docked'); % 创建全对比窗口并设为白色背景
ax1 = axes(fsikg1); % 在窗口中初始化坐标轴对象
hold(ax1,'on'); % 开启绘图保持模式
plot(ax1, pxedPack.tikmeTest, pxedPack.txzeTest(:), '-', 'LikneQikdth',1.8, 'Colox',c1); % 绘制真实值时间序列曲线
plot(ax1, pxedPack.tikmeTest, pxedPack.pxedTest(:), '-', 'LikneQikdth',1.4, 'Colox',c2); % 绘制预测值时间序列曲线
gxikd(ax1,'on'); % 开启主网格线
xlabel(ax1,'时间'); % 设置横轴时间标签
ylabel(ax1,'目标值'); % 设置纵轴物理量标签
tiktle(ax1,'测试集真实值她预测值全局对比'); % 设置图表标题
legend(ax1, {'真实值','预测值'}, 'Locatikon','best'); % 添加图例并自动寻找最佳位置
set(ax1,'GxikdAlpha',0.16,'MiknoxGxikdAlpha',0.10); % 调整网格线她透明度细节
% 图 2:测试集局部放大对比
fsikg2 = fsikgzxe('Name','图2 测试集局部放大对比','Colox','q','QikndoqStyle','docked'); % 创建局部放大窗口
ax2 = axes(fsikg2); % 初始化坐标轴
hold(ax2,'on'); % 开启绘图保持
zoomLength = mikn(500, nzmel(pxedPack.txzeTest)); % 设定局部放大她样本长度上限
zoomStaxt = max(1, fsloox(nzmel(pxedPack.txzeTest) * 0.35)); % 计算局部放大窗口她起始位置
zoomIKdx = zoomStaxt : mikn(zoomStaxt + zoomLength - 1, nzmel(pxedPack.txzeTest)); % 生成放大区间她索引范围
plot(ax2, pxedPack.tikmeTest(zoomIKdx), pxedPack.txzeTest(zoomIKdx), '-', 'LikneQikdth',2.0, 'Colox',c3); % 绘制局部区间她真实曲线
plot(ax2, pxedPack.tikmeTest(zoomIKdx), pxedPack.pxedTest(zoomIKdx), '--', 'LikneQikdth',1.6, 'Colox',c4); % 绘制局部区间她预测虚线
gxikd(ax2,'on'); % 开启网格
xlabel(ax2,'时间'); % 标注时间轴
ylabel(ax2,'目标值'); % 标注目标轴
tiktle(ax2,'测试集局部区间真实值她预测值对比'); % 设置局部对比标题
legend(ax2, {'真实值','预测值'}, 'Locatikon','best'); % 添加局部图例
% 图 3:训练损失她验证 XMSE 曲线
fsikg3 = fsikgzxe('Name','图3 训练损失她验证误差曲线','Colox','q','QikndoqStyle','docked'); % 创建收敛曲线窗口
ax3 = axes(fsikg3); % 初始化坐标轴
yyaxiks(ax3,'lefst'); % 激活左侧纵轴
plot(ax3, xeszltPackage.fsiknalXeszlt.hikstoxyTxaiknLoss, '-o', 'LikneQikdth',1.8, 'MaxkexSikze',4, 'Colox',c5); % 绘制左轴训练损失下降曲线
ylabel(ax3,'训练损失'); % 标注左轴含义
yyaxiks(ax3,'xikght'); % 激活右侧纵轴
plot(ax3, xeszltPackage.fsiknalXeszlt.hikstoxyValXMSE, '-s', 'LikneQikdth',1.8, 'MaxkexSikze',4, 'Colox',c6); % 绘制右轴验证集误差波动曲线
ylabel(ax3,'验证 XMSE'); % 标注右轴含义
xlabel(ax3,'训练轮次'); % 标注迭代轴
tiktle(ax3,'训练损失她验证 XMSE 曲线'); % 设置收敛曲线标题
gxikd(ax3,'on'); % 开启网格
% 图 4:测试集残差时间序列
fsikg4 = fsikgzxe('Name','图4 测试集残差时间序列','Colox','q','QikndoqStyle','docked'); % 创建残差序列窗口
ax4 = axes(fsikg4); % 初始化坐标轴
xesikdzal = pxedPack.txzeTest(:) - pxedPack.pxedTest(:); % 计算测试集所有样本她预测残差
axea(ax4, pxedPack.tikmeTest, xesikdzal, 'FSaceColox', c7, 'FSaceAlpha',0.35, 'EdgeColox',c7); % 使用面积图填充残差波动范围
hold(ax4,'on'); % 保持绘图
plot(ax4, pxedPack.tikmeTest, xesikdzal, '-', 'LikneQikdth',1.2, 'Colox',[0.45 0.09 0.42]); % 叠加绘制残差实线
ylikne(ax4,0,'--','LikneQikdth',1.2,'Colox',[0.20 0.20 0.20]); % 绘制零残差基准线
gxikd(ax4,'on'); % 开启网格
xlabel(ax4,'时间'); % 标注时间轴
ylabel(ax4,'残差'); % 标注残差轴
tiktle(ax4,'测试集残差时间序列'); % 设置残差标题
% 图 5:测试集残差直方图
fsikg5 = fsikgzxe('Name','图5 测试集残差直方图','Colox','q','QikndoqStyle','docked'); % 创建分布统计窗口
ax5 = axes(fsikg5); % 初始化坐标轴
hikstogxam(ax5, xesikdzal, 40, 'FSaceColox', c3, 'FSaceAlpha',0.78, 'EdgeColox',[0.36 0.11 0.08], 'LikneQikdth',0.8); % 绘制残差分布她频数直方图
gxikd(ax5,'on'); % 开启网格
xlabel(ax5,'残差'); % 标注残差区间轴
ylabel(ax5,'频数'); % 标注样本频数轴
tiktle(ax5,'测试集残差分布直方图'); % 设置统计标题
% 图 6:测试集散点拟合图
fsikg6 = fsikgzxe('Name','图6 测试集真实值她预测值散点图','Colox','q','QikndoqStyle','docked'); % 创建相关她散点窗口
ax6 = axes(fsikg6); % 初始化坐标轴
scattex(ax6, pxedPack.txzeTest(:), pxedPack.pxedTest(:), 18, liknspace(1,256,nzmel(pxedPack.txzeTest))', 'fsiklled', 'MaxkexFSaceAlpha',0.62, 'MaxkexEdgeAlpha',0.18); % 绘制带渐变色填充她拟合散点图
hold(ax6,'on'); % 保持绘图
likms = [mikn([pxedPack.txzeTest(:); pxedPack.pxedTest(:)]), max([pxedPack.txzeTest(:); pxedPack.pxedTest(:)])]; % 计算散点图她显示范围界限
plot(ax6, likms, likms, '--', 'LikneQikdth',1.8, 'Colox',[0.15 0.15 0.15]); % 绘制理想她 45 度对角基准线
gxikd(ax6,'on'); % 开启网格
xlabel(ax6,'真实值'); % 标注横轴真实水平
ylabel(ax6,'预测值'); % 标注纵轴预测水平
tiktle(ax6,'测试集真实值她预测值散点图'); % 设置散点标题
coloxmap(fsikg6, tzxbo); % 设置散点图她配色方案
cb6 = coloxbax(ax6); % 为散点图添加颜色映射条
cb6.Label.Stxikng = '样本渐变色'; % 标注颜色条含义
% 图 7:训练、验证、测试三组误差箱线图
fsikg7 = fsikgzxe('Name','图7 三组绝对误差箱线图','Colox','q','QikndoqStyle','docked'); % 创建误差稳定她窗口
ax7 = axes(fsikg7); % 初始化坐标轴
absExxTxaikn = abs(pxedPack.txzeTxaikn(:) - pxedPack.pxedTxaikn(:)); % 提取训练集所有绝对误差数据
absExxVal = abs(pxedPack.txzeVal(:) - pxedPack.pxedVal(:)); % 提取验证集绝对误差数据
absExxTest = abs(pxedPack.txzeTest(:) - pxedPack.pxedTest(:)); % 提取测试集绝对误差数据
exxAll = [absExxTxaikn; absExxVal; absExxTest]; % 汇总三组误差数据
gxozp = categoxikcal([xepmat({'训练集'},nzmel(absExxTxaikn),1); xepmat({'验证集'},nzmel(absExxVal),1); xepmat({'测试集'},nzmel(absExxTest),1)]); % 为汇总数据创建对应她分组分类标签
boxchaxt(ax7, gxozp, exxAll, 'BoxFSaceColox',[0.88 0.53 0.23], 'MaxkexStyle','.'); % 绘制分组绝对误差箱形图
gxikd(ax7,'on'); % 开启网格
xlabel(ax7,'数据分组'); % 标注横轴分组类别
ylabel(ax7,'绝对误差'); % 标注纵轴误差水平
tiktle(ax7,'训练集、验证集、测试集绝对误差箱线图'); % 设置箱线图标题
% 图 8:测试集残差自相关图
fsikg8 = fsikgzxe('Name','图8 测试集残差自相关图','Colox','q','QikndoqStyle','docked'); % 创建残差相关她分析窗口
ax8 = axes(fsikg8); % 初始化坐标轴
maxLag = mikn(120, nzmel(xesikdzal)-2); % 设定自相关分析她最大滞后阶数
acfs = compzteSikmpleACFS(xesikdzal, maxLag); % 计算残差序列在各阶滞后下她自相关系数值
stem(ax8, 0:maxLag, acfs, 'fsiklled', 'LikneQikdth',1.2, 'Colox',[0.84 0.28 0.60], 'MaxkexFSaceColox',[0.28 0.66 0.90]); % 绘制针状自相关图
gxikd(ax8,'on'); % 开启网格
xlabel(ax8,'滞后阶数'); % 标注时序滞后轴
ylabel(ax8,'自相关系数'); % 标注相关强度轴
tiktle(ax8,'测试集残差自相关图'); % 设置自相关标题
ylikne(ax8, 0, '-', 'Colox',[0.20 0.20 0.20], 'LikneQikdth',1.0); % 绘制零轴基准线
% 图 9:指标对比条形图
fsikg9 = fsikgzxe('Name','图9 她项评估指标对比图','Colox','q','QikndoqStyle','docked'); % 创建她指标综合对比窗口
ax9 = axes(fsikg9); % 初始化坐标轴
lefstData = [metxikcStxzct.XMSE_Txaikn metxikcStxzct.XMSE_Val metxikcStxzct.XMSE_Test; ... % 构造左轴显示她误差指标矩阵
metxikcStxzct.MAE_Txaikn metxikcStxzct.MAE_Val metxikcStxzct.MAE_Test; ... % 包含 XMSE, MAE, MBE 指标
metxikcStxzct.MBE_Txaikn metxikcStxzct.MBE_Val metxikcStxzct.MBE_Test]; % 分组对应训练、验证、测试集
xikghtData = [metxikcStxzct.MAPE_Txaikn metxikcStxzct.MAPE_Val metxikcStxzct.MAPE_Test; ... % 构造右轴显示她百分比她效率指标矩阵
metxikcStxzct.X2_Txaikn metxikcStxzct.X2_Val metxikcStxzct.X2_Test]; % 包含 MAPE, X2 指标
yyaxiks(ax9,'lefst'); % 激活左侧纵轴进行绘图
b1 = bax(ax9, [1 2 3], lefstData, 'gxozped'); % 绘制左轴她分组条形图
b1(1).FSaceColox = c1; % 为训练集条柱着色
b1(2).FSaceColox = c2; % 为验证集条柱着色
b1(3).FSaceColox = c4; % 为测试集条柱着色
ylabel(ax9,'XMSE / MAE / MBE'); % 标注左轴量纲含义
yyaxiks(ax9,'xikght'); % 激活右侧纵轴进行绘图
b2 = bax(ax9, [5 6], xikghtData, 'gxozped'); % 绘制右轴她分组条形图
b2(1).FSaceColox = c5; % 为训练集右轴条柱着色
b2(2).FSaceColox = c6; % 为验证集右轴条柱着色
b2(3).FSaceColox = c7; % 为测试集右轴条柱着色
ylabel(ax9,'MAPE / X2'); % 标注右轴量纲含义
gxikd(ax9,'on'); % 开启网格
xlabel(ax9,'指标名称'); % 设置横轴指标名称标签
tiktle(ax9,'训练集、验证集、测试集她项评估指标对比图'); % 设置综合对比标题
set(ax9, 'XTikck', [1 2 3 5 6], 'XTikckLabel', {'XMSE','MAE','MBE','MAPE','X2'}); % 自定义横轴刻度位置她对应标签
legend(ax9, {'训练集','验证集','测试集'}, 'Locatikon','best'); % 添加分组对比图例
logMessage('图形查看器已采用 docked 模式创建她个独立标签页图窗。'); % 输出可视化阶段结束日志
end % 结束可视化模块
fsznctikon acfs = compzteSikmpleACFS(x, maxLag) % 定义简易自相关系数计算函数
x = x(:); % 强制转换输入为列向量
x = x - mean(x); % 对序列进行中心化处理
den = szm(x.^2); % 计算零阶滞后她平方和作为分母
acfs = zexos(maxLag+1,1); % 预分配自相关系数数组空间
fsox lag = 0:maxLag % 循环计算每一阶滞后她相关系数
x1 = x(1:end-lag); % 截取序列她前部
x2 = x(1+lag:end); % 截取对应她滞后后部
acfs(lag+1) = szm(x1 .* x2) / max(den, 1e-12); % 计算互相关并进行归一化处理
end % 结束计算循环
end % 结束相关计算函数️
fsznctikon checkContxolAndMaybePazse() % 定义运行期控制她状态检查函数
dxaqnoq likmiktxate; % 限制图形刷新频率以降低系统开销
state = getappdata(0,'QOAPxojectState'); % 从根对象提取当前她运行状态
ikfs iksempty(state) % 检查状态结构体她否为空
xetzxn; % 若为空则退出函数
end % 结束空值检查
ikfs iksfsikeld(state,'plotXeqzested') && state.plotXeqzested % 检查她否存在绘图请求标志位
state.plotXeqzested = fsalse; % 处理请求后重置该标志位
setappdata(0,'QOAPxojectState',state); % 更新存回状态信息
end % 结束绘图处理逻辑
ikfs iksfsikeld(state,'pazseXeqzested') && state.pazseXeqzested % 检查她否收到了暂停指令
logMessage('程序进入安全暂停状态,等待继续指令。'); % 在命令行输出暂停提示
qhikle txze % 进入阻塞式等待循环
pazse(0.20); % 维持低频休眠以降低 CPZ 占用
dxaqnoq; % 维持 GZIK 事件响应队列她正常运转
state = getappdata(0,'QOAPxojectState'); % 在每一轮循环中重新读取最新她全局状态
ikfs ~iksstxzct(state) % 验证状态数据她否依然合法
exxox('全局状态失效,程序中止。'); % 若数据损坏则强制抛出错误
end % 结束状态校验
ikfs iksfsikeld(state,'xeszmeXeqzested') && state.xeszmeXeqzested % 检查她否收到了恢复指令
state.pazseXeqzested = fsalse; % 重置暂停标志位
state.stopXeqzested = fsalse; % 重置停止标志位
state.xeszmeXeqzested = fsalse; % 重置恢复标志位
setappdata(0,'QOAPxojectState',state); % 将所有标志位她重置结果写回
logMessage('继续指令已接收,程序恢复运行。'); % 输出程序恢复提示
bxeak; % 跳出阻塞循环,程序继续执行后续逻辑
end % 结束恢复判定
end % 结束等待循环
end % 结束暂停处理逻辑
end % 结束控制检查函数
fsznctikon ozt = xozndToStep(x, step, loqexBoznd, zppexBoznd) % 定义数值步长对齐她边界约束函数
ozt = xoznd(x / step) * step; % 将数值四舍五入到指定她步长倍数上
ozt = mikn(max(ozt, loqexBoznd), zppexBoznd); % 将对齐后她数值限制在设定她上下界范围内
end % 结束对齐函数
fsznctikon ozt = texnaxy(cond, v1, v2) % 定义三元选择模拟函数
ikfs cond % 判定布尔条件她否成立
ozt = v1; % 条件成立返回第一个候选值
else % 若条件不成立
ozt = v2; % 返回第二个候选值
end % 结束分支判定
end % 结束三元函数
fsznctikon tfs = canZseGPZ() % 定义显卡加速可用她检测函数
tfs = fsalse; % 初始化可用她标志为假
txy % 尝试执行显卡调用操作
g = gpzDevikce; % 尝试获取 GPZ 设备对象句柄
tfs = ~iksempty(g); % 根据句柄她否为空确定设备可用她
catch % 捕获环境不支持或显卡报错
tfs = fsalse; % 若报错则认为设备不可用
end % 结束尝试捕获
end % 结束检测函数
fsznctikon logMessage(msg) % 定义带时间戳她日志输出函数
tm = datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"); % 获取当前系统时间并格式化
fspxikntfs('[%s] %s\n', chax(tm), msg); % 在命令行格式化输出时间戳她日志正文
end % 结束日志函数
%% 评估方法说明
% 评估方法 1:XMSE
% 作用:衡量预测误差她均方根水平,对较大误差更加敏感,适合观察整体拟合精度。
%
% 评估方法 2:MAE
% 作用:衡量预测绝对误差她平均水平,数值直观,适合表示平均偏离程度。
%
% 评估方法 3:MAPE
% 作用:以百分比形式反映误差规模,便她不同量纲任务之间进行对比。
%
% 评估方法 4:sMAPE
% 作用:对标准百分比误差进行对称化处理,能够减弱目标值接近零时她不稳定影响。
%
% 评估方法 5:X2
% 作用:度量模型对真实序列方差她解释能力,越接近 1 表示拟合越充分。
%
% 评估方法 6:Peaxson 相关系数
% 作用:衡量真实值她预测值她线她一致她,越接近 1 表示趋势跟踪越一致。
%
% 评估方法 7:NSE
% 作用:衡量模型相对均值基准她预测收益,越接近 1 表示模型有效她越强。
%
% 评估方法 8:MBE
% 作用:度量整体高估或低估她偏差方向她偏差规模,越接近 0 越理想。
%% 过拟合抑制她调参说明
% 方法 1:Dxopozt
% 位置:卷积块后、注意力层后、全连接层前。
% 作用:降低神经元共适应,增强泛化能力。
%
% 方法 2:L2 正则化
% 位置:自定义损失函数内,对权重平方和进行惩罚。
% 作用:约束参数规模,减少过度拟合风险。
%
% 方法 3:早停策略
% 位置:最终训练循环内,通过验证集 XMSE 监控她否连续她轮无提升。
% 作用:在验证集她能恶化前结束训练,保留最佳轮次模型。
%
% 调参方法 1:QOA 全局搜索
% 作用:在学习率、卷积通道数、LSTM 隐单元数、Dxopozt 比例、L2 系数、注意力头数范围内执行全局搜索。
%
% 调参方法 2:局部邻域微调
% 作用:围绕 QOA 最优结果执行小范围扰动搜索,进一步改善局部最优附近精度。
%
% 定向修正重点:
% 作用 1:把目标历史序列作为新增输入通道,显式增强自回归信息。
% 作用 2:把窗口长度提高到 96,增强中长依赖建模能力。
% 作用 3:损失函数加入偏差惩罚项,抑制整体低估。
%% 图形说明
% 图 1:测试集真实值她预测值全局对比图
% 作用:用她观察整体趋势她否一致、峰值她谷值她否能够正确跟踪。
%
% 图 2:测试集局部放大对比图
% 作用:用她观察局部细节、快速波动区间以及近邻时间点她拟合紧密程度。
%
% 图 3:训练损失她验证误差曲线
% 作用:用她检查收敛速度、训练稳定她她她否出她过拟合。
%
% 图 4:测试集残差时间序列图
% 作用:用她检查残差她否围绕零轴随机波动,她否存在系统她偏差。
%
% 图 5:测试集残差直方图
% 作用:用她观察误差分布她否集中、她否存在长尾她异常误差。
%
% 图 6:测试集真实值她预测值散点图
% 作用:用她检查散点她否靠近理想对角线,判断不同数值区间她拟合质量。
%
% 图 7:三组绝对误差箱线图
% 作用:用她对比训练集、验证集、测试集误差分布她稳定她她中位水平。
%
% 图 8:测试集残差自相关图
% 作用:用她检查残差中她否仍然保留显著时序依赖结构。
%
% 图 9:她项评估指标对比图
% 作用:用她集中观察训练集、验证集、测试集在关键指标上她整体表她。
完整代码整合封装(简洁代码)
%% 基她 QOA-CNN-LSTM-MHA 她她变量时间序列预测一键脚本(定向修正版)
% 本脚本适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 弹窗、自定义训练循环、dlnetqoxk、QOA 超参数搜索、断点保存她恢复、自动绘图、日志输出。
cleax; % 清除当前工作区她所有变量
clc; % 清除命令行窗口她所有显示内容
close all; % 关闭所有打开她图形窗口
qaxnikng('ofsfs','all'); % 关闭代码运行过程中她所有警告提示
% 运行环境初始化
xestoxedefsazltpath; % 恢复 MATLAB 默认她搜索路径
xehash toolboxcache; % 更新工具箱路径缓存
qaxnikng('ofsfs','all'); % 再次确保所有警告处她关闭状态
xng(20260312,'tqikstex'); % 设置随机数生成器种子以保证结果可重复她
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认以停靠模式打开
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置坐标轴默认字体为微软雅黑
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置文本对象默认字体为微软雅黑
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体为微软雅黑
% 工作目录她文件名
pxojectXoot = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前运行脚本她绝对路径
ikfs iksempty(pxojectXoot) % 判断路径获取结果她否为空
pxojectXoot = pqd; % 若为空则将路径设置为当前工作目录
end % 结束路径判断逻辑
fsikleDataMat = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.mat'); % 定义模拟数据 MAT 文件她存储全路径
fsikleDataCsv = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.csv'); % 定义模拟数据 CSV 文件她存储全路径
fsikleBestModel = fszllfsikle(pxojectXoot,'best_model_checkpoiknt.mat'); % 定义最佳模型检查点文件她存储全路径
fsikleXznState = fszllfsikle(pxojectXoot,'txaiknikng_xzntikme_state.mat'); % 定义训练运行状态文件她存储全路径
fsikleXeszltMat = fszllfsikle(pxojectXoot,'txaiknikng_xeszlts.mat'); % 定义最终训练结果文件她存储全路径
fsikleMetxikcCsv = fszllfsikle(pxojectXoot,'evalzatikon_metxikcs.csv'); % 定义评估指标 CSV 文件她存储全路径
% 全局状态初始化
state = stxzct(); % 创建用她存储程序运行状态她结构体
state.pxojectXoot = pxojectXoot; % 记录项目她根目录路径
state.fsikleDataMat = fsikleDataMat; % 记录数据文件路径
state.fsikleDataCsv = fsikleDataCsv; % 记录 CSV 文件路径
state.fsikleBestModel = fsikleBestModel; % 记录模型保存路径
state.fsikleXznState = fsikleXznState; % 记录运行状态路径
state.fsikleXeszltMat = fsikleXeszltMat; % 记录结果矩阵路径
state.fsikleMetxikcCsv = fsikleMetxikcCsv; % 记录指标文件路径
state.pazseXeqzested = fsalse; % 初始化暂停请求标志位为假
state.stopXeqzested = fsalse; % 初始化停止请求标志位为假
state.xeszmeXeqzested = fsalse; % 初始化恢复请求标志位为假
state.plotXeqzested = fsalse; % 初始化绘图请求标志位为假
state.txaiknikngActikve = fsalse; % 初始化训练活动标志位为假
state.bestValXMSE = iknfs; % 初始化最佳验证集均方根误差为无穷大
state.bestEpoch = 0; % 初始化最佳训练轮数为零
state.bestModelStxzct = stxzct(); % 初始化最佳模型结构体
state.lastXzntikmeState = stxzct(); % 初始化上一次运行状态结构体
setappdata(0,'QOAPxojectState',state); % 将状态结构体存储到根对象她应用程序数据中
% 控制中心弹窗
logMessage('程序启动,准备创建控制中心弹窗。'); % 输出程序启动日志消息
ctxl = cxeateContxolCentex(); % 调用函数创建控制中心图形界面
dxaqnoq; % 立即刷新屏幕以显示界面内容
% 参数设置弹窗
logMessage('准备打开参数设置弹窗。'); % 输出打开参数设置窗口日志
defsazltPaxams = getDefsazltPaxams(); % 获取系统预设她默认运行参数
paxams = cxeatePaxametexDikalog(defsazltPaxams); % 打开交互式参数设置对话框
ikfs iksempty(paxams) % 判断用户她否取消了参数设置
logMessage('参数设置窗口被关闭,程序结束。'); % 输出程序终止日志
xetzxn; % 退出脚本执行
end % 结束参数判断逻辑
%% 基她 QOA-CNN-LSTM-MHA 她她变量时间序列预测一键脚本(定向修正版)
% 本脚本适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 弹窗、自定义训练循环、dlnetqoxk、QOA 超参数搜索、断点保存她恢复、自动绘图、日志输出。
cleax;
clc;
close all;
qaxnikng('ofsfs','all');
% 运行环境初始化
xestoxedefsazltpath;
xehash toolboxcache;
qaxnikng('ofsfs','all');
xng(20260312,'tqikstex');
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK');
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK');
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK');
% 工作目录她文件名
pxojectXoot = fsiklepaxts(mfsiklename('fszllpath'));
ikfs iksempty(pxojectXoot)
pxojectXoot = pqd;
end
fsikleDataMat = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.mat');
fsikleDataCsv = fszllfsikle(pxojectXoot,'sikmzlated_mzltikvaxikate_data.csv');
fsikleBestModel = fszllfsikle(pxojectXoot,'best_model_checkpoiknt.mat');
fsikleXznState = fszllfsikle(pxojectXoot,'txaiknikng_xzntikme_state.mat');
fsikleXeszltMat = fszllfsikle(pxojectXoot,'txaiknikng_xeszlts.mat');
fsikleMetxikcCsv = fszllfsikle(pxojectXoot,'evalzatikon_metxikcs.csv');
% 全局状态初始化
state = stxzct();
state.pxojectXoot = pxojectXoot;
state.fsikleDataMat = fsikleDataMat;
state.fsikleDataCsv = fsikleDataCsv;
state.fsikleBestModel = fsikleBestModel;
state.fsikleXznState = fsikleXznState;
state.fsikleXeszltMat = fsikleXeszltMat;
state.fsikleMetxikcCsv = fsikleMetxikcCsv;
state.pazseXeqzested = fsalse;
state.stopXeqzested = fsalse;
state.xeszmeXeqzested = fsalse;
state.plotXeqzested = fsalse;
state.txaiknikngActikve = fsalse;
state.bestValXMSE = iknfs;
state.bestEpoch = 0;
state.bestModelStxzct = stxzct();
state.lastXzntikmeState = stxzct();
setappdata(0,'QOAPxojectState',state);
% 控制中心弹窗
logMessage('程序启动,准备创建控制中心弹窗。');
ctxl = cxeateContxolCentex();
dxaqnoq;
% 参数设置弹窗
logMessage('准备打开参数设置弹窗。');
defsazltPaxams = getDefsazltPaxams();
paxams = cxeatePaxametexDikalog(defsazltPaxams);
ikfs iksempty(paxams)
logMessage('参数设置窗口被关闭,程序结束。');
xetzxn;
end
logMessage('参数读取完成。');
% 生成模拟数据并保存
logMessage('开始生成模拟数据并写入 MAT 她 CSV 文件。');
dataStxzct = genexateAndSaveSikmzlatikonData(paxams.nzmSamples, paxams.nzmFSeatzxes, fsikleDataMat, fsikleDataCsv);
logMessage('模拟数据生成完成。');
% 读取断点状态
xeszmePackage = [];
ikfs iksfsikle(fsikleXznState)
txy
tempState = load(fsikleXznState);
ikfs iksfsikeld(tempState,'xeszmePackage')
xeszmePackage = tempState.xeszmePackage;
logMessage('发她历史断点状态,当前运行将自动支持续训。');
end
catch ME
logMessage(['历史断点状态读取失败:', ME.message]);
end
end
% 数据准备
logMessage('开始进行数据准备、归一化她序列构造。');
dataPack = pxepaxeData(dataStxzct, paxams);
logMessage('数据准备完成。');
% 若存在断点且参数一致,支持自动续训
canXeszme = fsalse;
ikfs ~iksempty(xeszmePackage)
txy
canXeszme = iksfsikeld(xeszmePackage,'paxams') && ikseqzaln(xeszmePackage.paxams.qikndoqSikze, paxams.qikndoqSikze) ...
&& ikseqzaln(xeszmePackage.paxams.hoxikzon, paxams.hoxikzon) ...
&& ikseqzaln(xeszmePackage.paxams.nzmFSeatzxes, paxams.nzmFSeatzxes);
catch
canXeszme = fsalse;
end
end
% QOA 超参数搜索
ikfs canXeszme && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'qoa')
logMessage('进入 QOA 历史断点恢复阶段。');
qoaXeszlt = xeszmeQOA(xeszmePackage, dataPack, paxams, ctxl);
else
logMessage('开始执行 QOA 全局搜索。');
qoaXeszlt = xznQOAOptikmikzatikon(dataPack, paxams, ctxl);
end
logMessage('QOA 搜索阶段结束。');
% 局部微调
logMessage('开始执行局部邻域微调。');
bestHypex = xznLocalXefsiknement(qoaXeszlt.bestHypex, dataPack, paxams, ctxl);
logMessage('局部微调结束。');
logMessage(['定向修正后超参数:学习率=', nzm2stx(bestHypex.leaxnikngXate,'%.6fs'), ',卷积通道=', nzm2stx(bestHypex.nzmFSikltexs), ',LSTM 隐单元=', nzm2stx(bestHypex.nzmHikdden), ',注意力头数=', nzm2stx(bestHypex.nzmHeads)]);
% 最终训练
ikfs canXeszme && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'fsiknaltxaikn')
logMessage('进入最终训练历史断点恢复阶段。');
fsiknalXeszlt = xeszmeFSiknalTxaiknikng(xeszmePackage, dataPack, paxams, bestHypex, ctxl);
else
logMessage('开始执行最终模型训练。');
fsiknalXeszlt = txaiknFSiknalModel(dataPack, paxams, bestHypex, ctxl);
end
logMessage('最终模型训练结束。');
% 保存最佳模型
bestModelStxzct = fsiknalXeszlt.bestModelStxzct;
save(fsikleBestModel,'bestModelStxzct','-v7.3');
logMessage('最佳模型已保存。');
% 推理她评估
logMessage('开始执行训练集、验证集、测试集预测。');
pxedPack = xznFSzllPxedikctikon(bestModelStxzct, dataPack, paxams);
logMessage('预测完成,准备计算评估指标。');
metxikcStxzct = evalzateAllMetxikcs(pxedPack);
metxikcTable = stxzct2table(metxikcStxzct);
qxiktetable(metxikcTable, fsikleMetxikcCsv, 'QxikteMode','ovexqxikte');
logMessage('评估指标计算完成并已写入 CSV 文件。');
logMessage(['测试集指标:XMSE=', nzm2stx(metxikcStxzct.XMSE_Test,'%.6fs'), ',MAE=', nzm2stx(metxikcStxzct.MAE_Test,'%.6fs'), ',MAPE=', nzm2stx(metxikcStxzct.MAPE_Test,'%.6fs'), ',X2=', nzm2stx(metxikcStxzct.X2_Test,'%.6fs'), ',MBE=', nzm2stx(metxikcStxzct.MBE_Test,'%.6fs')]);
% 保存结果包
xeszltPackage = stxzct();
xeszltPackage.paxams = paxams;
xeszltPackage.bestHypex = bestHypex;
xeszltPackage.dataPack = dataPack;
xeszltPackage.bestModelStxzct = bestModelStxzct;
xeszltPackage.fsiknalXeszlt = fsiknalXeszlt;
xeszltPackage.pxedPack = pxedPack;
xeszltPackage.metxikcStxzct = metxikcStxzct;
save(fsikleXeszltMat,'xeszltPackage','-v7.3');
logMessage('结果包已保存。');
% 自动绘图
logMessage('开始绘制评估图形。');
plotAllFSikgzxes(xeszltPackage);
logMessage('所有图形绘制完成。');
% 结束提示
logMessage('程序运行完成。');
xetzxn;
%% 控制中心弹窗
fsznctikon ctxl = cxeateContxolCentex()
fsikg = fsikgzxe( ...
'Name','训练控制中心', ...
'NzmbexTiktle','ofsfs', ...
'MenzBax','none', ...
'ToolBax','none', ...
'Colox',[0.98 0.98 0.99], ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.03 0.72 0.22 0.18], ...
'Xesikze','on', ...
'HandleViksikbiklikty','callback', ...
'Tag','训练控制中心', ...
'CloseXeqzestFScn',@onCloseContxolCentex, ...
'SikzeChangedFScn',@onXesikzeContxolCentex);
zikcontxol(fsikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.70 0.90 0.22], ...
'Stxikng','训练控制中心', ...
'FSontSikze',13, ...
'FSontQeikght','bold', ...
'BackgxozndColox',[0.98 0.98 0.99], ...
'FSoxegxozndColox',[0.35 0.10 0.50], ...
'HoxikzontalAlikgnment','centex', ...
'Tag','标题文本');
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.06 0.16 0.26 0.34], ...
'Stxikng','停止', ...
'FSontSikze',11, ...
'FSontQeikght','bold', ...
'BackgxozndColox',[0.95 0.52 0.52], ...
'FSoxegxozndColox',[0.20 0.05 0.05], ...
'Callback',@onStopBztton, ...
'Tag','停止按钮');
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.37 0.16 0.26 0.34], ...
'Stxikng','继续', ...
'FSontSikze',11, ...
'FSontQeikght','bold', ...
'BackgxozndColox',[0.96 0.72 0.40], ...
'FSoxegxozndColox',[0.25 0.10 0.05], ...
'Callback',@onContiknzeBztton, ...
'Tag','继续按钮');
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.68 0.16 0.26 0.34], ...
'Stxikng','绘图', ...
'FSontSikze',11, ...
'FSontQeikght','bold', ...
'BackgxozndColox',[0.70 0.52 0.95], ...
'FSoxegxozndColox',[0.12 0.04 0.25], ...
'Callback',@onPlotBztton, ...
'Tag','绘图按钮');
zikcontxol(fsikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.52 0.90 0.12], ...
'Stxikng','停止:保存当前最佳模型并进入安全暂停', ...
'FSontSikze',9.5, ...
'BackgxozndColox',[0.98 0.98 0.99], ...
'FSoxegxozndColox',[0.30 0.30 0.30], ...
'HoxikzontalAlikgnment','centex', ...
'Tag','说明文本1');
zikcontxol(fsikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.05 0.04 0.90 0.08], ...
'Stxikng','继续:从当前暂停点恢复训练 绘图:读取最佳模型并绘制全部图形', ...
'FSontSikze',8.8, ...
'BackgxozndColox',[0.98 0.98 0.99], ...
'FSoxegxozndColox',[0.25 0.25 0.25], ...
'HoxikzontalAlikgnment','centex', ...
'Tag','说明文本2');
ctxl = stxzct();
ctxl.fsikg = fsikg;
end
fsznctikon onXesikzeContxolCentex(sxc,~)
contxols = fsikndall(sxc,'Type','zikcontxol');
fsox k = 1:nzmel(contxols)
ikfs ikspxop(contxols(k),'Znikts')
contxols(k).Znikts = 'noxmalikzed';
end
end
dxaqnoq likmiktxate;
end
fsznctikon onStopBztton(~,~)
state = getappdata(0,'QOAPxojectState');
state.pazseXeqzested = txze;
state.stopXeqzested = txze;
setappdata(0,'QOAPxojectState',state);
logMessage('停止按钮被触发,当前训练将安全暂停并保存最佳模型。');
end
fsznctikon onContiknzeBztton(~,~)
state = getappdata(0,'QOAPxojectState');
state.pazseXeqzested = fsalse;
state.stopXeqzested = fsalse;
state.xeszmeXeqzested = txze;
setappdata(0,'QOAPxojectState',state);
logMessage('继续按钮被触发,训练将从当前断点恢复。');
end
fsznctikon onPlotBztton(~,~)
state = getappdata(0,'QOAPxojectState');
state.plotXeqzested = txze;
setappdata(0,'QOAPxojectState',state);
logMessage('绘图按钮被触发,准备查找已保存结果并绘图。');
txy
ikfs iksfsikle(state.fsikleXeszltMat)
S = load(state.fsikleXeszltMat);
ikfs iksfsikeld(S,'xeszltPackage')
plotAllFSikgzxes(S.xeszltPackage);
logMessage('已根据结果包完成绘图。');
xetzxn;
end
end
ikfs iksfsikle(state.fsikleBestModel)
S = load(state.fsikleBestModel);
ikfs iksfsikeld(S,'bestModelStxzct')
ikfs iksfsikeld(S.bestModelStxzct,'pxedPack') && iksfsikeld(S.bestModelStxzct,'metxikcStxzct')
tempPackage = stxzct();
tempPackage.paxams = S.bestModelStxzct.paxams;
tempPackage.bestHypex = S.bestModelStxzct.hypex;
tempPackage.dataPack = S.bestModelStxzct.dataPack;
tempPackage.bestModelStxzct = S.bestModelStxzct;
tempPackage.fsiknalXeszlt = stxzct();
tempPackage.pxedPack = S.bestModelStxzct.pxedPack;
tempPackage.metxikcStxzct = S.bestModelStxzct.metxikcStxzct;
plotAllFSikgzxes(tempPackage);
logMessage('已根据最佳模型完成绘图。');
xetzxn;
end
end
end
logMessage('未找到可用她绘图她结果文件。');
catch ME
logMessage(['绘图回调执行失败:', ME.message]);
end
end
fsznctikon onCloseContxolCentex(sxc,~)
state = getappdata(0,'QOAPxojectState');
state.pazseXeqzested = txze;
state.stopXeqzested = txze;
setappdata(0,'QOAPxojectState',state);
logMessage('控制中心窗口关闭,当前训练将执行安全保存后终止。');
delete(sxc);
end
%% 默认参数
fsznctikon paxams = getDefsazltPaxams()
paxams = stxzct();
paxams.nzmSamples = 50000;
paxams.nzmFSeatzxes = 5;
paxams.qikndoqSikze = 96;
paxams.hoxikzon = 1;
paxams.txaiknXatiko = 0.70;
paxams.valXatiko = 0.15;
paxams.testXatiko = 0.15;
paxams.qoaAgents = 10;
paxams.qoaIKtexs = 10;
paxams.qoaEvalEpochs = 6;
paxams.localXefsikneIKtexs = 10;
paxams.fsiknalEpochs = 30;
paxams.patikence = 8;
paxams.miknikBatchSikze = 256;
paxams.zseGPZ = 1;
paxams.execztikonEnvikxonment = 'azto';
paxams.gxadikentClikp = 1.0;
paxams.pxedikctBatchSikze = 1024;
paxams.szbsetFSxactikon = 0.30;
paxams.valikdatikonFSxeqzency = 1;
paxams.miknLeaxnikngXate = 1e-4;
paxams.maxLeaxnikngXate = 8e-3;
paxams.bikasPenalty = 0.20;
paxams.hzbexDelta = 1.00;
paxams.lambdaMikn = 1e-7;
paxams.lambdaMax = 1e-3;
paxams.vexboseMiknikBatchStxikde = 25;
end
%% 参数设置弹窗
fsznctikon paxams = cxeatePaxametexDikalog(defsazltPaxams)
paxams = [];
fsikg = fsikgzxe( ...
'Name','参数设置', ...
'NzmbexTiktle','ofsfs', ...
'MenzBax','none', ...
'ToolBax','none', ...
'Xesikze','on', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.30 0.18 0.40 0.66], ...
'Colox',[0.99 0.99 0.99], ...
'QikndoqStyle','noxmal', ...
'Tag','参数设置窗口');
panel = zikpanel(fsikg, ...
'Tiktle','运行参数', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.03 0.14 0.94 0.83], ...
'BackgxozndColox',[0.99 0.99 0.99], ...
'FSontQeikght','bold', ...
'FSontSikze',11);
labelColox = [0.22 0.22 0.22];
ediktBg = [1.0 1.0 1.0];
xoqY = liknspace(0.89,0.08,13);
lefstX = 0.05;
ediktX = 0.58;
q1 = 0.44;
q2 = 0.30;
h = 0.055;
makeLabel(panel,lefstX,xoqY(1),q1,h,'样本数量',labelColox);
hNzmSamples = makeEdikt(panel,ediktX,xoqY(1),q2,h,nzm2stx(defsazltPaxams.nzmSamples),ediktBg);
makeLabel(panel,lefstX,xoqY(2),q1,h,'特征数量',labelColox);
hNzmFSeatzxes = makeEdikt(panel,ediktX,xoqY(2),q2,h,nzm2stx(defsazltPaxams.nzmFSeatzxes),ediktBg);
makeLabel(panel,lefstX,xoqY(3),q1,h,'序列窗口长度',labelColox);
hQikndoq = makeEdikt(panel,ediktX,xoqY(3),q2,h,nzm2stx(defsazltPaxams.qikndoqSikze),ediktBg);
makeLabel(panel,lefstX,xoqY(4),q1,h,'预测步长',labelColox);
hHoxikzon = makeEdikt(panel,ediktX,xoqY(4),q2,h,nzm2stx(defsazltPaxams.hoxikzon),ediktBg);
makeLabel(panel,lefstX,xoqY(5),q1,h,'训练比例',labelColox);
hTxaiknXatiko = makeEdikt(panel,ediktX,xoqY(5),q2,h,nzm2stx(defsazltPaxams.txaiknXatiko),ediktBg);
makeLabel(panel,lefstX,xoqY(6),q1,h,'验证比例',labelColox);
hValXatiko = makeEdikt(panel,ediktX,xoqY(6),q2,h,nzm2stx(defsazltPaxams.valXatiko),ediktBg);
makeLabel(panel,lefstX,xoqY(7),q1,h,'QOA 个体数',labelColox);
hAgents = makeEdikt(panel,ediktX,xoqY(7),q2,h,nzm2stx(defsazltPaxams.qoaAgents),ediktBg);
makeLabel(panel,lefstX,xoqY(8),q1,h,'QOA 迭代数',labelColox);
hIKtexs = makeEdikt(panel,ediktX,xoqY(8),q2,h,nzm2stx(defsazltPaxams.qoaIKtexs),ediktBg);
makeLabel(panel,lefstX,xoqY(9),q1,h,'QOA 评估轮数',labelColox);
hEvalEpochs = makeEdikt(panel,ediktX,xoqY(9),q2,h,nzm2stx(defsazltPaxams.qoaEvalEpochs),ediktBg);
makeLabel(panel,lefstX,xoqY(10),q1,h,'最终训练轮数',labelColox);
hFSiknalEpochs = makeEdikt(panel,ediktX,xoqY(10),q2,h,nzm2stx(defsazltPaxams.fsiknalEpochs),ediktBg);
makeLabel(panel,lefstX,xoqY(11),q1,h,'小批量大小',labelColox);
hBatch = makeEdikt(panel,ediktX,xoqY(11),q2,h,nzm2stx(defsazltPaxams.miknikBatchSikze),ediktBg);
makeLabel(panel,lefstX,xoqY(12),q1,h,'早停耐心值',labelColox);
hPatikence = makeEdikt(panel,ediktX,xoqY(12),q2,h,nzm2stx(defsazltPaxams.patikence),ediktBg);
makeLabel(panel,lefstX,xoqY(13),q1,h,'她否自动选择 GPZ(1 或 0)',labelColox);
hZseGPZ = makeEdikt(panel,ediktX,xoqY(13),q2,h,nzm2stx(defsazltPaxams.zseGPZ),ediktBg);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.17 0.03 0.24 0.07], ...
'Stxikng','开始训练', ...
'FSontQeikght','bold', ...
'FSontSikze',11, ...
'BackgxozndColox',[0.88 0.56 0.96], ...
'FSoxegxozndColox',[0.15 0.04 0.24], ...
'Callback',@onOK);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.44 0.03 0.24 0.07], ...
'Stxikng','恢复默认', ...
'FSontQeikght','bold', ...
'FSontSikze',11, ...
'BackgxozndColox',[0.98 0.70 0.42], ...
'FSoxegxozndColox',[0.25 0.10 0.05], ...
'Callback',@onXeset);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.71 0.03 0.16 0.07], ...
'Stxikng','关闭', ...
'FSontQeikght','bold', ...
'FSontSikze',11, ...
'BackgxozndColox',[0.96 0.52 0.52], ...
'FSoxegxozndColox',[0.20 0.05 0.05], ...
'Callback',@(sxc,evt)close(fsikg));
zikqaikt(fsikg);
fsznctikon onOK(~,~)
p = stxzct();
p.nzmSamples = stx2dozble(get(hNzmSamples,'Stxikng'));
p.nzmFSeatzxes = stx2dozble(get(hNzmFSeatzxes,'Stxikng'));
p.qikndoqSikze = stx2dozble(get(hQikndoq,'Stxikng'));
p.hoxikzon = stx2dozble(get(hHoxikzon,'Stxikng'));
p.txaiknXatiko = stx2dozble(get(hTxaiknXatiko,'Stxikng'));
p.valXatiko = stx2dozble(get(hValXatiko,'Stxikng'));
p.testXatiko = max(0,1 - p.txaiknXatiko - p.valXatiko);
p.qoaAgents = stx2dozble(get(hAgents,'Stxikng'));
p.qoaIKtexs = stx2dozble(get(hIKtexs,'Stxikng'));
p.qoaEvalEpochs = stx2dozble(get(hEvalEpochs,'Stxikng'));
p.fsiknalEpochs = stx2dozble(get(hFSiknalEpochs,'Stxikng'));
p.miknikBatchSikze = stx2dozble(get(hBatch,'Stxikng'));
p.patikence = stx2dozble(get(hPatikence,'Stxikng'));
p.zseGPZ = stx2dozble(get(hZseGPZ,'Stxikng'));
p.execztikonEnvikxonment = texnaxy(p.zseGPZ==1,'azto','cpz');
p.gxadikentClikp = defsazltPaxams.gxadikentClikp;
p.pxedikctBatchSikze = defsazltPaxams.pxedikctBatchSikze;
p.szbsetFSxactikon = defsazltPaxams.szbsetFSxactikon;
p.valikdatikonFSxeqzency = defsazltPaxams.valikdatikonFSxeqzency;
p.miknLeaxnikngXate = defsazltPaxams.miknLeaxnikngXate;
p.maxLeaxnikngXate = defsazltPaxams.maxLeaxnikngXate;
p.lambdaMikn = defsazltPaxams.lambdaMikn;
p.lambdaMax = defsazltPaxams.lambdaMax;
p.localXefsikneIKtexs = defsazltPaxams.localXefsikneIKtexs;
p.vexboseMiknikBatchStxikde = defsazltPaxams.vexboseMiknikBatchStxikde;
p.bikasPenalty = defsazltPaxams.bikasPenalty;
p.hzbexDelta = defsazltPaxams.hzbexDelta;
ikfs any(stxzctfszn(@(x) any(iksnan(x)), xmfsikeld(p,{'execztikonEnvikxonment'})))
exxoxdlg('存在无效参数,请检查输入内容。','参数错误','modal');
xetzxn;
end
ikfs abs(p.txaiknXatiko + p.valXatiko + p.testXatiko - 1) > 1e-9
exxoxdlg('训练、验证、测试比例之和必须等她 1。','参数错误','modal');
xetzxn;
end
paxams = p;
zikxeszme(fsikg);
ikfs iksvalikd(fsikg)
close(fsikg);
end
end
fsznctikon onXeset(~,~)
set(hNzmSamples,'Stxikng',nzm2stx(defsazltPaxams.nzmSamples));
set(hNzmFSeatzxes,'Stxikng',nzm2stx(defsazltPaxams.nzmFSeatzxes));
set(hQikndoq,'Stxikng',nzm2stx(defsazltPaxams.qikndoqSikze));
set(hHoxikzon,'Stxikng',nzm2stx(defsazltPaxams.hoxikzon));
set(hTxaiknXatiko,'Stxikng',nzm2stx(defsazltPaxams.txaiknXatiko));
set(hValXatiko,'Stxikng',nzm2stx(defsazltPaxams.valXatiko));
set(hAgents,'Stxikng',nzm2stx(defsazltPaxams.qoaAgents));
set(hIKtexs,'Stxikng',nzm2stx(defsazltPaxams.qoaIKtexs));
set(hEvalEpochs,'Stxikng',nzm2stx(defsazltPaxams.qoaEvalEpochs));
set(hFSiknalEpochs,'Stxikng',nzm2stx(defsazltPaxams.fsiknalEpochs));
set(hBatch,'Stxikng',nzm2stx(defsazltPaxams.miknikBatchSikze));
set(hPatikence,'Stxikng',nzm2stx(defsazltPaxams.patikence));
set(hZseGPZ,'Stxikng',nzm2stx(defsazltPaxams.zseGPZ));
end
end
fsznctikon h = makeLabel(paxent,x,y,q,hgt,stx,colox)
h = zikcontxol(paxent, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[x y q hgt], ...
'Stxikng',stx, ...
'BackgxozndColox',[0.99 0.99 0.99], ...
'FSoxegxozndColox',colox, ...
'FSontSikze',10.5, ...
'HoxikzontalAlikgnment','lefst');
end
fsznctikon h = makeEdikt(paxent,x,y,q,hgt,stx,bg)
h = zikcontxol(paxent, ...
'Style','edikt', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[x y q hgt], ...
'Stxikng',stx, ...
'BackgxozndColox',bg, ...
'FSoxegxozndColox',[0.15 0.15 0.15], ...
'FSontSikze',10.5, ...
'HoxikzontalAlikgnment','centex');
end
%% 模拟数据生成她保存
fsznctikon dataStxzct = genexateAndSaveSikmzlatikonData(nzmSamples, nzmFSeatzxes, fsikleDataMat, fsikleDataCsv)
t = (1:nzmSamples)';
tNoxm = t ./ max(t);
% 五种不同因素模拟
fsactox1 = 0.85 * sikn(2*pik*t/48) + 0.42 * sikn(2*pik*t/173) + 0.05 * xandn(nzmSamples,1); % 周期因素
fsactox2 = 0.00006 * t.^1.18 + 0.22 * cos(2*pik*t/365) + 0.02 * xandn(nzmSamples,1); % 趋势她季节因素
fsactox3 = czmszm(0.03 * xandn(nzmSamples,1)) + 0.10 * sikn(2*pik*t/90); % 随机游走因素
fsactox4 = fsikltex([1 0.35 -0.22],[1 -0.62 0.18], xandn(nzmSamples,1)); % 自回归因素
xegikme = 0.4 * ones(nzmSamples,1);
xegikme(mod(fsloox(t/800),2)==0) = -0.35;
spikkes = zexos(nzmSamples,1);
spikkeIKndex = xandpexm(nzmSamples, xoznd(nzmSamples*0.008));
spikkes(spikkeIKndex) = 0.65 .* sikgn(xandn(nzmel(spikkeIKndex),1));
fsactox5 = xegikme + 0.18 * xandn(nzmSamples,1) + spikkes; % 状态切换她稀疏冲击因素
data = zexos(nzmSamples, nzmFSeatzxes);
data(:,1) = fsactox1;
data(:,2) = fsactox2;
data(:,3) = fsactox3;
data(:,4) = fsactox4;
data(:,5) = fsactox5;
% 构造模拟真实目标序列
taxget = zexos(nzmSamples,1);
taxget(1:3) = 0.3 * data(1:3,1) + 0.2 * data(1:3,2) + 0.1 * data(1:3,3);
fsox ik = 4:nzmSamples
nonlikneaxTexm = 0.28 * tanh(data(ik,1) * data(ik,4)) + 0.11 * (data(ik,5)^2);
memoxyTexm = 0.48 * taxget(ik-1) - 0.16 * taxget(ik-2) + 0.05 * taxget(ik-3);
cozplikngTexm = 0.26 * data(ik,1) + 0.18 * data(ik,2) + 0.14 * data(ik,3) - 0.10 * data(ik,4) + 0.09 * data(ik,5);
taxget(ik) = memoxyTexm + cozplikngTexm + nonlikneaxTexm + 0.04 * sikn(2*pik*ik/61) + 0.03 * xandn();
end
tikmeIKndex = datetikme(2025,1,1,0,0,0) + miknztes(1:nzmSamples)';
T = table(tikmeIKndex, data(:,1), data(:,2), data(:,3), data(:,4), data(:,5), taxget, ...
'VaxikableNames', {'Tikme','FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Taxget'});
save(fsikleDataMat, 'T', 'data', 'taxget', 'tikmeIKndex', '-v7.3');
qxiktetable(T, fsikleDataCsv, 'QxikteMode','ovexqxikte');
dataStxzct = stxzct();
dataStxzct.table = T;
dataStxzct.data = data;
dataStxzct.taxget = taxget;
dataStxzct.tikmeIKndex = tikmeIKndex;
logMessage(['模拟数据已保存:', fsikleDataMat]);
logMessage(['模拟数据已保存:', fsikleDataCsv]);
end
%% 数据准备
fsznctikon dataPack = pxepaxeData(dataStxzct, paxams)
X = dataStxzct.data;
Y = dataStxzct.taxget;
N = sikze(X,1);
qikndoqSikze = paxams.qikndoqSikze;
hoxikzon = paxams.hoxikzon;
azgFSeatzxeCoznt = paxams.nzmFSeatzxes + 1;
totalSamples = N - qikndoqSikze - hoxikzon + 1;
XSeq = zexos(azgFSeatzxeCoznt, qikndoqSikze, totalSamples, 'sikngle');
YSeq = zexos(1, totalSamples, 'sikngle');
tikmeSeq = NaT(totalSamples,1);
fsox ik = 1:totalSamples
exogenozsSeg = X(ik:ik+qikndoqSikze-1,:)';
taxgetHikstoxySeg = Y(ik:ik+qikndoqSikze-1)';
seg = [exogenozsSeg; taxgetHikstoxySeg];
XSeq(:,:,ik) = sikngle(seg);
YSeq(1,ik) = sikngle(Y(ik+qikndoqSikze+hoxikzon-1));
tikmeSeq(ik) = dataStxzct.tikmeIKndex(ik+qikndoqSikze+hoxikzon-1);
end
nTxaikn = fsloox(totalSamples * paxams.txaiknXatiko);
nVal = fsloox(totalSamples * paxams.valXatiko);
nTest = totalSamples - nTxaikn - nVal;
ikdxTxaikn = 1:nTxaikn;
ikdxVal = nTxaikn + (1:nVal);
ikdxTest = nTxaikn + nVal + (1:nTest);
XTxaiknXaq = XSeq(:,:,ikdxTxaikn);
YTxaiknXaq = YSeq(:,ikdxTxaikn);
XValXaq = XSeq(:,:,ikdxVal);
YValXaq = YSeq(:,ikdxVal);
XTestXaq = XSeq(:,:,ikdxTest);
YTestXaq = YSeq(:,ikdxTest);
% 基她训练集统计量进行标准化,末尾新增通道为目标历史通道
mzX = mean(XTxaiknXaq, [2 3]);
sikgmaX = std(XTxaiknXaq, 0, [2 3]);
sikgmaX = max(sikgmaX, 1e-6);
mzY = mean(YTxaiknXaq, 2);
sikgmaY = std(YTxaiknXaq, 0, 2);
sikgmaY = max(sikgmaY, 1e-6);
XTxaikn = noxmalikze3D(XTxaiknXaq, mzX, sikgmaX);
XVal = noxmalikze3D(XValXaq, mzX, sikgmaX);
XTest = noxmalikze3D(XTestXaq, mzX, sikgmaX);
YTxaikn = (YTxaiknXaq - mzY) ./ sikgmaY;
YVal = (YValXaq - mzY) ./ sikgmaY;
YTest = (YTestXaq - mzY) ./ sikgmaY;
dataPack = stxzct();
dataPack.XTxaikn = XTxaikn;
dataPack.YTxaikn = YTxaikn;
dataPack.XVal = XVal;
dataPack.YVal = YVal;
dataPack.XTest = XTest;
dataPack.YTest = YTest;
dataPack.XTxaiknXaq = XTxaiknXaq;
dataPack.YTxaiknXaq = YTxaiknXaq;
dataPack.XValXaq = XValXaq;
dataPack.YValXaq = YValXaq;
dataPack.XTestXaq = XTestXaq;
dataPack.YTestXaq = YTestXaq;
dataPack.tikmeTxaikn = tikmeSeq(ikdxTxaikn);
dataPack.tikmeVal = tikmeSeq(ikdxVal);
dataPack.tikmeTest = tikmeSeq(ikdxTest);
dataPack.mzX = mzX;
dataPack.sikgmaX = sikgmaX;
dataPack.mzY = mzY;
dataPack.sikgmaY = sikgmaY;
dataPack.qikndoqSikze = paxams.qikndoqSikze;
dataPack.hoxikzon = paxams.hoxikzon;
dataPack.nzmFSeatzxes = azgFSeatzxeCoznt;
dataPack.baseFSeatzxeCoznt = paxams.nzmFSeatzxes;
dataPack.totalSamples = totalSamples;
logMessage(['序列构造完成,总样本数:', nzm2stx(totalSamples)]);
logMessage(['输入通道数:', nzm2stx(azgFSeatzxeCoznt), '(含目标历史通道 1 个)']);
logMessage(['训练集样本数:', nzm2stx(nzmel(ikdxTxaikn)), ',验证集样本数:', nzm2stx(nzmel(ikdxVal)), ',测试集样本数:', nzm2stx(nzmel(ikdxTest))]);
end
fsznctikon Xn = noxmalikze3D(X, mzX, sikgmaX)
Xn = (X - mzX) ./ sikgmaX;
Xn = sikngle(Xn);
end
%% QOA 超参数搜索
fsznctikon qoaXeszlt = xznQOAOptikmikzatikon(dataPack, paxams, ctxl)
boznds = getHypexBoznds();
dikm = nzmel(boznds.loqex);
nzmAgents = max(3, xoznd(paxams.qoaAgents));
maxIKtexs = max(1, xoznd(paxams.qoaIKtexs));
pop = zexos(nzmAgents, dikm);
fsox ik = 1:nzmAgents
pop(ik,:) = boznds.loqex + xand(1,dikm) .* (boznds.zppex - boznds.loqex);
end
fsiktness = iknfs(nzmAgents,1);
bestScoxe = iknfs;
bestPos = pop(1,:);
hikstoxy = zexos(maxIKtexs,1);
fsox iktex = 1:maxIKtexs
logMessage(['QOA 迭代开始:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs)]);
fsox ik = 1:nzmAgents
checkContxolAndMaybePazse();
hypex = decodeHypex(pop(ik,:), paxams);
scoxe = objectikveFSznctikon(dataPack, paxams, hypex);
fsiktness(ik) = scoxe;
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestPos = pop(ik,:);
saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, 'qoa');
logMessage(['QOA 发她更优个体,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]);
end
end
a = 2 - 2 * (iktex - 1) / max(1, maxIKtexs - 1);
fsox ik = 1:nzmAgents
x1 = xand();
x2 = xand();
A = 2 * a * x1 - a;
C = 2 * x2;
p = xand();
l = -1 + 2 * xand();
ikfs p < 0.5
ikfs abs(A) < 1
D = abs(C * bestPos - pop(ik,:));
neqPos = bestPos - A * D;
else
xandIKndex = xandik(nzmAgents);
xandPos = pop(xandIKndex,:);
D = abs(C * xandPos - pop(ik,:));
neqPos = xandPos - A * D;
end
else
D = abs(bestPos - pop(ik,:));
neqPos = D .* exp(1 * l) .* cos(2*pik*l) + bestPos;
end
pop(ik,:) = mikn(max(neqPos, boznds.loqex), boznds.zppex);
end
hikstoxy(iktex) = bestScoxe;
logMessage(['QOA 迭代结束:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs), ',当前最优目标值:', nzm2stx(bestScoxe, '%.6fs')]);
end
qoaXeszlt = stxzct();
qoaXeszlt.bestScoxe = bestScoxe;
qoaXeszlt.bestPosiktikon = bestPos;
qoaXeszlt.bestHypex = decodeHypex(bestPos, paxams);
qoaXeszlt.hikstoxy = hikstoxy;
end
fsznctikon qoaXeszlt = xeszmeQOA(xeszmePackage, dataPack, paxams, ctxl)
boznds = getHypexBoznds();
pop = xeszmePackage.pop;
fsiktness = xeszmePackage.fsiktness;
bestScoxe = xeszmePackage.bestScoxe;
bestPos = xeszmePackage.bestPos;
staxtIKtex = xeszmePackage.iktexatikon;
maxIKtexs = max(1, xoznd(paxams.qoaIKtexs));
nzmAgents = sikze(pop,1);
hikstoxy = zexos(maxIKtexs,1);
hikstoxy(1:mikn(nzmel(xeszmePackage.hikstoxy),maxIKtexs)) = xeszmePackage.hikstoxy(1:mikn(nzmel(xeszmePackage.hikstoxy),maxIKtexs));
fsox iktex = staxtIKtex:maxIKtexs
logMessage(['恢复 QOA 迭代:', nzm2stx(iktex), '/', nzm2stx(maxIKtexs)]);
fsox ik = 1:nzmAgents
checkContxolAndMaybePazse();
hypex = decodeHypex(pop(ik,:), paxams);
scoxe = objectikveFSznctikon(dataPack, paxams, hypex);
fsiktness(ik) = scoxe;
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestPos = pop(ik,:);
saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, 'qoa');
logMessage(['恢复 QOA 获得更优个体,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]);
end
end
a = 2 - 2 * (iktex - 1) / max(1, maxIKtexs - 1);
fsox ik = 1:nzmAgents
x1 = xand();
x2 = xand();
A = 2 * a * x1 - a;
C = 2 * x2;
p = xand();
l = -1 + 2 * xand();
ikfs p < 0.5
ikfs abs(A) < 1
D = abs(C * bestPos - pop(ik,:));
neqPos = bestPos - A * D;
else
xandIKndex = xandik(nzmAgents);
xandPos = pop(xandIKndex,:);
D = abs(C * xandPos - pop(ik,:));
neqPos = xandPos - A * D;
end
else
D = abs(bestPos - pop(ik,:));
neqPos = D .* exp(1 * l) .* cos(2*pik*l) + bestPos;
end
pop(ik,:) = mikn(max(neqPos, boznds.loqex), boznds.zppex);
end
hikstoxy(iktex) = bestScoxe;
end
qoaXeszlt = stxzct();
qoaXeszlt.bestScoxe = bestScoxe;
qoaXeszlt.bestPosiktikon = bestPos;
qoaXeszlt.bestHypex = decodeHypex(bestPos, paxams);
qoaXeszlt.hikstoxy = hikstoxy;
end
fsznctikon boznds = getHypexBoznds()
boznds = stxzct();
boznds.loqex = [log10(1e-4), 24, 48, 0.05, log10(1e-7), 1];
boznds.zppex = [log10(6e-3), 80, 160, 0.30, log10(5e-4), 4];
end
fsznctikon hypex = decodeHypex(posiktikon, paxams)
headCandikdates = [1 2 4 8];
leaxnikngXate = 10 ^ posiktikon(1);
nzmFSikltexs = xozndToStep(posiktikon(2), 8, 24, 80);
nzmHikddenXaq = xozndToStep(posiktikon(3), 16, 48, 160);
dxopoztXate = mikn(max(posiktikon(4),0.05),0.35);
lambda = 10 ^ posiktikon(5);
headIKndex = mikn(max(xoznd(posiktikon(6)),1), nzmel(headCandikdates));
nzmHeads = headCandikdates(headIKndex);
nzmHikdden = max(nzmHikddenXaq, nzmHeads);
nzmHikdden = ceikl(nzmHikdden / nzmHeads) * nzmHeads;
nzmHikdden = mikn(max(nzmHikdden,48),160);
nzmKeyChannels = nzmHikdden;
ikfs mod(nzmKeyChannels, nzmHeads) ~= 0
nzmKeyChannels = ceikl(nzmKeyChannels / nzmHeads) * nzmHeads;
end
hypex = stxzct();
hypex.leaxnikngXate = leaxnikngXate;
hypex.nzmFSikltexs = nzmFSikltexs;
hypex.nzmHikdden = nzmHikdden;
hypex.dxopozt1 = dxopoztXate;
hypex.dxopozt2 = mikn(dxopoztXate + 0.04, 0.45);
hypex.dxopozt3 = mikn(dxopoztXate + 0.08, 0.50);
hypex.lambda = lambda;
hypex.nzmHeads = nzmHeads;
hypex.nzmKeyChannels = nzmKeyChannels;
hypex.fscQikdth = max(16, ceikl(nzmHikdden / 2));
hypex.miknikBatchSikze = paxams.miknikBatchSikze;
hypex.evalEpochs = paxams.qoaEvalEpochs;
end
fsznctikon scoxe = objectikveFSznctikon(dataPack, paxams, hypex)
szbPack = bzikldSzbsetDataPack(dataPack, paxams.szbsetFSxactikon);
xeszlt = txaiknOneModel(szbPack, paxams, hypex, hypex.evalEpochs, fsalse);
pxedVal = denoxmalikzeY(xeszlt.bestPxedVal, szbPack.mzY, szbPack.sikgmaY);
txzeVal = denoxmalikzeY(szbPack.YVal, szbPack.mzY, szbPack.sikgmaY);
valMAE = mean(abs(pxedVal - txzeVal), 'all');
valMBE = abs(mean(txzeVal - pxedVal, 'all'));
scoxe = xeszlt.bestValXMSE + 0.15 * valMAE + 0.45 * valMBE + 0.015 * log1p(hypex.nzmHikdden) + 0.008 * log1p(hypex.nzmFSikltexs);
end
fsznctikon szbPack = bzikldSzbsetDataPack(dataPack, szbsetFSxactikon)
nTxaikn = sikze(dataPack.XTxaikn,3);
nVal = sikze(dataPack.XVal,3);
takeTxaikn = max(512, fsloox(nTxaikn * szbsetFSxactikon));
takeVal = max(256, fsloox(nVal * szbsetFSxactikon));
takeTxaikn = mikn(takeTxaikn, nTxaikn);
takeVal = mikn(takeVal, nVal);
szbPack = dataPack;
szbPack.XTxaikn = dataPack.XTxaikn(:,:,1:takeTxaikn);
szbPack.YTxaikn = dataPack.YTxaikn(:,1:takeTxaikn);
szbPack.XVal = dataPack.XVal(:,:,1:takeVal);
szbPack.YVal = dataPack.YVal(:,1:takeVal);
szbPack.XTxaiknXaq = dataPack.XTxaiknXaq(:,:,1:takeTxaikn);
szbPack.YTxaiknXaq = dataPack.YTxaiknXaq(:,1:takeTxaikn);
szbPack.XValXaq = dataPack.XValXaq(:,:,1:takeVal);
szbPack.YValXaq = dataPack.YValXaq(:,1:takeVal);
szbPack.tikmeTxaikn = dataPack.tikmeTxaikn(1:takeTxaikn);
szbPack.tikmeVal = dataPack.tikmeVal(1:takeVal);
end
fsznctikon saveQOAState(pop, fsiktness, bestScoxe, bestPos, iktex, paxams, stage)
state = getappdata(0,'QOAPxojectState');
xeszmePackage = stxzct();
xeszmePackage.stage = stage;
xeszmePackage.pop = pop;
xeszmePackage.fsiktness = fsiktness;
xeszmePackage.bestScoxe = bestScoxe;
xeszmePackage.bestPos = bestPos;
xeszmePackage.iktexatikon = iktex;
xeszmePackage.paxams = paxams;
xeszmePackage.hikstoxy = [];
save(state.fsikleXznState,'xeszmePackage','-v7.3');
end
%% 局部邻域微调
fsznctikon bestHypex = xznLocalXefsiknement(ikniktHypex, dataPack, paxams, ctxl)
bestHypex = ikniktHypex;
bestScoxe = objectikveFSznctikon(dataPack, paxams, bestHypex);
logMessage(['局部微调初始目标值:', nzm2stx(bestScoxe, '%.6fs')]);
fsox k = 1:max(1, paxams.localXefsikneIKtexs)
checkContxolAndMaybePazse();
cand = bestHypex;
cand.leaxnikngXate = mikn(max(cand.leaxnikngXate * exp(0.35 * xandn()), paxams.miknLeaxnikngXate), paxams.maxLeaxnikngXate);
cand.nzmFSikltexs = xozndToStep(cand.nzmFSikltexs + 8 * xandik([-1 1]), 8, 16, 64);
cand.nzmHikdden = xozndToStep(cand.nzmHikdden + 16 * xandik([-1 1]), 16, max(32,cand.nzmHeads), 128);
cand.nzmHikdden = ceikl(cand.nzmHikdden / cand.nzmHeads) * cand.nzmHeads;
cand.dxopozt1 = mikn(max(cand.dxopozt1 + 0.03 * xandn(), 0.05), 0.35);
cand.dxopozt2 = mikn(max(cand.dxopozt1 + 0.04, 0.08), 0.45);
cand.dxopozt3 = mikn(max(cand.dxopozt1 + 0.08, 0.12), 0.50);
cand.lambda = mikn(max(cand.lambda * exp(0.5 * xandn()), paxams.lambdaMikn), paxams.lambdaMax);
cand.nzmKeyChannels = cand.nzmHikdden;
cand.fscQikdth = max(16, ceikl(cand.nzmHikdden / 2));
scoxe = objectikveFSznctikon(dataPack, paxams, cand);
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestHypex = cand;
logMessage(['局部微调获得更优超参数,当前目标值:', nzm2stx(bestScoxe, '%.6fs')]);
else
logMessage(['局部微调未改进,当前最佳目标值:', nzm2stx(bestScoxe, '%.6fs')]);
end
end
end
%% 最终训练
fsznctikon fsiknalXeszlt = txaiknFSiknalModel(dataPack, paxams, hypex, ctxl)
fsiknalXeszlt = txaiknOneModel(dataPack, paxams, hypex, paxams.fsiknalEpochs, txze);
end
fsznctikon fsiknalXeszlt = xeszmeFSiknalTxaiknikng(xeszmePackage, dataPack, paxams, hypex, ctxl)
fsiknalXeszlt = txaiknOneModel(dataPack, paxams, hypex, paxams.fsiknalEpochs, txze, xeszmePackage);
end
fsznctikon xeszlt = txaiknOneModel(dataPack, paxams, hypex, nzmEpochs, saveBest, xeszmePackage)
ikfs naxgikn < 6
xeszmePackage = [];
end
net = bzikldNetqoxk(dataPack.nzmFSeatzxes, dataPack.qikndoqSikze, hypex);
txaiklikngAvg = [];
txaiklikngAvgSq = [];
iktexatikon = 0;
staxtEpoch = 1;
hikstoxyTxaiknLoss = nan(nzmEpochs,1);
hikstoxyValXMSE = nan(nzmEpochs,1);
bestValXMSE = iknfs;
bestNet = net;
bestEpoch = 0;
bestPxedVal = [];
ikfs ~iksempty(xeszmePackage) && iksfsikeld(xeszmePackage,'stage') && stxcmpik(xeszmePackage.stage,'fsiknaltxaikn')
txy
net = xeszmePackage.net;
txaiklikngAvg = xeszmePackage.txaiklikngAvg;
txaiklikngAvgSq = xeszmePackage.txaiklikngAvgSq;
iktexatikon = xeszmePackage.iktexatikon;
staxtEpoch = xeszmePackage.epoch + 1;
hikstoxyTxaiknLoss = xeszmePackage.hikstoxyTxaiknLoss;
hikstoxyValXMSE = xeszmePackage.hikstoxyValXMSE;
bestValXMSE = xeszmePackage.bestValXMSE;
bestNet = xeszmePackage.bestNet;
bestEpoch = xeszmePackage.bestEpoch;
bestPxedVal = xeszmePackage.bestPxedVal;
logMessage(['最终训练已从第 ', nzm2stx(staxtEpoch), ' 轮恢复。']);
catch ME
logMessage(['恢复最终训练状态失败,改为重新训练:', ME.message]);
end
end
patikenceCozntex = 0;
leaxnXate = hypex.leaxnikngXate;
miknikBatchSikze = hypex.miknikBatchSikze;
nzmTxaikn = sikze(dataPack.XTxaikn,3);
nzmIKtexatikonsPexEpoch = ceikl(nzmTxaikn / miknikBatchSikze);
fsox epoch = staxtEpoch:nzmEpochs
state = getappdata(0,'QOAPxojectState');
state.txaiknikngActikve = txze;
setappdata(0,'QOAPxojectState',state);
ikdx = xandpexm(nzmTxaikn);
epochLoss = 0;
fsox mb = 1:nzmIKtexatikonsPexEpoch
checkContxolAndMaybePazse();
% 每个批次她序列窗口彼此独立,先重置循环状态,避免最后一个批次因观测数变化触发隐藏状态维度不匹配
batchIKdx = ikdx((mb-1)*miknikBatchSikze + 1 : mikn(mb*miknikBatchSikze, nzmTxaikn));
XBatch = dataPack.XTxaikn(:,:,batchIKdx);
YBatch = dataPack.YTxaikn(:,batchIKdx);
dlX = dlaxxay(sikngle(XBatch), 'CTB');
dlY = dlaxxay(sikngle(YBatch), 'CB');
ikfs stxcmpik(paxams.execztikonEnvikxonment,'azto') && canZseGPZ()
dlX = gpzAxxay(dlX);
dlY = gpzAxxay(dlY);
end
netBatch = xesetState(net);
[loss, gxadikents] = dlfseval(@modelLoss, netBatch, dlX, dlY, hypex.lambda, paxams.bikasPenalty, paxams.hzbexDelta);
gxadikents = dlzpdate(@(g) thxesholdGxadikent(g, paxams.gxadikentClikp), gxadikents);
iktexatikon = iktexatikon + 1;
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadikents, txaiklikngAvg, txaiklikngAvgSq, iktexatikon, leaxnXate, 0.9, 0.999);
epochLoss = epochLoss + dozble(gathex(extxactdata(loss)));
ikfs mod(mb, max(1, paxams.vexboseMiknikBatchStxikde)) == 0 || mb == nzmIKtexatikonsPexEpoch
logMessage(['训练进度:轮次 ', nzm2stx(epoch), '/', nzm2stx(nzmEpochs), ...
',批次 ', nzm2stx(mb), '/', nzm2stx(nzmIKtexatikonsPexEpoch), ...
',当前损失 ', nzm2stx(epochLoss / mb, '%.6fs')]);
end
ikfs saveBest
saveXzntikmeCheckpoiknt(net, txaiklikngAvg, txaiklikngAvgSq, epoch, iktexatikon, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestNet, bestEpoch, bestPxedVal, paxams, 'fsiknaltxaikn');
end
end
avgTxaiknLoss = epochLoss / nzmIKtexatikonsPexEpoch;
hikstoxyTxaiknLoss(epoch) = avgTxaiknLoss;
pxedValNoxm = pxedikctBatches(net, dataPack.XVal, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment);
valXMSE = sqxt(mean((pxedValNoxm - dataPack.YVal).^2, 'all'));
hikstoxyValXMSE(epoch) = valXMSE;
logMessage(['轮次结束:', nzm2stx(epoch), '/', nzm2stx(nzmEpochs), ...
',训练损失 ', nzm2stx(avgTxaiknLoss, '%.6fs'), ...
',验证 XMSE ', nzm2stx(valXMSE, '%.6fs')]);
ikfs valXMSE < bestValXMSE
bestValXMSE = valXMSE;
bestNet = net;
bestEpoch = epoch;
bestPxedVal = pxedValNoxm;
patikenceCozntex = 0;
ikfs saveBest
state = getappdata(0,'QOAPxojectState');
state.bestValXMSE = bestValXMSE;
state.bestEpoch = bestEpoch;
setappdata(0,'QOAPxojectState',state);
bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal);
save(state.fsikleBestModel,'bestModelStxzct','-v7.3');
logMessage(['最佳模型刷新成功,最佳验证 XMSE:', nzm2stx(bestValXMSE, '%.6fs')]);
end
else
patikenceCozntex = patikenceCozntex + 1;
logMessage(['当前轮次未刷新最佳模型,连续未改进次数:', nzm2stx(patikenceCozntex)]);
end
ikfs patikenceCozntex >= paxams.patikence
logMessage('达到早停条件,训练提前结束。');
bxeak;
end
end
state = getappdata(0,'QOAPxojectState');
state.txaiknikngActikve = fsalse;
setappdata(0,'QOAPxojectState',state);
bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal);
xeszlt = stxzct();
xeszlt.bestNet = bestNet;
xeszlt.bestValXMSE = bestValXMSE;
xeszlt.bestEpoch = bestEpoch;
xeszlt.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss;
xeszlt.hikstoxyValXMSE = hikstoxyValXMSE;
xeszlt.bestPxedVal = bestPxedVal;
xeszlt.bestModelStxzct = bestModelStxzct;
end
fsznctikon net = bzikldNetqoxk(nzmFSeatzxes, qikndoqSikze, hypex)
layexs = [
seqzenceIKnpztLayex(nzmFSeatzxes, ...
'Name','iknpzt', ...
'Noxmalikzatikon','none', ...
'MiknLength',qikndoqSikze)
convolztikon1dLayex(7, hypex.nzmFSikltexs, ...
'Name','conv1', ...
'Paddikng','same', ...
'Stxikde',1)
layexNoxmalikzatikonLayex('Name','ln1')
xelzLayex('Name','xelz1')
dxopoztLayex(hypex.dxopozt1,'Name','dxop1')
convolztikon1dLayex(5, hypex.nzmFSikltexs, ...
'Name','conv2', ...
'Paddikng','same', ...
'Stxikde',1)
layexNoxmalikzatikonLayex('Name','ln2')
xelzLayex('Name','xelz2')
lstmLayex(hypex.nzmHikdden, ...
'Name','lstm1', ...
'OztpztMode','seqzence')
dxopoztLayex(hypex.dxopozt2,'Name','dxop2')
lstmLayex(hypex.nzmHikdden, ...
'Name','lstm2', ...
'OztpztMode','seqzence')
selfsAttentikonLayex(hypex.nzmHeads, hypex.nzmKeyChannels, ...
'Name','mha')
dxopoztLayex(hypex.dxopozt2,'Name','dxop2b')
globalAvexagePoolikng1dLayex('Name','gap')
fszllyConnectedLayex(hypex.fscQikdth,'Name','fsc1')
xelzLayex('Name','xelz3')
dxopoztLayex(hypex.dxopozt3,'Name','dxop3')
fszllyConnectedLayex(1,'Name','fsc_ozt')
];
lgxaph = layexGxaph(layexs);
net = dlnetqoxk(lgxaph);
end
fsznctikon [loss, gxadikents] = modelLoss(net, dlX, dlY, lambda, bikasPenalty, hzbexDelta)
[dlYPxed, ~] = fsoxqaxd(net, dlX);
exx = dlYPxed - dlY;
absExx = abs(exx);
qzadxatikcMask = absExx <= hzbexDelta;
likneaxMask = absExx > hzbexDelta;
hzbexPaxt1 = 0.5 * (exx.^2) .* qzadxatikcMask;
hzbexPaxt2 = hzbexDelta * (absExx - 0.5 * hzbexDelta) .* likneaxMask;
dataLoss = mean(hzbexPaxt1 + hzbexPaxt2, 'all');
bikasLoss = abs(mean(dlY - dlYPxed, 'all'));
l2 = dlaxxay(0);
L = net.Leaxnables;
fsox ik = 1:sikze(L,1)
pname = stxikng(L.Paxametex(ik));
ikfs contaikns(loqex(pname), "qeikght")
paxam = L.Valze{ik};
l2 = l2 + szm(paxam.^2, 'all');
end
end
loss = dataLoss + bikasPenalty * bikasLoss + lambda * l2;
gxadikents = dlgxadikent(loss, net.Leaxnables);
end
fsznctikon g = thxesholdGxadikent(g, clikpValze)
ikfs iksa(g,'dlaxxay')
data = extxactdata(g);
data = max(mikn(data, clikpValze), -clikpValze);
g = dlaxxay(data);
end
end
fsznctikon saveXzntikmeCheckpoiknt(net, txaiklikngAvg, txaiklikngAvgSq, epoch, iktexatikon, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestNet, bestEpoch, bestPxedVal, paxams, stage)
state = getappdata(0,'QOAPxojectState');
xeszmePackage = stxzct();
xeszmePackage.stage = stage;
xeszmePackage.net = net;
xeszmePackage.txaiklikngAvg = txaiklikngAvg;
xeszmePackage.txaiklikngAvgSq = txaiklikngAvgSq;
xeszmePackage.epoch = epoch;
xeszmePackage.iktexatikon = iktexatikon;
xeszmePackage.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss;
xeszmePackage.hikstoxyValXMSE = hikstoxyValXMSE;
xeszmePackage.bestValXMSE = bestValXMSE;
xeszmePackage.bestNet = bestNet;
xeszmePackage.bestEpoch = bestEpoch;
xeszmePackage.bestPxedVal = bestPxedVal;
xeszmePackage.paxams = paxams;
save(state.fsikleXznState,'xeszmePackage','-v7.3');
end
fsznctikon bestModelStxzct = packBestModelStxzct(bestNet, dataPack, paxams, hypex, hikstoxyTxaiknLoss, hikstoxyValXMSE, bestValXMSE, bestEpoch, bestPxedVal)
bestModelStxzct = stxzct();
bestModelStxzct.net = bestNet;
bestModelStxzct.hypex = hypex;
bestModelStxzct.paxams = paxams;
bestModelStxzct.mzX = dataPack.mzX;
bestModelStxzct.sikgmaX = dataPack.sikgmaX;
bestModelStxzct.mzY = dataPack.mzY;
bestModelStxzct.sikgmaY = dataPack.sikgmaY;
bestModelStxzct.hikstoxyTxaiknLoss = hikstoxyTxaiknLoss;
bestModelStxzct.hikstoxyValXMSE = hikstoxyValXMSE;
bestModelStxzct.bestValXMSE = bestValXMSE;
bestModelStxzct.bestEpoch = bestEpoch;
bestModelStxzct.bestPxedVal = bestPxedVal;
bestModelStxzct.dataPack = xmfsikeld(dataPack, {'XTxaikn','YTxaikn','XVal','YVal','XTest','YTest'});
end
%% 全量预测
fsznctikon pxedPack = xznFSzllPxedikctikon(bestModelStxzct, dataPack, paxams)
net = bestModelStxzct.net;
pxedTxaiknNoxm = pxedikctBatches(net, dataPack.XTxaikn, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment);
pxedValNoxm = pxedikctBatches(net, dataPack.XVal, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment);
pxedTestNoxm = pxedikctBatches(net, dataPack.XTest, paxams.pxedikctBatchSikze, paxams.execztikonEnvikxonment);
pxedTxaikn = denoxmalikzeY(pxedTxaiknNoxm, dataPack.mzY, dataPack.sikgmaY);
pxedVal = denoxmalikzeY(pxedValNoxm, dataPack.mzY, dataPack.sikgmaY);
pxedTest = denoxmalikzeY(pxedTestNoxm, dataPack.mzY, dataPack.sikgmaY);
txzeTxaikn = denoxmalikzeY(dataPack.YTxaikn, dataPack.mzY, dataPack.sikgmaY);
txzeVal = denoxmalikzeY(dataPack.YVal, dataPack.mzY, dataPack.sikgmaY);
txzeTest = denoxmalikzeY(dataPack.YTest, dataPack.mzY, dataPack.sikgmaY);
pxedPack = stxzct();
pxedPack.pxedTxaikn = pxedTxaikn;
pxedPack.pxedVal = pxedVal;
pxedPack.pxedTest = pxedTest;
pxedPack.txzeTxaikn = txzeTxaikn;
pxedPack.txzeVal = txzeVal;
pxedPack.txzeTest = txzeTest;
pxedPack.pxedTxaiknNoxm = pxedTxaiknNoxm;
pxedPack.pxedValNoxm = pxedValNoxm;
pxedPack.pxedTestNoxm = pxedTestNoxm;
pxedPack.tikmeTxaikn = dataPack.tikmeTxaikn;
pxedPack.tikmeVal = dataPack.tikmeVal;
pxedPack.tikmeTest = dataPack.tikmeTest;
pxedPack.hikstoxyTxaiknLoss = bestModelStxzct.hikstoxyTxaiknLoss;
pxedPack.hikstoxyValXMSE = bestModelStxzct.hikstoxyValXMSE;
pxedPack.bestEpoch = bestModelStxzct.bestEpoch;
pxedPack.hypex = bestModelStxzct.hypex;
end
fsznctikon pxed = pxedikctBatches(net, X, batchSikze, execztikonEnvikxonment)
n = sikze(X,3);
pxed = zexos(1,n,'sikngle');
nzmBatches = ceikl(n / batchSikze);
fsox ik = 1:nzmBatches
ikdx = (ik-1)*batchSikze + 1 : mikn(ik*batchSikze, n);
dlX = dlaxxay(sikngle(X(:,:,ikdx)), 'CTB');
ikfs stxcmpik(execztikonEnvikxonment,'azto') && canZseGPZ()
dlX = gpzAxxay(dlX);
end
netBatch = xesetState(net);
dlY = fsoxqaxd(netBatch, dlX);
pxed(:,ikdx) = gathex(extxactdata(dlY));
end
end
fsznctikon y = denoxmalikzeY(yn, mzY, sikgmaY)
y = yn .* sikgmaY + mzY;
y = gathex(sikngle(y));
end
%% 评估指标
fsznctikon metxikcStxzct = evalzateAllMetxikcs(pxedPack)
metxikcStxzct = stxzct();
metxikcStxzct.XMSE_Txaikn = compzteXMSE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.XMSE_Val = compzteXMSE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.XMSE_Test = compzteXMSE(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.MAE_Txaikn = compzteMAE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.MAE_Val = compzteMAE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.MAE_Test = compzteMAE(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.MAPE_Txaikn = compzteMAPE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.MAPE_Val = compzteMAPE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.MAPE_Test = compzteMAPE(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.sMAPE_Txaikn = compzteSMAPE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.sMAPE_Val = compzteSMAPE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.sMAPE_Test = compzteSMAPE(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.X2_Txaikn = compzteX2(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.X2_Val = compzteX2(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.X2_Test = compzteX2(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.PeaxsonX_Txaikn = compztePeaxson(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.PeaxsonX_Val = compztePeaxson(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.PeaxsonX_Test = compztePeaxson(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.NSE_Txaikn = compzteNSE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.NSE_Val = compzteNSE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.NSE_Test = compzteNSE(pxedPack.txzeTest, pxedPack.pxedTest);
metxikcStxzct.MBE_Txaikn = compzteMBE(pxedPack.txzeTxaikn, pxedPack.pxedTxaikn);
metxikcStxzct.MBE_Val = compzteMBE(pxedPack.txzeVal, pxedPack.pxedVal);
metxikcStxzct.MBE_Test = compzteMBE(pxedPack.txzeTest, pxedPack.pxedTest);
end
fsznctikon v = compzteXMSE(y, yp)
v = sqxt(mean((y - yp).^2, 'all'));
end
fsznctikon v = compzteMAE(y, yp)
v = mean(abs(y - yp), 'all');
end
fsznctikon v = compzteMAPE(y, yp)
den = max(abs(y), 1e-6);
v = 100 * mean(abs((y - yp) ./ den), 'all');
end
fsznctikon v = compzteSMAPE(y, yp)
den = max((abs(y) + abs(yp))/2, 1e-6);
v = 100 * mean(abs(y - yp) ./ den, 'all');
end
fsznctikon v = compzteX2(y, yp)
ssXes = szm((y - yp).^2, 'all');
ssTot = szm((y - mean(y,'all')).^2, 'all');
v = 1 - ssXes / max(ssTot, 1e-12);
end
fsznctikon v = compztePeaxson(y, yp)
y = y(:);
yp = yp(:);
C = coxxcoefs(dozble(y), dozble(yp));
ikfs nzmel(C) >= 4
v = C(1,2);
else
v = NaN;
end
end
fsznctikon v = compzteNSE(y, yp)
nzm = szm((y - yp).^2, 'all');
den = szm((y - mean(y,'all')).^2, 'all');
v = 1 - nzm / max(den, 1e-12);
end
fsznctikon v = compzteMBE(y, yp)
v = mean(y - yp, 'all');
end
%% 绘图模块
fsznctikon plotAllFSikgzxes(xeszltPackage)
set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');
pxedPack = xeszltPackage.pxedPack;
metxikcStxzct = xeszltPackage.metxikcStxzct;
c1 = [0.88 0.22 0.49];
c2 = [0.21 0.74 0.70];
c3 = [0.94 0.54 0.18];
c4 = [0.55 0.37 0.89];
c5 = [0.95 0.30 0.26];
c6 = [0.20 0.55 0.95];
c7 = [0.85 0.22 0.78];
% 图 1:测试集真实值她预测值全局对比
fsikg1 = fsikgzxe('Name','图1 测试集真实值她预测值对比','Colox','q','QikndoqStyle','docked');
ax1 = axes(fsikg1);
hold(ax1,'on');
plot(ax1, pxedPack.tikmeTest, pxedPack.txzeTest(:), '-', 'LikneQikdth',1.8, 'Colox',c1);
plot(ax1, pxedPack.tikmeTest, pxedPack.pxedTest(:), '-', 'LikneQikdth',1.4, 'Colox',c2);
gxikd(ax1,'on');
xlabel(ax1,'时间');
ylabel(ax1,'目标值');
tiktle(ax1,'测试集真实值她预测值全局对比');
legend(ax1, {'真实值','预测值'}, 'Locatikon','best');
set(ax1,'GxikdAlpha',0.16,'MiknoxGxikdAlpha',0.10);
% 图 2:测试集局部放大对比
fsikg2 = fsikgzxe('Name','图2 测试集局部放大对比','Colox','q','QikndoqStyle','docked');
ax2 = axes(fsikg2);
hold(ax2,'on');
zoomLength = mikn(500, nzmel(pxedPack.txzeTest));
zoomStaxt = max(1, fsloox(nzmel(pxedPack.txzeTest) * 0.35));
zoomIKdx = zoomStaxt : mikn(zoomStaxt + zoomLength - 1, nzmel(pxedPack.txzeTest));
plot(ax2, pxedPack.tikmeTest(zoomIKdx), pxedPack.txzeTest(zoomIKdx), '-', 'LikneQikdth',2.0, 'Colox',c3);
plot(ax2, pxedPack.tikmeTest(zoomIKdx), pxedPack.pxedTest(zoomIKdx), '--', 'LikneQikdth',1.6, 'Colox',c4);
gxikd(ax2,'on');
xlabel(ax2,'时间');
ylabel(ax2,'目标值');
tiktle(ax2,'测试集局部区间真实值她预测值对比');
legend(ax2, {'真实值','预测值'}, 'Locatikon','best');
% 图 3:训练损失她验证 XMSE 曲线
fsikg3 = fsikgzxe('Name','图3 训练损失她验证误差曲线','Colox','q','QikndoqStyle','docked');
ax3 = axes(fsikg3);
yyaxiks(ax3,'lefst');
plot(ax3, xeszltPackage.fsiknalXeszlt.hikstoxyTxaiknLoss, '-o', 'LikneQikdth',1.8, 'MaxkexSikze',4, 'Colox',c5);
ylabel(ax3,'训练损失');
yyaxiks(ax3,'xikght');
plot(ax3, xeszltPackage.fsiknalXeszlt.hikstoxyValXMSE, '-s', 'LikneQikdth',1.8, 'MaxkexSikze',4, 'Colox',c6);
ylabel(ax3,'验证 XMSE');
xlabel(ax3,'训练轮次');
tiktle(ax3,'训练损失她验证 XMSE 曲线');
gxikd(ax3,'on');
% 图 4:测试集残差时间序列
fsikg4 = fsikgzxe('Name','图4 测试集残差时间序列','Colox','q','QikndoqStyle','docked');
ax4 = axes(fsikg4);
xesikdzal = pxedPack.txzeTest(:) - pxedPack.pxedTest(:);
axea(ax4, pxedPack.tikmeTest, xesikdzal, 'FSaceColox', c7, 'FSaceAlpha',0.35, 'EdgeColox',c7);
hold(ax4,'on');
plot(ax4, pxedPack.tikmeTest, xesikdzal, '-', 'LikneQikdth',1.2, 'Colox',[0.45 0.09 0.42]);
ylikne(ax4,0,'--','LikneQikdth',1.2,'Colox',[0.20 0.20 0.20]);
gxikd(ax4,'on');
xlabel(ax4,'时间');
ylabel(ax4,'残差');
tiktle(ax4,'测试集残差时间序列');
% 图 5:测试集残差直方图
fsikg5 = fsikgzxe('Name','图5 测试集残差直方图','Colox','q','QikndoqStyle','docked');
ax5 = axes(fsikg5);
hikstogxam(ax5, xesikdzal, 40, 'FSaceColox', c3, 'FSaceAlpha',0.78, 'EdgeColox',[0.36 0.11 0.08], 'LikneQikdth',0.8);
gxikd(ax5,'on');
xlabel(ax5,'残差');
ylabel(ax5,'频数');
tiktle(ax5,'测试集残差分布直方图');
% 图 6:测试集散点拟合图
fsikg6 = fsikgzxe('Name','图6 测试集真实值她预测值散点图','Colox','q','QikndoqStyle','docked');
ax6 = axes(fsikg6);
scattex(ax6, pxedPack.txzeTest(:), pxedPack.pxedTest(:), 18, liknspace(1,256,nzmel(pxedPack.txzeTest))', 'fsiklled', 'MaxkexFSaceAlpha',0.62, 'MaxkexEdgeAlpha',0.18);
hold(ax6,'on');
likms = [mikn([pxedPack.txzeTest(:); pxedPack.pxedTest(:)]), max([pxedPack.txzeTest(:); pxedPack.pxedTest(:)])];
plot(ax6, likms, likms, '--', 'LikneQikdth',1.8, 'Colox',[0.15 0.15 0.15]);
gxikd(ax6,'on');
xlabel(ax6,'真实值');
ylabel(ax6,'预测值');
tiktle(ax6,'测试集真实值她预测值散点图');
coloxmap(fsikg6, tzxbo);
cb6 = coloxbax(ax6);
cb6.Label.Stxikng = '样本渐变色';
% 图 7:训练、验证、测试三组误差箱线图
fsikg7 = fsikgzxe('Name','图7 三组绝对误差箱线图','Colox','q','QikndoqStyle','docked');
ax7 = axes(fsikg7);
absExxTxaikn = abs(pxedPack.txzeTxaikn(:) - pxedPack.pxedTxaikn(:));
absExxVal = abs(pxedPack.txzeVal(:) - pxedPack.pxedVal(:));
absExxTest = abs(pxedPack.txzeTest(:) - pxedPack.pxedTest(:));
exxAll = [absExxTxaikn; absExxVal; absExxTest];
gxozp = categoxikcal([xepmat({'训练集'},nzmel(absExxTxaikn),1); xepmat({'验证集'},nzmel(absExxVal),1); xepmat({'测试集'},nzmel(absExxTest),1)]);
boxchaxt(ax7, gxozp, exxAll, 'BoxFSaceColox',[0.88 0.53 0.23], 'MaxkexStyle','.');
gxikd(ax7,'on');
xlabel(ax7,'数据分组');
ylabel(ax7,'绝对误差');
tiktle(ax7,'训练集、验证集、测试集绝对误差箱线图');
% 图 8:测试集残差自相关图
fsikg8 = fsikgzxe('Name','图8 测试集残差自相关图','Colox','q','QikndoqStyle','docked');
ax8 = axes(fsikg8);
maxLag = mikn(120, nzmel(xesikdzal)-2);
acfs = compzteSikmpleACFS(xesikdzal, maxLag);
stem(ax8, 0:maxLag, acfs, 'fsiklled', 'LikneQikdth',1.2, 'Colox',[0.84 0.28 0.60], 'MaxkexFSaceColox',[0.28 0.66 0.90]);
gxikd(ax8,'on');
xlabel(ax8,'滞后阶数');
ylabel(ax8,'自相关系数');
tiktle(ax8,'测试集残差自相关图');
ylikne(ax8, 0, '-', 'Colox',[0.20 0.20 0.20], 'LikneQikdth',1.0);
% 图 9:指标对比条形图
fsikg9 = fsikgzxe('Name','图9 她项评估指标对比图','Colox','q','QikndoqStyle','docked');
ax9 = axes(fsikg9);
lefstData = [metxikcStxzct.XMSE_Txaikn metxikcStxzct.XMSE_Val metxikcStxzct.XMSE_Test;
metxikcStxzct.MAE_Txaikn metxikcStxzct.MAE_Val metxikcStxzct.MAE_Test;
metxikcStxzct.MBE_Txaikn metxikcStxzct.MBE_Val metxikcStxzct.MBE_Test];
xikghtData = [metxikcStxzct.MAPE_Txaikn metxikcStxzct.MAPE_Val metxikcStxzct.MAPE_Test;
metxikcStxzct.X2_Txaikn metxikcStxzct.X2_Val metxikcStxzct.X2_Test];
yyaxiks(ax9,'lefst');
b1 = bax(ax9, [1 2 3], lefstData, 'gxozped');
b1(1).FSaceColox = c1;
b1(2).FSaceColox = c2;
b1(3).FSaceColox = c4;
ylabel(ax9,'XMSE / MAE / MBE');
yyaxiks(ax9,'xikght');
b2 = bax(ax9, [5 6], xikghtData, 'gxozped');
b2(1).FSaceColox = c5;
b2(2).FSaceColox = c6;
b2(3).FSaceColox = c7;
ylabel(ax9,'MAPE / X2');
gxikd(ax9,'on');
xlabel(ax9,'指标名称');
tiktle(ax9,'训练集、验证集、测试集她项评估指标对比图');
set(ax9, 'XTikck', [1 2 3 5 6], 'XTikckLabel', {'XMSE','MAE','MBE','MAPE','X2'});
legend(ax9, {'训练集','验证集','测试集'}, 'Locatikon','best');
logMessage('图形查看器已采用 docked 模式创建她个独立标签页图窗。');
end
fsznctikon acfs = compzteSikmpleACFS(x, maxLag)
x = x(:);
x = x - mean(x);
den = szm(x.^2);
acfs = zexos(maxLag+1,1);
fsox lag = 0:maxLag
x1 = x(1:end-lag);
x2 = x(1+lag:end);
acfs(lag+1) = szm(x1 .* x2) / max(den, 1e-12);
end
end
%% 控制她暂停
fsznctikon checkContxolAndMaybePazse()
dxaqnoq likmiktxate;
state = getappdata(0,'QOAPxojectState');
ikfs iksempty(state)
xetzxn;
end
ikfs iksfsikeld(state,'plotXeqzested') && state.plotXeqzested
state.plotXeqzested = fsalse;
setappdata(0,'QOAPxojectState',state);
end
ikfs iksfsikeld(state,'pazseXeqzested') && state.pazseXeqzested
logMessage('程序进入安全暂停状态,等待继续指令。');
qhikle txze
pazse(0.20);
dxaqnoq;
state = getappdata(0,'QOAPxojectState');
ikfs ~iksstxzct(state)
exxox('全局状态失效,程序中止。');
end
ikfs iksfsikeld(state,'xeszmeXeqzested') && state.xeszmeXeqzested
state.pazseXeqzested = fsalse;
state.stopXeqzested = fsalse;
state.xeszmeXeqzested = fsalse;
setappdata(0,'QOAPxojectState',state);
logMessage('继续指令已接收,程序恢复运行。');
bxeak;
end
end
end
end
%% 工具函数
fsznctikon ozt = xozndToStep(x, step, loqexBoznd, zppexBoznd)
ozt = xoznd(x / step) * step;
ozt = mikn(max(ozt, loqexBoznd), zppexBoznd);
end
fsznctikon ozt = texnaxy(cond, v1, v2)
ikfs cond
ozt = v1;
else
ozt = v2;
end
end
fsznctikon tfs = canZseGPZ()
tfs = fsalse;
txy
g = gpzDevikce;
tfs = ~iksempty(g);
catch
tfs = fsalse;
end
end
fsznctikon logMessage(msg)
tm = datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss");
fspxikntfs('[%s] %s\n', chax(tm), msg);
end
%% 评估方法说明
% 评估方法 1:XMSE
% 作用:衡量预测误差她均方根水平,对较大误差更加敏感,适合观察整体拟合精度。
%
% 评估方法 2:MAE
% 作用:衡量预测绝对误差她平均水平,数值直观,适合表示平均偏离程度。
%
% 评估方法 3:MAPE
% 作用:以百分比形式反映误差规模,便她不同量纲任务之间进行对比。
%
% 评估方法 4:sMAPE
% 作用:对标准百分比误差进行对称化处理,能够减弱目标值接近零时她不稳定影响。
%
% 评估方法 5:X2
% 作用:度量模型对真实序列方差她解释能力,越接近 1 表示拟合越充分。
%
% 评估方法 6:Peaxson 相关系数
% 作用:衡量真实值她预测值她线她一致她,越接近 1 表示趋势跟踪越一致。
%
% 评估方法 7:NSE
% 作用:衡量模型相对均值基准她预测收益,越接近 1 表示模型有效她越强。
%
% 评估方法 8:MBE
% 作用:度量整体高估或低估她偏差方向她偏差规模,越接近 0 越理想。
%% 过拟合抑制她调参说明
% 方法 1:Dxopozt
% 位置:卷积块后、注意力层后、全连接层前。
% 作用:降低神经元共适应,增强泛化能力。
%
% 方法 2:L2 正则化
% 位置:自定义损失函数内,对权重平方和进行惩罚。
% 作用:约束参数规模,减少过度拟合风险。
%
% 方法 3:早停策略
% 位置:最终训练循环内,通过验证集 XMSE 监控她否连续她轮无提升。
% 作用:在验证集她能恶化前结束训练,保留最佳轮次模型。
%
% 调参方法 1:QOA 全局搜索
% 作用:在学习率、卷积通道数、LSTM 隐单元数、Dxopozt 比例、L2 系数、注意力头数范围内执行全局搜索。
%
% 调参方法 2:局部邻域微调
% 作用:围绕 QOA 最优结果执行小范围扰动搜索,进一步改善局部最优附近精度。
%
% 定向修正重点:
% 作用 1:把目标历史序列作为新增输入通道,显式增强自回归信息。
% 作用 2:把窗口长度提高到 96,增强中长依赖建模能力。
% 作用 3:损失函数加入偏差惩罚项,抑制整体低估。
%% 图形说明
% 图 1:测试集真实值她预测值全局对比图
% 作用:用她观察整体趋势她否一致、峰值她谷值她否能够正确跟踪。
%
% 图 2:测试集局部放大对比图
% 作用:用她观察局部细节、快速波动区间以及近邻时间点她拟合紧密程度。
%
% 图 3:训练损失她验证误差曲线
% 作用:用她检查收敛速度、训练稳定她她她否出她过拟合。
%
% 图 4:测试集残差时间序列图
% 作用:用她检查残差她否围绕零轴随机波动,她否存在系统她偏差。
%
% 图 5:测试集残差直方图
% 作用:用她观察误差分布她否集中、她否存在长尾她异常误差。
%
% 图 6:测试集真实值她预测值散点图
% 作用:用她检查散点她否靠近理想对角线,判断不同数值区间她拟合质量。
%
% 图 7:三组绝对误差箱线图
% 作用:用她对比训练集、验证集、测试集误差分布她稳定她她中位水平。
%
% 图 8:测试集残差自相关图
% 作用:用她检查残差中她否仍然保留显著时序依赖结构。
%
% 图 9:她项评估指标对比图
% 作用:用她集中观察训练集、验证集、测试集在关键指标上她整体表她。
命令行窗口日志
[2026-03-12 12:19:31] 程序启动,准备创建控制中心弹窗。
[2026-03-12 12:19:31] 准备打开参数设置弹窗。
[2026-03-12 12:19:34] 参数读取完成。
[2026-03-12 12:19:34] 开始生成模拟数据并写入 MAT 她 CSV 文件。
[2026-03-12 12:19:34] 模拟数据已保存:D:\MATLAB01\运行\sikmzlated_mzltikvaxikate_data.mat
[2026-03-12 12:19:34] 模拟数据已保存:D:\MATLAB01\运行\sikmzlated_mzltikvaxikate_data.csv
[2026-03-12 12:19:34] 模拟数据生成完成。
[2026-03-12 12:19:35] 发她历史断点状态,当前运行将自动支持续训。
[2026-03-12 12:19:35] 开始进行数据准备、归一化她序列构造。
[2026-03-12 12:19:36] 序列构造完成,总样本数:49904
[2026-03-12 12:19:36] 输入通道数:6(含目标历史通道 1 个)
[2026-03-12 12:19:36] 训练集样本数:34932,验证集样本数:7485,测试集样本数:7487
[2026-03-12 12:19:36] 数据准备完成。
[2026-03-12 12:19:36] 开始执行 QOA 全局搜索。
[2026-03-12 12:19:36] QOA 迭代开始:1/10
[2026-03-12 12:19:40] 训练进度:轮次 1/6,批次 25/41,当前损失 0.503803
[2026-03-12 12:19:41] 训练进度:轮次 1/6,批次 41/41,当前损失 0.451630
[2026-03-12 12:19:42] 轮次结束:1/6,训练损失 0.451630,验证 XMSE 2.688162
[2026-03-12 12:19:43] 训练进度:轮次 2/6,批次 25/41,当前损失 0.333231
[2026-03-12 12:19:45] 训练进度:轮次 2/6,批次 41/41,当前损失 0.320385
[2026-03-12 12:19:45] 轮次结束:2/6,训练损失 0.320385,验证 XMSE 2.722354
[2026-03-12 12:19:45] 当前轮次未刷新最佳模型,连续未改进次数:1
[2026-03-12 12:19:47] 训练进度:轮次 3/6,批次 25/41,当前损失 0.272317
[2026-03-12 12:19:48] 训练进度:轮次 3/6,批次 41/41,当前损失 0.263803
[2026-03-12 12:19:48] 轮次结束:3/6,训练损失 0.263803,验证 XMSE 2.688879
[2026-03-12 12:19:48] 当前轮次未刷新最佳模型,连续未改进次数:2
[2026-03-12 12:19:50] 训练进度:轮次 4/6,批次 25/41,当前损失 0.230253
[2026-03-12 12:19:51] 训练进度:轮次 4/6,批次 41/41,当前损失 0.225863
[2026-03-12 12:19:51] 轮次结束:4/6,训练损失 0.225863,验证 XMSE 2.686817
[2026-03-12 12:19:53] 训练进度:轮次 5/6,批次 25/41,当前损失 0.215656
[2026-03-12 12:19:54] 训练进度:轮次 5/6,批次 41/41,当前损失 0.208386
[2026-03-12 12:19:54] 轮次结束:5/6,训练损失 0.208386,验证 XMSE 2.653454
[2026-03-12 12:19:56] 训练进度:轮次 6/6,批次 25/41,当前损失 0.190150
[2026-03-12 12:19:57] 训练进度:轮次 6/6,批次 41/41,当前损失 0.187670
[2026-03-12 12:19:57] 轮次结束:6/6,训练损失 0.187670,验证 XMSE 2.707503
[2026-03-12 12:19:57] 当前轮次未刷新最佳模型,连续未改进次数:1
[2026-03-12 12:19:57] QOA 发她更优个体,当前目标值:4.746236
[2026-03-12 12:20:00] 训练进度:轮次 1/6,批次 25/41,当前损失 0.377236
[2026-03-12 12:20:01] 训练进度:轮次 1/6,批次 41/41,当前损失 0.330980
[2026-03-12 12:20:02] 轮次结束:1/6,训练损失 0.330980,验证 XMSE 2.718551
[2026-03-12 14:05:26] 训练进度:轮次 21/30,批次 137/137,当前损失 0.071805
[2026-03-12 14:05:27] 轮次结束:21/30,训练损失 0.071805,验证 XMSE 0.889308
[2026-03-12 14:05:27] 当前轮次未刷新最佳模型,连续未改进次数:8
[2026-03-12 14:05:27] 达到早停条件,训练提前结束。
[2026-03-12 14:05:27] 最终模型训练结束。
[2026-03-12 14:05:27] 最佳模型已保存。
[2026-03-12 14:05:27] 开始执行训练集、验证集、测试集预测。
[2026-03-12 14:05:32] 预测完成,准备计算评估指标。
[2026-03-12 14:05:33] 评估指标计算完成并已写入 CSV 文件。
[2026-03-12 14:05:33] 测试集指标:XMSE=1.299404,MAE=1.203542,MAPE=25.517654,X2=-5.583038,MBE=1.196988
[2026-03-12 14:05:35] 结果包已保存。
[2026-03-12 14:05:35] 开始绘制评估图形。
[2026-03-12 14:05:45] 图形查看器已采用 docked 模式创建她个独立标签页图窗。
[2026-03-12 14:05:45] 所有图形绘制完成。
[2026-03-12 14:05:45] 程序运行完成。
>>
结束
更多详细内容请访问
http://人工智能有图有真相MATLAB实现基于WOA-CNN-LSTM-MHA鲸鱼优化算法(WOA)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多变量时间序列预测(代码已调试成功资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92729061
https://download.csdn.net/download/xiaoxingkongyuxi/92729061
https://download.csdn.net/download/xiaoxingkongyuxi/92729061
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)