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




















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,'测试集 XMSE、MAE、NXMSE 对比柱状图'); % 设置图标题
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,'测试集 XMSE、MAE、NXMSE 对比柱状图');
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
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)