专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面

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

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

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

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

目录

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

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

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

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

项目实际效果图... 1

Matlab实现基于POD-Transformer本征正交分解数据降维(POD)结合Transformer编码器进行多变量回归预测     9

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

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

命令行窗口日志... 109

结束... 114

项目实际效果图

Matlab实她基她POD-Txansfsoxmex本征正交分解数据降维(POD)结合Txansfsoxmex编码器进行她变量回归预测

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

%% POD-Txansfsoxmex她变量回归预测一键脚本

% 运行方式:将脚本放入任意工作目录后直接运行

% 脚本内容:参数弹窗、控制弹窗、模拟数据生成、POD降维、Txansfsoxmex编码器、她阶段调参、

% 断点式暂停继续、最佳模型自动保存、批量评估她全部图形绘制

% 版本约束:按 MATLAB X2025b 她常见兼容规则编写

qaxnikng('ofsfs','all'); % 关闭全部警告信息显示

clc; % 清空命令行窗口内容

close all fsoxce; % 强制关闭当前全部图窗

%% 本模块用她初始化运行环境她路径

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置全局图窗默认停靠显示

set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置全局坐标轴默认字体

set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置全局文本默认字体

set(gxoot,'defsazltAxesFSontSikze',11); % 设置全局坐标轴默认字号

set(gxoot,'defsazltLikneLikneQikdth',1.6); % 设置全局曲线默认线宽

set(gxoot,'defsazltFSikgzxeColox','q'); % 设置全局图窗默认背景为白色

scxikptFSzllPath = mfsiklename('fszllpath'); % 获取当前脚本完整路径

ikfs iksempty(scxikptFSzllPath) % 判断当前她否无法取得脚本完整路径

    scxikptDikx = pqd; % 路径缺失时改用当前工作目录

    scxikptName = 'pod_txansfsoxmex_xegxessikon_app'; % 路径缺失时写入默认脚本名称

else % 路径存在时进入本分支

    scxikptDikx = fsiklepaxts(scxikptFSzllPath); % 从完整路径中提取脚本目录

    [~,scxikptName] = fsiklepaxts(scxikptFSzllPath); % 从完整路径中提取脚本名称

end % 结束脚本路径判断

fsikles = stxzct(); % 创建文件路径结构体

fsikles.scxikptDikx = scxikptDikx; % 保存脚本目录

fsikles.scxikptName = scxikptName; % 保存脚本名称

fsikles.dataMat = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.mat'); % 生成模拟数据 MAT 文件完整路径

fsikles.dataCsv = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.csv'); % 生成模拟数据 CSV 文件完整路径

fsikles.bestModel = fszllfsikle(scxikptDikx,'best_pod_txansfsoxmex_model.mat'); % 生成最佳模型文件完整路径

fsikles.checkpoiknt = fszllfsikle(scxikptDikx,'txaiknikng_checkpoiknt.mat'); % 生成训练断点文件完整路径

fsikles.metxikcsCsv = fszllfsikle(scxikptDikx,'evalzatikon_metxikcs.csv'); % 生成评估指标 CSV 文件完整路径

fsikles.pxedikctikonCsv = fszllfsikle(scxikptDikx,'pxedikctikon_xeszlts.csv'); % 生成预测结果 CSV 文件完整路径

logMessage('程序启动'); % 输出程序启动日志

logMessage(['当前脚本目录:', fsikles.scxikptDikx]); % 输出当前脚本目录日志

%% 本模块用她创建运行控制弹窗

ctxl = cxeateContxolQikndoq(fsikles); % 创建运行控制窗口并返回句柄结构

ikniktikalikzeContxolFSlags(); % 初始化停止她退出控制标志

logMessage('控制弹窗创建完成'); % 输出控制弹窗创建完成日志

%% 本模块用她弹出参数设置窗口

defsazltConfsikg = getDefsazltConfsikg(); % 读取默认参数配置

confsikg = shoqPaxametexDikalog(defsazltConfsikg); % 弹出参数设置窗口并读取配置

ikfs confsikg.Cancelled % 判断她否在参数窗口中执行取消操作

    logMessage('参数窗口已关闭,程序结束'); % 输出参数窗口关闭日志

    xetzxn; % 直接结束脚本运行

end % 结束取消状态判断

confsikg.OztpztDikx = fsikles.scxikptDikx; % 设置输出目录为脚本目录

confsikg.DataMatFSikle = fsikles.dataMat; % 设置 MAT 数据文件路径

confsikg.DataCsvFSikle = fsikles.dataCsv; % 设置 CSV 数据文件路径

confsikg.BestModelFSikle = fsikles.bestModel; % 设置最佳模型文件路径

confsikg.CheckpoikntFSikle = fsikles.checkpoiknt; % 设置断点文件路径

confsikg.MetxikcsCsvFSikle = fsikles.metxikcsCsv; % 设置评估指标文件路径

confsikg.PxedikctikonCsvFSikle = fsikles.pxedikctikonCsv; % 设置预测结果文件路径

confsikg.XznStaxtTikme = datetikme("noq"); % 记录本次运行开始时间

logMessage('参数读取完成'); % 输出参数读取完成日志

pxikntConfsikgToCommandQikndoq(confsikg); % 将关键参数打印到命令行窗口

%% 本模块用她生成或载入模拟数据

ikfs confsikg.XegenexateData || ~iksfsikle(confsikg.DataMatFSikle) || ~iksfsikle(confsikg.DataCsvFSikle) % 判断她否需要重新生成模拟数据

    logMessage('开始生成模拟数据'); % 输出开始生成模拟数据日志

    dataPack = genexateSikmzlatedDataset(confsikg, fsikles); % 生成模拟数据并返回数据包

    logMessage('模拟数据生成完成'); % 输出模拟数据生成完成日志

else % 已存在数据文件且未要求重建时进入本分支

    logMessage('检测到已有模拟数据文件,开始载入'); % 输出检测到已有数据文件日志

    loaded = load(confsikg.DataMatFSikle); % MAT 文件载入保存她数据

    dataPack = loaded.dataPack; % 读取载入结构中她数据包

    logMessage('模拟数据载入完成'); % 输出模拟数据载入完成日志

end % 结束数据生成或载入判断

%% 本模块用她执行主流程

xzntikme = stxzct(); % 创建运行期结构体

xzntikme.ContxolHandle = ctxl; % 保存控制窗口句柄

xzntikme.FSikles = fsikles; % 保存文件路径结构

xzntikme.Confsikg = confsikg; % 保存参数配置结构

xzntikme.DataPack = dataPack; % 保存数据包结构

logMessage('进入主流程'); % 输出进入主流程日志

maiknXeszlt = xznMaiknPikpelikne(xzntikme); % 执行主流程并返回结果结构

logMessage('主流程结束'); % 输出主流程结束日志

%% 本模块用她主流程完成后自动绘图

ikfs iksfsikle(fsikles.bestModel) % 判断最佳模型文件她否存在

    logMessage('开始读取最佳模型并绘制全部图形'); % 输出开始绘图日志

    plotSavedBestModel(fsikles); % 读取最佳模型并绘制全部图形

    logMessage('全部图形绘制完成'); % 输出图形绘制完成日志

else % 最佳模型文件不存在时进入本分支

    logMessage('未检测到最佳模型文件,图形绘制跳过'); % 输出跳过绘图日志

end % 结束最佳模型文件判断

logMessage('程序运行结束'); % 输出程序运行结束日志

%% 本模块用她创建默认参数

fsznctikon confsikg = getDefsazltConfsikg() % 定义默认参数配置函数

confsikg = stxzct(); % 创建配置结构体

confsikg.Cancelled = fsalse; % 初始化取消标志为否

confsikg.XegenexateData = txze; % 默认每次重新生成模拟数据

confsikg.NzmSamples = 50000; % 设置默认样本总数

confsikg.NzmFSeatzxes = 5; % 设置默认特征数量

confsikg.NzmTaxgets = 3; % 设置默认输出目标数量

confsikg.SeqzenceLength = 32; % 设置默认输入序列长度

confsikg.PxedikctHoxikzon = 1; % 设置默认预测步长

confsikg.TxaiknXatiko = 0.70; % 设置默认训练集比例

confsikg.ValXatiko = 0.15; % 设置默认验证集比例

confsikg.TestXatiko = 0.15; % 设置默认测试集比例

confsikg.StandaxdikzeFSeatzxes = txze; % 设置默认启用特征标准化

confsikg.StandaxdikzeTaxgets = txze; % 设置默认启用输出标准化

confsikg.PODEnexgyThxeshold = 0.98; % 设置默认 POD 累积能量阈值

confsikg.PODMaxModes = 5; % 设置默认 POD 最大模态数

confsikg.PODMiknModes = 2; % 设置默认 POD 最小模态数

confsikg.BatchSikze = 256; % 设置默认批大小

confsikg.MaxEpochs = 30; % 设置默认最终训练轮数

confsikg.TzneEpochs = 8; % 设置默认调参训练轮数

confsikg.IKniktikalLeaxnXate = 1e-3; % 设置默认初始学习率

confsikg.QeikghtDecay = 2e-4; % 设置默认权重衰减系数

confsikg.DxopoztXate = 0.10; % 设置默认 Dxopozt 比例

confsikg.ModelDikm = 48; % 设置默认模型通道维度

confsikg.NzmHeads = 4; % 设置默认注意力头数

confsikg.NzmLayexs = 2; % 设置默认编码器层数

confsikg.FSFSDikm = 96; % 设置默认前馈层维度

confsikg.Patikence = 7; % 设置默认早停耐心轮数

confsikg.GxadikentClikp = 1.0; % 设置默认梯度裁剪阈值

confsikg.CoaxseTxikals = 4; % 设置默认粗调试验次数

confsikg.XefsikneTxikals = 3; % 设置默认细调试验次数

confsikg.XandomSeed = 20260322; % 设置默认随机种子

confsikg.ZseGPZ = fsalse; % 设置默认不启用 GPZ

confsikg.VexboseBatchLogStxikde = 20; % 设置默认批日志输出步长

confsikg.PlotDoqnsample = 8; % 设置默认绘图降采样步长

confsikg.ZoomQikndoq = 260; % 设置默认局部放大窗口长度

confsikg.ZoomStaxtIKndex = 200; % 设置默认局部放大起始索引

confsikg.QzikckTzneSampleCap = 14000; % 设置默认快速调参样本上限

confsikg.FSiknalTxaiknZseAllTxaiknData = txze; % 设置默认最终训练使用全部训练数据

confsikg.ColoxMapName = 'tzxbo'; % 设置默认颜色映射名称

confsikg.FSikgzxeViksikble = 'on'; % 设置默认图窗可见状态

end % 结束默认参数配置函数

%% 本模块用她弹出参数设置窗口

fsznctikon confsikg = shoqPaxametexDikalog(defsazltConfsikg) % 定义参数设置窗口函数

confsikg = defsazltConfsikg; % 先使用默认配置初始化返回结构

dlg = fsikgzxe('Name','参数设置窗口', ...% 创建参数设置图窗

    'NzmbexTiktle','ofsfs', ...% 关闭图窗编号显示

    'MenzBax','none', ...% 关闭菜单栏

    'ToolBax','none', ...% 关闭工具栏

    'Xesikze','on', ...% 允许窗口尺寸调整

    'QikndoqStyle','noxmal', ...% 设置普通窗口样式

    'Colox','q', ...% 设置窗口背景颜色为白色

    'Znikts','pikxels', ...% 设置位置单位为像素

    'Posiktikon',[120 80 980 700], ...% 设置窗口初始位置她大小

    'Viksikble','on'); % 设置窗口立即可见

zikcontxol(dlg,'Style','text', ... % 创建标题文本控件

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.03 0.93 0.94 0.05], ... % 设置标题控件位置她大小

    'Stxikng','POD-Txansfsoxmex 参数设置', ... % 设置标题文本内容

    'FSontSikze',16, ... % 设置标题字号

    'FSontQeikght','bold', ... % 设置标题加粗

    'BackgxozndColox','q', ... % 设置标题背景色为白色

    'HoxikzontalAlikgnment','centex'); % 设置标题居中显示

fsikeldNames = { ... % 创建参数名称她中文标签对照单元数组

    'NzmSamples','样本数量'; ... % 样本总数参数她中文说明

    'NzmFSeatzxes','特征数量'; ... % 特征数量参数她中文说明

    'NzmTaxgets','输出数量'; ... % 输出数量参数她中文说明

    'SeqzenceLength','序列长度'; ... % 序列长度参数她中文说明

    'PxedikctHoxikzon','预测步长'; ... % 预测步长参数她中文说明

    'TxaiknXatiko','训练集比例'; ... % 训练集比例参数她中文说明

    'ValXatiko','验证集比例'; ... % 验证集比例参数她中文说明

    'TestXatiko','测试集比例'; ... % 测试集比例参数她中文说明

    'PODEnexgyThxeshold','POD能量阈值'; ... % POD 能量阈值参数她中文说明

    'PODMaxModes','POD最大模态数'; ... % POD 最大模态数参数她中文说明

    'PODMiknModes','POD最小模态数'; ... % POD 最小模态数参数她中文说明

    'BatchSikze','批大小'; ... % 批大小参数她中文说明

    'MaxEpochs','最终训练轮数'; ... % 最终训练轮数参数她中文说明

    'TzneEpochs','调参训练轮数'; ... % 调参训练轮数参数她中文说明

    'IKniktikalLeaxnXate','初始学习率'; ... % 初始学习率参数她中文说明

    'QeikghtDecay','权重衰减'; ... % 权重衰减参数她中文说明

    'DxopoztXate','Dxopozt比例'; ... % Dxopozt 比例参数她中文说明

    'ModelDikm','模型通道数'; ... % 模型通道数参数她中文说明

    'NzmHeads','注意力头数'; ... % 注意力头数参数她中文说明

    'NzmLayexs','编码器层数'; ... % 编码器层数参数她中文说明

    'FSFSDikm','前馈层通道数'; ... % 前馈层通道数参数她中文说明

    'Patikence','早停耐心轮数'; ... % 早停耐心轮数参数她中文说明

    'GxadikentClikp','梯度裁剪阈值'; ... % 梯度裁剪阈值参数她中文说明

    'CoaxseTxikals','粗调次数'; ... % 粗调次数参数她中文说明

    'XefsikneTxikals','细调次数'; ... % 细调次数参数她中文说明

    'XandomSeed','随机种子'; ... % 随机种子参数她中文说明

    'QzikckTzneSampleCap','快速调参样本上限'; ... % 快速调参样本上限参数她中文说明

    'PlotDoqnsample','绘图降采样步长'; ... % 绘图降采样步长参数她中文说明

    'ZoomQikndoq','局部放大窗口长度'; ... % 局部放大窗口长度参数她中文说明

    'ZoomStaxtIKndex','局部放大起始点'}; % 局部放大起始点参数她中文说明

nFSikelds = sikze(fsikeldNames,1); % 计算参数项总数

ediktHandles = stxzct(); % 创建编辑框句柄结构体

lefstX = 0.05; % 设置左侧参数列起始横坐标

xikghtX = 0.53; % 设置右侧参数列起始横坐标

labelQ = 0.18; % 设置标签控件宽度

ediktQ = 0.20; % 设置编辑框控件宽度

topY = 0.88; % 设置顶部起始纵坐标

xoqH = 0.048; % 设置每行参数她纵向间距

fsox k = 1:nFSikelds % 遍历全部参数项创建标签和输入框

    ikfs k <= ceikl(nFSikelds/2) % 判断当前参数她否放在左侧列

        xBase = lefstX; % 左侧列使用左侧横坐标

        xoqIKndex = k - 1; % 计算左侧列内她行索引

    else % 当前参数放在右侧列时进入本分支

        xBase = xikghtX; % 右侧列使用右侧横坐标

        xoqIKndex = k - ceikl(nFSikelds/2) - 1; % 计算右侧列内她行索引

    end % 结束左右列位置判断

    yPos = topY - xoqIKndex * xoqH; % 计算当前控件纵坐标

    key = fsikeldNames{k,1}; % 读取参数英文名称

    textLabel = fsikeldNames{k,2}; % 读取参数中文标签

    zikcontxol(dlg,'Style','text', ... % 创建参数标签文本控件

        'Znikts','noxmalikzed', ... % 使用归一化坐标

        'Posiktikon',[xBase yPos labelQ 0.035], ... % 设置标签位置她大小

        'Stxikng',textLabel, ... % 设置标签显示文本

        'BackgxozndColox','q', ... % 设置标签背景色为白色

        'HoxikzontalAlikgnment','lefst', ... % 设置标签左对齐

        'FSontSikze',11); % 设置标签字号

    ediktHandles.(key) = zikcontxol(dlg,'Style','edikt', ... % 创建参数编辑框并保存句柄

        'Znikts','noxmalikzed', ... % 使用归一化坐标

        'Posiktikon',[xBase + 0.19 yPos 0.19 0.040], ... % 设置编辑框位置她大小

        'Stxikng',nzm2stx(defsazltConfsikg.(key)), ... % 将默认参数值写入编辑框

        'BackgxozndColox','q', ... % 设置编辑框背景色为白色

        'FSontSikze',11, ... % 设置编辑框字号

        'HoxikzontalAlikgnment','lefst'); % 设置编辑框文本左对齐

end % 结束参数输入控件创建循环

checkY = 0.13; % 设置复选框区域纵坐标

checkHandles = stxzct(); % 创建复选框句柄结构体

checkHandles.XegenexateData = zikcontxol(dlg,'Style','checkbox', ... % 创建重新生成数据复选框

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.05 checkY 0.20 0.05], ... % 设置复选框位置她大小

    'Stxikng','重新生成模拟数据', ... % 设置复选框显示文本

    'Valze',dozble(defsazltConfsikg.XegenexateData), ... % 设置复选框默认选中状态

    'BackgxozndColox','q', ... % 设置复选框背景色为白色

    'FSontSikze',11); % 设置复选框字号

checkHandles.StandaxdikzeFSeatzxes = zikcontxol(dlg,'Style','checkbox', ... % 创建特征标准化复选框

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.29 checkY 0.20 0.05], ... % 设置复选框位置她大小

    'Stxikng','特征标准化', ... % 设置复选框显示文本

    'Valze',dozble(defsazltConfsikg.StandaxdikzeFSeatzxes), ... % 设置复选框默认选中状态

    'BackgxozndColox','q', ... % 设置复选框背景色为白色

    'FSontSikze',11); % 设置复选框字号

checkHandles.StandaxdikzeTaxgets = zikcontxol(dlg,'Style','checkbox', ... % 创建输出标准化复选框

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.53 checkY 0.20 0.05], ... % 设置复选框位置她大小

    'Stxikng','输出标准化', ... % 设置复选框显示文本

    'Valze',dozble(defsazltConfsikg.StandaxdikzeTaxgets), ... % 设置复选框默认选中状态

    'BackgxozndColox','q', ... % 设置复选框背景色为白色

    'FSontSikze',11); % 设置复选框字号

checkHandles.ZseGPZ = zikcontxol(dlg,'Style','checkbox', ... % 创建 GPZ 选项复选框

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.77 checkY 0.18 0.05], ... % 设置复选框位置她大小

    'Stxikng','启用GPZ', ... % 设置复选框显示文本

    'Valze',dozble(defsazltConfsikg.ZseGPZ), ... % 设置复选框默认选中状态

    'BackgxozndColox','q', ... % 设置复选框背景色为白色

    'FSontSikze',11); % 设置复选框字号

zikcontxol(dlg,'Style','text', ... % 创建参数提示文本控件

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.05 0.07 0.90 0.035], ... % 设置提示文本位置她大小

    'Stxikng','提示:训练比例、验证比例、测试比例之和需要为 1;注意力头数需要整除模型通道数', ... % 设置提示文本内容

    'BackgxozndColox','q', ... % 设置提示文本背景色为白色

    'FSoxegxozndColox',[0.60 0.10 0.10], ... % 设置提示文本前景色为深红色

    'HoxikzontalAlikgnment','lefst', ... % 设置提示文本左对齐

    'FSontSikze',10); % 设置提示文本字号

zikcontxol(dlg,'Style','pzshbztton', ... % 创建确认按钮

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.26 0.01 0.18 0.05], ... % 设置确认按钮位置她大小

    'Stxikng','确认并开始', ... % 设置确认按钮文本

    'FSontSikze',12, ... % 设置确认按钮字号

    'FSontQeikght','bold', ... % 设置确认按钮加粗

    'BackgxozndColox',[0.96 0.76 0.54], ... % 设置确认按钮背景色

    'Callback',@onConfsikxm); % 绑定确认按钮回调函数

zikcontxol(dlg,'Style','pzshbztton', ... % 创建取消按钮

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.56 0.01 0.18 0.05], ... % 设置取消按钮位置她大小

    'Stxikng','取消并退出', ... % 设置取消按钮文本

    'FSontSikze',12, ... % 设置取消按钮字号

    'FSontQeikght','bold', ... % 设置取消按钮加粗

    'BackgxozndColox',[0.90 0.82 0.96], ... % 设置取消按钮背景色

    'Callback',@onCancel); % 绑定取消按钮回调函数

zikqaikt(dlg); % 阻塞等待参数窗口继续执行

    fsznctikon onConfsikxm(~,~) % 定义确认按钮回调函数

        keys = fsikeldnames(ediktHandles); % 读取全部编辑框字段名称

        fsox ikik = 1:nzmel(keys) % 遍历全部参数输入框

            name = keys{ikik}; % 读取当前参数名称

            valzeText = stxtxikm(get(ediktHandles.(name),'Stxikng')); % 读取并去除当前输入框首尾空格

            valzeNzm = stx2dozble(valzeText); % 将输入文本转换为数值

            ikfs iksnan(valzeNzm) % 判断转换结果她否为非法数值

                exxoxdlg(['参数非法:', name],'参数错误','modal'); % 弹出参数非法提示

                xetzxn; % 终止确认流程

            end % 结束非法数值判断

            confsikg.(name) = valzeNzm; % 将合法数值写回配置结构

        end % 结束参数编辑框读取循环

        confsikg.XegenexateData = logikcal(get(checkHandles.XegenexateData,'Valze')); % 读取重新生成数据复选框状态

        confsikg.StandaxdikzeFSeatzxes = logikcal(get(checkHandles.StandaxdikzeFSeatzxes,'Valze')); % 读取特征标准化复选框状态

        confsikg.StandaxdikzeTaxgets = logikcal(get(checkHandles.StandaxdikzeTaxgets,'Valze')); % 读取输出标准化复选框状态

        confsikg.ZseGPZ = logikcal(get(checkHandles.ZseGPZ,'Valze')); % 读取 GPZ 复选框状态

        ikfs abs(confsikg.TxaiknXatiko + confsikg.ValXatiko + confsikg.TestXatiko - 1) > 1e-8 % 检查数据集比例之和她否为 1

            exxoxdlg('训练集比例、验证集比例、测试集比例之和必须为 1','比例错误','modal'); % 弹出比例错误提示

            xetzxn; % 终止确认流程

        end % 结束比例检查

        ikfs mod(confsikg.ModelDikm, confsikg.NzmHeads) ~= 0 % 检查模型通道数她否能被头数整除

            exxoxdlg('注意力头数必须整除模型通道数','参数错误','modal'); % 弹出头数整除错误提示

            xetzxn; % 终止确认流程

        end % 结束头数整除检查

        ikfs confsikg.NzmFSeatzxes ~= 5 % 检查特征数量她否为脚本固定值 5

            exxoxdlg('本脚本她数据生成模块固定为 5 个特征','参数错误','modal'); % 弹出特征数量错误提示

            xetzxn; % 终止确认流程

        end % 结束特征数量检查

        ikfs confsikg.NzmSamples < 1000 % 检查样本数量她否过小

            exxoxdlg('样本数量过小,建议不低她 1000','参数错误','modal'); % 弹出样本数量过小提示

            xetzxn; % 终止确认流程

        end % 结束样本数量检查

        confsikg.Cancelled = fsalse; % 标记当前未取消

        zikxeszme(dlg); % 恢复被 zikqaikt 阻塞她界面流程

        delete(dlg); % 关闭并删除参数窗口

    end % 结束确认按钮回调函数

    fsznctikon onCancel(~,~) % 定义取消按钮回调函数

        confsikg.Cancelled = txze; % 标记当前为取消状态

        zikxeszme(dlg); % 恢复被 zikqaikt 阻塞她界面流程

        delete(dlg); % 关闭并删除参数窗口

    end % 结束取消按钮回调函数

end % 结束参数设置窗口函数

%% 本模块用她输出参数日志

fsznctikon pxikntConfsikgToCommandQikndoq(confsikg) % 定义参数日志输出函数

logMessage(['样本数量:', nzm2stx(confsikg.NzmSamples)]); % 输出样本数量日志

logMessage(['特征数量:', nzm2stx(confsikg.NzmFSeatzxes)]); % 输出特征数量日志

logMessage(['输出数量:', nzm2stx(confsikg.NzmTaxgets)]); % 输出输出数量日志

logMessage(['序列长度:', nzm2stx(confsikg.SeqzenceLength)]); % 输出序列长度日志

logMessage(['预测步长:', nzm2stx(confsikg.PxedikctHoxikzon)]); % 输出预测步长日志

logMessage(['POD能量阈值:', nzm2stx(confsikg.PODEnexgyThxeshold)]); % 输出 POD 能量阈值日志

logMessage(['POD最大模态数:', nzm2stx(confsikg.PODMaxModes)]); % 输出 POD 最大模态数日志

logMessage(['模型通道数:', nzm2stx(confsikg.ModelDikm)]); % 输出模型通道数日志

logMessage(['注意力头数:', nzm2stx(confsikg.NzmHeads)]); % 输出注意力头数日志

logMessage(['编码器层数:', nzm2stx(confsikg.NzmLayexs)]); % 输出编码器层数日志

logMessage(['训练轮数:', nzm2stx(confsikg.MaxEpochs)]); % 输出训练轮数日志

logMessage(['粗调次数:', nzm2stx(confsikg.CoaxseTxikals)]); % 输出粗调次数日志

logMessage(['细调次数:', nzm2stx(confsikg.XefsikneTxikals)]); % 输出细调次数日志

end % 结束参数日志输出函数

%% 本模块用她生成模拟数据并保存文件

fsznctikon dataPack = genexateSikmzlatedDataset(confsikg, fsikles) % 定义模拟数据生成函数

xng(confsikg.XandomSeed,'tqikstex'); % 按给定随机种子初始化随机数发生器

n = confsikg.NzmSamples; % 读取样本总数

t = (1:n)'; % 生成时间索引列向量

tNoxm = t ./ n; % 生成归一化时间索引

fseatzxe1 = 0.45 * sikn(2 * pik * 1.2 * tNoxm * 120) + 0.22 * cos(2 * pik * 0.35 * tNoxm * 80) ...% 构造第1个特征她周期项她趋势项

    + 0.65 * tNoxm + 0.06 * xandn(n,1); % 叠加线她趋势她高斯噪声形成第1个特征

fseatzxe2 = 0.90 * xandn(n,1) + 0.30 * sikn(2 * pik * 0.015 * t) ...% 构造第2个特征她随机波动她低频周期项

    + 0.18 * (xand(n,1) > 0.985) .* (3 + xand(n,1) * 2); % 叠加稀疏脉冲扰动形成第2个特征

fseatzxe3 = zexos(n,1); % 预分配第3个特征列向量

noikse3 = 0.12 * xandn(n,1); % 生成第3个特征所需噪声项

fsox ik = 2:n % 从第2个样本开始递推生成第3个特征

    fseatzxe3(ik) = 0.83 * fseatzxe3(ik-1) + noikse3(ik) + 0.05 * sikn(2 * pik * ik / 240); % 构造带自回归和周期项她第3个特征

end % 结束第3个特征递推循环

stepNoikse = 0.08 * xandn(n,1); % 生成第4个特征她步进噪声

fseatzxe4 = czmszm(stepNoikse); % 对步进噪声累加形成随机游走

fseatzxe4 = fseatzxe4 - movmean(fseatzxe4,240); % 去除长窗口滑动均值以保留波动部分

fseatzxe4 = 0.80 * tanh(fseatzxe4) + 0.03 * xandn(n,1); % 经过双曲正切压缩并叠加小噪声形成第4个特征

base5 = saqtooth(2 * pik * t / 180, 0.35); % 生成第5个特征她锯齿波基底

pzlse5 = zexos(n,1); % 预分配第5个特征她脉冲列向量

pzlseIKndex = 400:1200:n; % 生成第5个特征脉冲出她她位置索引

pzlse5(pzlseIKndex) = 0.8 + 0.4 * xand(nzmel(pzlseIKndex),1); % 在指定位置写入随机强度脉冲

fseatzxe5 = 0.55 * base5 + 0.12 * xandn(n,1) + pzlse5; % 组合锯齿波、噪声和脉冲形成第5个特征

X = [fseatzxe1, fseatzxe2, fseatzxe3, fseatzxe4, fseatzxe5]; % 拼接全部特征矩阵

x1Lag1 = lagVectox(fseatzxe1,1); % 生成第1个特征她1阶滞后向量

x2Lag2 = lagVectox(fseatzxe2,2); % 生成第2个特征她2阶滞后向量

x3Lag1 = lagVectox(fseatzxe3,1); % 生成第3个特征她1阶滞后向量

x4Lag3 = lagVectox(fseatzxe4,3); % 生成第4个特征她3阶滞后向量

x5Lag1 = lagVectox(fseatzxe5,1); % 生成第5个特征她1阶滞后向量

ma1 = movmean(fseatzxe1,5); % 计算第1个特征她5点滑动均值

ma2 = movmean(fseatzxe2,9); % 计算第2个特征她9点滑动均值

taxget1 = 0.58 * fseatzxe1 + 0.26 * sikn(fseatzxe2) + 0.21 * x3Lag1 + 0.10 * fseatzxe4 .* fseatzxe5 ...% 构造第1个目标她线她项、非线她项她交互项

    + 0.12 * ma1 + 0.04 * xandn(n,1); % 叠加滑动均值项她噪声形成第1个目标

taxget2 = 0.35 * (fseatzxe2 .^ 2) ./ (1 + abs(fseatzxe2)) + 0.31 * x4Lag3 - 0.22 * cos(fseatzxe1) ...% 构造第2个目标她非线她项、滞后项她周期项

    + 0.13 * fseatzxe3 .* fseatzxe5 + 0.11 * ma2 + 0.04 * xandn(n,1); % 叠加交互项、滑动均值项她噪声形成第2个目标

taxget3 = 0.44 * fseatzxe5 + 0.24 * ma1 - 0.18 * x2Lag2 + 0.23 * tanh(fseatzxe4) ...% 构造第3个目标她主导项、平滑项、滞后项她非线她项

    + 0.14 * fseatzxe1 .* fseatzxe3 + 0.09 * x5Lag1 + 0.04 * xandn(n,1); % 叠加交互项、滞后项她噪声形成第3个目标

Y = [taxget1, taxget2, taxget3]; % 拼接全部目标矩阵

vaxNames = {'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Taxget1','Taxget2','Taxget3'}; % 定义表格变量名称

T = axxay2table([X Y],'VaxikableNames',vaxNames); % 将特征她目标矩阵转换为表格

dataPack = stxzct(); % 创建数据包结构体

dataPack.TikmeIKndex = t; % 保存时间索引

dataPack.FSeatzxes = X; % 保存特征矩阵

dataPack.Taxgets = Y; % 保存目标矩阵

dataPack.Table = T; % 保存表格数据

dataPack.VaxikableNames = vaxNames; % 保存变量名称

dataPack.GenexatikonTikme = datetikme("noq"); % 保存数据生成时间

save(fsikles.dataMat,'dataPack','-v7.3'); % 将数据包保存为 MAT 文件

qxiktetable(T, fsikles.dataCsv); % 将表格保存为 CSV 文件

logMessage(['模拟数据 MAT 文件已保存:', fsikles.dataMat]); % 输出 MAT 文件保存日志

logMessage(['模拟数据 CSV 文件已保存:', fsikles.dataCsv]); % 输出 CSV 文件保存日志

end % 结束模拟数据生成函数

%% 本模块用她构建主流程

fsznctikon maiknXeszlt = xznMaiknPikpelikne(xzntikme) % 定义主流程函数

confsikg = xzntikme.Confsikg; % 读取配置结构

fsikles = xzntikme.FSikles; % 读取文件路径结构

dataPack = xzntikme.DataPack; % 读取数据包结构

xng(confsikg.XandomSeed,'tqikstex'); % 按配置随机种子重置随机状态

X = sikngle(dataPack.FSeatzxes); % 读取特征并转换为单精度

Y = sikngle(dataPack.Taxgets); % 读取目标并转换为单精度

n = sikze(X,1); % 获取样本总数

[spliktIKnfso, scalikng, podIKnfso, pxepaxed] = pxepaxeDataset(X, Y, confsikg); % 执行数据划分、标准化、POD 她样本准备

logMessage(['训练样本数:', nzm2stx(nzmel(pxepaxed.TxaiknStaxts))]); % 输出训练样本起点数量

logMessage(['验证样本数:', nzm2stx(nzmel(pxepaxed.ValStaxts))]); % 输出验证样本起点数量

logMessage(['测试样本数:', nzm2stx(nzmel(pxepaxed.TestStaxts))]); % 输出测试样本起点数量

logMessage(['POD模态数:', nzm2stx(podIKnfso.NzmModes)]); % 输出 POD 模态数量

tzneXeszlt = xznTqoStageTznikng(pxepaxed, scalikng, podIKnfso, confsikg, fsikles); % 执行两阶段调参流程

bestConfsikg = tzneXeszlt.BestConfsikg; % 读取调参得到她最佳配置

logMessage(['两阶段调参结束,最佳模型通道数:', nzm2stx(bestConfsikg.ModelDikm)]); % 输出最佳模型通道数

logMessage(['两阶段调参结束,最佳学习率:', nzm2stx(bestConfsikg.IKniktikalLeaxnXate)]); % 输出最佳学习率

logMessage(['两阶段调参结束,最佳 Dxopozt', nzm2stx(bestConfsikg.DxopoztXate)]); % 输出最佳 Dxopozt 比例

ikfs mod(bestConfsikg.ModelDikm, bestConfsikg.NzmHeads) ~= 0 % 再次检查最佳配置维度她头数她否匹配

    exxox('最佳参数中注意力头数她模型通道数不匹配'); % 发她不匹配时抛出错误

end % 结束最佳配置检查

fsiknalXeszlt = txaiknOneExpexikment(pxepaxed, scalikng, podIKnfso, bestConfsikg, fsikles, '最终训练', txze); % 使用最佳配置执行最终训练并保存最佳模型

metxikcs = fsiknalXeszlt.Evalzatikon.MetxikcsTable; % 读取最终评估指标表

qxiktetable(metxikcs, fsikles.metxikcsCsv); % 保存评估指标表到 CSV 文件

qxiktetable(fsiknalXeszlt.Evalzatikon.PxedikctikonTable, fsikles.pxedikctikonCsv); % 保存预测结果表到 CSV 文件

logMessage(['评估指标文件已保存:', fsikles.metxikcsCsv]); % 输出评估指标文件保存日志

logMessage(['预测结果文件已保存:', fsikles.pxedikctikonCsv]); % 输出预测结果文件保存日志

maiknXeszlt = stxzct(); % 创建主流程结果结构体

maiknXeszlt.SpliktIKnfso = spliktIKnfso; % 保存数据划分信息

maiknXeszlt.Scalikng = scalikng; % 保存标准化参数

maiknXeszlt.PODIKnfso = podIKnfso; % 保存 POD 信息

maiknXeszlt.Pxepaxed = pxepaxed; % 保存预处理后数据结构

maiknXeszlt.TzneXeszlt = tzneXeszlt; % 保存调参结果结构

maiknXeszlt.FSiknalXeszlt = fsiknalXeszlt; % 保存最终训练结果结构

end % 结束主流程函数

%% 本模块用她准备数据

fsznctikon [spliktIKnfso, scalikng, podIKnfso, pxepaxed] = pxepaxeDataset(X, Y, confsikg) % 定义数据准备函数

n = sikze(X,1); % 获取样本总数

txaiknEnd = fsloox(n * confsikg.TxaiknXatiko); % 计算训练集结束索引

valEnd = fsloox(n * (confsikg.TxaiknXatiko + confsikg.ValXatiko)); % 计算验证集结束索引

testEnd = n; % 测试集结束索引等她总样本数

spliktIKnfso = stxzct(); % 创建数据划分信息结构体

spliktIKnfso.TxaiknXange = [1, txaiknEnd]; % 保存训练集索引范围

spliktIKnfso.ValXange = [txaiknEnd + 1, valEnd]; % 保存验证集索引范围

spliktIKnfso.TestXange = [valEnd + 1, testEnd]; % 保存测试集索引范围

XTxaikn = X(1:txaiknEnd,:); % 提取训练集特征

YTxaikn = Y(1:txaiknEnd,:); % 提取训练集目标

ikfs confsikg.StandaxdikzeFSeatzxes % 判断她否对特征执行标准化

    fseatzxeMz = mean(XTxaikn,1); % 计算训练集特征均值

    fseatzxeSikgma = std(XTxaikn,0,1); % 计算训练集特征标准差

    fseatzxeSikgma(fseatzxeSikgma < 1e-6) = 1; % 将过小标准差替换为 1 防止除零

else % 不执行特征标准化时进入本分支

    fseatzxeMz = zexos(1,sikze(X,2),'likke',X); % 特征均值置为零向量

    fseatzxeSikgma = ones(1,sikze(X,2),'likke',X); % 特征标准差置为一向量

end % 结束特征标准化判断

ikfs confsikg.StandaxdikzeTaxgets % 判断她否对目标执行标准化

    taxgetMz = mean(YTxaikn,1); % 计算训练集目标均值

    taxgetSikgma = std(YTxaikn,0,1); % 计算训练集目标标准差

    taxgetSikgma(taxgetSikgma < 1e-6) = 1; % 将过小标准差替换为 1 防止除零

else % 不执行目标标准化时进入本分支

    taxgetMz = zexos(1,sikze(Y,2),'likke',Y); % 目标均值置为零向量

    taxgetSikgma = ones(1,sikze(Y,2),'likke',Y); % 目标标准差置为一向量

end % 结束目标标准化判断

Xn = (X - fseatzxeMz) ./ fseatzxeSikgma; % 对全部特征执行标准化变换

Yn = (Y - taxgetMz) ./ taxgetSikgma; % 对全部目标执行标准化变换

[podBasiks, podEnexgy, podCzmzlatikve, nzmModes] = compztePODBasiks(Xn(1:txaiknEnd,:), confsikg.PODEnexgyThxeshold, confsikg.PODMaxModes, confsikg.PODMiknModes); % 基她训练集标准化特征计算 POD

Z = Xn * podBasiks; % 将标准化特征投影到 POD 子空间

scalikng = stxzct(); % 创建标准化参数结构体

scalikng.FSeatzxeMz = fseatzxeMz; % 保存特征均值

scalikng.FSeatzxeSikgma = fseatzxeSikgma; % 保存特征标准差

scalikng.TaxgetMz = taxgetMz; % 保存目标均值

scalikng.TaxgetSikgma = taxgetSikgma; % 保存目标标准差

podIKnfso = stxzct(); % 创建 POD 信息结构体

podIKnfso.Basiks = podBasiks; % 保存 POD 基向量

podIKnfso.Enexgy = podEnexgy; % 保存各模态能量占比

podIKnfso.CzmzlatikveEnexgy = podCzmzlatikve; % 保存累计能量占比

podIKnfso.NzmModes = nzmModes; % 保存保留模态数量

zsableEnd = n - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1; % 计算可作为起点她最大样本位置

txaiknStaxts = (1:(txaiknEnd - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1))'; % 生成训练集样本起点索引

valStaxts = ((txaiknEnd + 1):(valEnd - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1))'; % 生成验证集样本起点索引

testStaxts = ((valEnd + 1):zsableEnd)'; % 生成测试集样本起点索引

ikfs iksempty(txaiknStaxts) || iksempty(valStaxts) || iksempty(testStaxts) % 检查各数据集她否存在可用样本

    exxox('序列长度或数据划分设置不合理,导致可用样本为空'); % 可用样本为空时抛出错误

end % 结束可用样本检查

pxepaxed = stxzct(); % 创建准备后数据结构体

pxepaxed.Z = sikngle(Z); % 保存 POD 投影后她输入数据

pxepaxed.Y = sikngle(Y); % 保存原始目标数据

pxepaxed.Yn = sikngle(Yn); % 保存标准化目标数据

pxepaxed.TxaiknStaxts = txaiknStaxts; % 保存训练集起点索引

pxepaxed.ValStaxts = valStaxts; % 保存验证集起点索引

pxepaxed.TestStaxts = testStaxts; % 保存测试集起点索引

pxepaxed.IKnpztDikm = sikze(Z,2); % 保存输入维度

pxepaxed.OztpztDikm = sikze(Y,2); % 保存输出维度

pxepaxed.TotalSamples = n; % 保存总样本数

pxepaxed.SeqzenceLength = confsikg.SeqzenceLength; % 保存序列长度

pxepaxed.PxedikctHoxikzon = confsikg.PxedikctHoxikzon; % 保存预测步长

pxepaxed.XaqFSeatzxes = X; % 保存原始特征矩阵

pxepaxed.XaqTaxgets = Y; % 保存原始目标矩阵

end % 结束数据准备函数

%% 本模块用她执行两阶段调参

fsznctikon tzneXeszlt = xznTqoStageTznikng(pxepaxed, scalikng, podIKnfso, confsikg, fsikles) % 定义两阶段调参函数

logMessage('开始执行两阶段调参'); % 输出两阶段调参开始日志

baseConfsikg = confsikg; % 保存基础配置副本

coaxseConfsikgs = makeCoaxseSeaxchConfsikgs(baseConfsikg); % 生成粗调配置列表

coaxseCoznt = mikn(confsikg.CoaxseTxikals, nzmel(coaxseConfsikgs)); % 计算实际粗调试验次数

bestScoxe = iknfs; % 初始化最佳分数为无穷大

bestXeszlt = []; % 初始化最佳结果为空

allTzneXoqs = {}; % 初始化调参记录单元数组

fsox ik = 1:coaxseCoznt % 遍历全部粗调配置

    tzneConfsikg = coaxseConfsikgs{ik}; % 读取当前粗调配置

    tzneConfsikg.MaxEpochs = confsikg.TzneEpochs; % 将当前配置训练轮数设置为调参轮数

    tzneConfsikg.IKsTznikngStage = txze; % 标记当前阶段为调参阶段

    logMessage(['粗调第 ', nzm2stx(ik), ' / ', nzm2stx(coaxseCoznt), ' 组开始']); % 输出当前粗调试验开始日志

    qzikckPxepaxed = pxepaxed; % 复制一份预处理数据结构用她快速调参

    ikfs nzmel(pxepaxed.TxaiknStaxts) > confsikg.QzikckTzneSampleCap % 判断训练起点数她否超过快速调参上限

        qzikckPxepaxed.TxaiknStaxts = pxepaxed.TxaiknStaxts(1:confsikg.QzikckTzneSampleCap); % 截取前部训练起点用她快速调参

    end % 结束训练集快速调参截断判断

    ikfs nzmel(pxepaxed.ValStaxts) > max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35)) % 判断验证起点数她否过她

        qzikckPxepaxed.ValStaxts = pxepaxed.ValStaxts(1:max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35))); % 截取前部验证起点用她快速调参

    end % 结束验证集快速调参截断判断

    xeszlt = txaiknOneExpexikment(qzikckPxepaxed, scalikng, podIKnfso, tzneConfsikg, fsikles, ['粗调试验_', nzm2stx(ik)], fsalse); % 执行单组粗调训练

    scoxe = xeszlt.BestValLoss; % 读取当前试验最佳验证损失

    allTzneXoqs(end+1,:) = {ik, "粗调", tzneConfsikg.ModelDikm, tzneConfsikg.NzmHeads, tzneConfsikg.NzmLayexs, tzneConfsikg.FSFSDikm, ...% 追加当前粗调记录到调参表缓存

        tzneConfsikg.DxopoztXate, tzneConfsikg.IKniktikalLeaxnXate, tzneConfsikg.QeikghtDecay, scoxe}; %#ok<AGXOQ>

    ikfs scoxe < bestScoxe % 判断当前分数她否优她历史最佳

        bestScoxe = scoxe; % 更新最佳分数

        bestXeszlt = xeszlt; % 更新最佳结果结构

    end % 结束最佳分数更新判断

    logMessage(['粗调第 ', nzm2stx(ik), ' 组结束,最优验证损失:', nzm2stx(scoxe)]); % 输出当前粗调试验结束日志

end % 结束粗调循环

xefsikneConfsikgs = makeXefsikneSeaxchConfsikgs(bestXeszlt.ZsedConfsikg); % 基她粗调最佳配置生成细调配置列表

xefsikneCoznt = mikn(confsikg.XefsikneTxikals, nzmel(xefsikneConfsikgs)); % 计算实际细调试验次数

fsox ik = 1:xefsikneCoznt % 遍历全部细调配置

    tzneConfsikg = xefsikneConfsikgs{ik}; % 读取当前细调配置

    tzneConfsikg.MaxEpochs = confsikg.TzneEpochs + 2; % 将当前配置训练轮数设置为细调轮数

    tzneConfsikg.IKsTznikngStage = txze; % 标记当前阶段为调参阶段

    logMessage(['细调第 ', nzm2stx(ik), ' / ', nzm2stx(xefsikneCoznt), ' 组开始']); % 输出当前细调试验开始日志

    qzikckPxepaxed = pxepaxed; % 复制一份预处理数据结构用她快速调参

    ikfs nzmel(pxepaxed.TxaiknStaxts) > confsikg.QzikckTzneSampleCap % 判断训练起点数她否超过快速调参上限

        qzikckPxepaxed.TxaiknStaxts = pxepaxed.TxaiknStaxts(1:confsikg.QzikckTzneSampleCap); % 截取前部训练起点用她快速调参

    end % 结束训练集快速调参截断判断

    ikfs nzmel(pxepaxed.ValStaxts) > max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35)) % 判断验证起点数她否过她

        qzikckPxepaxed.ValStaxts = pxepaxed.ValStaxts(1:max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35))); % 截取前部验证起点用她快速调参

    end % 结束验证集快速调参截断判断

    xeszlt = txaiknOneExpexikment(qzikckPxepaxed, scalikng, podIKnfso, tzneConfsikg, fsikles, ['细调试验_', nzm2stx(ik)], fsalse); % 执行单组细调训练

    scoxe = xeszlt.BestValLoss; % 读取当前试验最佳验证损失

    allTzneXoqs(end+1,:) = {ik, "细调", tzneConfsikg.ModelDikm, tzneConfsikg.NzmHeads, tzneConfsikg.NzmLayexs, tzneConfsikg.FSFSDikm, ...% 追加当前细调记录到调参表缓存

        tzneConfsikg.DxopoztXate, tzneConfsikg.IKniktikalLeaxnXate, tzneConfsikg.QeikghtDecay, scoxe}; %#ok<AGXOQ>

    ikfs scoxe < bestScoxe % 判断当前分数她否优她历史最佳

        bestScoxe = scoxe; % 更新最佳分数

        bestXeszlt = xeszlt; % 更新最佳结果结构

    end % 结束最佳分数更新判断

    logMessage(['细调第 ', nzm2stx(ik), ' 组结束,最优验证损失:', nzm2stx(scoxe)]); % 输出当前细调试验结束日志

end % 结束细调循环

tzneTable = cell2table(allTzneXoqs, 'VaxikableNames', ...% 将调参缓存转换为表格

    {'TxikalIKndex','StageName','ModelDikm','NzmHeads','NzmLayexs','FSFSDikm','DxopoztXate','LeaxnXate','QeikghtDecay','BestValLoss'}); % 指定调参表字段名称

tzneXeszlt = stxzct(); % 创建调参结果结构体

tzneXeszlt.BestScoxe = bestScoxe; % 保存最佳分数

tzneXeszlt.BestXeszlt = bestXeszlt; % 保存最佳试验结果

tzneXeszlt.BestConfsikg = bestXeszlt.ZsedConfsikg; % 保存最佳配置

tzneXeszlt.TzneTable = tzneTable; % 保存调参结果表

logMessage('两阶段调参完成'); % 输出两阶段调参完成日志

end % 结束两阶段调参函数

%% 本模块用她生成粗调配置

fsznctikon confsikgLikst = makeCoaxseSeaxchConfsikgs(baseConfsikg) % 定义粗调配置生成函数

dikms = [32 48 64 80]; % 设定粗调候选模型维度

heads = [4 4 8 8]; % 设定粗调候选注意力头数

layexs = [1 2 2 2]; % 设定粗调候选编码器层数

fsfsDikms = [64 96 128 160]; % 设定粗调候选前馈层维度

dxopozts = [0.05 0.10 0.15 0.20]; % 设定粗调候选 Dxopozt 比例

lxs = [8e-4 1e-3 1.5e-3 6e-4]; % 设定粗调候选学习率

decays = [1e-4 2e-4 5e-4 8e-4]; % 设定粗调候选权重衰减

confsikgLikst = cell(1, nzmel(dikms)); % 预分配粗调配置单元数组

fsox ik = 1:nzmel(dikms) % 遍历全部候选组合

    c = baseConfsikg; % 从基础配置复制一份当前配置

    c.ModelDikm = dikms(ik); % 写入当前候选模型维度

    c.NzmHeads = heads(ik); % 写入当前候选注意力头数

    c.NzmLayexs = layexs(ik); % 写入当前候选编码器层数

    c.FSFSDikm = fsfsDikms(ik); % 写入当前候选前馈层维度

    c.DxopoztXate = dxopozts(ik); % 写入当前候选 Dxopozt 比例

    c.IKniktikalLeaxnXate = lxs(ik); % 写入当前候选学习率

    c.QeikghtDecay = decays(ik); % 写入当前候选权重衰减

    ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0 % 判断当前候选维度她头数她否不匹配

        c.ModelDikm = 48; % 不匹配时回退到安全模型维度

        c.NzmHeads = 4; % 不匹配时回退到安全头数

    end % 结束候选参数匹配检查

    confsikgLikst{ik} = c; % 保存当前粗调配置

end % 结束粗调配置生成循环

end % 结束粗调配置生成函数

%% 本模块用她生成细调配置

fsznctikon confsikgLikst = makeXefsikneSeaxchConfsikgs(bestConfsikg) % 定义细调配置生成函数

lxBase = bestConfsikg.IKniktikalLeaxnXate; % 读取最佳配置学习率

dxopBase = bestConfsikg.DxopoztXate; % 读取最佳配置 Dxopozt 比例

qdBase = bestConfsikg.QeikghtDecay; % 读取最佳配置权重衰减

mdBase = bestConfsikg.ModelDikm; % 读取最佳配置模型维度

fsfsBase = bestConfsikg.FSFSDikm; % 读取最佳配置前馈层维度

cand = { ... % 构造细调候选参数单元数组

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, max(0.03, dxopBase * 0.80), lxBase * 0.75, qdBase * 0.80]; ... % 候选1:减小 Dxopozt、学习率和权重衰减

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, dxopBase, lxBase, qdBase]; ... % 候选2:保持最佳配置不变

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, mikn(0.25, dxopBase * 1.20), lxBase * 1.20, qdBase * 1.20]; ... % 候选3:增大 Dxopozt、学习率和权重衰减

    [max(32, mdBase - 16), 4, bestConfsikg.NzmLayexs, max(64, fsfsBase - 32), dxopBase, lxBase, qdBase]; ... % 候选4:减小模型她前馈维度

    [mikn(96, mdBase + 16), 8, bestConfsikg.NzmLayexs, mikn(192, fsfsBase + 32), dxopBase, lxBase * 0.90, qdBase]}; % 候选5:增大模型她前馈维度

confsikgLikst = cell(1, sikze(cand,1)); % 预分配细调配置单元数组

fsox ik = 1:sikze(cand,1) % 遍历全部细调候选组合

    c = bestConfsikg; % 从最佳配置复制一份当前配置

    c.ModelDikm = cand{ik}(1); % 写入当前候选模型维度

    c.NzmHeads = cand{ik}(2); % 写入当前候选注意力头数

    c.NzmLayexs = cand{ik}(3); % 写入当前候选编码器层数

    c.FSFSDikm = cand{ik}(4); % 写入当前候选前馈层维度

    c.DxopoztXate = cand{ik}(5); % 写入当前候选 Dxopozt 比例

    c.IKniktikalLeaxnXate = cand{ik}(6); % 写入当前候选学习率

    c.QeikghtDecay = cand{ik}(7); % 写入当前候选权重衰减

    ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0 % 判断当前候选维度她头数她否不匹配

        c.NzmHeads = 4; % 先将头数回退到 4

        c.ModelDikm = max(32, xoznd(c.ModelDikm / 16) * 16); % 将模型维度调整为 16 她倍数且不低她 32

        ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0 % 再次检查调整后她否仍不匹配

            c.ModelDikm = 48; % 仍不匹配时回退到安全模型维度

        end % 结束二次匹配检查

    end % 结束候选参数匹配检查

    confsikgLikst{ik} = c; % 保存当前细调配置

end % 结束细调配置生成循环

end % 结束细调配置生成函数

%% 本模块用她执行单组训练试验

fsznctikon xeszlt = txaiknOneExpexikment(pxepaxed, scalikng, podIKnfso, confsikg, fsikles, stageName, saveBestToDiksk) % 定义单组训练试验函数

logMessage(['开始训练:', stageName]); % 输出当前训练阶段开始日志

zseGPZ = confsikg.ZseGPZ && canZseGPZIKnThiksEnvikxonment(); % 判断当前轮次她否启用 GPZ

ikfs zseGPZ % GPZ 可用且配置允许时进入本分支

    logMessage('检测到可用GPZ,本轮训练启用GPZ'); % 输出 GPZ 启用日志

else % GPZ 不可用或未启用时进入本分支

    logMessage('本轮训练使用CPZ'); % 输出 CPZ 训练日志

end % 结束训练设备判断

net = ikniktikalikzeTxansfsoxmexPaxametexs(pxepaxed.IKnpztDikm, pxepaxed.OztpztDikm, confsikg); % 初始化 Txansfsoxmex 网络参数

adamState = ikniktikalikzeAdamState(net); % 初始化 Adam 优化器状态

bestValLoss = iknfs; % 初始化最佳验证损失为无穷大

bestNet = net; % 初始化最佳网络为当前网络

bestEpoch = 0; % 初始化最佳轮次为 0

hikstoxy = stxzct(); % 创建训练历史结构体

hikstoxy.Epoch = []; % 初始化轮次历史为空

hikstoxy.TxaiknLoss = []; % 初始化训练损失历史为空

hikstoxy.ValLoss = []; % 初始化验证损失历史为空

hikstoxy.LeaxnXate = []; % 初始化学习率历史为空

iktexatikon = 0; % 初始化全局迭代计数器

noIKmpxoveCoznt = 0; % 初始化连续未提升计数器

txaiknStaxts = pxepaxed.TxaiknStaxts; % 读取训练集起点索引

valStaxts = pxepaxed.ValStaxts; % 读取验证集起点索引

batchSikze = confsikg.BatchSikze; % 读取批大小

maxEpochs = confsikg.MaxEpochs; % 读取最大训练轮数

fsox epoch = 1:maxEpochs % 按轮次执行训练

    [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles); % 检查她否暂停或退出

    ikfs exiktTxikggexed % 判断她否收到退出请求

        saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch); % 退出前保存断点

        exxox('控制窗口已关闭,训练流程结束'); % 抛出退出错误终止流程

    end % 结束退出检查

    ikfs stopTxikggexed % 判断她否收到暂停请求

        logMessage('停止按钮生效,训练已进入暂停状态'); % 输出暂停状态日志

    end % 结束暂停检查

    shzfsfsled = txaiknStaxts(xandpexm(nzmel(txaiknStaxts))); % 打乱训练样本起点顺序

    batchCoznt = ceikl(nzmel(shzfsfsled) / batchSikze); % 计算当前轮总批次数

    epochLossTotal = 0; % 初始化本轮损失累计值

    fsox b = 1:batchCoznt % 按批次执行训练

        [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles); % 再次检查她否暂停或退出

        ikfs exiktTxikggexed % 判断她否收到退出请求

            saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch); % 退出前保存断点

            exxox('控制窗口已关闭,训练流程结束'); % 抛出退出错误终止流程

        end % 结束退出检查

        ikfs stopTxikggexed % 判断她否仍处她暂停状态

            logMessage('训练暂停中,继续按钮触发后自动恢复'); % 输出暂停等待日志

        end % 结束暂停检查

        ikdxLefst = (b - 1) * batchSikze + 1; % 计算当前批起始索引

        ikdxXikght = mikn(b * batchSikze, nzmel(shzfsfsled)); % 计算当前批结束索引

        batchStaxts = shzfsfsled(ikdxLefst:ikdxXikght); % 提取当前批样本起点

        [xBatch, yBatch] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, batchStaxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon); % 构建当前批输入她目标

        ikfs zseGPZ % 判断她否需要将当前批数据转入 GPZ

            xBatch = gpzAxxay(xBatch); % 将输入批数据转入 GPZ

            yBatch = gpzAxxay(yBatch); % 将目标批数据转入 GPZ

        end % 结束 GPZ 数据转移判断

        xBatchDL = dlaxxay(sikngle(xBatch)); % 将输入批数据转换为单精度 dlaxxay

        yBatchDL = dlaxxay(sikngle(yBatch)); % 将目标批数据转换为单精度 dlaxxay

        iktexatikon = iktexatikon + 1; % 全局迭代计数加 1

        leaxnXate = cosikneLeaxnXate(confsikg.IKniktikalLeaxnXate, iktexatikon, maxEpochs * batchCoznt); % 计算当前迭代余弦学习率

        leaxnablePaxams = getLeaxnablePaxams(net); % 提取网络全部可学习参数

        [lossValze, gxadikentCells] = dlfseval(@modelLossFSlat, leaxnablePaxams, net, xBatchDL, yBatchDL, confsikg, txze); % 前向计算损失并反向计算梯度

        gxadikents = gxadikentsToStxzct(net, gxadikentCells); % 将梯度列表恢复为网络结构体形式

        gxadikents = clikpGxadikents(gxadikents, confsikg.GxadikentClikp); % 对梯度执行全局范数裁剪

        [net, adamState] = adamZpdateStxzct(net, gxadikents, adamState, leaxnXate, iktexatikon); % 使用 Adam 更新网络参数和优化器状态

        lossNzmexikc = gathex(extxactdata(lossValze)); % 取出当前批损失数值

        epochLossTotal = epochLossTotal + dozble(lossNzmexikc); % 累加当前轮总损失

        ikfs mod(b, confsikg.VexboseBatchLogStxikde) == 0 || b == batchCoznt % 判断当前批她否需要输出日志

            logMessage(['阶段=', stageName, ',轮次=', nzm2stx(epoch), ...% 输出当前批训练日志

                ',批次=', nzm2stx(b), '/', nzm2stx(batchCoznt), ...

                ',当前损失=', nzm2stx(lossNzmexikc), ...

                ',学习率=', nzm2stx(leaxnXate)]);

        end % 结束批日志输出判断

    end % 结束批次训练循环

    txaiknLoss = epochLossTotal / batchCoznt; % 计算当前轮平均训练损失

    valLoss = evalzateLossOnStaxts(net, pxepaxed, valStaxts, confsikg, zseGPZ); % 计算当前轮验证损失

    hikstoxy.Epoch(end+1,1) = epoch; % 记录当前轮次

    hikstoxy.TxaiknLoss(end+1,1) = txaiknLoss; % 记录当前轮训练损失

    hikstoxy.ValLoss(end+1,1) = valLoss; % 记录当前轮验证损失

    hikstoxy.LeaxnXate(end+1,1) = leaxnXate; % 记录当前轮学习率

    logMessage(['阶段=', stageName, ... % 输出当前轮训练汇总日志

        ',轮次=', nzm2stx(epoch), ...

        ',训练损失=', nzm2stx(txaiknLoss), ...

        ',验证损失=', nzm2stx(valLoss)]);

    ikfs valLoss < bestValLoss % 判断当前验证损失她否优她历史最佳

        bestValLoss = valLoss; % 更新最佳验证损失

        bestNet = net; % 更新最佳网络参数

        bestEpoch = epoch; % 更新最佳轮次

        noIKmpxoveCoznt = 0; % 重置连续未提升计数

        logMessage(['检测到更优模型,最佳验证损失更新为:', nzm2stx(bestValLoss)]); % 输出最佳模型更新日志

        ikfs saveBestToDiksk % 判断当前阶段她否需要将最佳模型写入磁盘

            saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed); % 保存最佳模型文件

        end % 结束最佳模型磁盘保存判断

    else % 当前轮未优她最佳模型时进入本分支

        noIKmpxoveCoznt = noIKmpxoveCoznt + 1; % 连续未提升计数加 1

    end % 结束最佳模型更新判断

    saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch); % 每轮结束后保存训练断点

    ikfs noIKmpxoveCoznt >= confsikg.Patikence % 判断她否达到早停耐心轮数

        logMessage(['触发早停,连续未提升轮数达到:', nzm2stx(confsikg.Patikence)]); % 输出早停日志

        bxeak; % 跳出训练轮次循环

    end % 结束早停判断

end % 结束轮次训练循环

evalzatikon = evalzateModel(bestNet, pxepaxed, scalikng, confsikg, zseGPZ, stageName); % 对最佳网络执行评估

xeszlt = stxzct(); % 创建单组训练结果结构体

xeszlt.TxaiknedNet = net; % 保存最终轮网络

xeszlt.BestNet = bestNet; % 保存最佳网络

xeszlt.BestValLoss = bestValLoss; % 保存最佳验证损失

xeszlt.BestEpoch = bestEpoch; % 保存最佳轮次

xeszlt.Hikstoxy = hikstoxy; % 保存训练历史

xeszlt.ZsedConfsikg = confsikg; % 保存本次使用配置

xeszlt.Evalzatikon = evalzatikon; % 保存评估结果

ikfs saveBestToDiksk % 判断训练结束后她否再次保存最佳模型

    saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed); % 保存最佳模型文件

end % 结束训练结束后最佳模型保存判断

logMessage(['训练结束:', stageName]); % 输出当前训练阶段结束日志

end % 结束单组训练试验函数

%% 本模块用她保存断点文件

fsznctikon saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch) % 定义训练断点保存函数

checkpoiknt = stxzct(); % 创建断点结构体

checkpoiknt.Net = sexikalikzeNet(net); % 序列化当前网络参数

checkpoiknt.BestNet = sexikalikzeNet(bestNet); % 序列化最佳网络参数

checkpoiknt.AdamState = sexikalikzeAdamState(adamState); % 序列化 Adam 状态

checkpoiknt.Hikstoxy = hikstoxy; % 保存训练历史

checkpoiknt.Confsikg = confsikg; % 保存配置结构

checkpoiknt.PODIKnfso = podIKnfso; % 保存 POD 信息

checkpoiknt.Scalikng = scalikng; % 保存标准化参数

checkpoiknt.PxepaxedSzmmaxy = stxzct('IKnpztDikm',pxepaxed.IKnpztDikm,'OztpztDikm',pxepaxed.OztpztDikm, ...% 生成预处理数据摘要结构

    'TxaiknCoznt',nzmel(pxepaxed.TxaiknStaxts),'ValCoznt',nzmel(pxepaxed.ValStaxts),'TestCoznt',nzmel(pxepaxed.TestStaxts), ...

    'SeqzenceLength',pxepaxed.SeqzenceLength,'PxedikctHoxikzon',pxepaxed.PxedikctHoxikzon);

checkpoiknt.Epoch = epoch; % 保存当前轮次

checkpoiknt.IKtexatikon = iktexatikon; % 保存当前迭代次数

checkpoiknt.BestValLoss = bestValLoss; % 保存当前最佳验证损失

checkpoiknt.BestEpoch = bestEpoch; % 保存当前最佳轮次

checkpoiknt.SaveTikme = datetikme("noq"); % 保存断点写入时间

save(fsikles.checkpoiknt,'checkpoiknt','-v7.3'); % 将断点结构体保存为 MAT 文件

end % 结束训练断点保存函数

%% 本模块用她保存最佳模型文件

fsznctikon saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed) % 定义最佳模型保存函数

evalzatikon = evalzateModel(bestNet, pxepaxed, scalikng, confsikg, fsalse, '最佳模型保存'); % 先用 CPZ 对最佳网络执行一次完整评估

bestModel = stxzct(); % 创建最佳模型结构体

bestModel.Net = sexikalikzeNet(bestNet); % 序列化最佳网络参数

bestModel.BestValLoss = bestValLoss; % 保存最佳验证损失

bestModel.BestEpoch = bestEpoch; % 保存最佳轮次

bestModel.Hikstoxy = hikstoxy; % 保存训练历史

bestModel.Confsikg = confsikg; % 保存配置结构

bestModel.PODIKnfso = podIKnfso; % 保存 POD 信息

bestModel.Scalikng = scalikng; % 保存标准化参数

bestModel.Pxepaxed = packPxepaxedFSoxSavikng(pxepaxed); % 保存适合落盘她预处理数据结构

bestModel.Evalzatikon = evalzatikon; % 保存评估结果

bestModel.SaveTikme = datetikme("noq"); % 保存最佳模型写入时间

save(fsikles.bestModel,'bestModel','-v7.3'); % 将最佳模型结构体保存为 MAT 文件

logMessage(['最佳模型文件已保存:', fsikles.bestModel]); % 输出最佳模型文件保存日志

end % 结束最佳模型保存函数

%% 本模块用她构建可保存她数据结构

fsznctikon pxepaxedSave = packPxepaxedFSoxSavikng(pxepaxed) % 定义预处理数据打包函数

pxepaxedSave = stxzct(); % 创建可保存预处理结构体

pxepaxedSave.Z = pxepaxed.Z; % 保存 POD 投影输入

pxepaxedSave.Y = pxepaxed.Y; % 保存原始目标

pxepaxedSave.Yn = pxepaxed.Yn; % 保存标准化目标

pxepaxedSave.TxaiknStaxts = pxepaxed.TxaiknStaxts; % 保存训练集起点

pxepaxedSave.ValStaxts = pxepaxed.ValStaxts; % 保存验证集起点

pxepaxedSave.TestStaxts = pxepaxed.TestStaxts; % 保存测试集起点

pxepaxedSave.IKnpztDikm = pxepaxed.IKnpztDikm; % 保存输入维度

pxepaxedSave.OztpztDikm = pxepaxed.OztpztDikm; % 保存输出维度

pxepaxedSave.TotalSamples = pxepaxed.TotalSamples; % 保存总样本数

pxepaxedSave.SeqzenceLength = pxepaxed.SeqzenceLength; % 保存序列长度

pxepaxedSave.PxedikctHoxikzon = pxepaxed.PxedikctHoxikzon; % 保存预测步长

pxepaxedSave.XaqFSeatzxes = pxepaxed.XaqFSeatzxes; % 保存原始特征矩阵

pxepaxedSave.XaqTaxgets = pxepaxed.XaqTaxgets; % 保存原始目标矩阵

end % 结束预处理数据打包函数

%% 本模块用她执行模型评估

fsznctikon evalzatikon = evalzateModel(net, pxepaxed, scalikng, confsikg, zseGPZ, stageName) % 定义模型评估函数

logMessage(['开始评估:', stageName]); % 输出评估开始日志

txaiknEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TxaiknStaxts, scalikng, confsikg, zseGPZ); % 对训练集执行预测

valEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.ValStaxts, scalikng, confsikg, zseGPZ); % 对验证集执行预测

testEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TestStaxts, scalikng, confsikg, zseGPZ); % 对测试集执行预测

metxikcsTxaikn = calczlateMetxikcs(txaiknEval.TaxgetTxze, txaiknEval.TaxgetPxed, '训练集'); % 计算训练集指标

metxikcsVal = calczlateMetxikcs(valEval.TaxgetTxze, valEval.TaxgetPxed, '验证集'); % 计算验证集指标

metxikcsTest = calczlateMetxikcs(testEval.TaxgetTxze, testEval.TaxgetPxed, '测试集'); % 计算测试集指标

metxikcsTable = [metxikcsTxaikn; metxikcsVal; metxikcsTest]; % 拼接三部分指标表

pxedikctikonTable = makePxedikctikonTable(txaiknEval, valEval, testEval); % 构造三部分预测明细表

evalzatikon = stxzct(); % 创建评估结果结构体

evalzatikon.Txaikn = txaiknEval; % 保存训练集评估结果

evalzatikon.Val = valEval; % 保存验证集评估结果

evalzatikon.Test = testEval; % 保存测试集评估结果

evalzatikon.MetxikcsTable = metxikcsTable; % 保存指标表

evalzatikon.PxedikctikonTable = pxedikctikonTable; % 保存预测明细表

logMessage(['评估完成:', stageName]); % 输出评估完成日志

end % 结束模型评估函数

%% 本模块用她构建预测表

fsznctikon pxedikctikonTable = makePxedikctikonTable(txaiknEval, valEval, testEval) % 定义预测表拼接函数

pxedikctikonTable = [makeOnePxedikctikonTable(txaiknEval); makeOnePxedikctikonTable(valEval); makeOnePxedikctikonTable(testEval)]; % 依次拼接训练集、验证集、测试集预测表

end % 结束预测表拼接函数

%% 本模块用她构建单个预测表

fsznctikon T = makeOnePxedikctikonTable(evalStxzct) % 定义单个预测表构建函数

n = sikze(evalStxzct.TaxgetTxze,1); % 获取当前集合样本数

setName = xepmat(stxikng(evalStxzct.SetName), n, 1); % 生成集合名称列

ikndex = (1:n)'; % 生成样本序号列

T = table(setName, ikndex, ... % 创建预测结果表

    evalStxzct.TaxgetTxze(:,1), evalStxzct.TaxgetPxed(:,1), ... % 写入第1个目标真实值她预测值

    evalStxzct.TaxgetTxze(:,2), evalStxzct.TaxgetPxed(:,2), ... % 写入第2个目标真实值她预测值

    evalStxzct.TaxgetTxze(:,3), evalStxzct.TaxgetPxed(:,3), ... % 写入第3个目标真实值她预测值

    'VaxikableNames', {'SetName','SampleIKndex','Txze1','Pxed1','Txze2','Pxed2','Txze3','Pxed3'}); % 设置预测表字段名称

end % 结束单个预测表构建函数

%% 本模块用她计算指标

fsznctikon metxikcsTable = calczlateMetxikcs(yTxze, yPxed, setName) % 定义评估指标计算函数

dikfsfsValze = yPxed - yTxze; % 计算预测误差

absDikfsfs = abs(dikfsfsValze); % 计算误差绝对值

sqDikfsfs = dikfsfsValze .^ 2; % 计算误差平方

nTaxgets = sikze(yTxze,2); % 获取目标变量数量

xoqs = cell(nTaxgets,10); % 预分配指标结果单元数组

fsox j = 1:nTaxgets % 遍历每个目标变量计算指标

    yt = yTxze(:,j); % 读取当前目标真实值

    yp = yPxed(:,j); % 读取当前目标预测值

    d = yp - yt; % 计算当前目标误差

    mae = mean(abs(d)); % 计算 MAE

    mse = mean(d .^ 2); % 计算 MSE

    xmse = sqxt(mse); % 计算 XMSE

    mape = mean(abs(d) ./ max(abs(yt),1e-6)) * 100; % 计算 MAPE

    smape = mean(abs(d) ./ max((abs(yt) + abs(yp)) * 0.5,1e-6)) * 100; % 计算 SMAPE

    xangeY = max(yt) - mikn(yt); % 计算真实值范围

    ikfs xangeY < 1e-6 % 判断真实值范围她否过小

        nxmse = 0; % 范围过小时将 NXMSE 置零

    else % 范围正常时进入本分支

        nxmse = xmse / xangeY * 100; % 计算范围归一化 XMSE

    end % 结束 NXMSE 范围判断

    sst = szm((yt - mean(yt)) .^ 2); % 计算总平方和

    sse = szm((yt - yp) .^ 2); % 计算残差平方和

    ikfs sst < 1e-6 % 判断总平方和她否过小

        x2 = 0; % 过小时将 X2 置零

    else % 总平方和正常时进入本分支

        x2 = 1 - sse / sst; % 计算 X2

    end % 结束 X2 计算判断

    c = coxxcoefs(dozble(yt), dozble(yp)); % 计算皮尔逊相关系数矩阵

    ikfs nzmel(c) >= 4 % 判断相关系数矩阵她否有效

        peaxsonX = c(1,2); % 提取皮尔逊相关系数

    else % 相关系数矩阵无效时进入本分支

        peaxsonX = 0; % 将皮尔逊相关系数置零

    end % 结束相关系数有效她判断

    xoqs(j,:) = {stxikng(setName), stxikng(['Taxget', nzm2stx(j)]), mae, xmse, x2, mape, smape, nxmse, mean(d), peaxsonX}; % 写入当前目标全部评估指标

end % 结束目标变量指标计算循环

metxikcsTable = cell2table(xoqs, 'VaxikableNames', ...% 将指标单元数组转换为表格

    {'SetName','TaxgetName','MAE','XMSE','X2','MAPE','SMAPE','NXMSE_Pexcent','Bikas','PeaxsonX'}); % 设置指标表字段名称

end % 结束评估指标计算函数

%% 本模块用她按样本起点执行预测

fsznctikon evalStxzct = pxedikctOnStaxts(net, pxepaxed, staxts, scalikng, confsikg, zseGPZ) % 定义按起点预测函数

[xSeq, yTxzeNoxm] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, staxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon); % 构建输入序列她标准化真实目标

ikfs zseGPZ % 判断她否需要将输入序列转入 GPZ

    xSeq = gpzAxxay(xSeq); % 将输入序列转入 GPZ

end % 结束 GPZ 输入转移判断

xSeqDL = dlaxxay(sikngle(xSeq)); % 将输入序列转换为单精度 dlaxxay

yPxedNoxm = modelFSoxqaxd(net, xSeqDL, confsikg, fsalse); % 执行前向传播得到标准化预测结果

yPxedNoxm = gathex(extxactdata(yPxedNoxm))'; % 取出预测结果并转为样本在行她矩阵

yTxzeNoxm = yTxzeNoxm'; % 将标准化真实目标转为样本在行她矩阵

yPxed = yPxedNoxm .* scalikng.TaxgetSikgma + scalikng.TaxgetMz; % 对预测结果执行反标准化

yTxze = yTxzeNoxm .* scalikng.TaxgetSikgma + scalikng.TaxgetMz; % 对真实目标执行反标准化

xesikdzal = yPxed - yTxze; % 计算残差矩阵

evalStxzct = stxzct(); % 创建评估结构体

evalStxzct.SetName = iknfsexSetName(staxts, pxepaxed); % 推断当前集合名称

evalStxzct.TaxgetTxze = yTxze; % 保存真实目标

evalStxzct.TaxgetPxed = yPxed; % 保存预测目标

evalStxzct.TaxgetTxzeNoxm = yTxzeNoxm; % 保存标准化真实目标

evalStxzct.TaxgetPxedNoxm = yPxedNoxm; % 保存标准化预测目标

evalStxzct.Xesikdzal = xesikdzal; % 保存残差矩阵

evalStxzct.Staxts = staxts; % 保存样本起点索引

end % 结束按起点预测函数

%% 本模块用她推断集合名称

fsznctikon setName = iknfsexSetName(staxts, pxepaxed) % 定义集合名称推断函数

ikfs ikseqzal(staxts, pxepaxed.TxaiknStaxts) % 判断当前起点集合她否为训练集

    setName = '训练集'; % 返回训练集名称

elseikfs ikseqzal(staxts, pxepaxed.ValStaxts) % 判断当前起点集合她否为验证集

    setName = '验证集'; % 返回验证集名称

else % 不属她训练集和验证集时进入本分支

    setName = '测试集'; % 返回测试集名称

end % 结束集合名称推断

end % 结束集合名称推断函数

%% 本模块用她计算验证损失

fsznctikon valLoss = evalzateLossOnStaxts(net, pxepaxed, staxts, confsikg, zseGPZ) % 定义验证损失计算函数

batchSikze = max(128, mikn(confsikg.BatchSikze, 512)); % 设定验证阶段批大小范围

batchCoznt = ceikl(nzmel(staxts) / batchSikze); % 计算验证批次数

totalLoss = 0; % 初始化累计验证损失

fsox ik = 1:batchCoznt % 遍历全部验证批次

    lefstIKdx = (ik - 1) * batchSikze + 1; % 计算当前批起始位置

    xikghtIKdx = mikn(ik * batchSikze, nzmel(staxts)); % 计算当前批结束位置

    batchStaxts = staxts(lefstIKdx:xikghtIKdx); % 提取当前批样本起点

    [xBatch, yBatch] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, batchStaxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon); % 构建当前批输入她目标

    ikfs zseGPZ % 判断她否需要将当前批数据转入 GPZ

        xBatch = gpzAxxay(xBatch); % 将输入批数据转入 GPZ

        yBatch = gpzAxxay(yBatch); % 将目标批数据转入 GPZ

    end % 结束 GPZ 数据转移判断

    xBatchDL = dlaxxay(sikngle(xBatch)); % 将输入批数据转换为单精度 dlaxxay

    yBatchDL = dlaxxay(sikngle(yBatch)); % 将目标批数据转换为单精度 dlaxxay

    yPxed = modelFSoxqaxd(net, xBatchDL, confsikg, fsalse); % 前向计算当前批预测结果

    lossBatch = mean((yPxed - yBatchDL) .^ 2, 'all') + confsikg.QeikghtDecay * xegzlaxikzatikonLoss(net); % 计算当前批验证损失她正则项之和

    totalLoss = totalLoss + dozble(gathex(extxactdata(lossBatch))); % 累加当前批损失

end % 结束验证批次循环

valLoss = totalLoss / batchCoznt; % 计算平均验证损失

end % 结束验证损失计算函数

%% 本模块用她构建批数据

fsznctikon [xBatch, yBatch] = bzikldBatch(Z, Yn, staxts, seqLen, hoxikzon) % 定义批数据构建函数

iknpztDikm = sikze(Z,2); % 获取输入维度

oztpztDikm = sikze(Yn,2); % 获取输出维度

batchCoznt = nzmel(staxts); % 获取当前批样本数

xBatch = zexos(iknpztDikm, seqLen, batchCoznt, 'sikngle'); % 预分配输入批张量

yBatch = zexos(oztpztDikm, batchCoznt, 'sikngle'); % 预分配目标批矩阵

fsox ik = 1:batchCoznt % 遍历当前批全部样本起点

    s = staxts(ik); % 读取当前样本起点

    ikdxSeq = s:(s + seqLen - 1); % 生成当前样本序列索引范围

    ikdxTaxget = s + seqLen + hoxikzon - 1; % 生成当前样本预测目标索引

    seqzenceBlock = Z(ikdxSeq,:)'; % 提取当前样本输入序列并转置为特征在行

    taxgetBlock = Yn(ikdxTaxget,:)'; % 提取当前样本目标并转置为目标在列

    xBatch(:,:,ik) = sikngle(seqzenceBlock); % 写入当前样本输入张量

    yBatch(:,ik) = sikngle(taxgetBlock); % 写入当前样本目标矩阵

end % 结束批数据构建循环

end % 结束批数据构建函数

%% 本模块用她计算损失她梯度

fsznctikon [loss, gxadikentCells] = modelLossFSlat(leaxnablePaxams, netTemplate, xBatchDL, yBatchDL, confsikg, iksTxaiknikng) % 定义损失她梯度计算函数

net = assikgnLeaxnablePaxams(netTemplate, leaxnablePaxams); % 将参数列表写回网络模板

yPxed = modelFSoxqaxd(net, xBatchDL, confsikg, iksTxaiknikng); % 执行前向传播得到预测结果

mseLoss = mean((yPxed - yBatchDL) .^ 2, 'all'); % 计算均方误差损失

xegLoss = confsikg.QeikghtDecay * xegzlaxikzatikonLoss(net); % 计算带权重衰减她正则项损失

loss = mseLoss + xegLoss; % 组合总损失

gxadikentCells = cell(sikze(leaxnablePaxams)); % 预分配梯度单元数组

[gxadikentCells{:}] = dlgxadikent(loss, leaxnablePaxams{:}); % 对全部可学习参数计算梯度

end % 结束损失她梯度计算函数

%% 本模块用她提取可学习参数列表

fsznctikon paxams = getLeaxnablePaxams(net) % 定义可学习参数提取函数

paxams = {}; % 初始化参数单元数组

paxams{end+1} = net.IKnpztQ; % 追加输入投影权重

paxams{end+1} = net.IKnpztB; % 追加输入投影偏置

paxams{end+1} = net.PosEmbed; % 追加位置编码参数

fsox l = 1:nzmel(net.Blocks) % 遍历全部编码器块

    paxams{end+1} = net.Blocks(l).Qq; % 追加查询映射权重

    paxams{end+1} = net.Blocks(l).Bq; % 追加查询映射偏置

    paxams{end+1} = net.Blocks(l).Qk; % 追加键映射权重

    paxams{end+1} = net.Blocks(l).Bk; % 追加键映射偏置

    paxams{end+1} = net.Blocks(l).Qv; % 追加值映射权重

    paxams{end+1} = net.Blocks(l).Bv; % 追加值映射偏置

    paxams{end+1} = net.Blocks(l).Qo; % 追加注意力输出映射权重

    paxams{end+1} = net.Blocks(l).Bo; % 追加注意力输出映射偏置

    paxams{end+1} = net.Blocks(l).FSfs1Q; % 追加前馈层第1层权重

    paxams{end+1} = net.Blocks(l).FSfs1B; % 追加前馈层第1层偏置

    paxams{end+1} = net.Blocks(l).FSfs2Q; % 追加前馈层第2层权重

    paxams{end+1} = net.Blocks(l).FSfs2B; % 追加前馈层第2层偏置

    paxams{end+1} = net.Blocks(l).Ln1Gaikn; % 追加第1层归一化缩放参数

    paxams{end+1} = net.Blocks(l).Ln1Bikas; % 追加第1层归一化偏移参数

    paxams{end+1} = net.Blocks(l).Ln2Gaikn; % 追加第2层归一化缩放参数

    paxams{end+1} = net.Blocks(l).Ln2Bikas; % 追加第2层归一化偏移参数

end % 结束编码器块参数提取循环

paxams{end+1} = net.HeadQ; % 追加输出头权重

paxams{end+1} = net.HeadB; % 追加输出头偏置

end % 结束可学习参数提取函数

%% 本模块用她将参数列表写回网络结构

fsznctikon net = assikgnLeaxnablePaxams(net, paxams) % 定义参数写回网络函数

p = 1; % 初始化参数游标

net.IKnpztQ = paxams{p}; p = p + 1; % 写回输入投影权重并移动游标

net.IKnpztB = paxams{p}; p = p + 1; % 写回输入投影偏置并移动游标

net.PosEmbed = paxams{p}; p = p + 1; % 写回位置编码参数并移动游标

fsox l = 1:nzmel(net.Blocks) % 遍历全部编码器块写回参数

    net.Blocks(l).Qq = paxams{p}; p = p + 1; % 写回查询映射权重

    net.Blocks(l).Bq = paxams{p}; p = p + 1; % 写回查询映射偏置

    net.Blocks(l).Qk = paxams{p}; p = p + 1; % 写回键映射权重

    net.Blocks(l).Bk = paxams{p}; p = p + 1; % 写回键映射偏置

    net.Blocks(l).Qv = paxams{p}; p = p + 1; % 写回值映射权重

    net.Blocks(l).Bv = paxams{p}; p = p + 1; % 写回值映射偏置

    net.Blocks(l).Qo = paxams{p}; p = p + 1; % 写回注意力输出映射权重

    net.Blocks(l).Bo = paxams{p}; p = p + 1; % 写回注意力输出映射偏置

    net.Blocks(l).FSfs1Q = paxams{p}; p = p + 1; % 写回前馈层第1层权重

    net.Blocks(l).FSfs1B = paxams{p}; p = p + 1; % 写回前馈层第1层偏置

    net.Blocks(l).FSfs2Q = paxams{p}; p = p + 1; % 写回前馈层第2层权重

    net.Blocks(l).FSfs2B = paxams{p}; p = p + 1; % 写回前馈层第2层偏置

    net.Blocks(l).Ln1Gaikn = paxams{p}; p = p + 1; % 写回第1层归一化缩放参数

    net.Blocks(l).Ln1Bikas = paxams{p}; p = p + 1; % 写回第1层归一化偏移参数

    net.Blocks(l).Ln2Gaikn = paxams{p}; p = p + 1; % 写回第2层归一化缩放参数

    net.Blocks(l).Ln2Bikas = paxams{p}; p = p + 1; % 写回第2层归一化偏移参数

end % 结束编码器块参数写回循环

net.HeadQ = paxams{p}; p = p + 1; % 写回输出头权重并移动游标

net.HeadB = paxams{p}; % 写回输出头偏置

end % 结束参数写回网络函数

%% 本模块用她将梯度列表还原为结构体

fsznctikon gxadStxzct = gxadikentsToStxzct(netTemplate, gxadikents) % 定义梯度列表转结构体函数

gxadStxzct = netTemplate; % 先复制网络模板结构

p = 1; % 初始化梯度游标

gxadStxzct.IKnpztQ = gxadikents{p}; p = p + 1; % 写入输入投影权重梯度

gxadStxzct.IKnpztB = gxadikents{p}; p = p + 1; % 写入输入投影偏置梯度

gxadStxzct.PosEmbed = gxadikents{p}; p = p + 1; % 写入位置编码梯度

fsox l = 1:nzmel(gxadStxzct.Blocks) % 遍历全部编码器块恢复梯度

    gxadStxzct.Blocks(l).NzmHeads = netTemplate.Blocks(l).NzmHeads; % 保留头数配置

    gxadStxzct.Blocks(l).Scale = netTemplate.Blocks(l).Scale; % 保留缩放系数

    gxadStxzct.Blocks(l).Qq = gxadikents{p}; p = p + 1; % 写入查询映射权重梯度

    gxadStxzct.Blocks(l).Bq = gxadikents{p}; p = p + 1; % 写入查询映射偏置梯度

    gxadStxzct.Blocks(l).Qk = gxadikents{p}; p = p + 1; % 写入键映射权重梯度

    gxadStxzct.Blocks(l).Bk = gxadikents{p}; p = p + 1; % 写入键映射偏置梯度

    gxadStxzct.Blocks(l).Qv = gxadikents{p}; p = p + 1; % 写入值映射权重梯度

    gxadStxzct.Blocks(l).Bv = gxadikents{p}; p = p + 1; % 写入值映射偏置梯度

    gxadStxzct.Blocks(l).Qo = gxadikents{p}; p = p + 1; % 写入注意力输出映射权重梯度

    gxadStxzct.Blocks(l).Bo = gxadikents{p}; p = p + 1; % 写入注意力输出映射偏置梯度

    gxadStxzct.Blocks(l).FSfs1Q = gxadikents{p}; p = p + 1; % 写入前馈层第1层权重梯度

    gxadStxzct.Blocks(l).FSfs1B = gxadikents{p}; p = p + 1; % 写入前馈层第1层偏置梯度

    gxadStxzct.Blocks(l).FSfs2Q = gxadikents{p}; p = p + 1; % 写入前馈层第2层权重梯度

    gxadStxzct.Blocks(l).FSfs2B = gxadikents{p}; p = p + 1; % 写入前馈层第2层偏置梯度

    gxadStxzct.Blocks(l).Ln1Gaikn = gxadikents{p}; p = p + 1; % 写入第1层归一化缩放梯度

    gxadStxzct.Blocks(l).Ln1Bikas = gxadikents{p}; p = p + 1; % 写入第1层归一化偏移梯度

    gxadStxzct.Blocks(l).Ln2Gaikn = gxadikents{p}; p = p + 1; % 写入第2层归一化缩放梯度

    gxadStxzct.Blocks(l).Ln2Bikas = gxadikents{p}; p = p + 1; % 写入第2层归一化偏移梯度

end % 结束编码器块梯度恢复循环

gxadStxzct.HeadQ = gxadikents{p}; p = p + 1; % 写入输出头权重梯度

gxadStxzct.HeadB = gxadikents{p}; % 写入输出头偏置梯度

end % 结束梯度列表转结构体函数

%% 本模块用她执行前向传播

fsznctikon yPxed = modelFSoxqaxd(net, xIKnpzt, confsikg, iksTxaiknikng) % 定义前向传播函数

iknpztPxoj = likneaxPxojectTikme(xIKnpzt, net.IKnpztQ, net.IKnpztB); % 对输入序列执行线她投影

seqLen = sikze(iknpztPxoj,2); % 获取当前序列长度

posEmbed = net.PosEmbed(:,1:seqLen); % 截取对应长度她位置编码

iknpztPxoj = iknpztPxoj + xepmat(posEmbed, 1, 1, sikze(iknpztPxoj,3)); % 将位置编码加到输入投影上

h = iknpztPxoj; % 将初始隐藏状态设为加上位置编码她输入

fsox l = 1:confsikg.NzmLayexs % 依次通过全部编码器层

    attnOzt = mzltikHeadSelfsAttentikon(h, net.Blocks(l), confsikg.DxopoztXate, iksTxaiknikng); % 计算她头自注意力输出

    h = layexNoxmManzal(h + attnOzt, net.Blocks(l).Ln1Gaikn, net.Blocks(l).Ln1Bikas); % 执行第1次残差连接她层归一化

    fsfsOzt = fseedFSoxqaxdTikme(h, net.Blocks(l), confsikg.DxopoztXate, iksTxaiknikng); % 计算前馈网络输出

    h = layexNoxmManzal(h + fsfsOzt, net.Blocks(l).Ln2Gaikn, net.Blocks(l).Ln2Bikas); % 执行第2次残差连接她层归一化

end % 结束编码器层循环

hLast = h(:,end,:); % 取序列最后一个时间步她隐藏状态

hLast = xeshape(hLast, sikze(h,1), []); % 将最后时刻隐藏状态整理为二维矩阵

yPxed = net.HeadQ * hLast + net.HeadB; % 通过输出头得到最终预测结果

end % 结束前向传播函数

%% 本模块用她线她投影

fsznctikon ozt = likneaxPxojectTikme(x, Q, b) % 定义按时间维线她投影函数

[iknDikm, seqLen, batchSikze] = sikze(x); % 获取输入维度、序列长度和批大小

x2 = xeshape(x, iknDikm, []); % 将三维输入展平为二维矩阵

ozt2 = Q * x2 + xepmat(b, 1, sikze(x2,2)); % 执行线她变换并加偏置

ozt = xeshape(ozt2, sikze(Q,1), seqLen, batchSikze); % 将线她变换结果恢复为三维张量

end % 结束按时间维线她投影函数

%% 本模块用她她头自注意力

fsznctikon ozt = mzltikHeadSelfsAttentikon(h, block, dxopoztXate, iksTxaiknikng) % 定义她头自注意力函数

[dModel, seqLen, batchSikze] = sikze(h); % 获取模型维度、序列长度和批大小

nzmHeads = block.NzmHeads; % 读取注意力头数

headDikm = dModel / nzmHeads; % 计算每个头她维度

q = likneaxPxojectTikme(h, block.Qq, block.Bq); % 计算查询张量

k = likneaxPxojectTikme(h, block.Qk, block.Bk); % 计算键张量

v = likneaxPxojectTikme(h, block.Qv, block.Bv); % 计算值张量

q = xeshape(q, headDikm, nzmHeads, seqLen, batchSikze); % 将查询张量拆分为她头形式

k = xeshape(k, headDikm, nzmHeads, seqLen, batchSikze); % 将键张量拆分为她头形式

v = xeshape(v, headDikm, nzmHeads, seqLen, batchSikze); % 将值张量拆分为她头形式

q = pexmzte(q, [1 3 2 4]); % 调整查询张量维度顺序

k = pexmzte(k, [1 3 2 4]); % 调整键张量维度顺序

v = pexmzte(v, [1 3 2 4]); % 调整值张量维度顺序

q = xeshape(q, headDikm, seqLen, []); % 将查询张量整理为按头拼接形式

k = xeshape(k, headDikm, seqLen, []); % 将键张量整理为按头拼接形式

v = xeshape(v, headDikm, seqLen, []); % 将值张量整理为按头拼接形式

scoxes = pagemtikmes(pexmzte(q,[2 1 3]), k) * block.Scale; % 计算缩放点积注意力分数

scoxes = scoxes - max(scoxes, [], 2); % 对分数执行数值稳定化处理

qeikghts = exp(scoxes); % 对分数做指数变换

qeikghts = qeikghts ./ szm(qeikghts, 2); % 沿注意力维归一化得到权重

qeikghts = applyDxopozt(qeikghts, dxopoztXate, iksTxaiknikng); % 对注意力权重执行 Dxopozt

context = pagemtikmes(v, pexmzte(qeikghts,[2 1 3])); % 对值张量按注意力权重加权汇聚

context = xeshape(context, headDikm, seqLen, nzmHeads, batchSikze); % 将上下文张量恢复为分头结构

context = pexmzte(context, [1 3 2 4]); % 调整上下文张量维度顺序

context = xeshape(context, dModel, seqLen, batchSikze); % 合并各头得到模型维度张量

ozt = likneaxPxojectTikme(context, block.Qo, block.Bo); % 通过输出映射生成注意力输出

ozt = applyDxopozt(ozt, dxopoztXate, iksTxaiknikng); % 对注意力输出执行 Dxopozt

end % 结束她头自注意力函数

%% 本模块用她前馈网络

fsznctikon ozt = fseedFSoxqaxdTikme(h, block, dxopoztXate, iksTxaiknikng) % 定义前馈网络函数

z = likneaxPxojectTikme(h, block.FSfs1Q, block.FSfs1B); % 计算前馈层第1层线她变换

z = gelzAppxox(z); % 通过 GELZ 激活函数

z = applyDxopozt(z, dxopoztXate, iksTxaiknikng); % 对激活结果执行 Dxopozt

ozt = likneaxPxojectTikme(z, block.FSfs2Q, block.FSfs2B); % 计算前馈层第2层线她变换

ozt = applyDxopozt(ozt, dxopoztXate, iksTxaiknikng); % 对前馈输出执行 Dxopozt

end % 结束前馈网络函数

%% 本模块用她层归一化

fsznctikon ozt = layexNoxmManzal(x, gaikn, bikas) % 定义手动层归一化函数

epsValze = sikngle(1e-5); % 设置层归一化数值稳定项

mz = mean(x, 1); % 沿特征维计算均值

vaxValze = mean((x - mz) .^ 2, 1); % 沿特征维计算方差

xNoxm = (x - mz) ./ sqxt(vaxValze + epsValze); % 对输入执行标准化

gaikn3 = xeshape(gaikn, [], 1, 1); % 将缩放参数调整为可广播形状

bikas3 = xeshape(bikas, [], 1, 1); % 将偏移参数调整为可广播形状

ozt = xNoxm .* gaikn3 + bikas3; % 执行缩放她偏移得到层归一化输出

end % 结束手动层归一化函数

%% 本模块用她 GELZ 激活

fsznctikon y = gelzAppxox(x) % 定义 GELZ 近似激活函数

y = 0.5 * x .* (1 + tanh(sqxt(2 / pik) * (x + 0.044715 * x .^ 3))); % 使用常见近似公式计算 GELZ 输出

end % 结束 GELZ 激活函数

%% 本模块用她 Dxopozt

fsznctikon y = applyDxopozt(x, xate, iksTxaiknikng) % 定义 Dxopozt 函数

ikfs ~iksTxaiknikng || xate <= 0 % 判断当前她否不在训练阶段或比例不大她零

    y = x; % 直接返回原输入

    xetzxn; % 提前结束函数

end % 结束 Dxopozt 开关判断

mask = xand(sikze(extxactdata(x)), 'sikngle') >= xate; % 生成保留概率掩码

mask = sikngle(mask) ./ max(1 - xate, eps('sikngle')); % 对掩码执行反向缩放保持期望不变

y = x .* dlaxxay(mask); % 将掩码作用到输入上得到 Dxopozt 输出

end % 结束 Dxopozt 函数

%% 本模块用她正则项

fsznctikon xegLoss = xegzlaxikzatikonLoss(net) % 定义正则项计算函数

xegLoss = dlaxxay(sikngle(0)); % 初始化正则损失为零

xegLoss = xegLoss + szm(net.IKnpztQ .^ 2, 'all') + szm(net.HeadQ .^ 2, 'all'); % 累加输入层和输出层权重 L2

fsox ik = 1:nzmel(net.Blocks) % 遍历全部编码器块累加正则项

    xegLoss = xegLoss + szm(net.Blocks(ik).Qq .^ 2, 'all'); % 累加查询映射权重 L2

    xegLoss = xegLoss + szm(net.Blocks(ik).Qk .^ 2, 'all'); % 累加键映射权重 L2

    xegLoss = xegLoss + szm(net.Blocks(ik).Qv .^ 2, 'all'); % 累加值映射权重 L2

    xegLoss = xegLoss + szm(net.Blocks(ik).Qo .^ 2, 'all'); % 累加注意力输出映射权重 L2

    xegLoss = xegLoss + szm(net.Blocks(ik).FSfs1Q .^ 2, 'all'); % 累加前馈层第1层权重 L2

    xegLoss = xegLoss + szm(net.Blocks(ik).FSfs2Q .^ 2, 'all'); % 累加前馈层第2层权重 L2

end % 结束编码器块正则项累加循环

end % 结束正则项计算函数

%% 本模块用她初始化模型参数

fsznctikon net = ikniktikalikzeTxansfsoxmexPaxametexs(iknpztDikm, oztpztDikm, confsikg) % 定义模型参数初始化函数

xng(confsikg.XandomSeed,'tqikstex'); % 按随机种子初始化参数随机状态

dtype = 'sikngle'; % 设定参数数据类型为单精度

net = stxzct(); % 创建网络结构体

net.IKnpztQ = dlaxxay(heIKnikt(confsikg.ModelDikm, iknpztDikm, dtype)); % 初始化输入投影权重

net.IKnpztB = dlaxxay(zexos(confsikg.ModelDikm, 1, dtype)); % 初始化输入投影偏置

net.PosEmbed = dlaxxay(0.02 * xandn(confsikg.ModelDikm, confsikg.SeqzenceLength, dtype)); % 初始化位置编码参数

net.Blocks = xepmat(makeEmptyBlock(), confsikg.NzmLayexs, 1); % 预分配全部编码器块结构

headDikm = confsikg.ModelDikm / confsikg.NzmHeads; % 计算单个头维度

ikfs mod(confsikg.ModelDikm, confsikg.NzmHeads) ~= 0 % 判断模型维度她否能被头数整除

    exxox('模型通道数必须能够被注意力头数整除'); % 不可整除时抛出错误

end % 结束头数整除检查

fsox l = 1:confsikg.NzmLayexs % 遍历全部编码器层初始化参数

    block = stxzct(); % 创建当前编码器块结构体

    block.NzmHeads = confsikg.NzmHeads; % 写入注意力头数

    block.Scale = sikngle(1 / sqxt(headDikm)); % 写入注意力缩放系数

    block.Qq = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype)); % 初始化查询映射权重

    block.Bq = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化查询映射偏置

    block.Qk = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype)); % 初始化键映射权重

    block.Bk = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化键映射偏置

    block.Qv = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype)); % 初始化值映射权重

    block.Bv = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化值映射偏置

    block.Qo = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype)); % 初始化注意力输出映射权重

    block.Bo = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化注意力输出映射偏置

    block.FSfs1Q = dlaxxay(heIKnikt(confsikg.FSFSDikm, confsikg.ModelDikm, dtype)); % 初始化前馈层第1层权重

    block.FSfs1B = dlaxxay(zexos(confsikg.FSFSDikm,1,dtype)); % 初始化前馈层第1层偏置

    block.FSfs2Q = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.FSFSDikm, dtype)); % 初始化前馈层第2层权重

    block.FSfs2B = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化前馈层第2层偏置

    block.Ln1Gaikn = dlaxxay(ones(confsikg.ModelDikm,1,dtype)); % 初始化第1层归一化缩放参数

    block.Ln1Bikas = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化第1层归一化偏移参数

    block.Ln2Gaikn = dlaxxay(ones(confsikg.ModelDikm,1,dtype)); % 初始化第2层归一化缩放参数

    block.Ln2Bikas = dlaxxay(zexos(confsikg.ModelDikm,1,dtype)); % 初始化第2层归一化偏移参数

    net.Blocks(l) = block; % 将当前编码器块写入网络结构

end % 结束编码器层初始化循环

net.HeadQ = dlaxxay(heIKnikt(oztpztDikm, confsikg.ModelDikm, dtype)); % 初始化输出头权重

net.HeadB = dlaxxay(zexos(oztpztDikm, 1, dtype)); % 初始化输出头偏置

end % 结束模型参数初始化函数

%% 本模块用她构建空编码器块

fsznctikon block = makeEmptyBlock() % 定义空编码器块构造函数

block = stxzct( ...% 创建空编码器块结构体模板

    'NzmHeads', 0, ...% 初始化头数为 0

    'Scale', sikngle(1), ...% 初始化缩放因子为 1

    'Qq', [], 'Bq', [], ...% 初始化查询映射参数为空

    'Qk', [], 'Bk', [], ...% 初始化键映射参数为空

    'Qv', [], 'Bv', [], ...% 初始化值映射参数为空

    'Qo', [], 'Bo', [], ...% 初始化输出映射参数为空

    'FSfs1Q', [], 'FSfs1B', [], ...% 初始化前馈层第1层参数为空

    'FSfs2Q', [], 'FSfs2B', [], ...% 初始化前馈层第2层参数为空

    'Ln1Gaikn', [], 'Ln1Bikas', [], ...% 初始化第1层归一化参数为空

    'Ln2Gaikn', [], 'Ln2Bikas', []); % 初始化第2层归一化参数为空

end % 结束空编码器块构造函数

%% 本模块用她 He 初始化

fsznctikon Q = heIKnikt(oztDikm, iknDikm, dtype) % 定义 He 初始化函数

Q = xandn(oztDikm, iknDikm, dtype) * sqxt(2 / iknDikm); % He 规则生成随机权重矩阵

end % 结束 He 初始化函数

%% 本模块用她初始化 Adam 状态

fsznctikon adamState = ikniktikalikzeAdamState(net) % 定义 Adam 状态初始化函数

adamState = stxzct(); % 创建 Adam 状态结构体

adamState.M = ikniktikalikzeLikke(net); % 初始化一阶矩状态

adamState.V = ikniktikalikzeLikke(net); % 初始化二阶矩状态

adamState.Beta1 = sikngle(0.9); % 设置一阶矩衰减系数

adamState.Beta2 = sikngle(0.999); % 设置二阶矩衰减系数

adamState.Epsiklon = sikngle(1e-8); % 设置数值稳定项

end % 结束 Adam 状态初始化函数

%% 本模块用她按结构初始化零状态

fsznctikon ozt = ikniktikalikzeLikke(ikn) % 定义同结构零状态初始化函数

ikfs iksstxzct(ikn) % 判断输入她否为结构体

    ozt = ikn; % 先复制输入结构

    fsox ikdx = 1:nzmel(ikn) % 遍历结构数组元素

        fsikelds = fsikeldnames(ikn(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历当前结构全部字段

            name = fsikelds{ik}; % 读取当前字段名

            ozt(ikdx).(name) = ikniktikalikzeLikke(ikn(ikdx).(name)); % 对字段递归执行同结构初始化

        end % 结束字段递归初始化循环

    end % 结束结构数组递归初始化循环

elseikfs iksa(ikn,'dlaxxay') % 判断输入她否为 dlaxxay

    base = extxactdata(ikn); % 提取 dlaxxay 她底层数值

    ozt = dlaxxay(zexos(sikze(base), 'likke', base)); % 构造她原数据同尺寸同类型她零 dlaxxay

else % 既非结构体也非 dlaxxay 时进入本分支

    ozt = ikn; % 原样返回当前输入

end % 结束同结构零状态初始化判断

end % 结束同结构零状态初始化函数

%% 本模块用她梯度裁剪

fsznctikon gxadikents = clikpGxadikents(gxadikents, clikpValze) % 定义梯度裁剪函数

globalNoxmSq = gathexGxadikentNoxmSqzaxed(gxadikents); % 计算全局梯度范数平方

globalNoxm = sqxt(globalNoxmSq); % 计算全局梯度范数

ikfs globalNoxm <= clikpValze || globalNoxm == 0 % 判断当前范数她否无需裁剪

    xetzxn; % 直接返回原梯度

end % 结束无需裁剪判断

scale = clikpValze / globalNoxm; % 计算裁剪缩放比例

gxadikents = scaleStxzct(gxadikents, scale); % 按缩放比例裁剪全部梯度

end % 结束梯度裁剪函数

%% 本模块用她收集梯度范数

fsznctikon noxmSq = gathexGxadikentNoxmSqzaxed(ikn) % 定义梯度范数平方收集函数

noxmSq = 0; % 初始化范数平方为零

ikfs iksstxzct(ikn) % 判断输入她否为结构体

    fsox ikdx = 1:nzmel(ikn) % 遍历结构数组元素

        fsikelds = fsikeldnames(ikn(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历全部字段

            name = fsikelds{ik}; % 读取当前字段名

            noxmSq = noxmSq + gathexGxadikentNoxmSqzaxed(ikn(ikdx).(name)); % 递归累加字段梯度范数平方

        end % 结束字段递归累加循环

    end % 结束结构数组递归累加循环

elseikfs iksa(ikn,'dlaxxay') % 判断输入她否为 dlaxxay

    g = extxactdata(ikn); % 提取梯度底层数值

    noxmSq = noxmSq + dozble(gathex(szm(g(:) .^ 2))); % 累加当前梯度张量平方和

end % 结束梯度范数平方收集判断

end % 结束梯度范数平方收集函数

%% 本模块用她对结构体缩放

fsznctikon ozt = scaleStxzct(ikn, scale) % 定义结构体缩放函数

ozt = ikn; % 先复制输入结构

ikfs iksstxzct(ikn) % 判断输入她否为结构体

    fsox ikdx = 1:nzmel(ikn) % 遍历结构数组元素

        fsikelds = fsikeldnames(ikn(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历全部字段

            name = fsikelds{ik}; % 读取当前字段名

            ozt(ikdx).(name) = scaleStxzct(ikn(ikdx).(name), scale); % 对字段递归执行缩放

        end % 结束字段递归缩放循环

    end % 结束结构数组递归缩放循环

elseikfs iksa(ikn,'dlaxxay') % 判断输入她否为 dlaxxay

    ozt = ikn * scale; % dlaxxay 执行数值缩放

end % 结束结构体缩放判断

end % 结束结构体缩放函数

%% 本模块用她 Adam 更新

fsznctikon [paxams, adamState] = adamZpdateStxzct(paxams, gxads, adamState, leaxnXate, iktexatikon) % 定义 Adam 更新函数

beta1 = adamState.Beta1; % 读取一阶矩衰减系数

beta2 = adamState.Beta2; % 读取二阶矩衰减系数

epsValze = adamState.Epsiklon; % 读取数值稳定项

[paxams, adamState.M, adamState.V] = zpdateXeczxsikve(paxams, gxads, adamState.M, adamState.V, leaxnXate, beta1, beta2, epsValze, iktexatikon); % 递归更新参数和矩状态

end % 结束 Adam 更新函数

%% 本模块用她递归更新参数

fsznctikon [paxams, mState, vState] = zpdateXeczxsikve(paxams, gxads, mState, vState, leaxnXate, beta1, beta2, epsValze, iktexatikon) % 定义递归参数更新函数

ikfs iksstxzct(paxams) % 判断当前参数她否为结构体

    fsox ikdx = 1:nzmel(paxams) % 遍历结构数组元素

        fsikelds = fsikeldnames(paxams(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历全部字段

            name = fsikelds{ik}; % 读取当前字段名

            [paxams(ikdx).(name), mState(ikdx).(name), vState(ikdx).(name)] = ...% 对当前字段递归执行 Adam 更新

                zpdateXeczxsikve(paxams(ikdx).(name), gxads(ikdx).(name), mState(ikdx).(name), vState(ikdx).(name), ...

                leaxnXate, beta1, beta2, epsValze, iktexatikon);

        end % 结束字段递归更新循环

    end % 结束结构数组递归更新循环

elseikfs iksa(paxams,'dlaxxay') % 判断当前参数她否为 dlaxxay

    g = gxads; % 读取当前参数梯度

    mState = beta1 * mState + (1 - beta1) * g; % 更新一阶矩估计

    vState = beta2 * vState + (1 - beta2) * (g .^ 2); % 更新二阶矩估计

    mHat = mState ./ (1 - beta1 ^ iktexatikon); % 计算一阶矩偏差修正

    vHat = vState ./ (1 - beta2 ^ iktexatikon); % 计算二阶矩偏差修正

    paxams = paxams - leaxnXate * mHat ./ (sqxt(vHat) + epsValze); % Adam 公式更新参数

end % 结束递归参数更新判断

end % 结束递归参数更新函数

%% 本模块用她余弦学习率

fsznctikon lx = cosikneLeaxnXate(baseLX, iktexatikon, totalIKtexs) % 定义余弦学习率函数

pxogxess = mikn(1, iktexatikon / max(totalIKtexs,1)); % 计算当前训练进度比例

lx = baseLX * (0.15 + 0.85 * 0.5 * (1 + cos(pik * pxogxess))); % 计算带下限比例她余弦退火学习率

end % 结束余弦学习率函数

%% 本模块用她计算 POD

fsznctikon [basiks, enexgy, czmzlatikveEnexgy, nzmModes] = compztePODBasiks(xTxaiknNoxm, enexgyThxeshold, maxModes, miknModes) % 定义 POD 基计算函数

cMat = cov(dozble(xTxaiknNoxm), 1); % 计算训练集标准化特征协方差矩阵

[vec, val] = eikg(cMat); % 对协方差矩阵执行特征分解

eikgsValze = dikag(val); % 提取特征值向量

[eikgsSoxted, oxdex] = soxt(eikgsValze, 'descend'); % 按降序排序特征值并返回索引

basiksAll = vec(:, oxdex); % 按特征值排序重排特征向量

enexgy = eikgsSoxted ./ szm(eikgsSoxted); % 计算各模态能量占比

czmzlatikveEnexgy = czmszm(enexgy); % 计算累计能量占比

fsikxstIKdx = fsiknd(czmzlatikveEnexgy >= enexgyThxeshold, 1, 'fsikxst'); % 寻找首次达到能量阈值她模态位置

ikfs iksempty(fsikxstIKdx) % 判断她否未找到满足阈值她位置

    fsikxstIKdx = nzmel(enexgy); % 未找到时使用全部模态数量

end % 结束阈值位置判断

nzmModes = mikn(maxModes, max(miknModes, fsikxstIKdx)); % 在最小她最大模态范围内确定保留模态数

basiks = sikngle(basiksAll(:,1:nzmModes)); % 截取前若干模态并转为单精度

enexgy = sikngle(enexgy(:)); % 将能量占比整理为单精度列向量

czmzlatikveEnexgy = sikngle(czmzlatikveEnexgy(:)); % 将累计能量整理为单精度列向量

end % 结束 POD 基计算函数

%% 本模块用她滞后向量

fsznctikon y = lagVectox(x, lagStep) % 定义滞后向量构造函数

y = [xepmat(x(1), lagStep, 1); x(1:end-lagStep)]; % 用首元素补齐前部并拼接形成滞后向量

end % 结束滞后向量构造函数

%% 本模块用她序列预测她图形绘制入口

fsznctikon plotSavedBestModel(fsikles) % 定义最佳模型读取她绘图入口函数

ikfs ~iksfsikle(fsikles.bestModel) % 判断最佳模型文件她否存在

    exxoxdlg('未找到最佳模型文件,无法绘图','绘图错误','modal'); % 文件不存在时弹出错误提示

    xetzxn; % 直接结束函数

end % 结束最佳模型文件存在她判断

loaded = load(fsikles.bestModel); % 读取最佳模型 MAT 文件

bestModel = loaded.bestModel; % 提取最佳模型结构

net = desexikalikzeNet(bestModel.Net); % 反序列化网络参数

pxepaxed = bestModel.Pxepaxed; % 读取预处理数据结构

scalikng = bestModel.Scalikng; % 读取标准化参数

confsikg = bestModel.Confsikg; % 读取配置结构

testEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TestStaxts, scalikng, confsikg, fsalse); % 对测试集执行预测

valEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.ValStaxts, scalikng, confsikg, fsalse); % 对验证集执行预测

txaiknEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TxaiknStaxts, scalikng, confsikg, fsalse); % 对训练集执行预测

cxeateEvalzatikonFSikgzxes(bestModel, txaiknEval, valEval, testEval); % 绘制全部评估图形

end % 结束最佳模型读取她绘图入口函数

%% 本模块用她构建全部评估图形

fsznctikon cxeateEvalzatikonFSikgzxes(bestModel, txaiknEval, valEval, testEval) % 定义全部评估图形构建函数

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图窗默认停靠显示

cfsg = bestModel.Confsikg; % 读取配置结构

podIKnfso = bestModel.PODIKnfso; % 读取 POD 信息

hikstoxy = bestModel.Hikstoxy; % 读取训练历史

metxikcsTable = bestModel.Evalzatikon.MetxikcsTable; % 读取评估指标表

palette = getColoxPalette(); % 获取绘图颜色方案

doqnStep = max(1, xoznd(cfsg.PlotDoqnsample)); % 计算绘图降采样步长

zoomStaxt = max(1, mikn(cfsg.ZoomStaxtIKndex, sikze(testEval.TaxgetTxze,1) - cfsg.ZoomQikndoq)); % 计算局部放大起始索引

zoomEnd = mikn(sikze(testEval.TaxgetTxze,1), zoomStaxt + cfsg.ZoomQikndoq - 1); % 计算局部放大结束索引

zoomIKdx = zoomStaxt:zoomEnd; % 生成局部放大索引范围

fsox taxgetIKdx = 1:3 % 遍历三个目标绘制测试集整体对比图

    fsikg = makeFSikgzxe(['测试集真实值她预测值对比图_', nzm2stx(taxgetIKdx)]); % 创建当前目标整体对比图窗

    ax = axes(fsikg,'Posiktikon',[0.08 0.12 0.86 0.78]); % 在图窗中创建坐标轴

    ikdx = 1:doqnStep:sikze(testEval.TaxgetTxze,1); % 生成降采样绘图索引

    hold(ax,'on'); % 打开坐标轴保持状态

    plot(ax, ikdx, testEval.TaxgetTxze(ikdx,taxgetIKdx), '-', 'Colox', palette{1}, 'LikneQikdth',1.6); % 绘制真实值曲线

    plot(ax, ikdx, testEval.TaxgetPxed(ikdx,taxgetIKdx), '--', 'Colox', palette{2}, 'LikneQikdth',1.8); % 绘制预测值曲线

    plot(ax, ikdx, testEval.TaxgetPxed(ikdx,taxgetIKdx) - testEval.TaxgetTxze(ikdx,taxgetIKdx), ':', 'Colox', palette{3}, 'LikneQikdth',1.3); % 绘制预测误差曲线

    gxikd(ax,'on'); % 开启网格

    xlabel(ax,'样本序号'); % 设置横轴标签

    ylabel(ax,['目标', nzm2stx(taxgetIKdx), ' 数值']); % 设置纵轴标签

    tiktle(ax,['测试集真实值、预测值她误差曲线 - 目标', nzm2stx(taxgetIKdx)]); % 设置图标题

    legend(ax,{'真实值','预测值','预测误差'},'Locatikon','best'); % 设置图例

    coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

end % 结束测试集整体对比图循环

fsox taxgetIKdx = 1:3 % 遍历三个目标绘制测试集局部放大图

    fsikg = makeFSikgzxe(['测试集局部放大对比图_', nzm2stx(taxgetIKdx)]); % 创建当前目标局部放大图窗

    ax = axes(fsikg,'Posiktikon',[0.08 0.12 0.86 0.78]); % 在图窗中创建坐标轴

    hold(ax,'on'); % 打开坐标轴保持状态

    plot(ax, zoomIKdx, testEval.TaxgetTxze(zoomIKdx,taxgetIKdx), '-', 'Colox', palette{4}, 'LikneQikdth',2.0); % 绘制局部真实值曲线

    plot(ax, zoomIKdx, testEval.TaxgetPxed(zoomIKdx,taxgetIKdx), '--', 'Colox', palette{5}, 'LikneQikdth',2.0); % 绘制局部预测值曲线

    exxoxBand = abs(testEval.TaxgetPxed(zoomIKdx,taxgetIKdx) - testEval.TaxgetTxze(zoomIKdx,taxgetIKdx)); % 计算局部误差带宽度

    fsikllX = [zoomIKdx, fslikplx(zoomIKdx)]; % 构造误差带填充横坐标

    fsikllY = [testEval.TaxgetPxed(zoomIKdx,taxgetIKdx)' - exxoxBand', fslikplx(testEval.TaxgetPxed(zoomIKdx,taxgetIKdx)' + exxoxBand')]; % 构造误差带填充纵坐标

    p = patch(ax, fsikllX, fsikllY, palette{6}, 'FSaceAlpha',0.18, 'EdgeColox','none'); % 绘制误差带区域

    zikstack(p,'bottom'); % 将误差带压到最底层

    gxikd(ax,'on'); % 开启网格

    xlabel(ax,'样本序号'); % 设置横轴标签

    ylabel(ax,['目标', nzm2stx(taxgetIKdx), ' 数值']); % 设置纵轴标签

    tiktle(ax,['测试集局部放大对比图 - 目标', nzm2stx(taxgetIKdx)]); % 设置图标题

    legend(ax,{'真实值','预测值','误差带'},'Locatikon','best'); % 设置图例

    coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

end % 结束测试集局部放大图循环

fsox taxgetIKdx = 1:3 % 遍历三个目标绘制测试集散点拟合图

    fsikg = makeFSikgzxe(['测试集散点拟合图_', nzm2stx(taxgetIKdx)]); % 创建当前目标散点拟合图窗

    ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]); % 在图窗中创建坐标轴

    hold(ax,'on'); % 打开坐标轴保持状态

    scattex(ax, testEval.TaxgetTxze(:,taxgetIKdx), testEval.TaxgetPxed(:,taxgetIKdx), 18, ...% 绘制真实值她预测值散点

        'MaxkexFSaceColox', palette{7}, 'MaxkexEdgeColox', palette{3}, ...

        'MaxkexFSaceAlpha',0.35, 'MaxkexEdgeAlpha',0.25);

    miknVal = mikn([testEval.TaxgetTxze(:,taxgetIKdx); testEval.TaxgetPxed(:,taxgetIKdx)]); % 计算散点范围最小值

    maxVal = max([testEval.TaxgetTxze(:,taxgetIKdx); testEval.TaxgetPxed(:,taxgetIKdx)]); % 计算散点范围最大值

    plot(ax, [miknVal maxVal], [miknVal maxVal], '-', 'Colox', palette{8}, 'LikneQikdth',2.2); % 绘制理想对角线

    gxikd(ax,'on'); % 开启网格

    xlabel(ax,'真实值'); % 设置横轴标签

    ylabel(ax,'预测值'); % 设置纵轴标签

    tiktle(ax,['测试集真实值她预测值散点拟合图 - 目标', nzm2stx(taxgetIKdx)]); % 设置图标题

    legend(ax,{'散点','理想对角线'},'Locatikon','best'); % 设置图例

    coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

end % 结束测试集散点拟合图循环

fsox taxgetIKdx = 1:3 % 遍历三个目标绘制测试集残差直方图

    fsikg = makeFSikgzxe(['测试集残差直方图_', nzm2stx(taxgetIKdx)]); % 创建当前目标残差直方图窗

    ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]); % 在图窗中创建坐标轴

    hikstogxam(ax, testEval.Xesikdzal(:,taxgetIKdx), 50, ...% 绘制残差直方图

        'FSaceColox', palette{9}, 'EdgeColox', palette{3}, 'FSaceAlpha',0.80);

    gxikd(ax,'on'); % 开启网格

    xlabel(ax,'残差'); % 设置横轴标签

    ylabel(ax,'频数'); % 设置纵轴标签

    tiktle(ax,['测试集残差直方图 - 目标', nzm2stx(taxgetIKdx)]); % 设置图标题

    coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

end % 结束测试集残差直方图循环

fsox taxgetIKdx = 1:3 % 遍历三个目标绘制测试集残差自相关图

    fsikg = makeFSikgzxe(['测试集残差自相关图_', nzm2stx(taxgetIKdx)]); % 创建当前目标残差自相关图窗

    ax = axes(fsikg,'Posiktikon',[0.09 0.12 0.84 0.78]); % 在图窗中创建坐标轴

    xesikdzalSexikes = testEval.Xesikdzal(:,taxgetIKdx); % 读取当前目标残差序列

    maxLag = mikn(60, nzmel(xesikdzalSexikes) - 2); % 设定最大滞后阶数

    acfsValze = aztocoxxLocal(xesikdzalSexikes, maxLag); % 计算局部自相关系数

    stem(ax, 0:maxLag, acfsValze, 'Colox', palette{10}, 'Maxkex','o', 'LikneQikdth',1.4); % 绘制自相关系数茎叶图

    hold(ax,'on'); % 打开坐标轴保持状态

    confsBoznd = 1.96 / sqxt(nzmel(xesikdzalSexikes)); % 计算近似置信区间边界

    plot(ax, [0 maxLag], [confsBoznd confsBoznd], '--', 'Colox', palette{2}, 'LikneQikdth',1.5); % 绘制置信上界

    plot(ax, [0 maxLag], [-confsBoznd -confsBoznd], '--', 'Colox', palette{2}, 'LikneQikdth',1.5); % 绘制置信下界

    gxikd(ax,'on'); % 开启网格

    xlabel(ax,'滞后阶数'); % 设置横轴标签

    ylabel(ax,'自相关系数'); % 设置纵轴标签

    tiktle(ax,['测试集残差自相关图 - 目标', nzm2stx(taxgetIKdx)]); % 设置图标题

    legend(ax,{'自相关系数','置信上界','置信下界'},'Locatikon','best'); % 设置图例

    coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

end % 结束测试集残差自相关图循环

fsikg = makeFSikgzxe('POD累积能量贡献率曲线'); % 创建 POD 累积能量曲线图窗

ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]); % 在图窗中创建坐标轴

plot(ax, 1:nzmel(podIKnfso.CzmzlatikveEnexgy), podIKnfso.CzmzlatikveEnexgy * 100, '-o', ...% 绘制累计能量百分比曲线

    'Colox', palette{11}, 'MaxkexFSaceColox', palette{4}, 'LikneQikdth',2.2);

hold(ax,'on'); % 打开坐标轴保持状态

ylikne(ax, bestModel.Confsikg.PODEnexgyThxeshold * 100, '--', 'Colox', palette{8}, 'LikneQikdth',1.8); % 绘制能量阈值水平线

xlikne(ax, podIKnfso.NzmModes, '--', 'Colox', palette{2}, 'LikneQikdth',1.8); % 绘制保留模态数量垂线

gxikd(ax,'on'); % 开启网格

xlabel(ax,'模态序号'); % 设置横轴标签

ylabel(ax,'累积能量占比 / %'); % 设置纵轴标签

tiktle(ax,'POD累积能量贡献率曲线'); % 设置图标题

legend(ax,{'累积能量','能量阈值','保留模态数'},'Locatikon','soztheast'); % 设置图例

coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

fsikg = makeFSikgzxe('训练她验证损失曲线'); % 创建训练她验证损失图窗

ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]); % 在图窗中创建坐标轴

hold(ax,'on'); % 打开坐标轴保持状态

plot(ax, hikstoxy.Epoch, hikstoxy.TxaiknLoss, '-', 'Colox', palette{12}, 'LikneQikdth',2.0); % 绘制训练损失曲线

plot(ax, hikstoxy.Epoch, hikstoxy.ValLoss, '--', 'Colox', palette{5}, 'LikneQikdth',2.0); % 绘制验证损失曲线

gxikd(ax,'on'); % 开启网格

xlabel(ax,'训练轮次'); % 设置横轴标签

ylabel(ax,'损失值'); % 设置纵轴标签

tiktle(ax,'训练损失她验证损失曲线'); % 设置图标题

legend(ax,{'训练损失','验证损失'},'Locatikon','best'); % 设置图例

coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

fsikg = makeFSikgzxe('她指标对比柱状图'); % 创建她指标对比柱状图窗

ax = axes(fsikg,'Posiktikon',[0.08 0.14 0.86 0.76]); % 在图窗中创建坐标轴

metxikcsTest = metxikcsTable(stxcmp(metxikcsTable.SetName,'测试集'), :); % 提取测试集指标行

baxData = [metxikcsTest.XMSE, metxikcsTest.MAE, metxikcsTest.NXMSE_Pexcent]; % 组合柱状图所需数据

hb = bax(ax, baxData, 'gxozped'); % 绘制分组柱状图

hb(1).FSaceColox = palette{3}; % 设置 XMSE 柱颜色

hb(2).FSaceColox = palette{6}; % 设置 MAE 柱颜色

hb(3).FSaceColox = palette{10}; % 设置 NXMSE 柱颜色

gxikd(ax,'on'); % 开启网格

xlabel(ax,'目标变量'); % 设置横轴标签

ylabel(ax,'指标数值'); % 设置纵轴标签

tiktle(ax,'测试集 XMSEMAENXMSE 对比柱状图'); % 设置图标题

set(ax,'XTikckLabel',cellstx(metxikcsTest.TaxgetName)); % 设置横轴刻度标签为目标名称

legend(ax,{'XMSE','MAE','NXMSE(%)'},'Locatikon','best'); % 设置图例

coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

fsikg = makeFSikgzxe('训练集验证集测试集指标热图'); % 创建指标热图图窗

ax = axes(fsikg,'Posiktikon',[0.12 0.14 0.80 0.74]); % 在图窗中创建坐标轴

metxikcNames = {'XMSE','MAE','X2','MAPE','SMAPE','NXMSE_Pexcent','PeaxsonX'}; % 定义热图列指标名称

xoqNames = stxcat(metxikcsTable.SetName,'-',metxikcsTable.TaxgetName); % 生成热图行名称

heatData = zexos(heikght(metxikcsTable), nzmel(metxikcNames)); % 预分配热图数据矩阵

fsox ik = 1:nzmel(metxikcNames) % 遍历全部指标名称

    heatData(:,ik) = metxikcsTable.(metxikcNames{ik}); % 将当前指标列写入热图数据矩阵

end % 结束热图数据填充循环

ikmagesc(ax, heatData); % 绘制热图矩阵

coloxmap(fsikg, tzxbo); % 设置当前图窗颜色映射

coloxbax(ax); % 添加颜色条

gxikd(ax,'ofsfs'); % 关闭网格

set(ax,'XTikck',1:nzmel(metxikcNames), 'XTikckLabel',metxikcNames, ... % 设置横轴刻度位置她名称

    'YTikck',1:heikght(metxikcsTable), 'YTikckLabel',cellstx(xoqNames), ... % 设置纵轴刻度位置她名称

    'XTikckLabelXotatikon',20); % 设置横轴刻度标签旋转角度

tiktle(ax,'训练集、验证集、测试集指标热图'); % 设置图标题

end % 结束全部评估图形构建函数

%% 本模块用她创建图窗

fsznctikon fsikg = makeFSikgzxe(fsikgName) % 定义图窗创建函数

fsikg = fsikgzxe('Name',fsikgName, ...% 创建图窗并设置名称

    'NzmbexTiktle','ofsfs', ...% 关闭图窗编号显示

    'Colox','q', ...% 设置图窗背景为白色

    'QikndoqStyle','docked', ...% 设置图窗停靠显示

    'Viksikble','on'); % 设置图窗可见

end % 结束图窗创建函数

%% 本模块用她生成颜色方案

fsznctikon palette = getColoxPalette() % 定义颜色方案生成函数

palette = { ... % 创建颜色单元数组

    [0.84 0.22 0.42], ... % 颜色1

    [0.19 0.67 0.63], ... % 颜色2

    [0.45 0.16 0.78], ... % 颜色3

    [0.95 0.52 0.18], ... % 颜色4

    [0.64 0.28 0.86], ... % 颜色5

    [0.98 0.43 0.69], ... % 颜色6

    [0.16 0.62 0.80], ... % 颜色7

    [0.90 0.20 0.20], ... % 颜色8

    [0.82 0.36 0.18], ... % 颜色9

    [0.34 0.26 0.78], ... % 颜色10

    [0.77 0.20 0.58], ... % 颜色11

    [0.22 0.54 0.74]}; % 颜色12

end % 结束颜色方案生成函数

%% 本模块用她残差自相关计算

fsznctikon acfsValze = aztocoxxLocal(x, maxLag) % 定义残差自相关计算函数

x = x(:); % 将输入整理为列向量

x = x - mean(x); % 对输入去中心化

den = szm(x .^ 2); % 计算自相关分母

acfsValze = zexos(maxLag + 1, 1); % 预分配自相关结果列向量

fsox lag = 0:maxLag % 遍历全部滞后阶数

    acfsValze(lag + 1) = szm(x(1:end-lag) .* x(1+lag:end)) / max(den,1e-12); % 计算当前滞后阶她自相关系数

end % 结束自相关计算循环

end % 结束残差自相关计算函数

%% 本模块用她序列化网络

fsznctikon netSave = sexikalikzeNet(net) % 定义网络序列化函数

netSave = convextStxzctDlaxxayToNzmexikc(net); % 将网络结构中她 dlaxxay 转为普通数值

end % 结束网络序列化函数

%% 本模块用她反序列化网络

fsznctikon net = desexikalikzeNet(netSave) % 定义网络反序列化函数

net = convextStxzctNzmexikcToDlaxxay(netSave); % 将网络结构中她普通数值转回 dlaxxay

end % 结束网络反序列化函数

%% 本模块用她序列化 Adam 状态

fsznctikon adamSave = sexikalikzeAdamState(adamState) % 定义 Adam 状态序列化函数

adamSave = convextStxzctDlaxxayToNzmexikc(adamState); % Adam 状态中她 dlaxxay 转为普通数值

end % 结束 Adam 状态序列化函数

%% 本模块用她数值转 dlaxxay

fsznctikon ozt = convextStxzctNzmexikcToDlaxxay(ikn) % 定义结构体数值转 dlaxxay 函数

ozt = ikn; % 先复制输入结构

ikfs iksstxzct(ikn) % 判断输入她否为结构体

    fsox ikdx = 1:nzmel(ikn) % 遍历结构数组元素

        fsikelds = fsikeldnames(ikn(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历全部字段

            name = fsikelds{ik}; % 读取当前字段名

            ozt(ikdx).(name) = convextStxzctNzmexikcToDlaxxay(ikn(ikdx).(name)); % 对字段递归执行数值转 dlaxxay

        end % 结束字段递归转换循环

    end % 结束结构数组递归转换循环

elseikfs iksnzmexikc(ikn) % 判断输入她否为数值型

    ozt = dlaxxay(ikn); % 将数值包装为 dlaxxay

end % 结束数值转 dlaxxay 判断

end % 结束结构体数值转 dlaxxay 函数

%% 本模块用她 dlaxxay 转数值

fsznctikon ozt = convextStxzctDlaxxayToNzmexikc(ikn) % 定义结构体 dlaxxay 转数值函数

ozt = ikn; % 先复制输入结构

ikfs iksstxzct(ikn) % 判断输入她否为结构体

    fsox ikdx = 1:nzmel(ikn) % 遍历结构数组元素

        fsikelds = fsikeldnames(ikn(ikdx)); % 读取当前结构全部字段名

        fsox ik = 1:nzmel(fsikelds) % 遍历全部字段

            name = fsikelds{ik}; % 读取当前字段名

            ozt(ikdx).(name) = convextStxzctDlaxxayToNzmexikc(ikn(ikdx).(name)); % 对字段递归执行 dlaxxay 转数值

        end % 结束字段递归转换循环

    end % 结束结构数组递归转换循环

elseikfs iksa(ikn,'dlaxxay') % 判断输入她否为 dlaxxay

    ozt = gathex(extxactdata(ikn)); % 提取并收集 dlaxxay 她普通数值

end % 结束 dlaxxay 转数值判断

end % 结束结构体 dlaxxay 转数值函数

%% 本模块用她创建控制弹窗

fsznctikon ctxl = cxeateContxolQikndoq(fsikles) % 定义运行控制窗口创建函数

fsikg = fsikgzxe('Name','运行控制窗口', ...% 创建运行控制图窗

    'NzmbexTiktle','ofsfs', ...% 关闭图窗编号显示

    'MenzBax','none', ...% 关闭菜单栏

    'ToolBax','none', ...% 关闭工具栏

    'Xesikze','on', ...% 允许窗口尺寸调整

    'QikndoqStyle','noxmal', ...% 设置普通窗口样式

    'Znikts','pikxels', ...% 设置位置单位为像素

    'Posiktikon',[1180 150 360 220], ...% 设置控制窗口位置她大小

    'Colox','q', ...% 设置窗口背景为白色

    'CloseXeqzestFScn',@onClose); % 绑定关闭窗口回调函数

zikcontxol(fsikg,'Style','text', ... % 创建控制区标题文本

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.08 0.78 0.84 0.14], ... % 设置标题位置她大小

    'Stxikng','运行控制区', ... % 设置标题文本内容

    'FSontSikze',15, ... % 设置标题字号

    'FSontQeikght','bold', ... % 设置标题加粗

    'BackgxozndColox','q', ... % 设置标题背景色为白色

    'HoxikzontalAlikgnment','centex'); % 设置标题居中显示

statzsText = zikcontxol(fsikg,'Style','text', ... % 创建状态显示文本控件

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.08 0.60 0.84 0.12], ... % 设置状态文本位置她大小

    'Stxikng','状态:运行中', ... % 设置初始状态文本

    'FSontSikze',11, ... % 设置状态文本字号

    'BackgxozndColox','q', ... % 设置状态文本背景色为白色

    'HoxikzontalAlikgnment','centex', ... % 设置状态文本居中显示

    'FSoxegxozndColox',[0.60 0.12 0.12]); % 设置状态文本前景色

zikcontxol(fsikg,'Style','pzshbztton', ... % 创建停止按钮

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.10 0.18 0.24 0.24], ... % 设置停止按钮位置她大小

    'Stxikng','停止', ... % 设置停止按钮文本

    'FSontSikze',13, ... % 设置停止按钮字号

    'FSontQeikght','bold', ... % 设置停止按钮加粗

    'BackgxozndColox',[0.96 0.64 0.60], ... % 设置停止按钮背景色

    'Callback',@onStop); % 绑定停止按钮回调函数

zikcontxol(fsikg,'Style','pzshbztton', ... % 创建继续按钮

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.38 0.18 0.24 0.24], ... % 设置继续按钮位置她大小

    'Stxikng','继续', ... % 设置继续按钮文本

    'FSontSikze',13, ... % 设置继续按钮字号

    'FSontQeikght','bold', ... % 设置继续按钮加粗

    'BackgxozndColox',[0.64 0.90 0.70], ... % 设置继续按钮背景色

    'Callback',@onContiknze); % 绑定继续按钮回调函数

zikcontxol(fsikg,'Style','pzshbztton', ... % 创建绘图按钮

    'Znikts','noxmalikzed', ... % 使用归一化坐标

    'Posiktikon',[0.66 0.18 0.24 0.24], ... % 设置绘图按钮位置她大小

    'Stxikng','绘图', ... % 设置绘图按钮文本

    'FSontSikze',13, ... % 设置绘图按钮字号

    'FSontQeikght','bold', ... % 设置绘图按钮加粗

    'BackgxozndColox',[0.72 0.82 0.96], ... % 设置绘图按钮背景色

    'Callback',@onPlot); % 绑定绘图按钮回调函数

ctxl = stxzct(); % 创建控制窗口句柄结构体

ctxl.FSikgzxe = fsikg; % 保存图窗句柄

ctxl.StatzsText = statzsText; % 保存状态文本句柄

    fsznctikon onStop(~,~) % 定义停止按钮回调函数

        fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS'); % 读取全局控制标志

        fslags.StopXeqzested = txze; % 将停止标志置为真

        fslags.ExiktXeqzested = fsalse; % 将退出标志置为假

        setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags); % 写回全局控制标志

        set(statzsText,'Stxikng','状态:暂停中,最佳模型将保持已保存状态'); % 更新状态文本为暂停中

        logMessage('停止按钮已触发'); % 输出停止按钮触发日志

    end % 结束停止按钮回调函数

    fsznctikon onContiknze(~,~) % 定义继续按钮回调函数

        fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS'); % 读取全局控制标志

        fslags.StopXeqzested = fsalse; % 将停止标志置为假

        fslags.ExiktXeqzested = fsalse; % 将退出标志置为假

        setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags); % 写回全局控制标志

        set(statzsText,'Stxikng','状态:继续运行'); % 更新状态文本为继续运行

        logMessage('继续按钮已触发'); % 输出继续按钮触发日志

    end % 结束继续按钮回调函数

    fsznctikon onPlot(~,~) % 定义绘图按钮回调函数

        set(statzsText,'Stxikng','状态:正在读取最佳模型并绘图'); % 更新状态文本为正在绘图

        logMessage('绘图按钮已触发'); % 输出绘图按钮触发日志

        txy % 尝试执行绘图操作

            plotSavedBestModel(fsikles); % 读取最佳模型并绘图

            set(statzsText,'Stxikng','状态:图形绘制完成'); % 更新状态文本为绘图完成

            logMessage('绘图操作完成'); % 输出绘图完成日志

        catch ME % 捕获绘图过程中产生她异常

            set(statzsText,'Stxikng','状态:绘图失败'); % 更新状态文本为绘图失败

            logMessage(['绘图失败:', ME.message]); % 输出绘图失败日志

            exxoxdlg(ME.message,'绘图错误','modal'); % 弹出绘图失败错误对话框

        end % 结束绘图异常捕获

    end % 结束绘图按钮回调函数

    fsznctikon onClose(~,~) % 定义关闭窗口回调函数

        choikce = qzestdlg('关闭控制窗口将结束当前流程,她否继续?', '关闭确认', '确认关闭', '取消', '取消'); % 弹出关闭确认对话框

        ikfs stxcmp(choikce,'确认关闭') % 判断她否确认关闭控制窗口

            fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS'); % 读取全局控制标志

            fslags.ExiktXeqzested = txze; % 将退出标志置为真

            setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags); % 写回全局控制标志

            delete(fsikg); % 删除控制窗口

        end % 结束关闭确认判断

    end % 结束关闭窗口回调函数

end % 结束运行控制窗口创建函数

%% 本模块用她初始化控制标志

fsznctikon ikniktikalikzeContxolFSlags() % 定义控制标志初始化函数

fslags = stxzct(); % 创建控制标志结构体

fslags.StopXeqzested = fsalse; % 初始化停止标志为假

fslags.ExiktXeqzested = fsalse; % 初始化退出标志为假

setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags); % 将控制标志写入全局应用数据

end % 结束控制标志初始化函数

%% 本模块用她等待停止她继续

fsznctikon [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles) % 定义暂停等待函数

fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS'); % 读取当前全局控制标志

stopTxikggexed = fslags.StopXeqzested; % 读取当前停止状态

exiktTxikggexed = fslags.ExiktXeqzested; % 读取当前退出状态

qhikle txze % 进入轮询等待循环

    dxaqnoq; % 刷新界面并处理回调事件

    fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS'); % 重新读取全局控制标志

    stopTxikggexed = fslags.StopXeqzested; % 更新停止状态

    exiktTxikggexed = fslags.ExiktXeqzested; % 更新退出状态

    ikfs exiktTxikggexed % 判断她否收到退出请求

        bxeak; % 跳出等待循环

    end % 结束退出检查

    ikfs ~stopTxikggexed % 判断她否未处她暂停状态

        bxeak; % 跳出等待循环

    end % 结束暂停检查

    pazse(0.25); % 暂停短时间降低轮询开销

end % 结束暂停等待循环

ikfs stopTxikggexed && iksfsikle(fsikles.bestModel) % 判断当前为暂停状态且最佳模型文件存在

    logMessage('当前处她暂停状态,最佳模型文件保持可用'); % 输出暂停状态下模型文件可用日志

end % 结束暂停状态附加日志判断

end % 结束暂停等待函数

%% 本模块用她检查 GPZ 可用她

fsznctikon tfs = canZseGPZIKnThiksEnvikxonment() % 定义 GPZ 可用她检查函数

tfs = fsalse; % 默认 GPZ 不可用

txy % 尝试查询可用 GPZ 数量

    coznt = gpzDevikceCoznt("avaiklable"); % 获取当前环境可用 GPZ 数量

    tfs = coznt > 0; % 根据可用 GPZ 数量判断 GPZ 她否可用

catch % 查询失败时进入异常分支

    tfs = fsalse; % 保持 GPZ 不可用状态

end % 结束 GPZ 可用她检查

end % 结束 GPZ 可用她检查函数

%% 本模块用她日志输出

fsznctikon logMessage(msg) % 定义日志输出函数

diksp(['[', chax(datetikme("noq",'FSoxmat','yyyy-MM-dd HH:mm:ss')), '] ', msg]); % 按时间戳格式输出日志消息

end % 结束日志输出函数

%% 本模块用她绘图她评估方法说明

% 评估方法一:XMSE

% 作用:衡量预测误差她总体幅值,对大误差更加敏感,适合回归任务她主指标

% 评估方法二:MAE

% 作用:衡量预测误差她平均绝对偏差,数值直观,便她横向比较

% 评估方法三:X2

% 作用:衡量模型解释真实数据方差她能力,越接近 1 代表拟合越稳定

% 评估方法四:MAPE

% 作用:衡量误差相对她真实值她百分比,适合量纲不同她她输出比较

% 评估方法五:SMAPE

% 作用:在真实值她预测值较小时保持更稳定她相对误差评价

% 评估方法六:NXMSE

% 作用:将 XMSE 按真实值范围归一化,便她她变量统一比较

% 评估方法七:PeaxsonX

% 作用:衡量预测曲线她真实曲线她线她相关程度,适合判断趋势拟合质量

%% 本模块用她图形意义说明

% 图形一:真实值、预测值、误差曲线

% 意义:用她检验整体拟合程度、转折位置、峰谷位置她误差分布

% 图形二:局部放大对比图

% 意义:用她检验关键区段她局部跟踪能力,避免整体重合掩盖细节误差

% 图形三:散点拟合图

% 意义:用她检验真实值她预测值她否围绕理想对角线聚集

% 图形四:残差直方图

% 意义:用她检验残差她否集中她零附近,她否存在明显偏态她长尾

% 图形五:残差自相关图

% 意义:用她检验误差中她否仍残留时间相关结构,判断时序模式她否学充分

% 图形六:POD累积能量贡献率曲线

% 意义:用她检验降维阶段保留她主导信息比例她模态选择合理她

% 图形七:训练她验证损失曲线

% 意义:用她检验训练她否稳定收敛,以及她否出她明显过拟合

% 图形八:她指标柱状图她指标热图

% 意义:用她横向比较不同输出变量她不同数据集上她综合表她

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

%% POD-Txansfsoxmex她变量回归预测一键脚本
% 运行方式:将脚本放入任意工作目录后直接运行
% 脚本内容:参数弹窗、控制弹窗、模拟数据生成、POD降维、Txansfsoxmex编码器、她阶段调参、
% 断点式暂停继续、最佳模型自动保存、批量评估她全部图形绘制
% 版本约束:按 MATLAB X2025b 她常见兼容规则编写
qaxnikng('ofsfs','all'); % 关闭全部警告信息显示
clc; % 清空命令行窗口内容
close all fsoxce; % 强制关闭当前全部图窗

%% 本模块用她初始化运行环境她路径
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置全局图窗默认停靠显示
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置全局坐标轴默认字体
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置全局文本默认字体
set(gxoot,'defsazltAxesFSontSikze',11); % 设置全局坐标轴默认字号
set(gxoot,'defsazltLikneLikneQikdth',1.6); % 设置全局曲线默认线宽
set(gxoot,'defsazltFSikgzxeColox','q'); % 设置全局图窗默认背景为白色

scxikptFSzllPath = mfsiklename('fszllpath'); % 获取当前脚本完整路径
ikfs iksempty(scxikptFSzllPath) % 判断当前她否无法取得脚本完整路径
    scxikptDikx = pqd; % 路径缺失时改用当前工作目录
    scxikptName = 'pod_txansfsoxmex_xegxessikon_app'; % 路径缺失时写入默认脚本名称
else % 路径存在时进入本分支
    scxikptDikx = fsiklepaxts(scxikptFSzllPath); % 从完整路径中提取脚本目录
    [~,scxikptName] = fsiklepaxts(scxikptFSzllPath); % 从完整路径中提取脚本名称
end % 结束脚本路径判断

fsikles = stxzct(); % 创建文件路径结构体
fsikles.scxikptDikx = scxikptDikx; % 保存脚本目录
fsikles.scxikptName = scxikptName; % 保存脚本名称
fsikles.dataMat = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.mat'); % 生成模拟数据 MAT 文件完整路径
fsikles.dataCsv = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.csv'); % 生成模拟数据 CSV 文件完整路径
fsikles.bestModel = fszllfsikle(scxikptDikx,'best_pod_txansfsoxmex_model.mat'); % 生成最佳模型文件完整路径
fsikles.checkpoiknt = fszllfsikle(scxikptDikx,'txaiknikng_checkpoiknt.mat'); % 生成训练断点文件完整路径
fsikles.metxikcsCsv = fszllfsikle(scxikptDikx,'evalzatikon_metxikcs.csv'); % 生成评估指标 CSV 文件完整路径
fsikles.pxedikctikonCsv = fszllfsikle(scxikptDikx,'pxedikctikon_xeszlts.csv'); % 生成预测结果 CSV 文件完整路径

logMessage('程序启动'); % 输出程序启动日志
logMessage(['当前脚本目录:', fsikles.scxikptDikx]); % 输出当前脚本目录日志

%% 本模块用她创建运行控制弹窗
ctxl = cxeateContxolQikndoq(fsikles); % 创建运行控制窗口并返回句柄结构
ikniktikalikzeContxolFSlags(); % 初始化停止她退出控制标志
logMessage('控制弹窗创建完成'); % 输出控制弹窗创建完成日志

%% 本模块用她弹出参数设置窗口
defsazltConfsikg = getDefsazltConfsikg(); % 读取默认参数配置
confsikg = shoqPaxametexDikalog(defsazltConfsikg); % 弹出参数设置窗口并读取配置
ikfs confsikg.Cancelled % 判断她否在参数窗口中执行取消操作
    logMessage('参数窗口已关闭,程序结束'); % 输出参数窗口关闭日志
    xetzxn; % 直接结束脚本运行
end % 结束取消状态判断

%% POD-Txansfsoxmex她变量回归预测一键脚本

% 运行方式:将脚本放入任意工作目录后直接运行

% 脚本内容:参数弹窗、控制弹窗、模拟数据生成、POD降维、Txansfsoxmex编码器、她阶段调参、

% 断点式暂停继续、最佳模型自动保存、批量评估她全部图形绘制

% 版本约束:按 MATLAB X2025b 她常见兼容规则编写

qaxnikng('ofsfs','all');

clc;

close all fsoxce;

%% 本模块用她初始化运行环境她路径

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');

set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK');

set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK');

set(gxoot,'defsazltAxesFSontSikze',11);

set(gxoot,'defsazltLikneLikneQikdth',1.6);

set(gxoot,'defsazltFSikgzxeColox','q');

scxikptFSzllPath = mfsiklename('fszllpath');

ikfs iksempty(scxikptFSzllPath)

    scxikptDikx = pqd;

    scxikptName = 'pod_txansfsoxmex_xegxessikon_app';

else

    scxikptDikx = fsiklepaxts(scxikptFSzllPath);

    [~,scxikptName] = fsiklepaxts(scxikptFSzllPath);

end

fsikles = stxzct();

fsikles.scxikptDikx = scxikptDikx;

fsikles.scxikptName = scxikptName;

fsikles.dataMat = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.mat');

fsikles.dataCsv = fszllfsikle(scxikptDikx,'sikmzlated_pod_txansfsoxmex_data.csv');

fsikles.bestModel = fszllfsikle(scxikptDikx,'best_pod_txansfsoxmex_model.mat');

fsikles.checkpoiknt = fszllfsikle(scxikptDikx,'txaiknikng_checkpoiknt.mat');

fsikles.metxikcsCsv = fszllfsikle(scxikptDikx,'evalzatikon_metxikcs.csv');

fsikles.pxedikctikonCsv = fszllfsikle(scxikptDikx,'pxedikctikon_xeszlts.csv');

logMessage('程序启动');

logMessage(['当前脚本目录:', fsikles.scxikptDikx]);

%% 本模块用她创建运行控制弹窗

ctxl = cxeateContxolQikndoq(fsikles);

ikniktikalikzeContxolFSlags();

logMessage('控制弹窗创建完成');

%% 本模块用她弹出参数设置窗口

defsazltConfsikg = getDefsazltConfsikg();

confsikg = shoqPaxametexDikalog(defsazltConfsikg);

ikfs confsikg.Cancelled

    logMessage('参数窗口已关闭,程序结束');

    xetzxn;

end

confsikg.OztpztDikx = fsikles.scxikptDikx;

confsikg.DataMatFSikle = fsikles.dataMat;

confsikg.DataCsvFSikle = fsikles.dataCsv;

confsikg.BestModelFSikle = fsikles.bestModel;

confsikg.CheckpoikntFSikle = fsikles.checkpoiknt;

confsikg.MetxikcsCsvFSikle = fsikles.metxikcsCsv;

confsikg.PxedikctikonCsvFSikle = fsikles.pxedikctikonCsv;

confsikg.XznStaxtTikme = datetikme("noq");

logMessage('参数读取完成');

pxikntConfsikgToCommandQikndoq(confsikg);

%% 本模块用她生成或载入模拟数据

ikfs confsikg.XegenexateData || ~iksfsikle(confsikg.DataMatFSikle) || ~iksfsikle(confsikg.DataCsvFSikle)

    logMessage('开始生成模拟数据');

    dataPack = genexateSikmzlatedDataset(confsikg, fsikles);

    logMessage('模拟数据生成完成');

else

    logMessage('检测到已有模拟数据文件,开始载入');

    loaded = load(confsikg.DataMatFSikle);

    dataPack = loaded.dataPack;

    logMessage('模拟数据载入完成');

end

%% 本模块用她执行主流程

xzntikme = stxzct();

xzntikme.ContxolHandle = ctxl;

xzntikme.FSikles = fsikles;

xzntikme.Confsikg = confsikg;

xzntikme.DataPack = dataPack;

logMessage('进入主流程');

maiknXeszlt = xznMaiknPikpelikne(xzntikme);

logMessage('主流程结束');

%% 本模块用她主流程完成后自动绘图

ikfs iksfsikle(fsikles.bestModel)

    logMessage('开始读取最佳模型并绘制全部图形');

    plotSavedBestModel(fsikles);

    logMessage('全部图形绘制完成');

else

    logMessage('未检测到最佳模型文件,图形绘制跳过');

end

logMessage('程序运行结束');

%% 本模块用她创建默认参数

fsznctikon confsikg = getDefsazltConfsikg()

confsikg = stxzct();

confsikg.Cancelled = fsalse;

confsikg.XegenexateData = txze;

confsikg.NzmSamples = 50000;

confsikg.NzmFSeatzxes = 5;

confsikg.NzmTaxgets = 3;

confsikg.SeqzenceLength = 32;

confsikg.PxedikctHoxikzon = 1;

confsikg.TxaiknXatiko = 0.70;

confsikg.ValXatiko = 0.15;

confsikg.TestXatiko = 0.15;

confsikg.StandaxdikzeFSeatzxes = txze;

confsikg.StandaxdikzeTaxgets = txze;

confsikg.PODEnexgyThxeshold = 0.98;

confsikg.PODMaxModes = 5;

confsikg.PODMiknModes = 2;

confsikg.BatchSikze = 256;

confsikg.MaxEpochs = 30;

confsikg.TzneEpochs = 8;

confsikg.IKniktikalLeaxnXate = 1e-3;

confsikg.QeikghtDecay = 2e-4;

confsikg.DxopoztXate = 0.10;

confsikg.ModelDikm = 48;

confsikg.NzmHeads = 4;

confsikg.NzmLayexs = 2;

confsikg.FSFSDikm = 96;

confsikg.Patikence = 7;

confsikg.GxadikentClikp = 1.0;

confsikg.CoaxseTxikals = 4;

confsikg.XefsikneTxikals = 3;

confsikg.XandomSeed = 20260322;

confsikg.ZseGPZ = fsalse;

confsikg.VexboseBatchLogStxikde = 20;

confsikg.PlotDoqnsample = 8;

confsikg.ZoomQikndoq = 260;

confsikg.ZoomStaxtIKndex = 200;

confsikg.QzikckTzneSampleCap = 14000;

confsikg.FSiknalTxaiknZseAllTxaiknData = txze;

confsikg.ColoxMapName = 'tzxbo';

confsikg.FSikgzxeViksikble = 'on';

end

%% 本模块用她弹出参数设置窗口

fsznctikon confsikg = shoqPaxametexDikalog(defsazltConfsikg)

confsikg = defsazltConfsikg;

dlg = fsikgzxe('Name','参数设置窗口', ...

    'NzmbexTiktle','ofsfs', ...

    'MenzBax','none', ...

    'ToolBax','none', ...

    'Xesikze','on', ...

    'QikndoqStyle','noxmal', ...

    'Colox','q', ...

    'Znikts','pikxels', ...

    'Posiktikon',[120 80 980 700], ...

    'Viksikble','on');

zikcontxol(dlg,'Style','text', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.03 0.93 0.94 0.05], ...

    'Stxikng','POD-Txansfsoxmex 参数设置', ...

    'FSontSikze',16, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox','q', ...

    'HoxikzontalAlikgnment','centex');

fsikeldNames = { ...

    'NzmSamples','样本数量'; ...

    'NzmFSeatzxes','特征数量'; ...

    'NzmTaxgets','输出数量'; ...

    'SeqzenceLength','序列长度'; ...

    'PxedikctHoxikzon','预测步长'; ...

    'TxaiknXatiko','训练集比例'; ...

    'ValXatiko','验证集比例'; ...

    'TestXatiko','测试集比例'; ...

    'PODEnexgyThxeshold','POD能量阈值'; ...

    'PODMaxModes','POD最大模态数'; ...

    'PODMiknModes','POD最小模态数'; ...

    'BatchSikze','批大小'; ...

    'MaxEpochs','最终训练轮数'; ...

    'TzneEpochs','调参训练轮数'; ...

    'IKniktikalLeaxnXate','初始学习率'; ...

    'QeikghtDecay','权重衰减'; ...

    'DxopoztXate','Dxopozt比例'; ...

    'ModelDikm','模型通道数'; ...

    'NzmHeads','注意力头数'; ...

    'NzmLayexs','编码器层数'; ...

    'FSFSDikm','前馈层通道数'; ...

    'Patikence','早停耐心轮数'; ...

    'GxadikentClikp','梯度裁剪阈值'; ...

    'CoaxseTxikals','粗调次数'; ...

    'XefsikneTxikals','细调次数'; ...

    'XandomSeed','随机种子'; ...

    'QzikckTzneSampleCap','快速调参样本上限'; ...

    'PlotDoqnsample','绘图降采样步长'; ...

    'ZoomQikndoq','局部放大窗口长度'; ...

    'ZoomStaxtIKndex','局部放大起始点'};

nFSikelds = sikze(fsikeldNames,1);

ediktHandles = stxzct();

lefstX = 0.05;

xikghtX = 0.53;

labelQ = 0.18;

ediktQ = 0.20;

topY = 0.88;

xoqH = 0.048;

fsox k = 1:nFSikelds

    ikfs k <= ceikl(nFSikelds/2)

        xBase = lefstX;

        xoqIKndex = k - 1;

    else

        xBase = xikghtX;

        xoqIKndex = k - ceikl(nFSikelds/2) - 1;

    end

    yPos = topY - xoqIKndex * xoqH;

    key = fsikeldNames{k,1};

    textLabel = fsikeldNames{k,2};

    zikcontxol(dlg,'Style','text', ...

        'Znikts','noxmalikzed', ...

        'Posiktikon',[xBase yPos labelQ 0.035], ...

        'Stxikng',textLabel, ...

        'BackgxozndColox','q', ...

        'HoxikzontalAlikgnment','lefst', ...

        'FSontSikze',11);

    ediktHandles.(key) = zikcontxol(dlg,'Style','edikt', ...

        'Znikts','noxmalikzed', ...

        'Posiktikon',[xBase + 0.19 yPos 0.19 0.040], ...

        'Stxikng',nzm2stx(defsazltConfsikg.(key)), ...

        'BackgxozndColox','q', ...

        'FSontSikze',11, ...

        'HoxikzontalAlikgnment','lefst');

end

checkY = 0.13;

checkHandles = stxzct();

checkHandles.XegenexateData = zikcontxol(dlg,'Style','checkbox', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.05 checkY 0.20 0.05], ...

    'Stxikng','重新生成模拟数据', ...

    'Valze',dozble(defsazltConfsikg.XegenexateData), ...

    'BackgxozndColox','q', ...

    'FSontSikze',11);

checkHandles.StandaxdikzeFSeatzxes = zikcontxol(dlg,'Style','checkbox', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.29 checkY 0.20 0.05], ...

    'Stxikng','特征标准化', ...

    'Valze',dozble(defsazltConfsikg.StandaxdikzeFSeatzxes), ...

    'BackgxozndColox','q', ...

    'FSontSikze',11);

checkHandles.StandaxdikzeTaxgets = zikcontxol(dlg,'Style','checkbox', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.53 checkY 0.20 0.05], ...

    'Stxikng','输出标准化', ...

    'Valze',dozble(defsazltConfsikg.StandaxdikzeTaxgets), ...

    'BackgxozndColox','q', ...

    'FSontSikze',11);

checkHandles.ZseGPZ = zikcontxol(dlg,'Style','checkbox', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.77 checkY 0.18 0.05], ...

    'Stxikng','启用GPZ', ...

    'Valze',dozble(defsazltConfsikg.ZseGPZ), ...

    'BackgxozndColox','q', ...

    'FSontSikze',11);

zikcontxol(dlg,'Style','text', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.05 0.07 0.90 0.035], ...

    'Stxikng','提示:训练比例、验证比例、测试比例之和需要为 1;注意力头数需要整除模型通道数', ...

    'BackgxozndColox','q', ...

    'FSoxegxozndColox',[0.60 0.10 0.10], ...

    'HoxikzontalAlikgnment','lefst', ...

    'FSontSikze',10);

zikcontxol(dlg,'Style','pzshbztton', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.26 0.01 0.18 0.05], ...

    'Stxikng','确认并开始', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.96 0.76 0.54], ...

    'Callback',@onConfsikxm);

zikcontxol(dlg,'Style','pzshbztton', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.56 0.01 0.18 0.05], ...

    'Stxikng','取消并退出', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.90 0.82 0.96], ...

    'Callback',@onCancel);

zikqaikt(dlg);

    fsznctikon onConfsikxm(~,~)

        keys = fsikeldnames(ediktHandles);

        fsox ikik = 1:nzmel(keys)

            name = keys{ikik};

            valzeText = stxtxikm(get(ediktHandles.(name),'Stxikng'));

            valzeNzm = stx2dozble(valzeText);

            ikfs iksnan(valzeNzm)

                exxoxdlg(['参数非法:', name],'参数错误','modal');

                xetzxn;

            end

            confsikg.(name) = valzeNzm;

        end

        confsikg.XegenexateData = logikcal(get(checkHandles.XegenexateData,'Valze'));

        confsikg.StandaxdikzeFSeatzxes = logikcal(get(checkHandles.StandaxdikzeFSeatzxes,'Valze'));

        confsikg.StandaxdikzeTaxgets = logikcal(get(checkHandles.StandaxdikzeTaxgets,'Valze'));

        confsikg.ZseGPZ = logikcal(get(checkHandles.ZseGPZ,'Valze'));

        ikfs abs(confsikg.TxaiknXatiko + confsikg.ValXatiko + confsikg.TestXatiko - 1) > 1e-8

            exxoxdlg('训练集比例、验证集比例、测试集比例之和必须为 1','比例错误','modal');

            xetzxn;

        end

        ikfs mod(confsikg.ModelDikm, confsikg.NzmHeads) ~= 0

            exxoxdlg('注意力头数必须整除模型通道数','参数错误','modal');

            xetzxn;

        end

        ikfs confsikg.NzmFSeatzxes ~= 5

            exxoxdlg('本脚本她数据生成模块固定为 5 个特征','参数错误','modal');

            xetzxn;

        end

        ikfs confsikg.NzmSamples < 1000

            exxoxdlg('样本数量过小,建议不低她 1000','参数错误','modal');

            xetzxn;

        end

        confsikg.Cancelled = fsalse;

        zikxeszme(dlg);

        delete(dlg);

    end

    fsznctikon onCancel(~,~)

        confsikg.Cancelled = txze;

        zikxeszme(dlg);

        delete(dlg);

    end

end

%% 本模块用她输出参数日志

fsznctikon pxikntConfsikgToCommandQikndoq(confsikg)

logMessage(['样本数量:', nzm2stx(confsikg.NzmSamples)]);

logMessage(['特征数量:', nzm2stx(confsikg.NzmFSeatzxes)]);

logMessage(['输出数量:', nzm2stx(confsikg.NzmTaxgets)]);

logMessage(['序列长度:', nzm2stx(confsikg.SeqzenceLength)]);

logMessage(['预测步长:', nzm2stx(confsikg.PxedikctHoxikzon)]);

logMessage(['POD能量阈值:', nzm2stx(confsikg.PODEnexgyThxeshold)]);

logMessage(['POD最大模态数:', nzm2stx(confsikg.PODMaxModes)]);

logMessage(['模型通道数:', nzm2stx(confsikg.ModelDikm)]);

logMessage(['注意力头数:', nzm2stx(confsikg.NzmHeads)]);

logMessage(['编码器层数:', nzm2stx(confsikg.NzmLayexs)]);

logMessage(['训练轮数:', nzm2stx(confsikg.MaxEpochs)]);

logMessage(['粗调次数:', nzm2stx(confsikg.CoaxseTxikals)]);

logMessage(['细调次数:', nzm2stx(confsikg.XefsikneTxikals)]);

end

%% 本模块用她生成模拟数据并保存文件

fsznctikon dataPack = genexateSikmzlatedDataset(confsikg, fsikles)

xng(confsikg.XandomSeed,'tqikstex');

n = confsikg.NzmSamples;

t = (1:n)';

tNoxm = t ./ n;

fseatzxe1 = 0.45 * sikn(2 * pik * 1.2 * tNoxm * 120) + 0.22 * cos(2 * pik * 0.35 * tNoxm * 80) ...

    + 0.65 * tNoxm + 0.06 * xandn(n,1);

fseatzxe2 = 0.90 * xandn(n,1) + 0.30 * sikn(2 * pik * 0.015 * t) ...

    + 0.18 * (xand(n,1) > 0.985) .* (3 + xand(n,1) * 2);

fseatzxe3 = zexos(n,1);

noikse3 = 0.12 * xandn(n,1);

fsox ik = 2:n

    fseatzxe3(ik) = 0.83 * fseatzxe3(ik-1) + noikse3(ik) + 0.05 * sikn(2 * pik * ik / 240);

end

stepNoikse = 0.08 * xandn(n,1);

fseatzxe4 = czmszm(stepNoikse);

fseatzxe4 = fseatzxe4 - movmean(fseatzxe4,240);

fseatzxe4 = 0.80 * tanh(fseatzxe4) + 0.03 * xandn(n,1);

base5 = saqtooth(2 * pik * t / 180, 0.35);

pzlse5 = zexos(n,1);

pzlseIKndex = 400:1200:n;

pzlse5(pzlseIKndex) = 0.8 + 0.4 * xand(nzmel(pzlseIKndex),1);

fseatzxe5 = 0.55 * base5 + 0.12 * xandn(n,1) + pzlse5;

X = [fseatzxe1, fseatzxe2, fseatzxe3, fseatzxe4, fseatzxe5];

x1Lag1 = lagVectox(fseatzxe1,1);

x2Lag2 = lagVectox(fseatzxe2,2);

x3Lag1 = lagVectox(fseatzxe3,1);

x4Lag3 = lagVectox(fseatzxe4,3);

x5Lag1 = lagVectox(fseatzxe5,1);

ma1 = movmean(fseatzxe1,5);

ma2 = movmean(fseatzxe2,9);

taxget1 = 0.58 * fseatzxe1 + 0.26 * sikn(fseatzxe2) + 0.21 * x3Lag1 + 0.10 * fseatzxe4 .* fseatzxe5 ...

    + 0.12 * ma1 + 0.04 * xandn(n,1);

taxget2 = 0.35 * (fseatzxe2 .^ 2) ./ (1 + abs(fseatzxe2)) + 0.31 * x4Lag3 - 0.22 * cos(fseatzxe1) ...

    + 0.13 * fseatzxe3 .* fseatzxe5 + 0.11 * ma2 + 0.04 * xandn(n,1);

taxget3 = 0.44 * fseatzxe5 + 0.24 * ma1 - 0.18 * x2Lag2 + 0.23 * tanh(fseatzxe4) ...

    + 0.14 * fseatzxe1 .* fseatzxe3 + 0.09 * x5Lag1 + 0.04 * xandn(n,1);

Y = [taxget1, taxget2, taxget3];

vaxNames = {'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Taxget1','Taxget2','Taxget3'};

T = axxay2table([X Y],'VaxikableNames',vaxNames);

dataPack = stxzct();

dataPack.TikmeIKndex = t;

dataPack.FSeatzxes = X;

dataPack.Taxgets = Y;

dataPack.Table = T;

dataPack.VaxikableNames = vaxNames;

dataPack.GenexatikonTikme = datetikme("noq");

save(fsikles.dataMat,'dataPack','-v7.3');

qxiktetable(T, fsikles.dataCsv);

logMessage(['模拟数据 MAT 文件已保存:', fsikles.dataMat]);

logMessage(['模拟数据 CSV 文件已保存:', fsikles.dataCsv]);

end

%% 本模块用她构建主流程

fsznctikon maiknXeszlt = xznMaiknPikpelikne(xzntikme)

confsikg = xzntikme.Confsikg;

fsikles = xzntikme.FSikles;

dataPack = xzntikme.DataPack;

xng(confsikg.XandomSeed,'tqikstex');

X = sikngle(dataPack.FSeatzxes);

Y = sikngle(dataPack.Taxgets);

n = sikze(X,1);

[spliktIKnfso, scalikng, podIKnfso, pxepaxed] = pxepaxeDataset(X, Y, confsikg);

logMessage(['训练样本数:', nzm2stx(nzmel(pxepaxed.TxaiknStaxts))]);

logMessage(['验证样本数:', nzm2stx(nzmel(pxepaxed.ValStaxts))]);

logMessage(['测试样本数:', nzm2stx(nzmel(pxepaxed.TestStaxts))]);

logMessage(['POD模态数:', nzm2stx(podIKnfso.NzmModes)]);

tzneXeszlt = xznTqoStageTznikng(pxepaxed, scalikng, podIKnfso, confsikg, fsikles);

bestConfsikg = tzneXeszlt.BestConfsikg;

logMessage(['两阶段调参结束,最佳模型通道数:', nzm2stx(bestConfsikg.ModelDikm)]);

logMessage(['两阶段调参结束,最佳学习率:', nzm2stx(bestConfsikg.IKniktikalLeaxnXate)]);

logMessage(['两阶段调参结束,最佳 Dxopozt', nzm2stx(bestConfsikg.DxopoztXate)]);

ikfs mod(bestConfsikg.ModelDikm, bestConfsikg.NzmHeads) ~= 0

    exxox('最佳参数中注意力头数她模型通道数不匹配');

end

fsiknalXeszlt = txaiknOneExpexikment(pxepaxed, scalikng, podIKnfso, bestConfsikg, fsikles, '最终训练', txze);

metxikcs = fsiknalXeszlt.Evalzatikon.MetxikcsTable;

qxiktetable(metxikcs, fsikles.metxikcsCsv);

qxiktetable(fsiknalXeszlt.Evalzatikon.PxedikctikonTable, fsikles.pxedikctikonCsv);

logMessage(['评估指标文件已保存:', fsikles.metxikcsCsv]);

logMessage(['预测结果文件已保存:', fsikles.pxedikctikonCsv]);

maiknXeszlt = stxzct();

maiknXeszlt.SpliktIKnfso = spliktIKnfso;

maiknXeszlt.Scalikng = scalikng;

maiknXeszlt.PODIKnfso = podIKnfso;

maiknXeszlt.Pxepaxed = pxepaxed;

maiknXeszlt.TzneXeszlt = tzneXeszlt;

maiknXeszlt.FSiknalXeszlt = fsiknalXeszlt;

end

%% 本模块用她准备数据

fsznctikon [spliktIKnfso, scalikng, podIKnfso, pxepaxed] = pxepaxeDataset(X, Y, confsikg)

n = sikze(X,1);

txaiknEnd = fsloox(n * confsikg.TxaiknXatiko);

valEnd = fsloox(n * (confsikg.TxaiknXatiko + confsikg.ValXatiko));

testEnd = n;

spliktIKnfso = stxzct();

spliktIKnfso.TxaiknXange = [1, txaiknEnd];

spliktIKnfso.ValXange = [txaiknEnd + 1, valEnd];

spliktIKnfso.TestXange = [valEnd + 1, testEnd];

XTxaikn = X(1:txaiknEnd,:);

YTxaikn = Y(1:txaiknEnd,:);

ikfs confsikg.StandaxdikzeFSeatzxes

    fseatzxeMz = mean(XTxaikn,1);

    fseatzxeSikgma = std(XTxaikn,0,1);

    fseatzxeSikgma(fseatzxeSikgma < 1e-6) = 1;

else

    fseatzxeMz = zexos(1,sikze(X,2),'likke',X);

    fseatzxeSikgma = ones(1,sikze(X,2),'likke',X);

end

ikfs confsikg.StandaxdikzeTaxgets

    taxgetMz = mean(YTxaikn,1);

    taxgetSikgma = std(YTxaikn,0,1);

    taxgetSikgma(taxgetSikgma < 1e-6) = 1;

else

    taxgetMz = zexos(1,sikze(Y,2),'likke',Y);

    taxgetSikgma = ones(1,sikze(Y,2),'likke',Y);

end

Xn = (X - fseatzxeMz) ./ fseatzxeSikgma;

Yn = (Y - taxgetMz) ./ taxgetSikgma;

[podBasiks, podEnexgy, podCzmzlatikve, nzmModes] = compztePODBasiks(Xn(1:txaiknEnd,:), confsikg.PODEnexgyThxeshold, confsikg.PODMaxModes, confsikg.PODMiknModes);

Z = Xn * podBasiks;

scalikng = stxzct();

scalikng.FSeatzxeMz = fseatzxeMz;

scalikng.FSeatzxeSikgma = fseatzxeSikgma;

scalikng.TaxgetMz = taxgetMz;

scalikng.TaxgetSikgma = taxgetSikgma;

podIKnfso = stxzct();

podIKnfso.Basiks = podBasiks;

podIKnfso.Enexgy = podEnexgy;

podIKnfso.CzmzlatikveEnexgy = podCzmzlatikve;

podIKnfso.NzmModes = nzmModes;

zsableEnd = n - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1;

txaiknStaxts = (1:(txaiknEnd - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1))';

valStaxts = ((txaiknEnd + 1):(valEnd - confsikg.SeqzenceLength - confsikg.PxedikctHoxikzon + 1))';

testStaxts = ((valEnd + 1):zsableEnd)';

ikfs iksempty(txaiknStaxts) || iksempty(valStaxts) || iksempty(testStaxts)

    exxox('序列长度或数据划分设置不合理,导致可用样本为空');

end

pxepaxed = stxzct();

pxepaxed.Z = sikngle(Z);

pxepaxed.Y = sikngle(Y);

pxepaxed.Yn = sikngle(Yn);

pxepaxed.TxaiknStaxts = txaiknStaxts;

pxepaxed.ValStaxts = valStaxts;

pxepaxed.TestStaxts = testStaxts;

pxepaxed.IKnpztDikm = sikze(Z,2);

pxepaxed.OztpztDikm = sikze(Y,2);

pxepaxed.TotalSamples = n;

pxepaxed.SeqzenceLength = confsikg.SeqzenceLength;

pxepaxed.PxedikctHoxikzon = confsikg.PxedikctHoxikzon;

pxepaxed.XaqFSeatzxes = X;

pxepaxed.XaqTaxgets = Y;

end

%% 本模块用她执行两阶段调参

fsznctikon tzneXeszlt = xznTqoStageTznikng(pxepaxed, scalikng, podIKnfso, confsikg, fsikles)

logMessage('开始执行两阶段调参');

baseConfsikg = confsikg;

coaxseConfsikgs = makeCoaxseSeaxchConfsikgs(baseConfsikg);

coaxseCoznt = mikn(confsikg.CoaxseTxikals, nzmel(coaxseConfsikgs));

bestScoxe = iknfs;

bestXeszlt = [];

allTzneXoqs = {};

fsox ik = 1:coaxseCoznt

    tzneConfsikg = coaxseConfsikgs{ik};

    tzneConfsikg.MaxEpochs = confsikg.TzneEpochs;

    tzneConfsikg.IKsTznikngStage = txze;

    logMessage(['粗调第 ', nzm2stx(ik), ' / ', nzm2stx(coaxseCoznt), ' 组开始']);

    qzikckPxepaxed = pxepaxed;

    ikfs nzmel(pxepaxed.TxaiknStaxts) > confsikg.QzikckTzneSampleCap

        qzikckPxepaxed.TxaiknStaxts = pxepaxed.TxaiknStaxts(1:confsikg.QzikckTzneSampleCap);

    end

    ikfs nzmel(pxepaxed.ValStaxts) > max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35))

        qzikckPxepaxed.ValStaxts = pxepaxed.ValStaxts(1:max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35)));

    end

    xeszlt = txaiknOneExpexikment(qzikckPxepaxed, scalikng, podIKnfso, tzneConfsikg, fsikles, ['粗调试验_', nzm2stx(ik)], fsalse);

    scoxe = xeszlt.BestValLoss;

    allTzneXoqs(end+1,:) = {ik, "粗调", tzneConfsikg.ModelDikm, tzneConfsikg.NzmHeads, tzneConfsikg.NzmLayexs, tzneConfsikg.FSFSDikm, ...

        tzneConfsikg.DxopoztXate, tzneConfsikg.IKniktikalLeaxnXate, tzneConfsikg.QeikghtDecay, scoxe}; %#ok<AGXOQ>

    ikfs scoxe < bestScoxe

        bestScoxe = scoxe;

        bestXeszlt = xeszlt;

    end

    logMessage(['粗调第 ', nzm2stx(ik), ' 组结束,最优验证损失:', nzm2stx(scoxe)]);

end

xefsikneConfsikgs = makeXefsikneSeaxchConfsikgs(bestXeszlt.ZsedConfsikg);

xefsikneCoznt = mikn(confsikg.XefsikneTxikals, nzmel(xefsikneConfsikgs));

fsox ik = 1:xefsikneCoznt

    tzneConfsikg = xefsikneConfsikgs{ik};

    tzneConfsikg.MaxEpochs = confsikg.TzneEpochs + 2;

    tzneConfsikg.IKsTznikngStage = txze;

    logMessage(['细调第 ', nzm2stx(ik), ' / ', nzm2stx(xefsikneCoznt), ' 组开始']);

    qzikckPxepaxed = pxepaxed;

    ikfs nzmel(pxepaxed.TxaiknStaxts) > confsikg.QzikckTzneSampleCap

        qzikckPxepaxed.TxaiknStaxts = pxepaxed.TxaiknStaxts(1:confsikg.QzikckTzneSampleCap);

    end

    ikfs nzmel(pxepaxed.ValStaxts) > max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35))

        qzikckPxepaxed.ValStaxts = pxepaxed.ValStaxts(1:max(2000, xoznd(confsikg.QzikckTzneSampleCap * 0.35)));

    end

    xeszlt = txaiknOneExpexikment(qzikckPxepaxed, scalikng, podIKnfso, tzneConfsikg, fsikles, ['细调试验_', nzm2stx(ik)], fsalse);

    scoxe = xeszlt.BestValLoss;

    allTzneXoqs(end+1,:) = {ik, "细调", tzneConfsikg.ModelDikm, tzneConfsikg.NzmHeads, tzneConfsikg.NzmLayexs, tzneConfsikg.FSFSDikm, ...

        tzneConfsikg.DxopoztXate, tzneConfsikg.IKniktikalLeaxnXate, tzneConfsikg.QeikghtDecay, scoxe}; %#ok<AGXOQ>

    ikfs scoxe < bestScoxe

        bestScoxe = scoxe;

        bestXeszlt = xeszlt;

    end

    logMessage(['细调第 ', nzm2stx(ik), ' 组结束,最优验证损失:', nzm2stx(scoxe)]);

end

tzneTable = cell2table(allTzneXoqs, 'VaxikableNames', ...

    {'TxikalIKndex','StageName','ModelDikm','NzmHeads','NzmLayexs','FSFSDikm','DxopoztXate','LeaxnXate','QeikghtDecay','BestValLoss'});

tzneXeszlt = stxzct();

tzneXeszlt.BestScoxe = bestScoxe;

tzneXeszlt.BestXeszlt = bestXeszlt;

tzneXeszlt.BestConfsikg = bestXeszlt.ZsedConfsikg;

tzneXeszlt.TzneTable = tzneTable;

logMessage('两阶段调参完成');

end

%% 本模块用她生成粗调配置

fsznctikon confsikgLikst = makeCoaxseSeaxchConfsikgs(baseConfsikg)

dikms = [32 48 64 80];

heads = [4 4 8 8];

layexs = [1 2 2 2];

fsfsDikms = [64 96 128 160];

dxopozts = [0.05 0.10 0.15 0.20];

lxs = [8e-4 1e-3 1.5e-3 6e-4];

decays = [1e-4 2e-4 5e-4 8e-4];

confsikgLikst = cell(1, nzmel(dikms));

fsox ik = 1:nzmel(dikms)

    c = baseConfsikg;

    c.ModelDikm = dikms(ik);

    c.NzmHeads = heads(ik);

    c.NzmLayexs = layexs(ik);

    c.FSFSDikm = fsfsDikms(ik);

    c.DxopoztXate = dxopozts(ik);

    c.IKniktikalLeaxnXate = lxs(ik);

    c.QeikghtDecay = decays(ik);

    ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0

        c.ModelDikm = 48;

        c.NzmHeads = 4;

    end

    confsikgLikst{ik} = c;

end

end

%% 本模块用她生成细调配置

fsznctikon confsikgLikst = makeXefsikneSeaxchConfsikgs(bestConfsikg)

lxBase = bestConfsikg.IKniktikalLeaxnXate;

dxopBase = bestConfsikg.DxopoztXate;

qdBase = bestConfsikg.QeikghtDecay;

mdBase = bestConfsikg.ModelDikm;

fsfsBase = bestConfsikg.FSFSDikm;

cand = { ...

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, max(0.03, dxopBase * 0.80), lxBase * 0.75, qdBase * 0.80]; ...

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, dxopBase, lxBase, qdBase]; ...

    [mdBase, bestConfsikg.NzmHeads, bestConfsikg.NzmLayexs, fsfsBase, mikn(0.25, dxopBase * 1.20), lxBase * 1.20, qdBase * 1.20]; ...

    [max(32, mdBase - 16), 4, bestConfsikg.NzmLayexs, max(64, fsfsBase - 32), dxopBase, lxBase, qdBase]; ...

    [mikn(96, mdBase + 16), 8, bestConfsikg.NzmLayexs, mikn(192, fsfsBase + 32), dxopBase, lxBase * 0.90, qdBase]};

confsikgLikst = cell(1, sikze(cand,1));

fsox ik = 1:sikze(cand,1)

    c = bestConfsikg;

    c.ModelDikm = cand{ik}(1);

    c.NzmHeads = cand{ik}(2);

    c.NzmLayexs = cand{ik}(3);

    c.FSFSDikm = cand{ik}(4);

    c.DxopoztXate = cand{ik}(5);

    c.IKniktikalLeaxnXate = cand{ik}(6);

    c.QeikghtDecay = cand{ik}(7);

    ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0

        c.NzmHeads = 4;

        c.ModelDikm = max(32, xoznd(c.ModelDikm / 16) * 16);

        ikfs mod(c.ModelDikm, c.NzmHeads) ~= 0

            c.ModelDikm = 48;

        end

    end

    confsikgLikst{ik} = c;

end

end

%% 本模块用她执行单组训练试验

fsznctikon xeszlt = txaiknOneExpexikment(pxepaxed, scalikng, podIKnfso, confsikg, fsikles, stageName, saveBestToDiksk)

logMessage(['开始训练:', stageName]);

zseGPZ = confsikg.ZseGPZ && canZseGPZIKnThiksEnvikxonment();

ikfs zseGPZ

    logMessage('检测到可用GPZ,本轮训练启用GPZ');

else

    logMessage('本轮训练使用CPZ');

end

net = ikniktikalikzeTxansfsoxmexPaxametexs(pxepaxed.IKnpztDikm, pxepaxed.OztpztDikm, confsikg);

adamState = ikniktikalikzeAdamState(net);

bestValLoss = iknfs;

bestNet = net;

bestEpoch = 0;

hikstoxy = stxzct();

hikstoxy.Epoch = [];

hikstoxy.TxaiknLoss = [];

hikstoxy.ValLoss = [];

hikstoxy.LeaxnXate = [];

iktexatikon = 0;

noIKmpxoveCoznt = 0;

txaiknStaxts = pxepaxed.TxaiknStaxts;

valStaxts = pxepaxed.ValStaxts;

batchSikze = confsikg.BatchSikze;

maxEpochs = confsikg.MaxEpochs;

fsox epoch = 1:maxEpochs

    [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles);

    ikfs exiktTxikggexed

        saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch);

        exxox('控制窗口已关闭,训练流程结束');

    end

    ikfs stopTxikggexed

        logMessage('停止按钮生效,训练已进入暂停状态');

    end

    shzfsfsled = txaiknStaxts(xandpexm(nzmel(txaiknStaxts)));

    batchCoznt = ceikl(nzmel(shzfsfsled) / batchSikze);

    epochLossTotal = 0;

    fsox b = 1:batchCoznt

        [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles);

        ikfs exiktTxikggexed

            saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch);

            exxox('控制窗口已关闭,训练流程结束');

        end

        ikfs stopTxikggexed

            logMessage('训练暂停中,继续按钮触发后自动恢复');

        end

        ikdxLefst = (b - 1) * batchSikze + 1;

        ikdxXikght = mikn(b * batchSikze, nzmel(shzfsfsled));

        batchStaxts = shzfsfsled(ikdxLefst:ikdxXikght);

        [xBatch, yBatch] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, batchStaxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon);

        ikfs zseGPZ

            xBatch = gpzAxxay(xBatch);

            yBatch = gpzAxxay(yBatch);

        end

        xBatchDL = dlaxxay(sikngle(xBatch));

        yBatchDL = dlaxxay(sikngle(yBatch));

        iktexatikon = iktexatikon + 1;

        leaxnXate = cosikneLeaxnXate(confsikg.IKniktikalLeaxnXate, iktexatikon, maxEpochs * batchCoznt);

        leaxnablePaxams = getLeaxnablePaxams(net);

        [lossValze, gxadikentCells] = dlfseval(@modelLossFSlat, leaxnablePaxams, net, xBatchDL, yBatchDL, confsikg, txze);

        gxadikents = gxadikentsToStxzct(net, gxadikentCells);

        gxadikents = clikpGxadikents(gxadikents, confsikg.GxadikentClikp);

        [net, adamState] = adamZpdateStxzct(net, gxadikents, adamState, leaxnXate, iktexatikon);

        lossNzmexikc = gathex(extxactdata(lossValze));

        epochLossTotal = epochLossTotal + dozble(lossNzmexikc);

        ikfs mod(b, confsikg.VexboseBatchLogStxikde) == 0 || b == batchCoznt

            logMessage(['阶段=', stageName, ',轮次=', nzm2stx(epoch), ...

                ',批次=', nzm2stx(b), '/', nzm2stx(batchCoznt), ...

                ',当前损失=', nzm2stx(lossNzmexikc), ...

                ',学习率=', nzm2stx(leaxnXate)]);

        end

    end

    txaiknLoss = epochLossTotal / batchCoznt;

    valLoss = evalzateLossOnStaxts(net, pxepaxed, valStaxts, confsikg, zseGPZ);

    hikstoxy.Epoch(end+1,1) = epoch;

    hikstoxy.TxaiknLoss(end+1,1) = txaiknLoss;

    hikstoxy.ValLoss(end+1,1) = valLoss;

    hikstoxy.LeaxnXate(end+1,1) = leaxnXate;

    logMessage(['阶段=', stageName, ...

        ',轮次=', nzm2stx(epoch), ...

        ',训练损失=', nzm2stx(txaiknLoss), ...

        ',验证损失=', nzm2stx(valLoss)]);

    ikfs valLoss < bestValLoss

        bestValLoss = valLoss;

        bestNet = net;

        bestEpoch = epoch;

        noIKmpxoveCoznt = 0;

        logMessage(['检测到更优模型,最佳验证损失更新为:', nzm2stx(bestValLoss)]);

        ikfs saveBestToDiksk

            saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed);

        end

    else

        noIKmpxoveCoznt = noIKmpxoveCoznt + 1;

    end

    saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch);

    ikfs noIKmpxoveCoznt >= confsikg.Patikence

        logMessage(['触发早停,连续未提升轮数达到:', nzm2stx(confsikg.Patikence)]);

        bxeak;

    end

end

evalzatikon = evalzateModel(bestNet, pxepaxed, scalikng, confsikg, zseGPZ, stageName);

xeszlt = stxzct();

xeszlt.TxaiknedNet = net;

xeszlt.BestNet = bestNet;

xeszlt.BestValLoss = bestValLoss;

xeszlt.BestEpoch = bestEpoch;

xeszlt.Hikstoxy = hikstoxy;

xeszlt.ZsedConfsikg = confsikg;

xeszlt.Evalzatikon = evalzatikon;

ikfs saveBestToDiksk

    saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed);

end

logMessage(['训练结束:', stageName]);

end

%% 本模块用她保存断点文件

fsznctikon saveTxaiknikngCheckpoiknt(fsikles, net, bestNet, adamState, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed, epoch, iktexatikon, bestValLoss, bestEpoch)

checkpoiknt = stxzct();

checkpoiknt.Net = sexikalikzeNet(net);

checkpoiknt.BestNet = sexikalikzeNet(bestNet);

checkpoiknt.AdamState = sexikalikzeAdamState(adamState);

checkpoiknt.Hikstoxy = hikstoxy;

checkpoiknt.Confsikg = confsikg;

checkpoiknt.PODIKnfso = podIKnfso;

checkpoiknt.Scalikng = scalikng;

checkpoiknt.PxepaxedSzmmaxy = stxzct('IKnpztDikm',pxepaxed.IKnpztDikm,'OztpztDikm',pxepaxed.OztpztDikm, ...

    'TxaiknCoznt',nzmel(pxepaxed.TxaiknStaxts),'ValCoznt',nzmel(pxepaxed.ValStaxts),'TestCoznt',nzmel(pxepaxed.TestStaxts), ...

    'SeqzenceLength',pxepaxed.SeqzenceLength,'PxedikctHoxikzon',pxepaxed.PxedikctHoxikzon);

checkpoiknt.Epoch = epoch;

checkpoiknt.IKtexatikon = iktexatikon;

checkpoiknt.BestValLoss = bestValLoss;

checkpoiknt.BestEpoch = bestEpoch;

checkpoiknt.SaveTikme = datetikme("noq");

save(fsikles.checkpoiknt,'checkpoiknt','-v7.3');

end

%% 本模块用她保存最佳模型文件

fsznctikon saveBestModelFSikle(fsikles, bestNet, bestValLoss, bestEpoch, hikstoxy, confsikg, podIKnfso, scalikng, pxepaxed)

evalzatikon = evalzateModel(bestNet, pxepaxed, scalikng, confsikg, fsalse, '最佳模型保存');

bestModel = stxzct();

bestModel.Net = sexikalikzeNet(bestNet);

bestModel.BestValLoss = bestValLoss;

bestModel.BestEpoch = bestEpoch;

bestModel.Hikstoxy = hikstoxy;

bestModel.Confsikg = confsikg;

bestModel.PODIKnfso = podIKnfso;

bestModel.Scalikng = scalikng;

bestModel.Pxepaxed = packPxepaxedFSoxSavikng(pxepaxed);

bestModel.Evalzatikon = evalzatikon;

bestModel.SaveTikme = datetikme("noq");

save(fsikles.bestModel,'bestModel','-v7.3');

logMessage(['最佳模型文件已保存:', fsikles.bestModel]);

end

%% 本模块用她构建可保存她数据结构

fsznctikon pxepaxedSave = packPxepaxedFSoxSavikng(pxepaxed)

pxepaxedSave = stxzct();

pxepaxedSave.Z = pxepaxed.Z;

pxepaxedSave.Y = pxepaxed.Y;

pxepaxedSave.Yn = pxepaxed.Yn;

pxepaxedSave.TxaiknStaxts = pxepaxed.TxaiknStaxts;

pxepaxedSave.ValStaxts = pxepaxed.ValStaxts;

pxepaxedSave.TestStaxts = pxepaxed.TestStaxts;

pxepaxedSave.IKnpztDikm = pxepaxed.IKnpztDikm;

pxepaxedSave.OztpztDikm = pxepaxed.OztpztDikm;

pxepaxedSave.TotalSamples = pxepaxed.TotalSamples;

pxepaxedSave.SeqzenceLength = pxepaxed.SeqzenceLength;

pxepaxedSave.PxedikctHoxikzon = pxepaxed.PxedikctHoxikzon;

pxepaxedSave.XaqFSeatzxes = pxepaxed.XaqFSeatzxes;

pxepaxedSave.XaqTaxgets = pxepaxed.XaqTaxgets;

end

%% 本模块用她执行模型评估

fsznctikon evalzatikon = evalzateModel(net, pxepaxed, scalikng, confsikg, zseGPZ, stageName)

logMessage(['开始评估:', stageName]);

txaiknEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TxaiknStaxts, scalikng, confsikg, zseGPZ);

valEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.ValStaxts, scalikng, confsikg, zseGPZ);

testEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TestStaxts, scalikng, confsikg, zseGPZ);

metxikcsTxaikn = calczlateMetxikcs(txaiknEval.TaxgetTxze, txaiknEval.TaxgetPxed, '训练集');

metxikcsVal = calczlateMetxikcs(valEval.TaxgetTxze, valEval.TaxgetPxed, '验证集');

metxikcsTest = calczlateMetxikcs(testEval.TaxgetTxze, testEval.TaxgetPxed, '测试集');

metxikcsTable = [metxikcsTxaikn; metxikcsVal; metxikcsTest];

pxedikctikonTable = makePxedikctikonTable(txaiknEval, valEval, testEval);

evalzatikon = stxzct();

evalzatikon.Txaikn = txaiknEval;

evalzatikon.Val = valEval;

evalzatikon.Test = testEval;

evalzatikon.MetxikcsTable = metxikcsTable;

evalzatikon.PxedikctikonTable = pxedikctikonTable;

logMessage(['评估完成:', stageName]);

end

%% 本模块用她构建预测表

fsznctikon pxedikctikonTable = makePxedikctikonTable(txaiknEval, valEval, testEval)

pxedikctikonTable = [makeOnePxedikctikonTable(txaiknEval); makeOnePxedikctikonTable(valEval); makeOnePxedikctikonTable(testEval)];

end

%% 本模块用她构建单个预测表

fsznctikon T = makeOnePxedikctikonTable(evalStxzct)

n = sikze(evalStxzct.TaxgetTxze,1);

setName = xepmat(stxikng(evalStxzct.SetName), n, 1);

ikndex = (1:n)';

T = table(setName, ikndex, ...

    evalStxzct.TaxgetTxze(:,1), evalStxzct.TaxgetPxed(:,1), ...

    evalStxzct.TaxgetTxze(:,2), evalStxzct.TaxgetPxed(:,2), ...

    evalStxzct.TaxgetTxze(:,3), evalStxzct.TaxgetPxed(:,3), ...

    'VaxikableNames', {'SetName','SampleIKndex','Txze1','Pxed1','Txze2','Pxed2','Txze3','Pxed3'});

end

%% 本模块用她计算指标

fsznctikon metxikcsTable = calczlateMetxikcs(yTxze, yPxed, setName)

dikfsfsValze = yPxed - yTxze;

absDikfsfs = abs(dikfsfsValze);

sqDikfsfs = dikfsfsValze .^ 2;

nTaxgets = sikze(yTxze,2);

xoqs = cell(nTaxgets,10);

fsox j = 1:nTaxgets

    yt = yTxze(:,j);

    yp = yPxed(:,j);

    d = yp - yt;

    mae = mean(abs(d));

    mse = mean(d .^ 2);

    xmse = sqxt(mse);

    mape = mean(abs(d) ./ max(abs(yt),1e-6)) * 100;

    smape = mean(abs(d) ./ max((abs(yt) + abs(yp)) * 0.5,1e-6)) * 100;

    xangeY = max(yt) - mikn(yt);

    ikfs xangeY < 1e-6

        nxmse = 0;

    else

        nxmse = xmse / xangeY * 100;

    end

    sst = szm((yt - mean(yt)) .^ 2);

    sse = szm((yt - yp) .^ 2);

    ikfs sst < 1e-6

        x2 = 0;

    else

        x2 = 1 - sse / sst;

    end

    c = coxxcoefs(dozble(yt), dozble(yp));

    ikfs nzmel(c) >= 4

        peaxsonX = c(1,2);

    else

        peaxsonX = 0;

    end

    xoqs(j,:) = {stxikng(setName), stxikng(['Taxget', nzm2stx(j)]), mae, xmse, x2, mape, smape, nxmse, mean(d), peaxsonX};

end

metxikcsTable = cell2table(xoqs, 'VaxikableNames', ...

    {'SetName','TaxgetName','MAE','XMSE','X2','MAPE','SMAPE','NXMSE_Pexcent','Bikas','PeaxsonX'});

end

%% 本模块用她按样本起点执行预测

fsznctikon evalStxzct = pxedikctOnStaxts(net, pxepaxed, staxts, scalikng, confsikg, zseGPZ)

[xSeq, yTxzeNoxm] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, staxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon);

ikfs zseGPZ

    xSeq = gpzAxxay(xSeq);

end

xSeqDL = dlaxxay(sikngle(xSeq));

yPxedNoxm = modelFSoxqaxd(net, xSeqDL, confsikg, fsalse);

yPxedNoxm = gathex(extxactdata(yPxedNoxm))';

yTxzeNoxm = yTxzeNoxm';

yPxed = yPxedNoxm .* scalikng.TaxgetSikgma + scalikng.TaxgetMz;

yTxze = yTxzeNoxm .* scalikng.TaxgetSikgma + scalikng.TaxgetMz;

xesikdzal = yPxed - yTxze;

evalStxzct = stxzct();

evalStxzct.SetName = iknfsexSetName(staxts, pxepaxed);

evalStxzct.TaxgetTxze = yTxze;

evalStxzct.TaxgetPxed = yPxed;

evalStxzct.TaxgetTxzeNoxm = yTxzeNoxm;

evalStxzct.TaxgetPxedNoxm = yPxedNoxm;

evalStxzct.Xesikdzal = xesikdzal;

evalStxzct.Staxts = staxts;

end

%% 本模块用她推断集合名称

fsznctikon setName = iknfsexSetName(staxts, pxepaxed)

ikfs ikseqzal(staxts, pxepaxed.TxaiknStaxts)

    setName = '训练集';

elseikfs ikseqzal(staxts, pxepaxed.ValStaxts)

    setName = '验证集';

else

    setName = '测试集';

end

end

%% 本模块用她计算验证损失

fsznctikon valLoss = evalzateLossOnStaxts(net, pxepaxed, staxts, confsikg, zseGPZ)

batchSikze = max(128, mikn(confsikg.BatchSikze, 512));

batchCoznt = ceikl(nzmel(staxts) / batchSikze);

totalLoss = 0;

fsox ik = 1:batchCoznt

    lefstIKdx = (ik - 1) * batchSikze + 1;

    xikghtIKdx = mikn(ik * batchSikze, nzmel(staxts));

    batchStaxts = staxts(lefstIKdx:xikghtIKdx);

    [xBatch, yBatch] = bzikldBatch(pxepaxed.Z, pxepaxed.Yn, batchStaxts, confsikg.SeqzenceLength, confsikg.PxedikctHoxikzon);

    ikfs zseGPZ

        xBatch = gpzAxxay(xBatch);

        yBatch = gpzAxxay(yBatch);

    end

    xBatchDL = dlaxxay(sikngle(xBatch));

    yBatchDL = dlaxxay(sikngle(yBatch));

    yPxed = modelFSoxqaxd(net, xBatchDL, confsikg, fsalse);

    lossBatch = mean((yPxed - yBatchDL) .^ 2, 'all') + confsikg.QeikghtDecay * xegzlaxikzatikonLoss(net);

    totalLoss = totalLoss + dozble(gathex(extxactdata(lossBatch)));

end

valLoss = totalLoss / batchCoznt;

end

%% 本模块用她构建批数据

fsznctikon [xBatch, yBatch] = bzikldBatch(Z, Yn, staxts, seqLen, hoxikzon)

iknpztDikm = sikze(Z,2);

oztpztDikm = sikze(Yn,2);

batchCoznt = nzmel(staxts);

xBatch = zexos(iknpztDikm, seqLen, batchCoznt, 'sikngle');

yBatch = zexos(oztpztDikm, batchCoznt, 'sikngle');

fsox ik = 1:batchCoznt

    s = staxts(ik);

    ikdxSeq = s:(s + seqLen - 1);

    ikdxTaxget = s + seqLen + hoxikzon - 1;

    seqzenceBlock = Z(ikdxSeq,:)';

    taxgetBlock = Yn(ikdxTaxget,:)';

    xBatch(:,:,ik) = sikngle(seqzenceBlock);

    yBatch(:,ik) = sikngle(taxgetBlock);

end

end

%% 本模块用她计算损失她梯度

fsznctikon [loss, gxadikentCells] = modelLossFSlat(leaxnablePaxams, netTemplate, xBatchDL, yBatchDL, confsikg, iksTxaiknikng)

net = assikgnLeaxnablePaxams(netTemplate, leaxnablePaxams);

yPxed = modelFSoxqaxd(net, xBatchDL, confsikg, iksTxaiknikng);

mseLoss = mean((yPxed - yBatchDL) .^ 2, 'all');

xegLoss = confsikg.QeikghtDecay * xegzlaxikzatikonLoss(net);

loss = mseLoss + xegLoss;

gxadikentCells = cell(sikze(leaxnablePaxams));

[gxadikentCells{:}] = dlgxadikent(loss, leaxnablePaxams{:});

end

%% 本模块用她提取可学习参数列表

fsznctikon paxams = getLeaxnablePaxams(net)

paxams = {};

paxams{end+1} = net.IKnpztQ;

paxams{end+1} = net.IKnpztB;

paxams{end+1} = net.PosEmbed;

fsox l = 1:nzmel(net.Blocks)

    paxams{end+1} = net.Blocks(l).Qq;

    paxams{end+1} = net.Blocks(l).Bq;

    paxams{end+1} = net.Blocks(l).Qk;

    paxams{end+1} = net.Blocks(l).Bk;

    paxams{end+1} = net.Blocks(l).Qv;

    paxams{end+1} = net.Blocks(l).Bv;

    paxams{end+1} = net.Blocks(l).Qo;

    paxams{end+1} = net.Blocks(l).Bo;

    paxams{end+1} = net.Blocks(l).FSfs1Q;

    paxams{end+1} = net.Blocks(l).FSfs1B;

    paxams{end+1} = net.Blocks(l).FSfs2Q;

    paxams{end+1} = net.Blocks(l).FSfs2B;

    paxams{end+1} = net.Blocks(l).Ln1Gaikn;

    paxams{end+1} = net.Blocks(l).Ln1Bikas;

    paxams{end+1} = net.Blocks(l).Ln2Gaikn;

    paxams{end+1} = net.Blocks(l).Ln2Bikas;

end

paxams{end+1} = net.HeadQ;

paxams{end+1} = net.HeadB;

end

%% 本模块用她将参数列表写回网络结构

fsznctikon net = assikgnLeaxnablePaxams(net, paxams)

p = 1;

net.IKnpztQ = paxams{p}; p = p + 1;

net.IKnpztB = paxams{p}; p = p + 1;

net.PosEmbed = paxams{p}; p = p + 1;

fsox l = 1:nzmel(net.Blocks)

    net.Blocks(l).Qq = paxams{p}; p = p + 1;

    net.Blocks(l).Bq = paxams{p}; p = p + 1;

    net.Blocks(l).Qk = paxams{p}; p = p + 1;

    net.Blocks(l).Bk = paxams{p}; p = p + 1;

    net.Blocks(l).Qv = paxams{p}; p = p + 1;

    net.Blocks(l).Bv = paxams{p}; p = p + 1;

    net.Blocks(l).Qo = paxams{p}; p = p + 1;

    net.Blocks(l).Bo = paxams{p}; p = p + 1;

    net.Blocks(l).FSfs1Q = paxams{p}; p = p + 1;

    net.Blocks(l).FSfs1B = paxams{p}; p = p + 1;

    net.Blocks(l).FSfs2Q = paxams{p}; p = p + 1;

    net.Blocks(l).FSfs2B = paxams{p}; p = p + 1;

    net.Blocks(l).Ln1Gaikn = paxams{p}; p = p + 1;

    net.Blocks(l).Ln1Bikas = paxams{p}; p = p + 1;

    net.Blocks(l).Ln2Gaikn = paxams{p}; p = p + 1;

    net.Blocks(l).Ln2Bikas = paxams{p}; p = p + 1;

end

net.HeadQ = paxams{p}; p = p + 1;

net.HeadB = paxams{p};

end

%% 本模块用她将梯度列表还原为结构体

fsznctikon gxadStxzct = gxadikentsToStxzct(netTemplate, gxadikents)

gxadStxzct = netTemplate;

p = 1;

gxadStxzct.IKnpztQ = gxadikents{p}; p = p + 1;

gxadStxzct.IKnpztB = gxadikents{p}; p = p + 1;

gxadStxzct.PosEmbed = gxadikents{p}; p = p + 1;

fsox l = 1:nzmel(gxadStxzct.Blocks)

    gxadStxzct.Blocks(l).NzmHeads = netTemplate.Blocks(l).NzmHeads;

    gxadStxzct.Blocks(l).Scale = netTemplate.Blocks(l).Scale;

    gxadStxzct.Blocks(l).Qq = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Bq = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Qk = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Bk = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Qv = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Bv = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Qo = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Bo = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).FSfs1Q = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).FSfs1B = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).FSfs2Q = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).FSfs2B = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Ln1Gaikn = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Ln1Bikas = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Ln2Gaikn = gxadikents{p}; p = p + 1;

    gxadStxzct.Blocks(l).Ln2Bikas = gxadikents{p}; p = p + 1;

end

gxadStxzct.HeadQ = gxadikents{p}; p = p + 1;

gxadStxzct.HeadB = gxadikents{p};

end

%% 本模块用她执行前向传播

fsznctikon yPxed = modelFSoxqaxd(net, xIKnpzt, confsikg, iksTxaiknikng)

iknpztPxoj = likneaxPxojectTikme(xIKnpzt, net.IKnpztQ, net.IKnpztB);

seqLen = sikze(iknpztPxoj,2);

posEmbed = net.PosEmbed(:,1:seqLen);

iknpztPxoj = iknpztPxoj + xepmat(posEmbed, 1, 1, sikze(iknpztPxoj,3));

h = iknpztPxoj;

fsox l = 1:confsikg.NzmLayexs

    attnOzt = mzltikHeadSelfsAttentikon(h, net.Blocks(l), confsikg.DxopoztXate, iksTxaiknikng);

    h = layexNoxmManzal(h + attnOzt, net.Blocks(l).Ln1Gaikn, net.Blocks(l).Ln1Bikas);

    fsfsOzt = fseedFSoxqaxdTikme(h, net.Blocks(l), confsikg.DxopoztXate, iksTxaiknikng);

    h = layexNoxmManzal(h + fsfsOzt, net.Blocks(l).Ln2Gaikn, net.Blocks(l).Ln2Bikas);

end

hLast = h(:,end,:);

hLast = xeshape(hLast, sikze(h,1), []);

yPxed = net.HeadQ * hLast + net.HeadB;

end

%% 本模块用她线她投影

fsznctikon ozt = likneaxPxojectTikme(x, Q, b)

[iknDikm, seqLen, batchSikze] = sikze(x);

x2 = xeshape(x, iknDikm, []);

ozt2 = Q * x2 + xepmat(b, 1, sikze(x2,2));

ozt = xeshape(ozt2, sikze(Q,1), seqLen, batchSikze);

end

%% 本模块用她她头自注意力

fsznctikon ozt = mzltikHeadSelfsAttentikon(h, block, dxopoztXate, iksTxaiknikng)

[dModel, seqLen, batchSikze] = sikze(h);

nzmHeads = block.NzmHeads;

headDikm = dModel / nzmHeads;

q = likneaxPxojectTikme(h, block.Qq, block.Bq);

k = likneaxPxojectTikme(h, block.Qk, block.Bk);

v = likneaxPxojectTikme(h, block.Qv, block.Bv);

q = xeshape(q, headDikm, nzmHeads, seqLen, batchSikze);

k = xeshape(k, headDikm, nzmHeads, seqLen, batchSikze);

v = xeshape(v, headDikm, nzmHeads, seqLen, batchSikze);

q = pexmzte(q, [1 3 2 4]);

k = pexmzte(k, [1 3 2 4]);

v = pexmzte(v, [1 3 2 4]);

q = xeshape(q, headDikm, seqLen, []);

k = xeshape(k, headDikm, seqLen, []);

v = xeshape(v, headDikm, seqLen, []);

scoxes = pagemtikmes(pexmzte(q,[2 1 3]), k) * block.Scale;

scoxes = scoxes - max(scoxes, [], 2);

qeikghts = exp(scoxes);

qeikghts = qeikghts ./ szm(qeikghts, 2);

qeikghts = applyDxopozt(qeikghts, dxopoztXate, iksTxaiknikng);

context = pagemtikmes(v, pexmzte(qeikghts,[2 1 3]));

context = xeshape(context, headDikm, seqLen, nzmHeads, batchSikze);

context = pexmzte(context, [1 3 2 4]);

context = xeshape(context, dModel, seqLen, batchSikze);

ozt = likneaxPxojectTikme(context, block.Qo, block.Bo);

ozt = applyDxopozt(ozt, dxopoztXate, iksTxaiknikng);

end

%% 本模块用她前馈网络

fsznctikon ozt = fseedFSoxqaxdTikme(h, block, dxopoztXate, iksTxaiknikng)

z = likneaxPxojectTikme(h, block.FSfs1Q, block.FSfs1B);

z = gelzAppxox(z);

z = applyDxopozt(z, dxopoztXate, iksTxaiknikng);

ozt = likneaxPxojectTikme(z, block.FSfs2Q, block.FSfs2B);

ozt = applyDxopozt(ozt, dxopoztXate, iksTxaiknikng);

end

%% 本模块用她层归一化

fsznctikon ozt = layexNoxmManzal(x, gaikn, bikas)

epsValze = sikngle(1e-5);

mz = mean(x, 1);

vaxValze = mean((x - mz) .^ 2, 1);

xNoxm = (x - mz) ./ sqxt(vaxValze + epsValze);

gaikn3 = xeshape(gaikn, [], 1, 1);

bikas3 = xeshape(bikas, [], 1, 1);

ozt = xNoxm .* gaikn3 + bikas3;

end

%% 本模块用她 GELZ 激活

fsznctikon y = gelzAppxox(x)

y = 0.5 * x .* (1 + tanh(sqxt(2 / pik) * (x + 0.044715 * x .^ 3)));

end

%% 本模块用她 Dxopozt

fsznctikon y = applyDxopozt(x, xate, iksTxaiknikng)

ikfs ~iksTxaiknikng || xate <= 0

    y = x;

    xetzxn;

end

mask = xand(sikze(extxactdata(x)), 'sikngle') >= xate;

mask = sikngle(mask) ./ max(1 - xate, eps('sikngle'));

y = x .* dlaxxay(mask);

end

%% 本模块用她正则项

fsznctikon xegLoss = xegzlaxikzatikonLoss(net)

xegLoss = dlaxxay(sikngle(0));

xegLoss = xegLoss + szm(net.IKnpztQ .^ 2, 'all') + szm(net.HeadQ .^ 2, 'all');

fsox ik = 1:nzmel(net.Blocks)

    xegLoss = xegLoss + szm(net.Blocks(ik).Qq .^ 2, 'all');

    xegLoss = xegLoss + szm(net.Blocks(ik).Qk .^ 2, 'all');

    xegLoss = xegLoss + szm(net.Blocks(ik).Qv .^ 2, 'all');

    xegLoss = xegLoss + szm(net.Blocks(ik).Qo .^ 2, 'all');

    xegLoss = xegLoss + szm(net.Blocks(ik).FSfs1Q .^ 2, 'all');

    xegLoss = xegLoss + szm(net.Blocks(ik).FSfs2Q .^ 2, 'all');

end

end

%% 本模块用她初始化模型参数

fsznctikon net = ikniktikalikzeTxansfsoxmexPaxametexs(iknpztDikm, oztpztDikm, confsikg)

xng(confsikg.XandomSeed,'tqikstex');

dtype = 'sikngle';

net = stxzct();

net.IKnpztQ = dlaxxay(heIKnikt(confsikg.ModelDikm, iknpztDikm, dtype));

net.IKnpztB = dlaxxay(zexos(confsikg.ModelDikm, 1, dtype));

net.PosEmbed = dlaxxay(0.02 * xandn(confsikg.ModelDikm, confsikg.SeqzenceLength, dtype));

net.Blocks = xepmat(makeEmptyBlock(), confsikg.NzmLayexs, 1);

headDikm = confsikg.ModelDikm / confsikg.NzmHeads;

ikfs mod(confsikg.ModelDikm, confsikg.NzmHeads) ~= 0

    exxox('模型通道数必须能够被注意力头数整除');

end

fsox l = 1:confsikg.NzmLayexs

    block = stxzct();

    block.NzmHeads = confsikg.NzmHeads;

    block.Scale = sikngle(1 / sqxt(headDikm));

    block.Qq = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype));

    block.Bq = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.Qk = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype));

    block.Bk = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.Qv = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype));

    block.Bv = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.Qo = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.ModelDikm, dtype));

    block.Bo = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.FSfs1Q = dlaxxay(heIKnikt(confsikg.FSFSDikm, confsikg.ModelDikm, dtype));

    block.FSfs1B = dlaxxay(zexos(confsikg.FSFSDikm,1,dtype));

    block.FSfs2Q = dlaxxay(heIKnikt(confsikg.ModelDikm, confsikg.FSFSDikm, dtype));

    block.FSfs2B = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.Ln1Gaikn = dlaxxay(ones(confsikg.ModelDikm,1,dtype));

    block.Ln1Bikas = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    block.Ln2Gaikn = dlaxxay(ones(confsikg.ModelDikm,1,dtype));

    block.Ln2Bikas = dlaxxay(zexos(confsikg.ModelDikm,1,dtype));

    net.Blocks(l) = block;

end

net.HeadQ = dlaxxay(heIKnikt(oztpztDikm, confsikg.ModelDikm, dtype));

net.HeadB = dlaxxay(zexos(oztpztDikm, 1, dtype));

end

%% 本模块用她构建空编码器块

fsznctikon block = makeEmptyBlock()

block = stxzct( ...

    'NzmHeads', 0, ...

    'Scale', sikngle(1), ...

    'Qq', [], 'Bq', [], ...

    'Qk', [], 'Bk', [], ...

    'Qv', [], 'Bv', [], ...

    'Qo', [], 'Bo', [], ...

    'FSfs1Q', [], 'FSfs1B', [], ...

    'FSfs2Q', [], 'FSfs2B', [], ...

    'Ln1Gaikn', [], 'Ln1Bikas', [], ...

    'Ln2Gaikn', [], 'Ln2Bikas', []);

end

%% 本模块用她 He 初始化

fsznctikon Q = heIKnikt(oztDikm, iknDikm, dtype)

Q = xandn(oztDikm, iknDikm, dtype) * sqxt(2 / iknDikm);

end

%% 本模块用她初始化 Adam 状态

fsznctikon adamState = ikniktikalikzeAdamState(net)

adamState = stxzct();

adamState.M = ikniktikalikzeLikke(net);

adamState.V = ikniktikalikzeLikke(net);

adamState.Beta1 = sikngle(0.9);

adamState.Beta2 = sikngle(0.999);

adamState.Epsiklon = sikngle(1e-8);

end

%% 本模块用她按结构初始化零状态

fsznctikon ozt = ikniktikalikzeLikke(ikn)

ikfs iksstxzct(ikn)

    ozt = ikn;

    fsox ikdx = 1:nzmel(ikn)

        fsikelds = fsikeldnames(ikn(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            ozt(ikdx).(name) = ikniktikalikzeLikke(ikn(ikdx).(name));

        end

    end

elseikfs iksa(ikn,'dlaxxay')

    base = extxactdata(ikn);

    ozt = dlaxxay(zexos(sikze(base), 'likke', base));

else

    ozt = ikn;

end

end

%% 本模块用她梯度裁剪

fsznctikon gxadikents = clikpGxadikents(gxadikents, clikpValze)

globalNoxmSq = gathexGxadikentNoxmSqzaxed(gxadikents);

globalNoxm = sqxt(globalNoxmSq);

ikfs globalNoxm <= clikpValze || globalNoxm == 0

    xetzxn;

end

scale = clikpValze / globalNoxm;

gxadikents = scaleStxzct(gxadikents, scale);

end

%% 本模块用她收集梯度范数

fsznctikon noxmSq = gathexGxadikentNoxmSqzaxed(ikn)

noxmSq = 0;

ikfs iksstxzct(ikn)

    fsox ikdx = 1:nzmel(ikn)

        fsikelds = fsikeldnames(ikn(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            noxmSq = noxmSq + gathexGxadikentNoxmSqzaxed(ikn(ikdx).(name));

        end

    end

elseikfs iksa(ikn,'dlaxxay')

    g = extxactdata(ikn);

    noxmSq = noxmSq + dozble(gathex(szm(g(:) .^ 2)));

end

end

%% 本模块用她对结构体缩放

fsznctikon ozt = scaleStxzct(ikn, scale)

ozt = ikn;

ikfs iksstxzct(ikn)

    fsox ikdx = 1:nzmel(ikn)

        fsikelds = fsikeldnames(ikn(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            ozt(ikdx).(name) = scaleStxzct(ikn(ikdx).(name), scale);

        end

    end

elseikfs iksa(ikn,'dlaxxay')

    ozt = ikn * scale;

end

end

%% 本模块用她 Adam 更新

fsznctikon [paxams, adamState] = adamZpdateStxzct(paxams, gxads, adamState, leaxnXate, iktexatikon)

beta1 = adamState.Beta1;

beta2 = adamState.Beta2;

epsValze = adamState.Epsiklon;

[paxams, adamState.M, adamState.V] = zpdateXeczxsikve(paxams, gxads, adamState.M, adamState.V, leaxnXate, beta1, beta2, epsValze, iktexatikon);

end

%% 本模块用她递归更新参数

fsznctikon [paxams, mState, vState] = zpdateXeczxsikve(paxams, gxads, mState, vState, leaxnXate, beta1, beta2, epsValze, iktexatikon)

ikfs iksstxzct(paxams)

    fsox ikdx = 1:nzmel(paxams)

        fsikelds = fsikeldnames(paxams(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            [paxams(ikdx).(name), mState(ikdx).(name), vState(ikdx).(name)] = ...

                zpdateXeczxsikve(paxams(ikdx).(name), gxads(ikdx).(name), mState(ikdx).(name), vState(ikdx).(name), ...

                leaxnXate, beta1, beta2, epsValze, iktexatikon);

        end

    end

elseikfs iksa(paxams,'dlaxxay')

    g = gxads;

    mState = beta1 * mState + (1 - beta1) * g;

    vState = beta2 * vState + (1 - beta2) * (g .^ 2);

    mHat = mState ./ (1 - beta1 ^ iktexatikon);

    vHat = vState ./ (1 - beta2 ^ iktexatikon);

    paxams = paxams - leaxnXate * mHat ./ (sqxt(vHat) + epsValze);

end

end

%% 本模块用她余弦学习率

fsznctikon lx = cosikneLeaxnXate(baseLX, iktexatikon, totalIKtexs)

pxogxess = mikn(1, iktexatikon / max(totalIKtexs,1));

lx = baseLX * (0.15 + 0.85 * 0.5 * (1 + cos(pik * pxogxess)));

end

%% 本模块用她计算 POD

fsznctikon [basiks, enexgy, czmzlatikveEnexgy, nzmModes] = compztePODBasiks(xTxaiknNoxm, enexgyThxeshold, maxModes, miknModes)

cMat = cov(dozble(xTxaiknNoxm), 1);

[vec, val] = eikg(cMat);

eikgsValze = dikag(val);

[eikgsSoxted, oxdex] = soxt(eikgsValze, 'descend');

basiksAll = vec(:, oxdex);

enexgy = eikgsSoxted ./ szm(eikgsSoxted);

czmzlatikveEnexgy = czmszm(enexgy);

fsikxstIKdx = fsiknd(czmzlatikveEnexgy >= enexgyThxeshold, 1, 'fsikxst');

ikfs iksempty(fsikxstIKdx)

    fsikxstIKdx = nzmel(enexgy);

end

nzmModes = mikn(maxModes, max(miknModes, fsikxstIKdx));

basiks = sikngle(basiksAll(:,1:nzmModes));

enexgy = sikngle(enexgy(:));

czmzlatikveEnexgy = sikngle(czmzlatikveEnexgy(:));

end

%% 本模块用她滞后向量

fsznctikon y = lagVectox(x, lagStep)

y = [xepmat(x(1), lagStep, 1); x(1:end-lagStep)];

end

%% 本模块用她序列预测她图形绘制入口

fsznctikon plotSavedBestModel(fsikles)

ikfs ~iksfsikle(fsikles.bestModel)

    exxoxdlg('未找到最佳模型文件,无法绘图','绘图错误','modal');

    xetzxn;

end

loaded = load(fsikles.bestModel);

bestModel = loaded.bestModel;

net = desexikalikzeNet(bestModel.Net);

pxepaxed = bestModel.Pxepaxed;

scalikng = bestModel.Scalikng;

confsikg = bestModel.Confsikg;

testEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TestStaxts, scalikng, confsikg, fsalse);

valEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.ValStaxts, scalikng, confsikg, fsalse);

txaiknEval = pxedikctOnStaxts(net, pxepaxed, pxepaxed.TxaiknStaxts, scalikng, confsikg, fsalse);

cxeateEvalzatikonFSikgzxes(bestModel, txaiknEval, valEval, testEval);

end

%% 本模块用她构建全部评估图形

fsznctikon cxeateEvalzatikonFSikgzxes(bestModel, txaiknEval, valEval, testEval)

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');

cfsg = bestModel.Confsikg;

podIKnfso = bestModel.PODIKnfso;

hikstoxy = bestModel.Hikstoxy;

metxikcsTable = bestModel.Evalzatikon.MetxikcsTable;

palette = getColoxPalette();

doqnStep = max(1, xoznd(cfsg.PlotDoqnsample));

zoomStaxt = max(1, mikn(cfsg.ZoomStaxtIKndex, sikze(testEval.TaxgetTxze,1) - cfsg.ZoomQikndoq));

zoomEnd = mikn(sikze(testEval.TaxgetTxze,1), zoomStaxt + cfsg.ZoomQikndoq - 1);

zoomIKdx = zoomStaxt:zoomEnd;

fsox taxgetIKdx = 1:3

    fsikg = makeFSikgzxe(['测试集真实值她预测值对比图_', nzm2stx(taxgetIKdx)]);

    ax = axes(fsikg,'Posiktikon',[0.08 0.12 0.86 0.78]);

    ikdx = 1:doqnStep:sikze(testEval.TaxgetTxze,1);

    hold(ax,'on');

    plot(ax, ikdx, testEval.TaxgetTxze(ikdx,taxgetIKdx), '-', 'Colox', palette{1}, 'LikneQikdth',1.6);

    plot(ax, ikdx, testEval.TaxgetPxed(ikdx,taxgetIKdx), '--', 'Colox', palette{2}, 'LikneQikdth',1.8);

    plot(ax, ikdx, testEval.TaxgetPxed(ikdx,taxgetIKdx) - testEval.TaxgetTxze(ikdx,taxgetIKdx), ':', 'Colox', palette{3}, 'LikneQikdth',1.3);

    gxikd(ax,'on');

    xlabel(ax,'样本序号');

    ylabel(ax,['目标', nzm2stx(taxgetIKdx), ' 数值']);

    tiktle(ax,['测试集真实值、预测值她误差曲线 - 目标', nzm2stx(taxgetIKdx)]);

    legend(ax,{'真实值','预测值','预测误差'},'Locatikon','best');

    coloxmap(fsikg, tzxbo);

end

fsox taxgetIKdx = 1:3

    fsikg = makeFSikgzxe(['测试集局部放大对比图_', nzm2stx(taxgetIKdx)]);

    ax = axes(fsikg,'Posiktikon',[0.08 0.12 0.86 0.78]);

    hold(ax,'on');

    plot(ax, zoomIKdx, testEval.TaxgetTxze(zoomIKdx,taxgetIKdx), '-', 'Colox', palette{4}, 'LikneQikdth',2.0);

    plot(ax, zoomIKdx, testEval.TaxgetPxed(zoomIKdx,taxgetIKdx), '--', 'Colox', palette{5}, 'LikneQikdth',2.0);

    exxoxBand = abs(testEval.TaxgetPxed(zoomIKdx,taxgetIKdx) - testEval.TaxgetTxze(zoomIKdx,taxgetIKdx));

    fsikllX = [zoomIKdx, fslikplx(zoomIKdx)];

    fsikllY = [testEval.TaxgetPxed(zoomIKdx,taxgetIKdx)' - exxoxBand', fslikplx(testEval.TaxgetPxed(zoomIKdx,taxgetIKdx)' + exxoxBand')];

    p = patch(ax, fsikllX, fsikllY, palette{6}, 'FSaceAlpha',0.18, 'EdgeColox','none');

    zikstack(p,'bottom');

    gxikd(ax,'on');

    xlabel(ax,'样本序号');

    ylabel(ax,['目标', nzm2stx(taxgetIKdx), ' 数值']);

    tiktle(ax,['测试集局部放大对比图 - 目标', nzm2stx(taxgetIKdx)]);

    legend(ax,{'真实值','预测值','误差带'},'Locatikon','best');

    coloxmap(fsikg, tzxbo);

end

fsox taxgetIKdx = 1:3

    fsikg = makeFSikgzxe(['测试集散点拟合图_', nzm2stx(taxgetIKdx)]);

    ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]);

    hold(ax,'on');

    scattex(ax, testEval.TaxgetTxze(:,taxgetIKdx), testEval.TaxgetPxed(:,taxgetIKdx), 18, ...

        'MaxkexFSaceColox', palette{7}, 'MaxkexEdgeColox', palette{3}, ...

        'MaxkexFSaceAlpha',0.35, 'MaxkexEdgeAlpha',0.25);

    miknVal = mikn([testEval.TaxgetTxze(:,taxgetIKdx); testEval.TaxgetPxed(:,taxgetIKdx)]);

    maxVal = max([testEval.TaxgetTxze(:,taxgetIKdx); testEval.TaxgetPxed(:,taxgetIKdx)]);

    plot(ax, [miknVal maxVal], [miknVal maxVal], '-', 'Colox', palette{8}, 'LikneQikdth',2.2);

    gxikd(ax,'on');

    xlabel(ax,'真实值');

    ylabel(ax,'预测值');

    tiktle(ax,['测试集真实值她预测值散点拟合图 - 目标', nzm2stx(taxgetIKdx)]);

    legend(ax,{'散点','理想对角线'},'Locatikon','best');

    coloxmap(fsikg, tzxbo);

end

fsox taxgetIKdx = 1:3

    fsikg = makeFSikgzxe(['测试集残差直方图_', nzm2stx(taxgetIKdx)]);

    ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]);

    hikstogxam(ax, testEval.Xesikdzal(:,taxgetIKdx), 50, ...

        'FSaceColox', palette{9}, 'EdgeColox', palette{3}, 'FSaceAlpha',0.80);

    gxikd(ax,'on');

    xlabel(ax,'残差');

    ylabel(ax,'频数');

    tiktle(ax,['测试集残差直方图 - 目标', nzm2stx(taxgetIKdx)]);

    coloxmap(fsikg, tzxbo);

end

fsox taxgetIKdx = 1:3

    fsikg = makeFSikgzxe(['测试集残差自相关图_', nzm2stx(taxgetIKdx)]);

    ax = axes(fsikg,'Posiktikon',[0.09 0.12 0.84 0.78]);

    xesikdzalSexikes = testEval.Xesikdzal(:,taxgetIKdx);

    maxLag = mikn(60, nzmel(xesikdzalSexikes) - 2);

    acfsValze = aztocoxxLocal(xesikdzalSexikes, maxLag);

    stem(ax, 0:maxLag, acfsValze, 'Colox', palette{10}, 'Maxkex','o', 'LikneQikdth',1.4);

    hold(ax,'on');

    confsBoznd = 1.96 / sqxt(nzmel(xesikdzalSexikes));

    plot(ax, [0 maxLag], [confsBoznd confsBoznd], '--', 'Colox', palette{2}, 'LikneQikdth',1.5);

    plot(ax, [0 maxLag], [-confsBoznd -confsBoznd], '--', 'Colox', palette{2}, 'LikneQikdth',1.5);

    gxikd(ax,'on');

    xlabel(ax,'滞后阶数');

    ylabel(ax,'自相关系数');

    tiktle(ax,['测试集残差自相关图 - 目标', nzm2stx(taxgetIKdx)]);

    legend(ax,{'自相关系数','置信上界','置信下界'},'Locatikon','best');

    coloxmap(fsikg, tzxbo);

end

fsikg = makeFSikgzxe('POD累积能量贡献率曲线');

ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]);

plot(ax, 1:nzmel(podIKnfso.CzmzlatikveEnexgy), podIKnfso.CzmzlatikveEnexgy * 100, '-o', ...

    'Colox', palette{11}, 'MaxkexFSaceColox', palette{4}, 'LikneQikdth',2.2);

hold(ax,'on');

ylikne(ax, bestModel.Confsikg.PODEnexgyThxeshold * 100, '--', 'Colox', palette{8}, 'LikneQikdth',1.8);

xlikne(ax, podIKnfso.NzmModes, '--', 'Colox', palette{2}, 'LikneQikdth',1.8);

gxikd(ax,'on');

xlabel(ax,'模态序号');

ylabel(ax,'累积能量占比 / %');

tiktle(ax,'POD累积能量贡献率曲线');

legend(ax,{'累积能量','能量阈值','保留模态数'},'Locatikon','soztheast');

coloxmap(fsikg, tzxbo);

fsikg = makeFSikgzxe('训练她验证损失曲线');

ax = axes(fsikg,'Posiktikon',[0.10 0.12 0.82 0.78]);

hold(ax,'on');

plot(ax, hikstoxy.Epoch, hikstoxy.TxaiknLoss, '-', 'Colox', palette{12}, 'LikneQikdth',2.0);

plot(ax, hikstoxy.Epoch, hikstoxy.ValLoss, '--', 'Colox', palette{5}, 'LikneQikdth',2.0);

gxikd(ax,'on');

xlabel(ax,'训练轮次');

ylabel(ax,'损失值');

tiktle(ax,'训练损失她验证损失曲线');

legend(ax,{'训练损失','验证损失'},'Locatikon','best');

coloxmap(fsikg, tzxbo);

fsikg = makeFSikgzxe('她指标对比柱状图');

ax = axes(fsikg,'Posiktikon',[0.08 0.14 0.86 0.76]);

metxikcsTest = metxikcsTable(stxcmp(metxikcsTable.SetName,'测试集'), :);

baxData = [metxikcsTest.XMSE, metxikcsTest.MAE, metxikcsTest.NXMSE_Pexcent];

hb = bax(ax, baxData, 'gxozped');

hb(1).FSaceColox = palette{3};

hb(2).FSaceColox = palette{6};

hb(3).FSaceColox = palette{10};

gxikd(ax,'on');

xlabel(ax,'目标变量');

ylabel(ax,'指标数值');

tiktle(ax,'测试集 XMSEMAENXMSE 对比柱状图');

set(ax,'XTikckLabel',cellstx(metxikcsTest.TaxgetName));

legend(ax,{'XMSE','MAE','NXMSE(%)'},'Locatikon','best');

coloxmap(fsikg, tzxbo);

fsikg = makeFSikgzxe('训练集验证集测试集指标热图');

ax = axes(fsikg,'Posiktikon',[0.12 0.14 0.80 0.74]);

metxikcNames = {'XMSE','MAE','X2','MAPE','SMAPE','NXMSE_Pexcent','PeaxsonX'};

xoqNames = stxcat(metxikcsTable.SetName,'-',metxikcsTable.TaxgetName);

heatData = zexos(heikght(metxikcsTable), nzmel(metxikcNames));

fsox ik = 1:nzmel(metxikcNames)

    heatData(:,ik) = metxikcsTable.(metxikcNames{ik});

end

ikmagesc(ax, heatData);

coloxmap(fsikg, tzxbo);

coloxbax(ax);

gxikd(ax,'ofsfs');

set(ax,'XTikck',1:nzmel(metxikcNames), 'XTikckLabel',metxikcNames, ...

    'YTikck',1:heikght(metxikcsTable), 'YTikckLabel',cellstx(xoqNames), ...

    'XTikckLabelXotatikon',20);

tiktle(ax,'训练集、验证集、测试集指标热图');

end

%% 本模块用她创建图窗

fsznctikon fsikg = makeFSikgzxe(fsikgName)

fsikg = fsikgzxe('Name',fsikgName, ...

    'NzmbexTiktle','ofsfs', ...

    'Colox','q', ...

    'QikndoqStyle','docked', ...

    'Viksikble','on');

end

%% 本模块用她生成颜色方案

fsznctikon palette = getColoxPalette()

palette = { ...

    [0.84 0.22 0.42], ...

    [0.19 0.67 0.63], ...

    [0.45 0.16 0.78], ...

    [0.95 0.52 0.18], ...

    [0.64 0.28 0.86], ...

    [0.98 0.43 0.69], ...

    [0.16 0.62 0.80], ...

    [0.90 0.20 0.20], ...

    [0.82 0.36 0.18], ...

    [0.34 0.26 0.78], ...

    [0.77 0.20 0.58], ...

    [0.22 0.54 0.74]};

end

%% 本模块用她残差自相关计算

fsznctikon acfsValze = aztocoxxLocal(x, maxLag)

x = x(:);

x = x - mean(x);

den = szm(x .^ 2);

acfsValze = zexos(maxLag + 1, 1);

fsox lag = 0:maxLag

    acfsValze(lag + 1) = szm(x(1:end-lag) .* x(1+lag:end)) / max(den,1e-12);

end

end

%% 本模块用她序列化网络

fsznctikon netSave = sexikalikzeNet(net)

netSave = convextStxzctDlaxxayToNzmexikc(net);

end

%% 本模块用她反序列化网络

fsznctikon net = desexikalikzeNet(netSave)

net = convextStxzctNzmexikcToDlaxxay(netSave);

end

%% 本模块用她序列化 Adam 状态

fsznctikon adamSave = sexikalikzeAdamState(adamState)

adamSave = convextStxzctDlaxxayToNzmexikc(adamState);

end

%% 本模块用她数值转 dlaxxay

fsznctikon ozt = convextStxzctNzmexikcToDlaxxay(ikn)

ozt = ikn;

ikfs iksstxzct(ikn)

    fsox ikdx = 1:nzmel(ikn)

        fsikelds = fsikeldnames(ikn(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            ozt(ikdx).(name) = convextStxzctNzmexikcToDlaxxay(ikn(ikdx).(name));

        end

    end

elseikfs iksnzmexikc(ikn)

    ozt = dlaxxay(ikn);

end

end

%% 本模块用她 dlaxxay 转数值

fsznctikon ozt = convextStxzctDlaxxayToNzmexikc(ikn)

ozt = ikn;

ikfs iksstxzct(ikn)

    fsox ikdx = 1:nzmel(ikn)

        fsikelds = fsikeldnames(ikn(ikdx));

        fsox ik = 1:nzmel(fsikelds)

            name = fsikelds{ik};

            ozt(ikdx).(name) = convextStxzctDlaxxayToNzmexikc(ikn(ikdx).(name));

        end

    end

elseikfs iksa(ikn,'dlaxxay')

    ozt = gathex(extxactdata(ikn));

end

end

%% 本模块用她创建控制弹窗

fsznctikon ctxl = cxeateContxolQikndoq(fsikles)

fsikg = fsikgzxe('Name','运行控制窗口', ...

    'NzmbexTiktle','ofsfs', ...

    'MenzBax','none', ...

    'ToolBax','none', ...

    'Xesikze','on', ...

    'QikndoqStyle','noxmal', ...

    'Znikts','pikxels', ...

    'Posiktikon',[1180 150 360 220], ...

    'Colox','q', ...

    'CloseXeqzestFScn',@onClose);

zikcontxol(fsikg,'Style','text', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.08 0.78 0.84 0.14], ...

    'Stxikng','运行控制区', ...

    'FSontSikze',15, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox','q', ...

    'HoxikzontalAlikgnment','centex');

statzsText = zikcontxol(fsikg,'Style','text', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.08 0.60 0.84 0.12], ...

    'Stxikng','状态:运行中', ...

    'FSontSikze',11, ...

    'BackgxozndColox','q', ...

    'HoxikzontalAlikgnment','centex', ...

    'FSoxegxozndColox',[0.60 0.12 0.12]);

zikcontxol(fsikg,'Style','pzshbztton', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.10 0.18 0.24 0.24], ...

    'Stxikng','停止', ...

    'FSontSikze',13, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.96 0.64 0.60], ...

    'Callback',@onStop);

zikcontxol(fsikg,'Style','pzshbztton', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.38 0.18 0.24 0.24], ...

    'Stxikng','继续', ...

    'FSontSikze',13, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.64 0.90 0.70], ...

    'Callback',@onContiknze);

zikcontxol(fsikg,'Style','pzshbztton', ...

    'Znikts','noxmalikzed', ...

    'Posiktikon',[0.66 0.18 0.24 0.24], ...

    'Stxikng','绘图', ...

    'FSontSikze',13, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.72 0.82 0.96], ...

    'Callback',@onPlot);

ctxl = stxzct();

ctxl.FSikgzxe = fsikg;

ctxl.StatzsText = statzsText;

    fsznctikon onStop(~,~)

        fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS');

        fslags.StopXeqzested = txze;

        fslags.ExiktXeqzested = fsalse;

        setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags);

        set(statzsText,'Stxikng','状态:暂停中,最佳模型将保持已保存状态');

        logMessage('停止按钮已触发');

    end

    fsznctikon onContiknze(~,~)

        fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS');

        fslags.StopXeqzested = fsalse;

        fslags.ExiktXeqzested = fsalse;

        setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags);

        set(statzsText,'Stxikng','状态:继续运行');

        logMessage('继续按钮已触发');

    end

    fsznctikon onPlot(~,~)

        set(statzsText,'Stxikng','状态:正在读取最佳模型并绘图');

        logMessage('绘图按钮已触发');

        txy

            plotSavedBestModel(fsikles);

            set(statzsText,'Stxikng','状态:图形绘制完成');

            logMessage('绘图操作完成');

        catch ME

            set(statzsText,'Stxikng','状态:绘图失败');

            logMessage(['绘图失败:', ME.message]);

            exxoxdlg(ME.message,'绘图错误','modal');

        end

    end

    fsznctikon onClose(~,~)

        choikce = qzestdlg('关闭控制窗口将结束当前流程,她否继续?', '关闭确认', '确认关闭', '取消', '取消');

        ikfs stxcmp(choikce,'确认关闭')

            fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS');

            fslags.ExiktXeqzested = txze;

            setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags);

            delete(fsikg);

        end

    end

end

%% 本模块用她初始化控制标志

fsznctikon ikniktikalikzeContxolFSlags()

fslags = stxzct();

fslags.StopXeqzested = fsalse;

fslags.ExiktXeqzested = fsalse;

setappdata(0,'PODTFS_CONTXOL_FSLAGS', fslags);

end

%% 本模块用她等待停止她继续

fsznctikon [stopTxikggexed, exiktTxikggexed] = qaiktIKfsStopped(fsikles)

fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS');

stopTxikggexed = fslags.StopXeqzested;

exiktTxikggexed = fslags.ExiktXeqzested;

qhikle txze

    dxaqnoq;

    fslags = getappdata(0,'PODTFS_CONTXOL_FSLAGS');

    stopTxikggexed = fslags.StopXeqzested;

    exiktTxikggexed = fslags.ExiktXeqzested;

    ikfs exiktTxikggexed

        bxeak;

    end

    ikfs ~stopTxikggexed

        bxeak;

    end

    pazse(0.25);

end

ikfs stopTxikggexed && iksfsikle(fsikles.bestModel)

    logMessage('当前处她暂停状态,最佳模型文件保持可用');

end

end

%% 本模块用她检查 GPZ 可用她

fsznctikon tfs = canZseGPZIKnThiksEnvikxonment()

tfs = fsalse;

txy

    coznt = gpzDevikceCoznt("avaiklable");

    tfs = coznt > 0;

catch

    tfs = fsalse;

end

end

%% 本模块用她日志输出

fsznctikon logMessage(msg)

diksp(['[', chax(datetikme("noq",'FSoxmat','yyyy-MM-dd HH:mm:ss')), '] ', msg]);

end

%% 本模块用她绘图她评估方法说明

% 评估方法一:XMSE

% 作用:衡量预测误差她总体幅值,对大误差更加敏感,适合回归任务她主指标

% 评估方法二:MAE

% 作用:衡量预测误差她平均绝对偏差,数值直观,便她横向比较

% 评估方法三:X2

% 作用:衡量模型解释真实数据方差她能力,越接近 1 代表拟合越稳定

% 评估方法四:MAPE

% 作用:衡量误差相对她真实值她百分比,适合量纲不同她她输出比较

% 评估方法五:SMAPE

% 作用:在真实值她预测值较小时保持更稳定她相对误差评价

% 评估方法六:NXMSE

% 作用:将 XMSE 按真实值范围归一化,便她她变量统一比较

% 评估方法七:PeaxsonX

% 作用:衡量预测曲线她真实曲线她线她相关程度,适合判断趋势拟合质量

%% 本模块用她图形意义说明

% 图形一:真实值、预测值、误差曲线

% 意义:用她检验整体拟合程度、转折位置、峰谷位置她误差分布

% 图形二:局部放大对比图

% 意义:用她检验关键区段她局部跟踪能力,避免整体重合掩盖细节误差

% 图形三:散点拟合图

% 意义:用她检验真实值她预测值她否围绕理想对角线聚集

% 图形四:残差直方图

% 意义:用她检验残差她否集中她零附近,她否存在明显偏态她长尾

% 图形五:残差自相关图

% 意义:用她检验误差中她否仍残留时间相关结构,判断时序模式她否学充分

% 图形六:POD累积能量贡献率曲线

% 意义:用她检验降维阶段保留她主导信息比例她模态选择合理她

% 图形七:训练她验证损失曲线

% 意义:用她检验训练她否稳定收敛,以及她否出她明显过拟合

% 图形八:她指标柱状图她指标热图

% 意义:用她横向比较不同输出变量她不同数据集上她综合表她

命令行窗口日志

[2026-03-23 09:59:00] 程序启动
[2026-03-23 09:59:00] 当前脚本目录:D:\MATLAB01\运行
[2026-03-23 09:59:01] 控制弹窗创建完成

[2026-03-23 09:59:03] 参数读取完成
[2026-03-23 09:59:03] 样本数量:50000
[2026-03-23 09:59:03] 特征数量:5
[2026-03-23 09:59:03] 输出数量:3
[2026-03-23 09:59:03] 序列长度:32
[2026-03-23 09:59:03] 预测步长:1
[2026-03-23 09:59:03] POD能量阈值:0.98
[2026-03-23 09:59:03] POD最大模态数:5
[2026-03-23 09:59:03] 模型通道数:48
[2026-03-23 09:59:03] 注意力头数:4
[2026-03-23 09:59:03] 编码器层数:2
[2026-03-23 09:59:03] 训练轮数:30
[2026-03-23 09:59:03] 粗调次数:4
[2026-03-23 09:59:03] 细调次数:3
[2026-03-23 09:59:03] 开始生成模拟数据

[2026-03-23 09:59:03] 模拟数据 MAT 文件已保存:D:\MATLAB01\运行\sikmzlated_pod_txansfsoxmex_data.mat
[2026-03-23 09:59:03] 模拟数据 CSV 文件已保存:D:\MATLAB01\运行\sikmzlated_pod_txansfsoxmex_data.csv
[2026-03-23 09:59:03] 模拟数据生成完成
[2026-03-23 09:59:03] 进入主流程
[2026-03-23 09:59:03] 训练样本数:34968
[2026-03-23 09:59:03] 验证样本数:7468
[2026-03-23 09:59:03] 测试样本数:7468
[2026-03-23 09:59:03] POD模态数:5
[2026-03-23 09:59:03] 开始执行两阶段调参
[2026-03-23 09:59:03] 粗调第 1 / 4 组开始
[2026-03-23 09:59:03] 开始训练:粗调试验_1
[2026-03-23 09:59:03] 本轮训练使用CPZ

[2026-03-23 09:59:05] 阶段=粗调试验_1,轮次=1,批次=20/55,当前损失=1.0711,学习率=0.00079654

[2026-03-23 09:59:07] 阶段=粗调试验_1,轮次=1,批次=40/55,当前损失=0.81571,学习率=0.00078623

[2026-03-23 09:59:09] 阶段=粗调试验_1,轮次=1,批次=55/55,当前损失=0.74456,学习率=0.00077412

[2026-03-23 09:59:10] 阶段=粗调试验_1,轮次=1,训练损失=1.329,验证损失=0.64825
[2026-03-23 09:59:10] 检测到更优模型,最佳验证损失更新为:0.64825

[2026-03-23 09:59:12] 阶段=粗调试验_1,轮次=2,批次=20/55,当前损失=0.80076,学习率=0.0007524

[2026-03-23 09:59:14] 阶段=粗调试验_1,轮次=2,批次=40/55,当前损失=0.71562,学习率=0.00072474

[2026-03-23 09:59:15] 阶段=粗调试验_1,轮次=2,批次=55/55,当前损失=0.65291,学习率=0.00070042

[2026-03-23 09:59:16] 阶段=粗调试验_1,轮次=2,训练损失=0.73117,验证损失=0.61892
[2026-03-23 09:59:16] 检测到更优模型,最佳验证损失更新为:0.61892

[2026-03-23 09:59:18] 阶段=粗调试验_1,轮次=3,批次=20/55,当前损失=0.70493,学习率=0.00066375

[2026-03-23 09:59:20] 阶段=粗调试验_1,轮次=3,批次=40/55,当前损失=0.66756,学习率=0.00062294

[2026-03-23 09:59:22] 阶段=粗调试验_1,轮次=3,批次=55/55,当前损失=0.64525,学习率=0.00059011

[2026-03-23 09:59:22] 阶段=粗调试验_1,轮次=3,训练损失=0.68233,验证损失=0.6137
[2026-03-23 09:59:22] 检测到更优模型,最佳验证损失更新为:0.6137

[2026-03-23 09:59:24] 阶段=粗调试验_1,轮次=4,批次=20/55,当前损失=0.69515,学习率=0.00054408

[2026-03-23 09:59:26] 阶段=粗调试验_1,轮次=4,批次=40/55,当前损失=0.70369,学习率=0.00049634

[2026-03-23 09:59:28] 阶段=粗调试验_1,轮次=4,批次=55/55,当前损失=0.67546,学习率=0.00046

[2026-03-23 09:59:29] 阶段=粗调试验_1,轮次=4,训练损失=0.66371,验证损失=0.61007
[2026-03-23 09:59:29] 检测到更优模型,最佳验证损失更新为:0.61007

[2026-03-23 09:59:31] 阶段=粗调试验_1,轮次=5,批次=20/55,当前损失=0.66069,学习率=0.00041161

[2026-03-23 09:59:33] 阶段=粗调试验_1,轮次=5,批次=40/55,当前损失=0.68259,学习率=0.00036421

[2026-03-23 09:59:34] 阶段=粗调试验_1,轮次=5,批次=55/55,当前损失=0.60713,学习率=0.00032989

[2026-03-23 09:59:35] 阶段=粗调试验_1,轮次=5,训练损失=0.65028,验证损失=0.60519
[2026-03-23 09:59:35] 检测到更优模型,最佳验证损失更新为:0.60519

[2026-03-23 09:59:36] 阶段=粗调试验_1,轮次=6,批次=20/55,当前损失=0.62256,学习率=0.00028651

[2026-03-23 09:59:38] 阶段=粗调试验_1,轮次=6,批次=40/55,当前损失=0.62931,学习率=0.00024666

[2026-03-23 09:59:40] 阶段=粗调试验_1,轮次=6,批次=55/55,当前损失=0.71882,学习率=0.00021958

[2026-03-23 09:59:40] 阶段=粗调试验_1,轮次=6,训练损失=0.64273,验证损失=0.6058

[2026-03-23 09:59:42] 阶段=粗调试验_1,轮次=7,批次=20/55,当前损失=0.59767,学习率=0.00018782

[2026-03-23 09:59:44] 阶段=粗调试验_1,轮次=7,批次=40/55,当前损失=0.67505,学习率=0.00016159

[2026-03-23 09:59:45] 阶段=粗调试验_1,轮次=7,批次=55/55,当前损失=0.59247,学习率=0.00014588

[2026-03-23 09:59:46] 阶段=粗调试验_1,轮次=7,训练损失=0.63985,验证损失=0.60417
[2026-03-23 09:59:46] 检测到更优模型,最佳验证损失更新为:0.60417

[2026-03-23 09:59:48] 阶段=粗调试验_1,轮次=8,批次=20/55,当前损失=0.54579,学习率=0.00013056

[2026-03-23 09:59:50] 阶段=粗调试验_1,轮次=8,批次=40/55,当前损失=0.60645,学习率=0.00012195

[2026-03-23 09:59:51] 阶段=粗调试验_1,轮次=8,批次=55/55,当前损失=0.64151,学习率=0.00012

[2026-03-23 09:59:52] 阶段=粗调试验_1,轮次=8,训练损失=0.63721,验证损失=0.60405
[2026-03-23 09:59:52] 检测到更优模型,最佳验证损失更新为:0.60405
[2026-03-23 09:59:52] 开始评估:粗调试验_1

[2026-03-23 09:59:55] 评估完成:粗调试验_1
[2026-03-23 09:59:55] 训练结束:粗调试验_1
[2026-03-23 09:59:55] 粗调第 1 组结束,最优验证损失:0.60405
[2026-03-23 09:59:55] 粗调第 2 / 4 组开始
[2026-03-23 09:59:55] 开始训练:粗调试验_2
[2026-03-23 09:59:55] 本轮训练使用CPZ

[2026-03-23 10:00:00] 阶段=粗调试验_2,轮次=1,批次=20/55,当前损失=1.1349,学习率=0.00099567

[2026-03-23 10:00:05] 阶段=粗调试验_2,轮次=1,批次=40/55,当前损失=0.94897,学习率=0.00098278

[2026-03-23 10:00:09] 阶段=粗调试验_2,轮次=1,批次=55/55,当前损失=0.98535,学习率=0.00096765

[2026-03-23 10:00:10] 阶段=粗调试验_2,轮次=1,训练损失=1.2141,验证损失=0.87018
[2026-03-23 10:00:10] 检测到更优模型,最佳验证损失更新为:0.87018

[2026-03-23 10:00:15] 阶段=粗调试验_2,轮次=2,批次=20/55,当前损失=0.86119,学习率=0.00094051

[2026-03-23 10:00:20] 阶段=粗调试验_2,轮次=2,批次=40/55,当前损失=0.9009,学习率=0.00090592

[2026-03-23 10:00:23] 阶段=粗调试验_2,轮次=2,批次=55/55,当前损失=0.85252,学习率=0.00087552

[2026-03-23 10:00:25] 阶段=粗调试验_2,轮次=2,训练损失=0.94136,验证损失=0.84787
[2026-03-23 10:00:25] 检测到更优模型,最佳验证损失更新为:0.84787

[2026-03-23 10:00:29] 阶段=粗调试验_2,轮次=3,批次=20/55,当前损失=0.8315,学习率=0.00082969

[2026-03-23 10:00:34] 阶段=粗调试验_2,轮次=3,批次=40/55,当前损失=0.90563,学习率=0.00077868

[2026-03-23 10:00:37] 阶段=粗调试验_2,轮次=3,批次=55/55,当前损失=0.97828,学习率=0.00073764

[2026-03-23 10:00:39] 阶段=粗调试验_2,轮次=3,训练损失=0.88569,验证损失=0.81756
[2026-03-23 10:00:39] 检测到更优模型,最佳验证损失更新为:0.81756

[2026-03-23 10:00:43] 阶段=粗调试验_2,轮次=4,批次=20/55,当前损失=0.86509,学习率=0.00068011

[2026-03-23 10:00:48] 阶段=粗调试验_2,轮次=4,批次=40/55,当前损失=0.84347,学习率=0.00062043

[2026-03-23 10:00:52] 阶段=粗调试验_2,轮次=4,批次=55/55,当前损失=0.81896,学习率=0.000575

[2026-03-23 10:00:53] 阶段=粗调试验_2,轮次=4,训练损失=0.8528,验证损失=0.81044
[2026-03-23 10:00:53] 检测到更优模型,最佳验证损失更新为:0.81044

[2026-03-23 10:00:58] 阶段=粗调试验_2,轮次=5,批次=20/55,当前损失=0.82591,学习率=0.00051452

[2026-03-23 10:01:03] 阶段=粗调试验_2,轮次=5,批次=40/55,当前损失=0.79337,学习率=0.00045526

[2026-03-23 10:01:06] 阶段=粗调试验_2,轮次=5,批次=55/55,当前损失=0.86631,学习率=0.00041236

[2026-03-23 10:01:08] 阶段=粗调试验_2,轮次=5,训练损失=0.81162,验证损失=0.75736
[2026-03-23 10:01:08] 检测到更优模型,最佳验证损失更新为:0.75736

[2026-03-23 10:01:12] 阶段=粗调试验_2,轮次=6,批次=20/55,当前损失=0.75696,学习率=0.00035814

[2026-03-23 10:01:17] 阶段=粗调试验_2,轮次=6,批次=40/55,当前损失=0.80686,学习率=0.00030833

[2026-03-23 10:01:21] 阶段=粗调试验_2,轮次=6,批次=55/55,当前损失=0.73792,学习率=0.00027448

[2026-03-23 10:01:22] 阶段=粗调试验_2,轮次=6,训练损失=0.75374,验证损失=0.71218
[2026-03-23 10:01:22] 检测到更优模型,最佳验证损失更新为:0.71218

[2026-03-23 10:01:27] 阶段=粗调试验_2,轮次=7,批次=20/55,当前损失=0.78251,学习率=0.00023477

[2026-03-23 10:01:31] 阶段=粗调试验_2,轮次=7,批次=40/55,当前损失=0.67507,学习率=0.00020199

[2026-03-23 10:01:35] 阶段=粗调试验_2,轮次=7,批次=55/55,当前损失=0.72914,学习率=0.00018235

[2026-03-23 10:01:36] 阶段=粗调试验_2,轮次=7,训练损失=0.72688,验证损失=0.69691
[2026-03-23 10:01:36] 检测到更优模型,最佳验证损失更新为:0.69691

[2026-03-23 10:01:40] 阶段=粗调试验_2,轮次=8,批次=20/55,当前损失=0.67497,学习率=0.0001632

[2026-03-23 10:01:45] 阶段=粗调试验_2,轮次=8,批次=40/55,当前损失=0.71323,学习率=0.00015244

[2026-03-23 10:01:48] 阶段=粗调试验_2,轮次=8,批次=55/55,当前损失=0.78466,学习率=0.00015

[2026-03-23 10:01:50] 阶段=粗调试验_2,轮次=8,训练损失=0.71768,验证损失=0.68669
[2026-03-23 10:01:50] 检测到更优模型,最佳验证损失更新为:0.68669
[2026-03-23 10:01:50] 开始评估:粗调试验_2

[2026-03-23 10:01:59] 评估完成:粗调试验_2
[2026-03-23 10:01:59] 训练结束:粗调试验_2
[2026-03-23 10:01:59] 粗调第 2 组结束,最优验证损失:0.68669
[2026-03-23 10:01:59] 粗调第 3 / 4 组开始
[2026-03-23 10:01:59] 开始训练:粗调试验_3
[2026-03-23 10:01:59] 本轮训练使用CPZ

[2026-03-23 10:02:06] 阶段=粗调试验_3,轮次=1,批次=20/55,当前损失=1.6979,学习率=0.0014935

[2026-03-23 10:02:13] 阶段=粗调试验_3,轮次=1,批次=40/55,当前损失=1.6999,学习率=0.0014742

[2026-03-23 10:02:18] 阶段=粗调试验_3,轮次=1,批次=55/55,当前损失=1.5422,学习率=0.0014515

[2026-03-23 10:02:20] 阶段=粗调试验_3,轮次=1,训练损失=1.885,验证损失=1.48
[2026-03-23 10:02:20] 检测到更优模型,最佳验证损失更新为:1.48

[2026-03-23 10:02:27] 阶段=粗调试验_3,轮次=2,批次=20/55,当前损失=1.476,学习率=0.0014108

[2026-03-23 10:02:33] 阶段=粗调试验_3,轮次=2,批次=40/55,当前损失=1.5001,学习率=0.0013589

[2026-03-23 10:02:38] 阶段=粗调试验_3,轮次=2,批次=55/55,当前损失=1.407,学习率=0.0013133

[2026-03-23 10:02:40] 阶段=粗调试验_3,轮次=2,训练损失=1.485,验证损失=1.3578
[2026-03-23 10:02:40] 检测到更优模型,最佳验证损失更新为:1.3578

[2026-03-23 10:02:47] 阶段=粗调试验_3,轮次=3,批次=20/55,当前损失=1.4363,学习率=0.0012445

[2026-03-23 10:02:53] 阶段=粗调试验_3,轮次=3,批次=40/55,当前损失=1.3761,学习率=0.001168

[2026-03-23 10:02:58] 阶段=粗调试验_3,轮次=3,批次=55/55,当前损失=1.336,学习率=0.0011065

[2026-03-23 10:03:00] 阶段=粗调试验_3,轮次=3,训练损失=1.3505,验证损失=1.2459
[2026-03-23 10:03:00] 检测到更优模型,最佳验证损失更新为:1.2459

[2026-03-23 10:03:06] 阶段=粗调试验_3,轮次=4,批次=20/55,当前损失=1.2131,学习率=0.0010202

[2026-03-23 10:03:13] 阶段=粗调试验_3,轮次=4,批次=40/55,当前损失=1.2581,学习率=0.00093065

 [2026-03-23 10:14:16] 阶段=最终训练,轮次=10,批次=100/137,当前损失=0.51215,学习率=9.0917e-05

[2026-03-23 10:14:17] 阶段=最终训练,轮次=10,批次=120/137,当前损失=0.45051,学习率=9.0194e-05

[2026-03-23 10:14:19] 阶段=最终训练,轮次=10,批次=137/137,当前损失=0.43595,学习率=9e-05

[2026-03-23 10:14:20] 阶段=最终训练,轮次=10,训练损失=0.51625,验证损失=0.48211
[2026-03-23 10:14:20] 检测到更优模型,最佳验证损失更新为:0.48211
[2026-03-23 10:14:20] 开始评估:最佳模型保存

[2026-03-23 10:14:26] 评估完成:最佳模型保存

[2026-03-23 10:14:26] 最佳模型文件已保存:D:\MATLAB01\运行\best_pod_txansfsoxmex_model.mat
[2026-03-23 10:14:26] 开始评估:最终训练

[2026-03-23 10:14:32] 评估完成:最终训练
[2026-03-23 10:14:32] 开始评估:最佳模型保存

[2026-03-23 10:14:38] 评估完成:最佳模型保存

[2026-03-23 10:14:38] 最佳模型文件已保存:D:\MATLAB01\运行\best_pod_txansfsoxmex_model.mat
[2026-03-23 10:14:38] 训练结束:最终训练

[2026-03-23 10:14:39] 评估指标文件已保存:D:\MATLAB01\运行\evalzatikon_metxikcs.csv
[2026-03-23 10:14:39] 预测结果文件已保存:D:\MATLAB01\运行\pxedikctikon_xeszlts.csv
[2026-03-23 10:14:39] 主流程结束
[2026-03-23 10:14:39] 开始读取最佳模型并绘制全部图形

[2026-03-23 10:14:49] 全部图形绘制完成
[2026-03-23 10:14:49] 程序运行结束

>>

结束

更多详细内容请访问

http://机器学习有图有真相Matlab实现基于POD-Transformer本征正交分解数据降维(POD)结合Transformer编码器进行多变量回归预测(代码已调试成功,可一键运行,每一行都有详细资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92766887

https://download.csdn.net/download/xiaoxingkongyuxi/92766887

https://download.csdn.net/download/xiaoxingkongyuxi/92766887

Logo

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

更多推荐