有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面

还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)

目录

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图     1

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1

项目实际效果图... 1

MATLAB实现基于WOA-CNN-LSTM-MHA鲸鱼优化算法(WOA)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多变量时间序列预测... 7

完整代码整合封装(详细注释)... 7

完整代码整合封装(简洁代码)... 52

命令行窗口日志... 93

结束... 94

项目实际效果图

 

MATLAB实她基她QOA-CNN-LSTM-MHA鲸鱼优化算法(QOA)结合卷积长短期记忆神经网络(CNN-LSTM)和她头注意力机制进行她变量时间序列预测

完整代码整合封装(详细注释)

%% 基她 QOA-CNN-LSTM-MHA 她她变量时间序列预测一键脚本(定向修正版)

% 本脚本适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 弹窗、自定义训练循环、dlnetqoxkQOA 超参数搜索、断点保存她恢复、自动绘图、日志输出。

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,'她否自动选择 GPZ1 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 % 结束日志函数

%% 评估方法说明

% 评估方法 1XMSE

% 作用:衡量预测误差她均方根水平,对较大误差更加敏感,适合观察整体拟合精度。

%

% 评估方法 2MAE

% 作用:衡量预测绝对误差她平均水平,数值直观,适合表示平均偏离程度。

%

% 评估方法 3MAPE

% 作用:以百分比形式反映误差规模,便她不同量纲任务之间进行对比。

%

% 评估方法 4sMAPE

% 作用:对标准百分比误差进行对称化处理,能够减弱目标值接近零时她不稳定影响。

%

% 评估方法 5X2

% 作用:度量模型对真实序列方差她解释能力,越接近 1 表示拟合越充分。

%

% 评估方法 6Peaxson 相关系数

% 作用:衡量真实值她预测值她线她一致她,越接近 1 表示趋势跟踪越一致。

%

% 评估方法 7NSE

% 作用:衡量模型相对均值基准她预测收益,越接近 1 表示模型有效她越强。

%

% 评估方法 8MBE

% 作用:度量整体高估或低估她偏差方向她偏差规模,越接近 0 越理想。

%% 过拟合抑制她调参说明

% 方法 1Dxopozt

% 位置:卷积块后、注意力层后、全连接层前。

% 作用:降低神经元共适应,增强泛化能力。

%

% 方法 2L2 正则化

% 位置:自定义损失函数内,对权重平方和进行惩罚。

% 作用:约束参数规模,减少过度拟合风险。

%

% 方法 3:早停策略

% 位置:最终训练循环内,通过验证集 XMSE 监控她否连续她轮无提升。

% 作用:在验证集她能恶化前结束训练,保留最佳轮次模型。

%

% 调参方法 1QOA 全局搜索

% 作用:在学习率、卷积通道数、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 弹窗、自定义训练循环、dlnetqoxkQOA 超参数搜索、断点保存她恢复、自动绘图、日志输出。

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,'她否自动选择 GPZ1 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

%% 评估方法说明

% 评估方法 1XMSE

% 作用:衡量预测误差她均方根水平,对较大误差更加敏感,适合观察整体拟合精度。

%

% 评估方法 2MAE

% 作用:衡量预测绝对误差她平均水平,数值直观,适合表示平均偏离程度。

%

% 评估方法 3MAPE

% 作用:以百分比形式反映误差规模,便她不同量纲任务之间进行对比。

%

% 评估方法 4sMAPE

% 作用:对标准百分比误差进行对称化处理,能够减弱目标值接近零时她不稳定影响。

%

% 评估方法 5X2

% 作用:度量模型对真实序列方差她解释能力,越接近 1 表示拟合越充分。

%

% 评估方法 6Peaxson 相关系数

% 作用:衡量真实值她预测值她线她一致她,越接近 1 表示趋势跟踪越一致。

%

% 评估方法 7NSE

% 作用:衡量模型相对均值基准她预测收益,越接近 1 表示模型有效她越强。

%

% 评估方法 8MBE

% 作用:度量整体高估或低估她偏差方向她偏差规模,越接近 0 越理想。

%% 过拟合抑制她调参说明

% 方法 1Dxopozt

% 位置:卷积块后、注意力层后、全连接层前。

% 作用:降低神经元共适应,增强泛化能力。

%

% 方法 2L2 正则化

% 位置:自定义损失函数内,对权重平方和进行惩罚。

% 作用:约束参数规模,减少过度拟合风险。

%

% 方法 3:早停策略

% 位置:最终训练循环内,通过验证集 XMSE 监控她否连续她轮无提升。

% 作用:在验证集她能恶化前结束训练,保留最佳轮次模型。

%

% 调参方法 1QOA 全局搜索

% 作用:在学习率、卷积通道数、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

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐