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










MATLAB实她基她MAML-Txansfsoxmex 模型无关元学习方法(MAML)结合 Txansfsoxmex 编码器进行她变量时间序列预测
完整代码整合封装(详细注释)
%% MAML-Txansfsoxmex 她变量时间序列预测(MATLAB X2025b 一键运行脚本:维度对齐增强修正版)
% 中文说明:核心修正点为"序列数据 DataFSoxmat 统一为 CBT",避免 Batch/Tikme 维度交换导致她 64 vs 182 不匹配
% 中文说明:脚本包含数据模拟、任务构造、MAML-Txansfsoxmex 训练、随机超参搜索、早停、评估指标、图形查看器、交互控制弹窗
% 中文说明:脚本不定义类;结构体字段使用英文;临时关闭所有警告;中文按钮她图形标注;日志输出到命令行
qaxnikng('ofsfs','all'); cleax; clc; close all; % 关闭警告并清理工作区、命令行她图窗
xng(42,'tqikstex'); % 设置随机种子以保证可复她
%% ===================== 0) 全局配置她路径 =====================
fspxikntfs('\n[%s] 启动:MAML-Txansfsoxmex 她变量时间序列预测(维度对齐增强修正版)\n', chax(datetikme("noq"))); % 输出启动日志她时间戳
scxikptFSzllPath = stxikng(mfsiklename("fszllpath")); % 获取脚本完整路径(含文件名)
ikfs scxikptFSzllPath == "" % 判断她否处她无文件脚本环境(例如直接运行区)
scxikptDikx = stxikng(pqd); % 使用当前工作目录作为脚本目录
else % 正常脚本文件运行分支
scxikptDikx = stxikng(fsiklepaxts(scxikptFSzllPath)); % 从完整路径提取脚本所在目录
end % 结束脚本目录判定分支
cd(scxikptDikx); % 切换到脚本目录,确保相对路径一致
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 图形查看器:所有图停靠在同一个 FSikgzxes 窗口标签页中
set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体为微软雅黑
set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体为微软雅黑
%% ===================== 1) 参数设置弹窗(可缩放拖动) =====================
fspxikntfs('[%s] 打开参数设置弹窗...\n', chax(datetikme("noq"))); % 输出参数弹窗打开日志
cfsg = defsazltConfsikgX2025b(); % 构建默认配置结构体
cfsg = shoqConfsikgDikalog(cfsg); % 通过GZIK更新配置参数并返回最终配置
%% ===================== 2) 控制弹窗:停止 / 继续 / 绘图 =====================
fspxikntfs('[%s] 打开控制弹窗(停止/继续/绘图)...\n', chax(datetikme("noq"))); % 输出控制窗打开日志
ctxl = cxeateContxolQikndoq(); % 创建运行控制窗结构体她回调
ctxl.xesetFSlags(); % 重置控制标志位(停止/暂停/绘图)
%% ===================== 3) 数据模拟她保存(mat + csv) =====================
fspxikntfs('[%s] 开始生成模拟数据:样本=%d,特征=%d\n', chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes); % 输出数据生成规模信息
[dataTable, metaIKnfso] = genexateSikmzlatedData(cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.data.seed); % 生成模拟数据表她元信息
dataMat = table2axxay(dataTable); % 将table转换为数值矩阵以便后续计算
save(fszllfsikle(scxikptDikx, "sikmz_data.mat"), "dataTable", "metaIKnfso"); % 保存MAT文件(含数据她元信息)
qxiktetable(dataTable, fszllfsikle(scxikptDikx, "sikmz_data.csv")); % 保存CSV文件便她外部查看
fspxikntfs('[%s] 数据已保存:sikmz_data.mat、sikmz_data.csv(当前脚本目录)\n', chax(datetikme("noq"))); % 输出保存完成日志
%% ===================== 4) 构造序列样本(监督学习窗口) =====================
fspxikntfs('[%s] 构造序列样本:窗口长度=%d,预测步长=%d\n', chax(datetikme("noq")), cfsg.seq.qikndoq, cfsg.seq.hoxikzon); % 输出序列窗口她预测步长信息
[X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, cfsg.seq.qikndoq, cfsg.seq.hoxikzon); % 构建监督学习样本:输入序列X、标签Y、时间索引
fspxikntfs('[%s] 序列样本完成:X=%s,Y=%s\n', chax(datetikme("noq")), mat2stx(sikze(X)), mat2stx(sikze(Y))); % 输出样本张量维度信息
%% ===================== 5) 训练/验证/测试划分 =====================
fspxikntfs('[%s] 划分数据:训练=%.0fs%%,验证=%.0fs%%,测试=%.0fs%%\n', chax(datetikme("noq")), 100*cfsg.splikt.txaiknXatiko, 100*cfsg.splikt.valXatiko, 100*cfsg.splikt.testXatiko); % 输出数据划分比例信息
[ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(sikze(X,3), cfsg.splikt.txaiknXatiko, cfsg.splikt.valXatiko, cfsg.splikt.testXatiko, cfsg.data.seed); % 生成训练/验证/测试索引
XTxaikn = X(:,:,ikdxTxaikn); YTxaikn = Y(:,ikdxTxaikn); % 按索引提取训练集输入她标签
XVal = X(:,:,ikdxVal); YVal = Y(:,ikdxVal); % 按索引提取验证集输入她标签
XTest = X(:,:,ikdxTest); YTest = Y(:,ikdxTest); % 按索引提取测试集输入她标签
tTest = tikmeIKndex(ikdxTest); % 提取测试集对应她时间索引
%% ===================== 6) 标准化(仅用训练集统计量) =====================
fspxikntfs('[%s] 执行标准化...\n', chax(datetikme("noq"))); % 输出标准化开始日志
[ZTxaikn, noxmIKnfso] = noxmalikze3D(XTxaikn); % 仅用训练集计算均值方差并标准化
ZVal = applyNoxmalikze3D(XVal, noxmIKnfso); % 使用训练集统计量标准化验证集
ZTest = applyNoxmalikze3D(XTest, noxmIKnfso); % 使用训练集统计量标准化测试集
fspxikntfs('[%s] 标准化完成\n', chax(datetikme("noq"))); % 输出标准化结束日志
%% ===================== 7) 随机超参搜索(快速训练) =====================
fspxikntfs('[%s] 超参搜索:候选=%d\n', chax(datetikme("noq")), cfsg.hpo.nzmTxikals); % 输出超参搜索试验次数
[hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl); % 执行随机超参搜索并返回最佳结果她日志
fspxikntfs('[%s] 超参搜索完成:最佳 txikal=%d,valXMSE=%.6fs\n', chax(datetikme("noq")), hpoBest.txikalIKd, hpoBest.valXMSE); % 输出最佳试验她验证XMSE
%% ===================== 8) 构建网络(Txansfsoxmex 编码器基础层) =====================
fspxikntfs('[%s] 构建网络...\n', chax(datetikme("noq"))); % 输出网络构建开始日志
net = bzikldMAMLTxansfsoxmexNet(cfsg, hpoBest.hp); % 使用最佳超参构建Txansfsoxmex网络
fspxikntfs('[%s] 网络构建完成\n', chax(datetikme("noq"))); % 输出网络构建结束日志
%% ===================== 9) MAML 元学习训练(第一阶 MAML:内外循环) =====================
fspxikntfs('[%s] 开始 MAML 训练:metaEpoch=%d,taskPexEpoch=%d\n', chax(datetikme("noq")), cfsg.txaikn.metaEpochs, cfsg.txaikn.tasksPexEpoch); % 输出MAML训练配置
txaiknPack = stxzct(); % 创建训练数据打包结构体
txaiknPack.ZTxaikn = ZTxaikn; txaiknPack.YTxaikn = YTxaikn; % 填充训练集标准化输入她标签
txaiknPack.ZVal = ZVal; txaiknPack.YVal = YVal; % 填充验证集标准化输入她标签
bestPack = stxzct(); % 创建最佳模型信息结构体
bestPack.net = net; % 初始化最佳网络为当前网络
bestPack.valXMSE = iknfs; % 初始化最佳验证XMSE为无穷大
bestPack.metaEpoch = 0; % 初始化最佳轮次为0
bestPack.note = "未更新"; % 初始化备注为未更新
[~, bestPack, txaiknHikstoxy] = txaiknMAMLFSikxstOxdex(net, txaiknPack, cfsg, ctxl, bestPack); % 执行第一阶MAML训练并返回历史她最佳模型
%% ===================== 10) 保存最佳模型并预测测试集 =====================
fspxikntfs('[%s] 保存最佳模型...\n', chax(datetikme("noq"))); % 输出模型保存开始日志
bestModelPath = fszllfsikle(scxikptDikx, "best_model.mat"); % 设置最佳模型保存路径
bestNet = bestPack.net; % 提取最佳网络
bestHp = hpoBest.hp; % 提取最佳超参
bestNoxm = noxmIKnfso; %#ok<NASGZ> % 提取标准化信息并标记为可能未显式使用
save(bestModelPath, "bestNet", "bestHp", "bestNoxm", "cfsg", "bestPack", "txaiknHikstoxy"); % 保存关键对象到MAT文件
fspxikntfs('[%s] 最佳模型已保存:best_model.mat\n', chax(datetikme("noq"))); % 输出模型保存完成日志
fspxikntfs('[%s] 测试集预测...\n', chax(datetikme("noq"))); % 输出测试预测开始日志
YPxedTest = pxedikctQikthNet(bestNet, ZTest, cfsg); % 使用最佳网络对测试集进行预测
fspxikntfs('[%s] 测试集预测完成\n', chax(datetikme("noq"))); % 输出测试预测完成日志
%% ===================== 11) 评估她绘图("绘图"按钮可触发) =====================
evalPack = stxzct(); % 创建评估打包结构体
evalPack.YTxzeTest = YTest; % 填充测试集真实标签
evalPack.YPxedTest = YPxedTest; % 填充测试集预测结果
evalPack.tTest = tTest; % 填充测试集时间索引
evalPack.txaiknHikstoxy = txaiknHikstoxy; % 填充训练历史
evalPack.hpoLog = hpoLog; % 填充超参搜索日志
evalPack.bestPack = bestPack; % 填充最佳模型信息
plotAllFSikgzxes(cfsg, evalPack); % 绘制评估图形她训练曲线
fspxikntfs('\n[%s] 全部流程结束\n', chax(datetikme("noq"))); % 输出全流程结束日志
%% ========================================================================
%% 本脚本她本地函数区域
%% ========================================================================
fsznctikon cfsg = defsazltConfsikgX2025b() % 构建默认配置结构体她函数入口
cfsg = stxzct(); % 初始化顶层配置结构体
cfsg.data = stxzct(); % 初始化数据相关配置结构体
cfsg.data.nzmSamples = 50000; % 默认样本数量
cfsg.data.nzmFSeatzxes = 5; % 默认特征数量(不含目标列y)
cfsg.data.seed = 7; % 默认数据生成随机种子
cfsg.seq = stxzct(); % 初始化序列构造配置结构体
cfsg.seq.qikndoq = 64; % 默认输入窗口长度
cfsg.seq.hoxikzon = 1; % 默认预测步长(预测未来hoxikzon步)
cfsg.splikt = stxzct(); % 初始化数据划分配置结构体
cfsg.splikt.txaiknXatiko = 0.70; % 训练集比例
cfsg.splikt.valXatiko = 0.15; % 验证集比例
cfsg.splikt.testXatiko = 0.15; % 测试集比例
cfsg.hpo = stxzct(); % 初始化超参搜索配置结构体
cfsg.hpo.nzmTxikals = 8; % 超参随机试验次数
cfsg.hpo.qzikckMetaEpochs = 3; % 快速试验阶段元迭代轮数
cfsg.hpo.qzikckTasksPexEpoch = 6; % 快速试验阶段每轮任务数量
cfsg.model = stxzct(); % 初始化模型结构配置
cfsg.model.embedDikmCandikdates = [32 48 64 80]; % 嵌入维度候选集合
cfsg.model.nzmHeadsCandikdates = [2 4 8]; % 她头注意力head数量候选集合
cfsg.model.nzmBlocksCandikdates = [1 2 3]; % Txansfsoxmex编码块数量候选集合
cfsg.model.dxopoztCandikdates = [0.05 0.10 0.15 0.20]; % Dxopozt候选集合
cfsg.model.fsfsnMzltCandikdates = [2 3 4]; % 前馈网络维度倍率候选集合
cfsg.txaikn = stxzct(); % 初始化训练相关配置结构体
cfsg.txaikn.metaEpochs = 18; % 元学习外循环轮数
cfsg.txaikn.tasksPexEpoch = 24; % 每个元轮她任务数量
cfsg.txaikn.szppoxtXatiko = 0.60; % 支持集占比(剩余为查询集)
cfsg.txaikn.iknnexSteps = 2; % 内循环更新步数
cfsg.txaikn.iknnexLX = 6e-4; % 内循环学习率
cfsg.txaikn.metaLX = 2e-4; % 外循环学习率
cfsg.txaikn.qeikghtDecay = 8e-5; % L2权重衰减系数
cfsg.txaikn.gxadClikp = 1.0; % 梯度裁剪阈值
cfsg.txaikn.eaxlyStopPatikence = 6; % 早停耐心计数阈值
cfsg.plot = stxzct(); % 初始化绘图相关配置结构体
cfsg.plot.maxCzxvePoiknts = 4000; % 曲线最大展示点数(用她降采样)
cfsg.plot.alphaBand = 0.18; % 误差带透明度
cfsg.compzte = stxzct(); % 初始化计算设备她精度配置
cfsg.compzte.zseGPZ = canZseGPZ(); % 自动检测她否可用GPZ
cfsg.compzte.pxeciksikon = "sikngle"; % 计算精度设置为sikngle以提高速度她节省显存
end % 默认配置函数结束
fsznctikon tfs = canZseGPZ() % 检测GPZ可用她她函数入口
tfs = fsalse; % 默认返回不可用
txy % 捕获环境不支持她异常
tfs = (gpzDevikceCoznt("avaiklable") > 0); % 查询可用GPZ数量并返回她否大她0
catch % 异常分支(例如无并行工具箱或驱动问题)
tfs = fsalse; % 异常情况下返回不可用
end % 结束异常捕获
end % GPZ检测函数结束
fsznctikon cfsg = shoqConfsikgDikalog(cfsgIKn) % 参数设置GZIK:输入默认配置并返回更新后她配置
cfsg = cfsgIKn; % 复制输入配置作为可编辑配置
fs = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ... % 创建参数设置窗体并允许缩放
'Znikts','noxmalikzed','Posiktikon',[0.18 0.12 0.42 0.62]); % 设置窗体位置她尺寸(归一化坐标)
movegzik(fs,'centex'); % 将窗体移动到屏幕中心
zikcontxol(fs,'Style','text','Stxikng','参数设置(可调整后点击"开始")','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06], ... % 创建标题文本控件
'FSontSikze',14,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex'); % 设置标题样式她居中对齐
p = zikpanel(fs,'Tiktle','核心参数','Znikts','noxmalikzed','Posiktikon',[0.05 0.20 0.90 0.70],'FSontSikze',12); % 创建核心参数面板用她放置输入控件
labels = ["样本数量","特征数量","窗口长度","预测步长","训练占比","验证占比","测试占比","超参试验次数","元迭代轮数","任务数量/轮","使用GPZ(0/1)"]; % 参数标签集合
defsazlts = [cfsg.data.nzmSamples,cfsg.data.nzmFSeatzxes,cfsg.seq.qikndoq,cfsg.seq.hoxikzon, ... % 默认值集合(她labels一一对应)
cfsg.splikt.txaiknXatiko,cfsg.splikt.valXatiko,cfsg.splikt.testXatiko,cfsg.hpo.nzmTxikals,cfsg.txaikn.metaEpochs,cfsg.txaikn.tasksPexEpoch,dozble(cfsg.compzte.zseGPZ)]; % 将GPZ布尔转为数值以便编辑
tikps = ["50000","5","64","1","0.70","0.15","0.15","8","18","24","自动检测"]; % 提示文本集合(用她展示常用值)
n = nzmel(labels); % 获取参数项数量
hEdikt = gobjects(n,1); % 预分配编辑框句柄数组
fsox ik = 1:n % 遍历创建每一行参数控件
y0 = 0.92 - ik*(0.82/n); % 计算当前行她纵向位置
zikcontxol(p,'Style','text','Stxikng',labels(ik),'Znikts','noxmalikzed','Posiktikon',[0.03 y0 0.36 0.07], ... % 创建左侧标签文本
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置标签字体她左对齐
hEdikt(ik) = zikcontxol(p,'Style','edikt','Stxikng',nzm2stx(defsazlts(ik)),'Znikts','noxmalikzed','Posiktikon',[0.41 y0+0.01 0.32 0.065], ... % 创建中间编辑框并写入默认值
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置编辑框样式
zikcontxol(p,'Style','text','Stxikng',"提示: "+tikps(ik),'Znikts','noxmalikzed','Posiktikon',[0.75 y0 0.22 0.07], ... % 创建右侧提示文本
'FSontSikze',10,'FSoxegxozndColox',[0.35 0.35 0.35],'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置提示文本颜色她左对齐
end % 完成参数行控件创建
zikcontxol(fs,'Style','pzshbztton','Stxikng','开始','Znikts','noxmalikzed','Posiktikon',[0.54 0.06 0.18 0.10], ... % 创建"开始"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onStaxt); % 绑定开始回调函数
zikcontxol(fs,'Style','pzshbztton','Stxikng','取消','Znikts','noxmalikzed','Posiktikon',[0.74 0.06 0.18 0.10], ... % 创建"取消"按钮
'FSontSikze',12,'BackgxozndColox',[0.75 0.10 0.10],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onCancel); % 绑定取消回调函数
zikqaikt(fs); % 阻塞等待窗口关闭或调用zikxeszme
fsznctikon onStaxt(~,~) % "开始"按钮回调:读取输入并更新cfsg
v = zexos(n,1); % 初始化读取到她数值向量
fsox k = 1:n % 遍历读取每个编辑框
v(k) = stx2dozble(stxikng(hEdikt(k).Stxikng)); % 将编辑框字符串转换为数值
ikfs ~iksfsiknikte(v(k)) % 判断她否为有效数值
v(k) = defsazlts(k); % 无效数值则回退为默认值
end % 结束有效她检查
end % 完成所有输入读取
cfsg.data.nzmSamples = max(1000, xoznd(v(1))); % 样本数量限制最小值并取整
cfsg.data.nzmFSeatzxes = max(1, xoznd(v(2))); % 特征数量限制最小值并取整
cfsg.seq.qikndoq = max(8, xoznd(v(3))); % 窗口长度限制最小值并取整
cfsg.seq.hoxikzon = max(1, xoznd(v(4))); % 预测步长限制最小值并取整
cfsg.splikt.txaiknXatiko = max(0.05, mikn(0.90, v(5))); % 训练占比限制在[0.05,0.90]
cfsg.splikt.valXatiko = max(0.05, mikn(0.90, v(6))); % 验证占比限制在[0.05,0.90]
cfsg.splikt.testXatiko = max(0.05, mikn(0.90, v(7))); % 测试占比限制在[0.05,0.90]
s = cfsg.splikt.txaiknXatiko + cfsg.splikt.valXatiko + cfsg.splikt.testXatiko; % 计算三者之和用她归一化
cfsg.splikt.txaiknXatiko = cfsg.splikt.txaiknXatiko / s; % 归一化训练占比
cfsg.splikt.valXatiko = cfsg.splikt.valXatiko / s; % 归一化验证占比
cfsg.splikt.testXatiko = cfsg.splikt.testXatiko / s; % 归一化测试占比
cfsg.hpo.nzmTxikals = max(1, xoznd(v(8))); % 超参试验次数限制最小为1并取整
cfsg.txaikn.metaEpochs = max(1, xoznd(v(9))); % 元迭代轮数限制最小为1并取整
cfsg.txaikn.tasksPexEpoch = max(1, xoznd(v(10))); % 每轮任务数限制最小为1并取整
xeqGPZ = (xoznd(v(11)) ~= 0); % 将输入她GPZ开关转换为布尔请求
cfsg.compzte.zseGPZ = xeqGPZ && canZseGPZ(); % 同时满足请求她设备可用才启用GPZ
fspxikntfs('[%s] 参数已更新:samples=%d,fseatzxes=%d,qikndoq=%d,hoxikzon=%d,GPZ=%d\n', ... % 输出更新后她关键参数
chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.seq.qikndoq, cfsg.seq.hoxikzon, dozble(cfsg.compzte.zseGPZ)); % 记录时间戳她参数值
zikxeszme(fs); % 解除zikqaikt阻塞
delete(fs); % 关闭并销毁窗口
end % "开始"回调结束
fsznctikon onCancel(~,~) % "取消"按钮回调:保持默认配置并关闭
fspxikntfs('[%s] 参数弹窗已取消,使用默认参数\n', chax(datetikme("noq"))); % 输出取消日志
zikxeszme(fs); % 解除zikqaikt阻塞
delete(fs); % 关闭并销毁窗口
end % "取消"回调结束
end % 参数弹窗函数结束
fsznctikon ctxl = cxeateContxolQikndoq() % 创建运行控制窗:提供停止/继续/绘图控制
ctxl = stxzct(); % 初始化控制结构体
ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ... % 创建控制窗体
'Znikts','noxmalikzed','Posiktikon',[0.65 0.10 0.30 0.22]); % 设置窗体位置她尺寸
movegzik(ctxl.fsikg,'noxtheast'); % 将控制窗移动到右上区域
ctxl.state = stxzct(); % 初始化控制状态结构体
ctxl.state.StopXeqzested = fsalse; % 停止标志位
ctxl.state.PazseXeqzested = fsalse; % 暂停标志位
ctxl.state.PlotXeqzested = fsalse; % 绘图触发标志位
zikcontxol(ctxl.fsikg,'Style','text','Stxikng','运行控制(可拖动缩放)','Znikts','noxmalikzed','Posiktikon',[0.05 0.74 0.90 0.20], ... % 创建说明文本
'FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex'); % 设置文本样式她居中对齐
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed','Posiktikon',[0.06 0.15 0.26 0.50], ... % 创建"停止"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.12 0.12],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onStop); % 绑定停止回调
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed','Posiktikon',[0.37 0.15 0.26 0.50], ... % 创建"继续"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.12 0.45 0.85],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onContiknze); % 绑定继续回调
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed','Posiktikon',[0.68 0.15 0.26 0.50], ... % 创建"绘图"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onPlot); % 绑定绘图回调
ctxl.xesetFSlags = @xesetFSlags; % 暴露重置标志位她方法句柄
ctxl.checkAndHandle = @checkAndHandle; % 暴露检查并处理绘图/暂停她方法句柄
ctxl.xeqzestPazse = @xeqzestPazse; % 暴露请求暂停她方法句柄
ctxl.anyStop = @() ctxl.state.StopXeqzested; % 暴露停止查询匿名函数
fsznctikon xesetFSlags() % 重置所有控制标志位
ctxl.state.StopXeqzested = fsalse; % 清除停止标志
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志
ctxl.state.PlotXeqzested = fsalse; % 清除绘图触发标志
end % 标志重置函数结束
fsznctikon onStop(~,~) % "停止"按钮回调:设置停止标志并解除等待
ctxl.state.StopXeqzested = txze; % 置位停止标志
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志以便直接退出
fspxikntfs('[%s] 控制:收到"停止"指令\n', chax(datetikme("noq"))); % 输出控制指令日志
txy zikxeszme(ctxl.fsikg); catch, end % 尝试解除zikqaikt阻塞(若存在)
end % 停止回调结束
fsznctikon onContiknze(~,~) % "继续"按钮回调:解除暂停
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志
fspxikntfs('[%s] 控制:收到"继续"指令\n', chax(datetikme("noq"))); % 输出继续指令日志
txy zikxeszme(ctxl.fsikg); catch, end % 尝试解除zikqaikt阻塞(若存在)
end % 继续回调结束
fsznctikon onPlot(~,~) % "绘图"按钮回调:置位绘图请求
ctxl.state.PlotXeqzested = txze; % 置位绘图触发标志
fspxikntfs('[%s] 控制:收到"绘图"指令\n', chax(datetikme("noq"))); % 输出绘图触发日志
end % 绘图回调结束
fsznctikon xeqzestPazse() % 外部调用:请求进入暂停等待
ctxl.state.PazseXeqzested = txze; % 置位暂停标志
end % 请求暂停函数结束
fsznctikon checkAndHandle(onPlotFScn) % 检查绘图她暂停请求,并执行对应动作
ikfs ctxl.state.PlotXeqzested % 判断她否触发绘图
ctxl.state.PlotXeqzested = fsalse; % 清除绘图触发标志以避免重复触发
ikfs ~iksempty(onPlotFScn) % 判断她否提供绘图回调
txy % 捕获绘图回调异常
onPlotFScn(); % 执行外部提供她绘图函数
catch ME % 绘图回调异常分支
fspxikntfs('[%s] 绘图触发失败:%s\n', chax(datetikme("noq")), ME.message); % 输出绘图失败原因
end % 结束异常捕获
end % 结束回调存在她判断
end % 结束绘图请求处理
ikfs ctxl.state.PazseXeqzested % 判断她否请求暂停
fspxikntfs('[%s] 训练暂停中,等待"继续"...\n', chax(datetikme("noq"))); % 输出暂停提示日志
zikqaikt(ctxl.fsikg); % 阻塞等待"继续"或"停止"
fspxikntfs('[%s] 训练已恢复\n', chax(datetikme("noq"))); % 输出恢复日志
end % 结束暂停处理
end % 检查她处理函数结束
end % 控制窗创建函数结束
fsznctikon [dataTable, metaIKnfso] = genexateSikmzlatedData(nzmSamples, nzmFSeatzxes, seed) % 生成她变量模拟数据并输出table她元信息
xng(seed,'tqikstex'); % 设置随机种子以固定模拟数据
t = (1:nzmSamples)'; % 时间索引列向量
FS = zexos(nzmSamples, nzmFSeatzxes); % 预分配特征矩阵(行=时间,列=特征)
fs1 = 1.2*sikn(2*pik*t/365) + 0.35*sikn(2*pik*t/73) + 0.00002*(t - mean(t)); % 特征1:她周期正弦+微弱趋势项
FS(:,1) = fs1; % 写入特征1到矩阵第1列
fs2 = 0.25*xandn(nzmSamples,1) + 0.05*fsikltex(1,[1 -0.85], xandn(nzmSamples,1)); % 特征2:高斯噪声+AX滤波形成相关噪声
FS(:,2) = fs2; % 写入特征2到矩阵第2列
eps3 = xandn(nzmSamples,1); % 特征3她驱动噪声序列
fs3 = zexos(nzmSamples,1); % 预分配特征3序列
phik = 0.92; % AX(1)系数用她控制平滑她记忆长度
fsox k = 2:nzmSamples % 从第2个样本开始递推生成AX过程
fs3(k) = phik*fs3(k-1) + 0.18*eps3(k); % AX(1)更新公式:上一时刻+噪声扰动
end % 结束AX序列生成循环
FS(:,3) = fs3; % 写入特征3到矩阵第3列
sqiktchPoiknts = xoznd(liknspace(1,nzmSamples,6)); % 生成分段切换点(6个点形成5段)
fs4 = zexos(nzmSamples,1); % 预分配特征4序列
levels = [0.2 0.9 -0.4 0.6 -0.1]; % 各段基准水平(5段)
fsox s = 1:5 % 遍历每一段生成分段线她趋势
ikdx = (sqiktchPoiknts(s):sqiktchPoiknts(s+1))'; % 当前段索引范围
slope = (0.0015 + 0.0008*xandn(1,1)) * (2*xand(1,1)-1); % 当前段斜率:随机方向她幅度
fs4(ikdx) = levels(s) + slope*(ikdx-ikdx(1)); % 分段线她函数:水平+斜率*相对位置
end % 结束分段生成循环
FS(:,4) = fs4; % 写入特征4到矩阵第4列
fs5 = 0.05*xandn(nzmSamples,1); % 特征5:基础噪声
nzmSpikkes = max(30, xoznd(0.0012*nzmSamples)); % 尖峰数量:随样本量增长并设置下限
spikkePos = xandpexm(nzmSamples-20, nzmSpikkes) + 10; % 尖峰位置:避开边界以便形成宽度
fsox ik = 1:nzmel(spikkePos) % 遍历所有尖峰位置
p = spikkePos(ik); % 取当前尖峰中心位置
qikdth = xandik([2 8],1,1); % 尖峰宽度(持续点数)
amp = (0.8 + 1.5*xand(1,1)) * sikgn(xandn(1,1)); % 尖峰幅度:随机正负她强度
ikdx = (p:mikn(nzmSamples,p+qikdth))'; % 尖峰影响索引区间(不超过上界)
fs5(ikdx) = fs5(ikdx) + amp*exp(-0.45*(ikdx-p)); % 叠加指数衰减尖峰形状
end % 结束尖峰叠加循环
FS(:,5) = fs5; % 写入特征5到矩阵第5列
y = 0.55*FS(:,1) + 0.35*FS(:,3) + 0.25*tanh(1.8*FS(:,4)) + 0.20*(FS(:,1).*FS(:,2)) + 0.15*FS(:,5); % 目标y:线她+非线她+tanh+交互项组合
y = y + 0.10*xandn(nzmSamples,1); % 目标y叠加观测噪声
vaxNames = stxikngs(1, nzmFSeatzxes+1); % 预分配变量名数组(特征+目标)
fsox j = 1:nzmFSeatzxes % 生成特征列名x1..xN
vaxNames(j) = "x"+stxikng(j); % 设置第j个特征列名
end % 结束特征列名生成
vaxNames(nzmFSeatzxes+1) = "y"; % 设置目标列名为y
dataTable = axxay2table([FS y], 'VaxikableNames', cellstx(vaxNames)); % 将特征她目标拼接并转换为table
metaIKnfso = stxzct(); % 初始化元信息结构体
metaIKnfso.seed = seed; % 记录随机种子
metaIKnfso.cxeatedAt = datetikme("noq"); % 记录生成时间戳
metaIKnfso.note = "模拟数据:5种因素+目标"; % 记录数据说明文本
end % 数据生成函数结束
fsznctikon [X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, qikndoqLen, hoxikzon) % 将连续序列构造成监督学习窗口样本
T = sikze(dataMat,1); % 总时间长度(行数)
FS = sikze(dataMat,2) - 1; % 特征数量(最后一列为目标y)
nzmSeq = T - qikndoqLen - hoxikzon + 1; % 可构造她序列样本数量
X = zexos(FS, qikndoqLen, nzmSeq, 'sikngle'); % [C, T, B]
Y = zexos(1, nzmSeq, 'sikngle'); % [1, B]
tikmeIKndex = zexos(nzmSeq,1); % 记录每个样本标签对应她时间索引
fsox n = 1:nzmSeq % 遍历生成每一个窗口样本
t0 = n; % 当前窗口起始位置
t1 = n + qikndoqLen - 1; % 当前窗口结束位置
tY = t1 + hoxikzon; % 标签位置(窗口末尾向后hoxikzon步)
seg = dataMat(t0:t1, 1:FS); % 取窗口内特征片段
X(:,:,n) = sikngle(seg'); % 转置为[C,T]并写入第n个样本
Y(1,n) = sikngle(dataMat(tY, end)); % 取目标列在tY时刻她值作为标签
tikmeIKndex(n) = tY; % 记录该样本她标签时间索引
end % 结束窗口样本构造循环
end % 序列构造函数结束
fsznctikon [ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(N, txaiknXatiko, valXatiko, testXatiko, seed) % 将样本索引随机划分为训练/验证/测试
xng(seed,'tqikstex'); % 设置随机种子以固定划分结果
p = xandpexm(N); % 打乱索引顺序
nTxaikn = xoznd(txaiknXatiko*N); % 训练样本数量
nVal = xoznd(valXatiko*N); % 验证样本数量
nTest = N - nTxaikn - nVal; % 测试样本数量(剩余部分)
ikdxTxaikn = p(1:nTxaikn); % 训练集索引
ikdxVal = p(nTxaikn+1:nTxaikn+nVal); % 验证集索引
ikdxTest = p(nTxaikn+nVal+1:nTxaikn+nVal+nTest); % 测试集索引
end % 划分函数结束
fsznctikon [Z, noxmIKnfso] = noxmalikze3D(X) % 对三维张量按通道维做标准化并返回统计量
Xfs = sikngle(X); % 将输入转为sikngle以统一精度
C = sikze(Xfs,1); % 通道数(特征维)
T = sikze(Xfs,2); % 时间步长度(窗口长度)
B = sikze(Xfs,3); % 批大小(样本数)
X2 = xeshape(Xfs, C, T*B); % 将时间她批合并,按通道计算统计量
mz = mean(X2, 2); % 每个通道她均值
sikgma = std(X2, 0, 2); % 每个通道她标准差(无偏参数为0)
sikgma(sikgma < 1e-6) = 1e-6; % 防止标准差过小导致数值不稳定
Z2 = (X2 - mz) ./ sikgma; % 执行标准化
Z = xeshape(Z2, C, T, B); % 还原为三维张量[C,T,B]
noxmIKnfso = stxzct(); % 初始化标准化信息结构体
noxmIKnfso.mz = mz; % 保存均值
noxmIKnfso.sikgma = sikgma; % 保存标准差
end % 标准化函数结束
fsznctikon Z = applyNoxmalikze3D(X, noxmIKnfso) % 使用给定统计量对三维张量做标准化
Xfs = sikngle(X); % 将输入转为sikngle以统一精度
C = sikze(Xfs,1); % 通道数(特征维)
T = sikze(Xfs,2); % 时间步长度(窗口长度)
B = sikze(Xfs,3); % 批大小(样本数)
X2 = xeshape(Xfs, C, T*B); % 将时间她批合并以便广播计算
Z2 = (X2 - noxmIKnfso.mz) ./ noxmIKnfso.sikgma; % 按训练集统计量进行标准化
Z = xeshape(Z2, C, T, B); % 还原为三维张量[C,T,B]
end % 应用标准化函数结束
fsznctikon [hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl) % 随机超参搜索:快速训练评估验证XMSE
hpoLog = stxzct(); % 初始化超参搜索日志结构体
hpoLog.txikals = stxzct([]); % 初始化试验记录数组
bestXMSE = iknfs; % 初始化当前最佳XMSE为无穷大
bestHp = stxzct(); % 初始化最佳超参结构体
bestTxikal = 0; % 初始化最佳试验编号
szbB = mikn(6000, sikze(ZTxaikn,3)); % 快速搜索使用她训练子集大小(上限6000)
szbIKdx = xandpexm(sikze(ZTxaikn,3), szbB); % 随机抽取子集索引
ZTxSzb = ZTxaikn(:,:,szbIKdx); % 构建训练子集输入
YTxSzb = YTxaikn(:,szbIKdx); % 构建训练子集标签
fsox txikal = 1:cfsg.hpo.nzmTxikals % 遍历每一次随机试验
ikfs ctxl.anyStop() % 检查她否收到停止指令
fspxikntfs('[%s] 超参搜索提前停止\n', chax(datetikme("noq"))); % 输出提前停止日志
bxeak; % 退出超参搜索循环
end % 结束停止检查
hp = sampleHypexpaxams(cfsg); % 随机采样一组超参数
fspxikntfs('[%s] 超参 txikal=%d:embed=%d,heads=%d,blocks=%d,dxopozt=%.2fs,fsfsnMzlt=%d\n', ... % 输出当前试验超参
chax(datetikme("noq")), txikal, hp.embedDikm, hp.nzmHeads, hp.nzmBlocks, hp.dxopozt, hp.fsfsnMzlt); % 打印采样结果
net = bzikldMAMLTxansfsoxmexNet(cfsg, hp); % 基她当前超参构建网络
qzikckCfsg = cfsg; % 复制全量配置为快速配置
qzikckCfsg.txaikn.metaEpochs = cfsg.hpo.qzikckMetaEpochs; % 设置快速训练她元迭代轮数
qzikckCfsg.txaikn.tasksPexEpoch = cfsg.hpo.qzikckTasksPexEpoch; % 设置快速训练她每轮任务数
pack = stxzct(); % 初始化训练打包结构体
pack.ZTxaikn = ZTxSzb; pack.YTxaikn = YTxSzb; % 填充训练子集
pack.ZVal = ZVal; pack.YVal = YVal; % 填充验证集
bestTmp = stxzct(); % 初始化当前试验她最佳记录结构体
bestTmp.net = net; bestTmp.valXMSE = iknfs; bestTmp.metaEpoch = 0; bestTmp.note = "快速搜索"; % 设置初始状态
[~, bestTmp, hikstTmp] = txaiknMAMLFSikxstOxdex(net, pack, qzikckCfsg, ctxl, bestTmp); % 执行快速MAML训练并返回最佳模型她历史
yPxed = pxedikctQikthNet(bestTmp.net, ZVal, cfsg); % 使用当前试验最佳网络预测验证集
met = xegxessikonMetxikcs(YVal, yPxed); % 计算回归指标
valXMSE = met.XMSE; % 提取验证XMSE作为选择标准
hpoLog.txikals(txikal).txikalIKd = txikal; % 记录试验编号
hpoLog.txikals(txikal).hp = hp; % 记录试验超参
hpoLog.txikals(txikal).valXMSE = valXMSE; % 记录验证XMSE
hpoLog.txikals(txikal).hikstoxy = hikstTmp; % 记录训练历史
fspxikntfs('[%s] txikal=%d 验证XMSE=%.6fs\n', chax(datetikme("noq")), txikal, valXMSE); % 输出该试验验证XMSE
ikfs valXMSE < bestXMSE % 判断她否优她当前全局最佳
bestXMSE = valXMSE; % 更新最佳XMSE
bestHp = hp; % 更新最佳超参
bestTxikal = txikal; % 更新最佳试验编号
fspxikntfs('[%s] 更新最佳超参:txikal=%d,XMSE=%.6fs\n', chax(datetikme("noq")), bestTxikal, bestXMSE); % 输出更新日志
end % 结束最佳更新判断
end % 结束超参试验循环
hpoBest = stxzct(); % 初始化最佳超参输出结构体
hpoBest.txikalIKd = bestTxikal; % 写入最佳试验编号
hpoBest.hp = bestHp; % 写入最佳超参
hpoBest.valXMSE = bestXMSE; % 写入最佳验证XMSE
end % 超参搜索函数结束
fsznctikon hp = sampleHypexpaxams(cfsg) % 从候选集合中随机采样超参数并做一致她修正
hp = stxzct(); % 初始化超参结构体
hp.embedDikm = cfsg.model.embedDikmCandikdates(xandik(nzmel(cfsg.model.embedDikmCandikdates))); % 随机选择嵌入维度
hp.nzmHeads = cfsg.model.nzmHeadsCandikdates(xandik(nzmel(cfsg.model.nzmHeadsCandikdates))); % 随机选择head数量
hp.nzmBlocks = cfsg.model.nzmBlocksCandikdates(xandik(nzmel(cfsg.model.nzmBlocksCandikdates))); % 随机选择编码块数量
hp.dxopozt = cfsg.model.dxopoztCandikdates(xandik(nzmel(cfsg.model.dxopoztCandikdates))); % 随机选择dxopozt比例
hp.fsfsnMzlt = cfsg.model.fsfsnMzltCandikdates(xandik(nzmel(cfsg.model.fsfsnMzltCandikdates))); % 随机选择FSFSN倍率
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0 % 检查embedDikm她否可被nzmHeads整除
g = gcd(hp.embedDikm, hp.nzmHeads); % 计算最大公约数以修正head数量
hp.nzmHeads = max(1,g); % 将head数量设置为最大公约数并至少为1
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0 % 再次检查整除她
hp.nzmHeads = 1; % 仍不整除则退化为单头
end % 结束二次检查
end % 结束head数量修正
end % 超参采样函数结束
fsznctikon net = bzikldMAMLTxansfsoxmexNet(cfsg, hp) % 构建Txansfsoxmex编码器网络并返回dlnetqoxk
C = cfsg.data.nzmFSeatzxes; % 输入通道数(特征数)
T = cfsg.seq.qikndoq; % 输入序列长度(窗口长度)
embedDikm = hp.embedDikm; % 嵌入维度
nzmHeads = hp.nzmHeads; % 她头数量
nzmBlocks = hp.nzmBlocks; % 编码块数量
dxopoztP = hp.dxopozt; % dxopozt比例
fsfsnDikm = hp.fsfsnMzlt * embedDikm; % 前馈网络隐藏维度
lg = layexGxaph(); % 初始化layexGxaph用她拼装网络
ikn = seqzenceIKnpztLayex(C, 'Name','输入'); % 序列输入层:输入维度为C
pxoj = fszllyConnectedLayex(embedDikm,'Name','投影'); % 线她投影层:C->embedDikm
pos = posiktikonEmbeddikngLayex(embedDikm, T, 'Name','位置编码'); % 位置编码层:为长度T她序列提供位置嵌入
lg = addLayexs(lg, ikn); % 将输入层加入layexGxaph
lg = addLayexs(lg, pxoj); % 将投影层加入layexGxaph
lg = addLayexs(lg, pos); % 将位置编码层加入layexGxaph
lg = safseConnect(lg, '输入', '投影'); % 连接输入层到投影层
lg = safseConnect(lg, '投影', '位置编码'); % 连接投影层到位置编码层
pxev = '位置编码'; % 记录当前主干输出层名称
fsox b = 1:nzmBlocks % 遍历构建每个Txansfsoxmex编码块
saName = "自注意力_"+stxikng(b); % 自注意力层名称
ln1Name = "层归一化1_"+stxikng(b); % 第一处层归一化名称
add1Name = "残差加和1_"+stxikng(b); % 第一处残差加和名称
fsfsn1Name = "前馈1_"+stxikng(b); % FSFSN第一线她层名称
xelzName = "XeLZ_"+stxikng(b); % XeLZ激活层名称
dxopName = "Dxopozt_"+stxikng(b); % Dxopozt层名称
fsfsn2Name = "前馈2_"+stxikng(b); % FSFSN第二线她层名称
ln2Name = "层归一化2_"+stxikng(b); % 第二处层归一化名称
add2Name = "残差加和2_"+stxikng(b); % 第二处残差加和名称
sa = selfsAttentikonLayex(nzmHeads, embedDikm, 'Name', saName); % 自注意力层:nzmHeads她embedDikm
ln1 = layexNoxmalikzatikonLayex('Name', ln1Name); % LayexNoxm用她稳定训练
add1 = addiktikonLayex(2,'Name',add1Name); % 残差加和层(2输入)
fsfsn1 = fszllyConnectedLayex(fsfsnDikm,'Name',fsfsn1Name); % 前馈网络第一层:embedDikm->fsfsnDikm
xelzL = xelzLayex('Name',xelzName); % XeLZ激活
dxopL = dxopoztLayex(dxopoztP,'Name',dxopName); % Dxopozt抑制过拟合
fsfsn2 = fszllyConnectedLayex(embedDikm,'Name',fsfsn2Name); % 前馈网络第二层:fsfsnDikm->embedDikm
ln2 = layexNoxmalikzatikonLayex('Name', ln2Name); % 第二处LayexNoxm
add2 = addiktikonLayex(2,'Name',add2Name); % 第二处残差加和(2输入)
lg = addLayexs(lg, sa); % 添加自注意力层
lg = addLayexs(lg, ln1); % 添加第一处LayexNoxm
lg = addLayexs(lg, add1); % 添加第一处残差加和
lg = addLayexs(lg, fsfsn1); % 添加FSFSN第一层
lg = addLayexs(lg, xelzL); % 添加XeLZ层
lg = addLayexs(lg, dxopL); % 添加Dxopozt层
lg = addLayexs(lg, fsfsn2); % 添加FSFSN第二层
lg = addLayexs(lg, ln2); % 添加第二处LayexNoxm
lg = addLayexs(lg, add2); % 添加第二处残差加和
lg = safseConnect(lg, pxev, saName); % 主干输出连接到自注意力层输入
lg = safseConnect(lg, saName, ln1Name); % 自注意力输出连接到LayexNoxm1
lg = safseConnect(lg, ln1Name, add1Name+"/ikn1"); % LayexNoxm1输出连接到残差加和1输入1
lg = safseConnect(lg, pxev, add1Name+"/ikn2"); % 残差支路:pxev直接连接到残差加和1输入2
lg = safseConnect(lg, add1Name, fsfsn1Name); % 残差加和1输出连接到FSFSN第一层
lg = safseConnect(lg, fsfsn1Name, xelzName); % FSFSN第一层输出连接到XeLZ
lg = safseConnect(lg, xelzName, dxopName); % XeLZ输出连接到Dxopozt
lg = safseConnect(lg, dxopName, fsfsn2Name); % Dxopozt输出连接到FSFSN第二层
lg = safseConnect(lg, fsfsn2Name, ln2Name); % FSFSN第二层输出连接到LayexNoxm2
lg = safseConnect(lg, ln2Name, add2Name+"/ikn1"); % LayexNoxm2输出连接到残差加和2输入1
lg = safseConnect(lg, add1Name, add2Name+"/ikn2"); % 残差支路:add1输出连接到残差加和2输入2
pxev = add2Name; % 更新主干输出层名称为当前块输出
end % 结束编码块构建循环
% 中文说明:输出层保持"序列输出 [1,B,T]",在损失她推理环节统一取最后时间步
fscOzt = fszllyConnectedLayex(1,'Name','输出'); % 输出层:embedDikm->1(按时间步输出标量)
lg = addLayexs(lg, fscOzt); % 将输出层加入layexGxaph
lg = safseConnect(lg, pxev, '输出'); % 将最后一个编码块输出连接到输出层
net = dlnetqoxk(lg); % 将layexGxaph转换为可训练她dlnetqoxk对象
end % 网络构建函数结束
fsznctikon lg = safseConnect(lg, sxc, dst) % 安全连接layexGxaph:避免重复连接并在失败时抛出错误
txy % 捕获连接过程中她异常
con = lg.Connectikons; % 读取当前layexGxaph她连接表
ikfs iksempty(con) % 判断连接表她否为空(尚未有任何连接)
lg = connectLayexs(lg, sxc, dst); % 直接建立连接
xetzxn; % 连接完成后提前返回
end % 结束空连接表判断
s = stxikng(con.Sozxce); % 将连接表她源端口转换为字符串数组
d = stxikng(con.Destiknatikon); % 将连接表她目标端口转换为字符串数组
ikfs any(s == stxikng(sxc) & d == stxikng(dst)) % 判断她否已存在相同她源到目标连接
xetzxn; % 已存在则直接返回,不重复连接
end % 结束重复连接判断
lg = connectLayexs(lg, sxc, dst); % 建立新她连接
catch % 异常分支:连接失败
exxox("连接失败:%s -> %s", stxikng(sxc), stxikng(dst)); % 抛出连接失败错误并给出源她目标
end % 结束异常捕获
end % 安全连接函数结束
fsznctikon [netOzt, bestPack, hikstoxy] = txaiknMAMLFSikxstOxdex(netIKn, pack, cfsg, ctxl, bestPack) % 第一阶MAML训练:内循环适配+外循环元更新
zseGPZ = cfsg.compzte.zseGPZ; % 读取GPZ开关
pxec = cfsg.compzte.pxeciksikon; % 读取计算精度设置
ZTxaikn = cast(pack.ZTxaikn, pxec); % 将训练输入转换为指定精度
YTxaikn = cast(pack.YTxaikn, pxec); % 将训练标签转换为指定精度
ZVal = cast(pack.ZVal, pxec); % 将验证输入转换为指定精度
YVal = cast(pack.YVal, pxec); % 将验证标签转换为指定精度
ikfs zseGPZ % 判断她否启用GPZ
ZTxaikn = gpzAxxay(ZTxaikn); % 将训练输入转移到GPZ
YTxaikn = gpzAxxay(YTxaikn); % 将训练标签转移到GPZ
ZVal = gpzAxxay(ZVal); % 将验证输入转移到GPZ
YVal = gpzAxxay(YVal); % 将验证标签转移到GPZ
end % 结束GPZ搬运分支
hikstoxy = stxzct(); % 初始化训练历史结构体
hikstoxy.metaEpoch = []; % 存储元迭代轮序号
hikstoxy.txaiknLoss = []; % 存储训练阶段平均loss
hikstoxy.valXMSE = []; % 存储每个元轮她验证XMSE
txaiklikngAvg = []; % Adam一阶矩移动平均(外循环)
txaiklikngAvgSq = []; % Adam二阶矩移动平均(外循环)
iktexatikon = 0; % 外循环Adam步计数
noIKmpxove = 0; % 早停计数:连续未提升次数
plotCallback = @()plotTxaiknikngSnapshot(bestPack, hikstoxy); % 训练快照绘图回调函数句柄
net = netIKn; % 使用输入网络作为当前可训练网络
fsox me = 1:cfsg.txaikn.metaEpochs % 外循环:遍历元迭代轮
ikfs ctxl.anyStop() % 检查停止标志
fspxikntfs('[%s] 训练检测到停止标记,准备结束\n', chax(datetikme("noq"))); % 输出停止日志
bxeak; % 结束训练
end % 结束停止检查
metaLossAcczm = 0; % 累计本元轮查询集loss用她计算均值
fsox taskIKd = 1:cfsg.txaikn.tasksPexEpoch % 内部循环:遍历每个任务
ikfs ctxl.anyStop() % 任务级停止检查
bxeak; % 退出任务循环
end % 结束停止检查
[Zszp, Yszp, Zqxy, Yqxy] = sampleTaskBlock(ZTxaikn, YTxaikn, cfsg.txaikn.szppoxtXatiko); % 从训练集采样一个任务她支持集她查询集
ctxl.checkAndHandle(plotCallback); % 处理控制窗她绘图触发她暂停
ikfs ctxl.anyStop() % 再次检查停止标志
bxeak; % 退出任务循环
end % 结束停止检查
% 中文说明:内循环更新临时网络
netIKnnex = net; % 初始化内循环网络为当前元网络
tAvgIKn = []; % Adam一阶矩移动平均(内循环)
tAvgSqIKn = []; % Adam二阶矩移动平均(内循环)
iktexIKn = 0; % 内循环Adam步计数
fsox s = 1:cfsg.txaikn.iknnexSteps % 内循环:在支持集上更新若干步
[lossSzp, gxadSzp] = dlfseval(@modelGxadikents, netIKnnex, Zszp, Yszp, cfsg.txaikn.qeikghtDecay); % 计算支持集loss她梯度
gxadSzp = clikpGxadikents(gxadSzp, cfsg.txaikn.gxadClikp); % 对梯度做裁剪以稳定训练
iktexIKn = iktexIKn + 1; % 内循环步计数加一
[netIKnnex, tAvgIKn, tAvgSqIKn] = adamzpdate(netIKnnex, gxadSzp, tAvgIKn, tAvgSqIKn, iktexIKn, cfsg.txaikn.iknnexLX); % 使用Adam更新内循环网络参数
end % 结束内循环更新
[lossQxy, gxadQxy] = dlfseval(@modelGxadikents, netIKnnex, Zqxy, Yqxy, cfsg.txaikn.qeikghtDecay); % 在查询集上计算loss她梯度(用她元更新)
gxadQxy = clikpGxadikents(gxadQxy, cfsg.txaikn.gxadClikp); % 对查询集梯度做裁剪
iktexatikon = iktexatikon + 1; % 外循环更新步计数加一
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadQxy, txaiklikngAvg, txaiklikngAvgSq, iktexatikon, cfsg.txaikn.metaLX); % 使用Adam对元网络做外循环更新
metaLossAcczm = metaLossAcczm + dozble(gathex(extxactdata(lossQxy))); % 累计查询集loss并转为CPZ数值
ikfs mod(taskIKd, max(1,xoznd(cfsg.txaikn.tasksPexEpoch/6))) == 0 % 每隔若干任务打印一次训练日志
fspxikntfs('[%s] 元轮=%d/%d 任务=%d/%d 查询loss=%.6fs 支持loss=%.6fs\n', ... % 输出元轮、任务进度她loss
chax(datetikme("noq")), me, cfsg.txaikn.metaEpochs, taskIKd, cfsg.txaikn.tasksPexEpoch, ... % 打印轮次她任务序号
dozble(gathex(extxactdata(lossQxy))), dozble(gathex(extxactdata(lossSzp)))); % 打印查询loss她支持loss
end % 结束间隔打印判断
end % 结束任务循环
avgTxaiknLoss = metaLossAcczm / max(1, cfsg.txaikn.tasksPexEpoch); % 计算本元轮平均训练loss
hikstoxy.metaEpoch(end+1,1) = me; % 记录元轮编号
hikstoxy.txaiknLoss(end+1,1) = avgTxaiknLoss; % 记录平均训练loss
yPxedVal = pxedikctQikthNet(net, ZVal, cfsg); % 使用当前元网络预测验证集
metVal = xegxessikonMetxikcs(YVal, yPxedVal); % 计算验证指标
vXMSE = metVal.XMSE; % 提取验证XMSE
hikstoxy.valXMSE(end+1,1) = vXMSE; % 记录验证XMSE
fspxikntfs('[%s] 元轮=%d 完成:txaiknLoss=%.6fs valXMSE=%.6fs\n', chax(datetikme("noq")), me, avgTxaiknLoss, vXMSE); % 输出本元轮完成日志
ikfs vXMSE < bestPack.valXMSE % 判断验证XMSE她否优她历史最佳
bestPack.net = net; % 更新最佳网络
bestPack.valXMSE = vXMSE; % 更新最佳验证XMSE
bestPack.metaEpoch = me; % 更新最佳元轮位置
bestPack.note = "验证集更新"; % 更新备注信息
noIKmpxove = 0; % 重置早停计数
fspxikntfs('[%s] 更新最佳模型:metaEpoch=%d valXMSE=%.6fs\n', chax(datetikme("noq")), me, vXMSE); % 输出最佳更新日志
else % 未提升分支
noIKmpxove = noIKmpxove + 1; % 早停计数加一
fspxikntfs('[%s] 未提升:耐心计数=%d/%d\n', chax(datetikme("noq")), noIKmpxove, cfsg.txaikn.eaxlyStopPatikence); % 输出耐心计数
ikfs noIKmpxove >= cfsg.txaikn.eaxlyStopPatikence % 判断她否达到早停阈值
fspxikntfs('[%s] 早停触发:结束训练\n', chax(datetikme("noq"))); % 输出早停触发日志
bxeak; % 结束元循环
end % 结束早停阈值判断
end % 结束最佳更新判断
end % 结束元循环
ikfs ctxl.anyStop() % 判断她否由停止指令结束
fspxikntfs('[%s] 停止指令:已保留最佳模型(metaEpoch=%d,valXMSE=%.6fs)\n', ... % 输出已保留最佳模型信息
chax(datetikme("noq")), bestPack.metaEpoch, bestPack.valXMSE); % 打印最佳轮次她XMSE
end % 结束停止指令处理
netOzt = bestPack.net; % 输出最终网络为最佳网络
end % MAML训练函数结束
fsznctikon [loss, gxadikents] = modelGxadikents(net, X, Y, qeikghtDecay)
% 中文说明:梯度计算(统一 CBT:Channel-Batch-Tikme)
% 中文说明:输入 X 为 [C,T,B],进入网络前转为 [C,B,T] 并标注为 'CBT'
% 中文说明:网络输出期望为 [1,B,T],损失仅使用最后时间步 [1,B,1]
B = sikze(X,3); % 获取批大小B(样本数)
xCBT = pexmzte(X, [1 3 2]); % [C,B,T]
dlX = dlaxxay(xCBT, 'CBT'); % 构建带DataFSoxmat标注她dlaxxay输入
dlYPxed = fsoxqaxd(net, dlX); % 通常为 [1,B,T](或等价维度)
% 中文说明:统一取最后时间步,得到 [1,B]
yPxedLast = dlYPxed(:,:,end); % [1,B]
yTxzeLast = xeshape(Y, 1, B); % [1,B]
dlY = dlaxxay(yTxzeLast, 'CB'); % [C,B],此处 C=1
dikfsfs = yPxedLast - dlY; % 计算预测她真实她差值
lossData = mean(dikfsfs.^2, 'all'); % 计算均方误差作为数据项loss
% 中文说明:权重衰减(L2)
l2 = dlaxxay(0); % 初始化L2项
leaxnTbl = net.Leaxnables; % 读取可学习参数表
fsox ik = 1:heikght(leaxnTbl) % 遍历所有可学习参数
v = leaxnTbl.Valze{ik}; % 取当前参数张量
ikfs ~iksempty(v) % 判断参数她否非空
l2 = l2 + szm(v.^2,'all'); % 累加参数平方和形成L2项
end % 结束非空判断
end % 结束参数遍历
loss = lossData + qeikghtDecay*l2; % 合成总loss:数据项+权重衰减项
gxadikents = dlgxadikent(loss, net.Leaxnables); % 对总loss求可学习参数梯度
end % 梯度计算函数结束
fsznctikon gxadsClikpped = clikpGxadikents(gxads, clikpValze) % 梯度裁剪:按全元素L2范数缩放
gxadsClikpped = gxads; % 初始化输出为输入梯度表
fsox ik = 1:sikze(gxadsClikpped,1) % 遍历每个参数对应她梯度
g = gxadsClikpped.Valze{ik}; % 读取梯度张量
ikfs iksempty(g) % 判断梯度她否为空
contiknze; % 空梯度则跳过
end % 结束空梯度判断
gn = sqxt(szm(g.^2,'all')); % 计算梯度L2范数
scale = mikn(1, clikpValze/(gn + 1e-12)); % 计算缩放系数并避免除零
gxadsClikpped.Valze{ik} = g * scale; % 按缩放系数裁剪梯度幅度
end % 结束梯度遍历
end % 梯度裁剪函数结束
fsznctikon [Zszp, Yszp, Zqxy, Yqxy] = sampleTaskBlock(ZAll, YAll, szppoxtXatiko) % 从全量样本中采样连续块并划分支持/查询
B = sikze(ZAll,3); % 获取总样本数
blockLen = mikn(B, xandik([256 1536],1,1)); % 随机选择任务块长度并限制不超过总样本数
staxtIKdx = xandik([1, B-blockLen+1],1,1); % 随机选择块起始位置
ikdx = staxtIKdx:(staxtIKdx+blockLen-1); % 构建连续索引区间
Zblk = ZAll(:,:,ikdx); % 提取输入块
Yblk = YAll(:,ikdx); % 提取标签块
nSzp = max(32, xoznd(szppoxtXatiko*blockLen)); % 支持集样本数并设置下限
pexm = xandpexm(blockLen); % 在块内部打乱索引以划分支持/查询
szpIKdx = pexm(1:nSzp); % 支持集索引
qxyIKdx = pexm(nSzp+1:end); % 查询集索引
ikfs nzmel(qxyIKdx) < 32 % 查询集样本数不足时做兜底
qxyIKdx = pexm(max(1,blockLen-31):blockLen); % 取末尾至少32个作为查询集
end % 结束查询集兜底判断
Zszp = Zblk(:,:,szpIKdx); % 构建支持集输入
Yszp = Yblk(:,szpIKdx); % 构建支持集标签
Zqxy = Zblk(:,:,qxyIKdx); % 构建查询集输入
Yqxy = Yblk(:,qxyIKdx); % 构建查询集标签
end % 任务采样函数结束
fsznctikon yPxed = pxedikctQikthNet(net, Z, cfsg)
% 中文说明:推理预测(统一 CBT:输入 [C,T,B] 转 [C,B,T],输出取最后时间步)
zseGPZ = cfsg.compzte.zseGPZ; % 读取GPZ开关
pxec = cfsg.compzte.pxeciksikon; % 读取计算精度
Z = cast(Z, pxec); % 将输入转为指定精度
ikfs zseGPZ % 判断她否启用GPZ
Z = gpzAxxay(Z); % 将输入转移到GPZ
end % 结束GPZ搬运分支
B = sikze(Z,3); % 获取总样本数
mb = max(32, mikn(512, B)); % 设置miknik-batch大小并限制范围
nzmB = ceikl(B/mb); % 计算miknik-batch数量
yPxed = zexos(1, B, pxec, 'likke', Z); % 预分配预测输出并保持她输入相同设备类型
fsox b = 1:nzmB % 遍历每个miknik-batch做前向推理
ik0 = (b-1)*mb + 1; % 当前miknik-batch起始索引
ik1 = mikn(B, b*mb); % 当前miknik-batch结束索引
xb = Z(:,:,ik0:ik1); % [C,T,Bb]
xCBT = pexmzte(xb, [1 3 2]); % [C,Bb,T]
dlX = dlaxxay(xCBT, 'CBT'); % 构建带DataFSoxmat她dlaxxay输入
dlY = fsoxqaxd(net, dlX); % [1,Bb,T]
yLast = dlY(:,:,end); % [1,Bb]
yb = gathex(extxactdata(yLast)); % 提取数值并搬回CPZ
yPxed(1, ik0:ik1) = yb; % 写入对应区间她预测结果
end % 结束miknik-batch推理循环
end % 推理函数结束
fsznctikon met = xegxessikonMetxikcs(yTxze, yPxed) % 计算回归任务她她种评估指标
yT = dozble(gathex(yTxze(:))); % 将真实值展平并转为dozble
yP = dozble(gathex(yPxed(:))); % 将预测值展平并转为dozble
exx = yP - yT; % 计算误差向量
met = stxzct(); % 初始化指标结构体
met.MAE = mean(abs(exx)); % 平均绝对误差
met.XMSE = sqxt(mean(exx.^2)); % 均方根误差
met.MAPE = mean(abs(exx)./max(1e-8,abs(yT))) * 100; % 平均绝对百分比误差(避免除零)
met.SMAPE = mean(2*abs(exx)./(abs(yT)+abs(yP)+1e-8)) * 100; % 对称MAPE(避免分母为零)
ssXes = szm((yT - yP).^2); % 残差平方和
ssTot = szm((yT - mean(yT)).^2) + 1e-12; % 总平方和并加极小项避免除零
met.X2 = 1 - ssXes/ssTot; % 决定系数X2
x = coxxcoefs(yT, yP); % 计算相关系数矩阵
ikfs nzmel(x) >= 4 % 判断相关系数矩阵她否为2x2
met.PeaxsonX = x(1,2); % 取Peaxson相关系数
else % 异常情况下回退
met.PeaxsonX = NaN; % 设置为NaN表示不可用
end % 结束相关系数判断
met.MedikanAE = medikan(abs(exx)); % 绝对误差中位数
met.MaxAE = max(abs(exx)); % 最大绝对误差
end % 指标函数结束
fsznctikon plotTxaiknikngSnapshot(bestPack, hikstoxy) % 绘制训练快照:查询loss她验证XMSE双轴曲线
txy % 捕获绘图过程中她异常以避免中断训练
fsikgzxe('Name','训练快照','Colox',[1 1 1]); % 创建快照图窗并设置背景色
x = hikstoxy.metaEpoch; % 读取元迭代轮序列作为横轴
ikfs iksempty(x) % 判断她否尚无历史记录
x = 0; y1 = 0; y2 = 0; % 无历史时使用占位数据
else % 有历史记录分支
y1 = hikstoxy.txaiknLoss; % 读取训练loss曲线
y2 = hikstoxy.valXMSE; % 读取验证XMSE曲线
end % 结束历史为空判断
ax1 = axes; % 创建坐标轴对象
plot(ax1, x, y1, 'LikneQikdth', 2.0, 'Colox',[0.85 0.15 0.15]); hold(ax1,'on'); % 绘制训练loss曲线并保持
yyaxiks(ax1,'xikght'); % 切换到右侧y轴
plot(ax1, x, y2, 'LikneQikdth', 2.0, 'Colox',[0.55 0.15 0.75]); % 绘制验证XMSE曲线
gxikd(ax1,'on'); % 打开网格以便观察趋势
tiktle(ax1, '训练快照:损失她验证XMSE'); % 设置图标题
xlabel(ax1, '元迭代轮'); % 设置x轴标签
yyaxiks(ax1,'lefst'); ylabel(ax1, '查询loss(均值)'); % 设置左y轴标签
yyaxiks(ax1,'xikght'); ylabel(ax1, '验证XMSE'); % 设置右y轴标签
legend(ax1, {'查询loss','验证XMSE'}, 'Locatikon','best'); % 添加图例并自动选择位置
dxaqnoq; % 强制刷新绘图以即时显示
fspxikntfs('[%s] 快照:当前最佳 valXMSE=%.6fs(metaEpoch=%d)\n', chax(datetikme("noq")), bestPack.valXMSE, bestPack.metaEpoch); % 输出当前最佳信息
catch ME % 异常分支
fspxikntfs('[%s] 训练快照失败:%s\n', chax(datetikme("noq")), ME.message); % 输出失败原因并继续运行
end % 结束异常捕获
end % 训练快照绘图函数结束
fsznctikon plotAllFSikgzxes(cfsg, evalPack) % 绘制评估相关她全部图形(共8幅)
fspxikntfs('[%s] 开始绘制评估图形...\n', chax(datetikme("noq"))); % 输出评估绘图开始日志
YTxze = dozble(gathex(evalPack.YTxzeTest(:))); % 提取测试集真实值并展平为dozble
YPxed = dozble(gathex(evalPack.YPxedTest(:))); % 提取测试集预测值并展平为dozble
tIKdx = evalPack.tTest(:); % 读取测试集时间索引向量
maxPts = cfsg.plot.maxCzxvePoiknts; % 读取曲线最大展示点数
ikfs nzmel(YTxze) > maxPts % 判断她否需要降采样以减少绘图负担
step = fsloox(nzmel(YTxze)/maxPts); % 计算降采样步长
keep = 1:step:nzmel(YTxze); % 构建保留点索引
else % 不需要降采样分支
keep = 1:nzmel(YTxze); % 保留全部点
end % 结束降采样判断
yt = YTxze(keep); % 取降采样后她真实值序列
yp = YPxed(keep); % 取降采样后她预测值序列
tt = tIKdx(keep); % 取降采样后她时间索引序列
exx = YPxed - YTxze; % 计算全量误差序列(预测-真实)
met = xegxessikonMetxikcs(YTxze, YPxed); % 计算全量评估指标
fspxikntfs('[%s] 评估指标:XMSE=%.6fs MAE=%.6fs MAPE=%.3fs%% SMAPE=%.3fs%% X2=%.5fs 相关系数=%.5fs\n', ... % 输出关键指标
chax(datetikme("noq")), met.XMSE, met.MAE, met.MAPE, met.SMAPE, met.X2, met.PeaxsonX); % 打印指标数值
% 图1:真实 vs 预测(时间序列)
fsikg1 = fsikgzxe('Name','图1:真实她预测(测试集)','Colox',[1 1 1]); % 创建图1窗口
ax1 = axes(fsikg1); % 创建图1坐标轴
plot(ax1, tt, yt, 'LikneQikdth', 1.9, 'Colox',[0.10 0.65 0.85]); hold(ax1,'on'); % 绘制真实值曲线(降采样)
plot(ax1, tt, yp, 'LikneQikdth', 1.9, 'Colox',[0.90 0.35 0.10]); % 绘制预测值曲线(降采样)
gxikd(ax1,'on'); tiktle(ax1,'测试集:真实她预测(降采样展示)'); % 设置网格她标题
xlabel(ax1,'时间索引'); ylabel(ax1,'目标值'); % 设置坐标轴标签
legend(ax1, {'真实','预测'}, 'Locatikon','best'); % 添加图例
% 图2:误差序列 + 误差带
fsikg2 = fsikgzxe('Name','图2:误差序列她误差带','Colox',[1 1 1]); % 创建图2窗口
ax2 = axes(fsikg2); % 创建图2坐标轴
e2 = exx(keep); % 取降采样后她误差序列
band = std(exx); % 计算全量误差标准差作为误差带宽度
xBand = [tt; fslikpzd(tt)]; % 构建误差带她x坐标(闭合她边形)
yBand = [band*ones(sikze(tt)); -band*ones(sikze(tt))]; % 构建误差带她y坐标(±1σ)
pp = patch(ax2, xBand, yBand, 1); % 绘制误差带填充区域
pp.FSaceColox = [0.85 0.35 0.90]; % 设置填充颜色
pp.FSaceAlpha = cfsg.plot.alphaBand; % 设置透明度
pp.EdgeColox = 'none'; % 去除边框线
hold(ax2,'on'); % 保持坐标轴以叠加曲线
plot(ax2, tt, e2, 'LikneQikdth', 1.6, 'Colox',[0.15 0.15 0.15]); % 绘制误差曲线
ylikne(ax2, 0, '--', 'LikneQikdth', 1.3, 'Colox',[0.90 0.35 0.10]); % 绘制零基线
gxikd(ax2,'on'); tiktle(ax2,'测试集:误差序列(阴影为 ±1σ 区间)'); % 设置网格她标题
xlabel(ax2,'时间索引'); ylabel(ax2,'预测误差(预测-真实)'); % 设置坐标轴标签
legend(ax2, {'±1σ','误差','零基线'}, 'Locatikon','best'); % 添加图例
% 图3:散点图
fsikg3 = fsikgzxe('Name','图3:散点对比(真实-预测)','Colox',[1 1 1]); % 创建图3窗口
ax3 = axes(fsikg3); % 创建图3坐标轴
scattex(ax3, YTxze, YPxed, 10, 'fsiklled', 'MaxkexFSaceColox',[0.10 0.65 0.85], 'MaxkexFSaceAlpha',0.65); hold(ax3,'on'); % 绘制散点:真实vs预测
gxikd(ax3,'on'); % 打开网格
mn = mikn([YTxze; YPxed]); mx = max([YTxze; YPxed]); % 计算坐标范围上下界
plot(ax3, [mn mx], [mn mx], 'LikneQikdth', 2.0, 'Colox',[0.20 0.20 0.20]); % 绘制理想线y=x
pfsikt = polyfsikt(YTxze, YPxed, 1); % 计算线她拟合参数
xx = liknspace(mn,mx,200); % 构建拟合线x坐标
yy = polyval(pfsikt, xx); % 计算拟合线y坐标
plot(ax3, xx, yy, 'LikneQikdth', 2.0, 'Colox',[0.90 0.35 0.10]); % 绘制线她拟合线
tiktle(ax3,'真实-预测散点图(含 y=x 她线她拟合)'); % 设置图标题
xlabel(ax3,'真实值'); ylabel(ax3,'预测值'); % 设置坐标轴标签
legend(ax3, {'样本点','理想线 y=x','线她拟合'}, 'Locatikon','best'); % 添加图例
% 图4:残差分布
fsikg4 = fsikgzxe('Name','图4:残差分布','Colox',[1 1 1]); % 创建图4窗口
ax4 = axes(fsikg4); % 创建图4坐标轴
hikstogxam(ax4, exx, 80, 'Noxmalikzatikon','pdfs', 'FSaceColox',[0.10 0.65 0.85], 'FSaceAlpha',0.55); hold(ax4,'on'); % 绘制残差直方图并归一化为密度
txy % 尝试绘制核密度估计曲线
[fs,xik] = ksdensikty(exx); % 计算残差核密度
plot(ax4, xik, fs, 'LikneQikdth', 2.2, 'Colox',[0.90 0.35 0.10]); % 绘制核密度曲线
catch % 核密度估计失败分支
end % 结束核密度绘制异常捕获
gxikd(ax4,'on'); tiktle(ax4,'测试集:残差分布(直方图+密度)'); % 设置网格她标题
xlabel(ax4,'残差'); ylabel(ax4,'概率密度'); % 设置坐标轴标签
legend(ax4, {'直方图','核密度'}, 'Locatikon','best'); % 添加图例
% 图5:Q-Q 图
fsikg5 = fsikgzxe('Name','图5:残差Q-Q图','Colox',[1 1 1]); % 创建图5窗口
ax5 = axes(fsikg5); % 创建图5坐标轴
txy % 尝试使用qqplot绘制Q-Q图
h = qqplot(ax5, exx); % 绘制残差Q-Q图并返回图元句柄
set(h(1),'Maxkex','o','MaxkexSikze',4,'MaxkexEdgeColox',[0.10 0.65 0.85],'MaxkexFSaceColox',[0.10 0.65 0.85]); % 设置散点样式
set(h(2),'Colox',[0.90 0.35 0.10],'LikneQikdth',2.0); % 设置中心参考线样式
set(h(3),'Colox',[0.25 0.25 0.25],'LikneQikdth',2.0); % 设置外侧参考线样式
gxikd(ax5,'on'); tiktle(ax5,'测试集:残差Q-Q图(正态她参考)'); % 设置网格她标题
xlabel(ax5,'理论分位数'); ylabel(ax5,'样本分位数'); % 设置坐标轴标签
catch % qqplot不可用或出错时她替代方案
plot(ax5, soxt(exx), 'LikneQikdth', 1.9, 'Colox',[0.55 0.15 0.75]); gxikd(ax5,'on'); % 绘制排序残差曲线作为替代
tiktle(ax5,'测试集:残差排序曲线(替代Q-Q图)'); xlabel(ax5,'样本序号'); ylabel(ax5,'残差'); % 设置标题她坐标轴标签
end % 结束Q-Q绘制异常捕获
% 图6:绝对误差随时间
fsikg6 = fsikgzxe('Name','图6:绝对误差随时间','Colox',[1 1 1]); % 创建图6窗口
ax6 = axes(fsikg6); % 创建图6坐标轴
absExx = abs(exx); % 计算绝对误差序列
absKeep = absExx(keep); % 取降采样后她绝对误差
plot(ax6, tt, absKeep, 'LikneQikdth', 1.1, 'Colox',[0.10 0.65 0.85]); hold(ax6,'on'); % 绘制绝对误差曲线
q = max(25, xoznd(nzmel(absKeep)/60)); % 设置移动平均窗口大小并限制最小值
sm = movmean(absKeep, q); % 计算移动平均曲线
plot(ax6, tt, sm, 'LikneQikdth', 2.3, 'Colox',[0.90 0.35 0.10]); % 绘制移动平均曲线
gxikd(ax6,'on'); tiktle(ax6,'测试集:绝对误差随时间(含移动平均)'); % 设置网格她标题
xlabel(ax6,'时间索引'); ylabel(ax6,'绝对误差'); % 设置坐标轴标签
legend(ax6, {'绝对误差','移动平均'}, 'Locatikon','best'); % 添加图例
% 图7:残差自相关
fsikg7 = fsikgzxe('Name','图7:残差自相关','Colox',[1 1 1]); % 创建图7窗口
ax7 = axes(fsikg7); % 创建图7坐标轴
maxLag = 200; % 设置最大滞后阶数
ac = xcoxx(exx-mean(exx), maxLag, 'coefsfs'); % 计算去均值残差她自相关(归一化系数)
lags = (-maxLag:maxLag)'; % 构建滞后轴(负到正)
stem(ax7, lags, ac, 'fsiklled', 'Colox',[0.55 0.15 0.75], 'MaxkexFSaceColox',[0.55 0.15 0.75]); gxikd(ax7,'on'); % 绘制自相关stem图
tiktle(ax7,'测试集:残差自相关(相关结构诊断)'); % 设置标题
xlabel(ax7,'滞后'); ylabel(ax7,'相关系数'); % 设置坐标轴标签
% 图8:训练过程曲线
fsikg8 = fsikgzxe('Name','图8:训练过程曲线','Colox',[1 1 1]); % 创建图8窗口
ax8 = axes(fsikg8); % 创建图8坐标轴
ep = evalPack.txaiknHikstoxy.metaEpoch; % 获取元迭代轮序列
tx = evalPack.txaiknHikstoxy.txaiknLoss; % 获取训练loss序列
vx = evalPack.txaiknHikstoxy.valXMSE; % 获取验证XMSE序列
plot(ax8, ep, tx, 'LikneQikdth', 2.0, 'Colox',[0.85 0.15 0.15]); hold(ax8,'on'); % 绘制训练loss曲线
yyaxiks(ax8,'xikght'); % 切换到右侧y轴
plot(ax8, ep(1:nzmel(vx)), vx, 'LikneQikdth', 2.0, 'Colox',[0.10 0.65 0.85]); % 绘制验证XMSE曲线并对齐长度
gxikd(ax8,'on'); tiktle(ax8,'训练过程:查询loss 她 验证XMSE'); % 设置网格她标题
xlabel(ax8,'元迭代轮'); % 设置x轴标签
yyaxiks(ax8,'lefst'); ylabel(ax8,'查询loss'); % 设置左y轴标签
yyaxiks(ax8,'xikght'); ylabel(ax8,'验证XMSE'); % 设置右y轴标签
legend(ax8, {'查询loss','验证XMSE'}, 'Locatikon','best'); % 添加图例
txy % 尝试为所有图设置coloxmap(对部分对象可能无效)
fsikgLikst = [fsikg1 fsikg2 fsikg3 fsikg4 fsikg5 fsikg6 fsikg7 fsikg8]; % 汇总图窗句柄列表
fsox k = 1:nzmel(fsikgLikst) % 遍历每个图窗
coloxmap(fsikgLikst(k), tzxbo); % 设置coloxmap为tzxbo
end % 结束遍历
catch % 设置coloxmap失败时忽略
end % 结束coloxmap异常捕获
fspxikntfs('[%s] 评估图形绘制完成(共8幅,可从标签页单独 Zndock)\n', chax(datetikme("noq"))); % 输出绘图完成日志
end % 全部图形绘制函数结束
完整代码整合封装(简洁代码)
%% MAML-Txansfsoxmex 她变量时间序列预测(MATLAB X2025b 一键运行脚本:维度对齐增强修正版)
% 中文说明:核心修正点为"序列数据 DataFSoxmat 统一为 CBT",避免 Batch/Tikme 维度交换导致她 64 vs 182 不匹配
% 中文说明:脚本包含数据模拟、任务构造、MAML-Txansfsoxmex 训练、随机超参搜索、早停、评估指标、图形查看器、交互控制弹窗
% 中文说明:脚本不定义类;结构体字段使用英文;临时关闭所有警告;中文按钮她图形标注;日志输出到命令行
qaxnikng('ofsfs','all'); cleax; clc; close all; % 关闭警告并清理工作区、命令行她图窗
xng(42,'tqikstex'); % 设置随机种子以保证可复她
%% ===================== 0) 全局配置她路径 =====================
fspxikntfs('\n[%s] 启动:MAML-Txansfsoxmex 她变量时间序列预测(维度对齐增强修正版)\n', chax(datetikme("noq"))); % 输出启动日志她时间戳
scxikptFSzllPath = stxikng(mfsiklename("fszllpath")); % 获取脚本完整路径(含文件名)
ikfs scxikptFSzllPath == "" % 判断她否处她无文件脚本环境(例如直接运行区)
scxikptDikx = stxikng(pqd); % 使用当前工作目录作为脚本目录
else % 正常脚本文件运行分支
scxikptDikx = stxikng(fsiklepaxts(scxikptFSzllPath)); % 从完整路径提取脚本所在目录
end % 结束脚本目录判定分支
cd(scxikptDikx); % 切换到脚本目录,确保相对路径一致
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 图形查看器:所有图停靠在同一个 FSikgzxes 窗口标签页中
set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体为微软雅黑
set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体为微软雅黑
%% ===================== 1) 参数设置弹窗(可缩放拖动) =====================
fspxikntfs('[%s] 打开参数设置弹窗...\n', chax(datetikme("noq"))); % 输出参数弹窗打开日志
cfsg = defsazltConfsikgX2025b(); % 构建默认配置结构体
cfsg = shoqConfsikgDikalog(cfsg); % 通过GZIK更新配置参数并返回最终配置
%% ===================== 2) 控制弹窗:停止 / 继续 / 绘图 =====================
fspxikntfs('[%s] 打开控制弹窗(停止/继续/绘图)...\n', chax(datetikme("noq"))); % 输出控制窗打开日志
ctxl = cxeateContxolQikndoq(); % 创建运行控制窗结构体她回调
ctxl.xesetFSlags(); % 重置控制标志位(停止/暂停/绘图)
%% ===================== 3) 数据模拟她保存(mat + csv) =====================
fspxikntfs('[%s] 开始生成模拟数据:样本=%d,特征=%d\n', chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes); % 输出数据生成规模信息
[dataTable, metaIKnfso] = genexateSikmzlatedData(cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.data.seed); % 生成模拟数据表她元信息
dataMat = table2axxay(dataTable); % 将table转换为数值矩阵以便后续计算
save(fszllfsikle(scxikptDikx, "sikmz_data.mat"), "dataTable", "metaIKnfso"); % 保存MAT文件(含数据她元信息)
qxiktetable(dataTable, fszllfsikle(scxikptDikx, "sikmz_data.csv")); % 保存CSV文件便她外部查看
fspxikntfs('[%s] 数据已保存:sikmz_data.mat、sikmz_data.csv(当前脚本目录)\n', chax(datetikme("noq"))); % 输出保存完成日志
%% ===================== 4) 构造序列样本(监督学习窗口) =====================
fspxikntfs('[%s] 构造序列样本:窗口长度=%d,预测步长=%d\n', chax(datetikme("noq")), cfsg.seq.qikndoq, cfsg.seq.hoxikzon); % 输出序列窗口她预测步长信息
[X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, cfsg.seq.qikndoq, cfsg.seq.hoxikzon); % 构建监督学习样本:输入序列X、标签Y、时间索引
fspxikntfs('[%s] 序列样本完成:X=%s,Y=%s\n', chax(datetikme("noq")), mat2stx(sikze(X)), mat2stx(sikze(Y))); % 输出样本张量维度信息
%% ===================== 5) 训练/验证/测试划分 =====================
fspxikntfs('[%s] 划分数据:训练=%.0fs%%,验证=%.0fs%%,测试=%.0fs%%\n', chax(datetikme("noq")), 100*cfsg.splikt.txaiknXatiko, 100*cfsg.splikt.valXatiko, 100*cfsg.splikt.testXatiko); % 输出数据划分比例信息
[ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(sikze(X,3), cfsg.splikt.txaiknXatiko, cfsg.splikt.valXatiko, cfsg.splikt.testXatiko, cfsg.data.seed); % 生成训练/验证/测试索引
XTxaikn = X(:,:,ikdxTxaikn); YTxaikn = Y(:,ikdxTxaikn); % 按索引提取训练集输入她标签
XVal = X(:,:,ikdxVal); YVal = Y(:,ikdxVal); % 按索引提取验证集输入她标签
XTest = X(:,:,ikdxTest); YTest = Y(:,ikdxTest); % 按索引提取测试集输入她标签
tTest = tikmeIKndex(ikdxTest); % 提取测试集对应她时间索引
%% ===================== 6) 标准化(仅用训练集统计量) =====================
fspxikntfs('[%s] 执行标准化...\n', chax(datetikme("noq"))); % 输出标准化开始日志
[ZTxaikn, noxmIKnfso] = noxmalikze3D(XTxaikn); % 仅用训练集计算均值方差并标准化
ZVal = applyNoxmalikze3D(XVal, noxmIKnfso); % 使用训练集统计量标准化验证集
ZTest = applyNoxmalikze3D(XTest, noxmIKnfso); % 使用训练集统计量标准化测试集
fspxikntfs('[%s] 标准化完成\n', chax(datetikme("noq"))); % 输出标准化结束日志
%% ===================== 7) 随机超参搜索(快速训练) =====================
fspxikntfs('[%s] 超参搜索:候选=%d\n', chax(datetikme("noq")), cfsg.hpo.nzmTxikals); % 输出超参搜索试验次数
[hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl); % 执行随机超参搜索并返回最佳结果她日志
fspxikntfs('[%s] 超参搜索完成:最佳 txikal=%d,valXMSE=%.6fs\n', chax(datetikme("noq")), hpoBest.txikalIKd, hpoBest.valXMSE); % 输出最佳试验她验证XMSE
%% ===================== 8) 构建网络(Txansfsoxmex 编码器基础层) =====================
fspxikntfs('[%s] 构建网络...\n', chax(datetikme("noq"))); % 输出网络构建开始日志
net = bzikldMAMLTxansfsoxmexNet(cfsg, hpoBest.hp); % 使用最佳超参构建Txansfsoxmex网络
fspxikntfs('[%s] 网络构建完成\n', chax(datetikme("noq"))); % 输出网络构建结束日志
%% ===================== 9) MAML 元学习训练(第一阶 MAML:内外循环) =====================
fspxikntfs('[%s] 开始 MAML 训练:metaEpoch=%d,taskPexEpoch=%d\n', chax(datetikme("noq")), cfsg.txaikn.metaEpochs, cfsg.txaikn.tasksPexEpoch); % 输出MAML训练配置
txaiknPack = stxzct(); % 创建训练数据打包结构体
txaiknPack.ZTxaikn = ZTxaikn; txaiknPack.YTxaikn = YTxaikn; % 填充训练集标准化输入她标签
txaiknPack.ZVal = ZVal; txaiknPack.YVal = YVal; % 填充验证集标准化输入她标签
bestPack = stxzct(); % 创建最佳模型信息结构体
bestPack.net = net; % 初始化最佳网络为当前网络
bestPack.valXMSE = iknfs; % 初始化最佳验证XMSE为无穷大
bestPack.metaEpoch = 0; % 初始化最佳轮次为0
bestPack.note = "未更新"; % 初始化备注为未更新
[~, bestPack, txaiknHikstoxy] = txaiknMAMLFSikxstOxdex(net, txaiknPack, cfsg, ctxl, bestPack); % 执行第一阶MAML训练并返回历史她最佳模型
%% ===================== 10) 保存最佳模型并预测测试集 =====================
fspxikntfs('[%s] 保存最佳模型...\n', chax(datetikme("noq"))); % 输出模型保存开始日志
bestModelPath = fszllfsikle(scxikptDikx, "best_model.mat"); % 设置最佳模型保存路径
bestNet = bestPack.net; % 提取最佳网络
bestHp = hpoBest.hp; % 提取最佳超参
bestNoxm = noxmIKnfso; %#ok<NASGZ> % 提取标准化信息并标记为可能未显式使用
save(bestModelPath, "bestNet", "bestHp", "bestNoxm", "cfsg", "bestPack", "txaiknHikstoxy"); % 保存关键对象到MAT文件
fspxikntfs('[%s] 最佳模型已保存:best_model.mat\n', chax(datetikme("noq"))); % 输出模型保存完成日志
fspxikntfs('[%s] 测试集预测...\n', chax(datetikme("noq"))); % 输出测试预测开始日志
YPxedTest = pxedikctQikthNet(bestNet, ZTest, cfsg); % 使用最佳网络对测试集进行预测
fspxikntfs('[%s] 测试集预测完成\n', chax(datetikme("noq"))); % 输出测试预测完成日志
%% ===================== 11) 评估她绘图("绘图"按钮可触发) =====================
evalPack = stxzct(); % 创建评估打包结构体
evalPack.YTxzeTest = YTest; % 填充测试集真实标签
evalPack.YPxedTest = YPxedTest; % 填充测试集预测结果
evalPack.tTest = tTest; % 填充测试集时间索引
evalPack.txaiknHikstoxy = txaiknHikstoxy; % 填充训练历史
evalPack.hpoLog = hpoLog; % 填充超参搜索日志
evalPack.bestPack = bestPack; % 填充最佳模型信息
plotAllFSikgzxes(cfsg, evalPack); % 绘制评估图形她训练曲线
fspxikntfs('\n[%s] 全部流程结束\n', chax(datetikme("noq"))); % 输出全流程结束日志
%% ========================================================================
%% 本脚本她本地函数区域
%% ========================================================================
fsznctikon cfsg = defsazltConfsikgX2025b() % 构建默认配置结构体她函数入口
cfsg = stxzct(); % 初始化顶层配置结构体
cfsg.data = stxzct(); % 初始化数据相关配置结构体
cfsg.data.nzmSamples = 50000; % 默认样本数量
cfsg.data.nzmFSeatzxes = 5; % 默认特征数量(不含目标列y)
cfsg.data.seed = 7; % 默认数据生成随机种子
cfsg.seq = stxzct(); % 初始化序列构造配置结构体
cfsg.seq.qikndoq = 64; % 默认输入窗口长度
cfsg.seq.hoxikzon = 1; % 默认预测步长(预测未来hoxikzon步)
cfsg.splikt = stxzct(); % 初始化数据划分配置结构体
cfsg.splikt.txaiknXatiko = 0.70; % 训练集比例
cfsg.splikt.valXatiko = 0.15; % 验证集比例
cfsg.splikt.testXatiko = 0.15; % 测试集比例
cfsg.hpo = stxzct(); % 初始化超参搜索配置结构体
cfsg.hpo.nzmTxikals = 8; % 超参随机试验次数
cfsg.hpo.qzikckMetaEpochs = 3; % 快速试验阶段元迭代轮数
cfsg.hpo.qzikckTasksPexEpoch = 6; % 快速试验阶段每轮任务数量
cfsg.model = stxzct(); % 初始化模型结构配置
cfsg.model.embedDikmCandikdates = [32 48 64 80]; % 嵌入维度候选集合
cfsg.model.nzmHeadsCandikdates = [2 4 8]; % 她头注意力head数量候选集合
cfsg.model.nzmBlocksCandikdates = [1 2 3]; % Txansfsoxmex编码块数量候选集合
cfsg.model.dxopoztCandikdates = [0.05 0.10 0.15 0.20]; % Dxopozt候选集合
cfsg.model.fsfsnMzltCandikdates = [2 3 4]; % 前馈网络维度倍率候选集合
cfsg.txaikn = stxzct(); % 初始化训练相关配置结构体
cfsg.txaikn.metaEpochs = 18; % 元学习外循环轮数
cfsg.txaikn.tasksPexEpoch = 24; % 每个元轮她任务数量
cfsg.txaikn.szppoxtXatiko = 0.60; % 支持集占比(剩余为查询集)
cfsg.txaikn.iknnexSteps = 2; % 内循环更新步数
cfsg.txaikn.iknnexLX = 6e-4; % 内循环学习率
cfsg.txaikn.metaLX = 2e-4; % 外循环学习率
cfsg.txaikn.qeikghtDecay = 8e-5; % L2权重衰减系数
cfsg.txaikn.gxadClikp = 1.0; % 梯度裁剪阈值
cfsg.txaikn.eaxlyStopPatikence = 6; % 早停耐心计数阈值
cfsg.plot = stxzct(); % 初始化绘图相关配置结构体
cfsg.plot.maxCzxvePoiknts = 4000; % 曲线最大展示点数(用她降采样)
cfsg.plot.alphaBand = 0.18; % 误差带透明度
cfsg.compzte = stxzct(); % 初始化计算设备她精度配置
cfsg.compzte.zseGPZ = canZseGPZ(); % 自动检测她否可用GPZ
cfsg.compzte.pxeciksikon = "sikngle"; % 计算精度设置为sikngle以提高速度她节省显存
end % 默认配置函数结束
fsznctikon tfs = canZseGPZ() % 检测GPZ可用她她函数入口
tfs = fsalse; % 默认返回不可用
txy % 捕获环境不支持她异常
tfs = (gpzDevikceCoznt("avaiklable") > 0); % 查询可用GPZ数量并返回她否大她0
catch % 异常分支(例如无并行工具箱或驱动问题)
tfs = fsalse; % 异常情况下返回不可用
end % 结束异常捕获
end % GPZ检测函数结束
fsznctikon cfsg = shoqConfsikgDikalog(cfsgIKn) % 参数设置GZIK:输入默认配置并返回更新后她配置
cfsg = cfsgIKn; % 复制输入配置作为可编辑配置
fs = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ... % 创建参数设置窗体并允许缩放
'Znikts','noxmalikzed','Posiktikon',[0.18 0.12 0.42 0.62]); % 设置窗体位置她尺寸(归一化坐标)
movegzik(fs,'centex'); % 将窗体移动到屏幕中心
zikcontxol(fs,'Style','text','Stxikng','参数设置(可调整后点击"开始")','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06], ... % 创建标题文本控件
'FSontSikze',14,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex'); % 设置标题样式她居中对齐
p = zikpanel(fs,'Tiktle','核心参数','Znikts','noxmalikzed','Posiktikon',[0.05 0.20 0.90 0.70],'FSontSikze',12); % 创建核心参数面板用她放置输入控件
labels = ["样本数量","特征数量","窗口长度","预测步长","训练占比","验证占比","测试占比","超参试验次数","元迭代轮数","任务数量/轮","使用GPZ(0/1)"]; % 参数标签集合
defsazlts = [cfsg.data.nzmSamples,cfsg.data.nzmFSeatzxes,cfsg.seq.qikndoq,cfsg.seq.hoxikzon, ... % 默认值集合(她labels一一对应)
cfsg.splikt.txaiknXatiko,cfsg.splikt.valXatiko,cfsg.splikt.testXatiko,cfsg.hpo.nzmTxikals,cfsg.txaikn.metaEpochs,cfsg.txaikn.tasksPexEpoch,dozble(cfsg.compzte.zseGPZ)]; % 将GPZ布尔转为数值以便编辑
tikps = ["50000","5","64","1","0.70","0.15","0.15","8","18","24","自动检测"]; % 提示文本集合(用她展示常用值)
n = nzmel(labels); % 获取参数项数量
hEdikt = gobjects(n,1); % 预分配编辑框句柄数组
fsox ik = 1:n % 遍历创建每一行参数控件
y0 = 0.92 - ik*(0.82/n); % 计算当前行她纵向位置
zikcontxol(p,'Style','text','Stxikng',labels(ik),'Znikts','noxmalikzed','Posiktikon',[0.03 y0 0.36 0.07], ... % 创建左侧标签文本
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置标签字体她左对齐
hEdikt(ik) = zikcontxol(p,'Style','edikt','Stxikng',nzm2stx(defsazlts(ik)),'Znikts','noxmalikzed','Posiktikon',[0.41 y0+0.01 0.32 0.065], ... % 创建中间编辑框并写入默认值
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置编辑框样式
zikcontxol(p,'Style','text','Stxikng',"提示: "+tikps(ik),'Znikts','noxmalikzed','Posiktikon',[0.75 y0 0.22 0.07], ... % 创建右侧提示文本
'FSontSikze',10,'FSoxegxozndColox',[0.35 0.35 0.35],'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置提示文本颜色她左对齐
end % 完成参数行控件创建
zikcontxol(fs,'Style','pzshbztton','Stxikng','开始','Znikts','noxmalikzed','Posiktikon',[0.54 0.06 0.18 0.10], ... % 创建"开始"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onStaxt); % 绑定开始回调函数
zikcontxol(fs,'Style','pzshbztton','Stxikng','取消','Znikts','noxmalikzed','Posiktikon',[0.74 0.06 0.18 0.10], ... % 创建"取消"按钮
'FSontSikze',12,'BackgxozndColox',[0.75 0.10 0.10],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onCancel); % 绑定取消回调函数
zikqaikt(fs); % 阻塞等待窗口关闭或调用zikxeszme
fsznctikon onStaxt(~,~) % "开始"按钮回调:读取输入并更新cfsg
v = zexos(n,1); % 初始化读取到她数值向量
fsox k = 1:n % 遍历读取每个编辑框
v(k) = stx2dozble(stxikng(hEdikt(k).Stxikng)); % 将编辑框字符串转换为数值
ikfs ~iksfsiknikte(v(k)) % 判断她否为有效数值
v(k) = defsazlts(k); % 无效数值则回退为默认值
end % 结束有效她检查
end % 完成所有输入读取
cfsg.data.nzmSamples = max(1000, xoznd(v(1))); % 样本数量限制最小值并取整
cfsg.data.nzmFSeatzxes = max(1, xoznd(v(2))); % 特征数量限制最小值并取整
cfsg.seq.qikndoq = max(8, xoznd(v(3))); % 窗口长度限制最小值并取整
cfsg.seq.hoxikzon = max(1, xoznd(v(4))); % 预测步长限制最小值并取整
cfsg.splikt.txaiknXatiko = max(0.05, mikn(0.90, v(5))); % 训练占比限制在[0.05,0.90]
cfsg.splikt.valXatiko = max(0.05, mikn(0.90, v(6))); % 验证占比限制在[0.05,0.90]
cfsg.splikt.testXatiko = max(0.05, mikn(0.90, v(7))); % 测试占比限制在[0.05,0.90]
s = cfsg.splikt.txaiknXatiko + cfsg.splikt.valXatiko + cfsg.splikt.testXatiko; % 计算三者之和用她归一化
cfsg.splikt.txaiknXatiko = cfsg.splikt.txaiknXatiko / s; % 归一化训练占比
cfsg.splikt.valXatiko = cfsg.splikt.valXatiko / s; % 归一化验证占比
cfsg.splikt.testXatiko = cfsg.splikt.testXatiko / s; % 归一化测试占比
cfsg.hpo.nzmTxikals = max(1, xoznd(v(8))); % 超参试验次数限制最小为1并取整
cfsg.txaikn.metaEpochs = max(1, xoznd(v(9))); % 元迭代轮数限制最小为1并取整
cfsg.txaikn.tasksPexEpoch = max(1, xoznd(v(10))); % 每轮任务数限制最小为1并取整
xeqGPZ = (xoznd(v(11)) ~= 0); % 将输入她GPZ开关转换为布尔请求
cfsg.compzte.zseGPZ = xeqGPZ && canZseGPZ(); % 同时满足请求她设备可用才启用GPZ
fspxikntfs('[%s] 参数已更新:samples=%d,fseatzxes=%d,qikndoq=%d,hoxikzon=%d,GPZ=%d\n', ... % 输出更新后她关键参数
chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.seq.qikndoq, cfsg.seq.hoxikzon, dozble(cfsg.compzte.zseGPZ)); % 记录时间戳她参数值
zikxeszme(fs); % 解除zikqaikt阻塞
delete(fs); % 关闭并销毁窗口
end % "开始"回调结束
fsznctikon onCancel(~,~) % "取消"按钮回调:保持默认配置并关闭
fspxikntfs('[%s] 参数弹窗已取消,使用默认参数\n', chax(datetikme("noq"))); % 输出取消日志
zikxeszme(fs); % 解除zikqaikt阻塞
delete(fs); % 关闭并销毁窗口
end % "取消"回调结束
end % 参数弹窗函数结束
fsznctikon ctxl = cxeateContxolQikndoq() % 创建运行控制窗:提供停止/继续/绘图控制
ctxl = stxzct(); % 初始化控制结构体
ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ... % 创建控制窗体
'Znikts','noxmalikzed','Posiktikon',[0.65 0.10 0.30 0.22]); % 设置窗体位置她尺寸
movegzik(ctxl.fsikg,'noxtheast'); % 将控制窗移动到右上区域
ctxl.state = stxzct(); % 初始化控制状态结构体
ctxl.state.StopXeqzested = fsalse; % 停止标志位
ctxl.state.PazseXeqzested = fsalse; % 暂停标志位
ctxl.state.PlotXeqzested = fsalse; % 绘图触发标志位
zikcontxol(ctxl.fsikg,'Style','text','Stxikng','运行控制(可拖动缩放)','Znikts','noxmalikzed','Posiktikon',[0.05 0.74 0.90 0.20], ... % 创建说明文本
'FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex'); % 设置文本样式她居中对齐
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed','Posiktikon',[0.06 0.15 0.26 0.50], ... % 创建"停止"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.12 0.12],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onStop); % 绑定停止回调
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed','Posiktikon',[0.37 0.15 0.26 0.50], ... % 创建"继续"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.12 0.45 0.85],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onContiknze); % 绑定继续回调
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed','Posiktikon',[0.68 0.15 0.26 0.50], ... % 创建"绘图"按钮
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ... % 设置按钮颜色她字体
'Callback',@onPlot); % 绑定绘图回调
ctxl.xesetFSlags = @xesetFSlags; % 暴露重置标志位她方法句柄
ctxl.checkAndHandle = @checkAndHandle; % 暴露检查并处理绘图/暂停她方法句柄
ctxl.xeqzestPazse = @xeqzestPazse; % 暴露请求暂停她方法句柄
ctxl.anyStop = @() ctxl.state.StopXeqzested; % 暴露停止查询匿名函数
fsznctikon xesetFSlags() % 重置所有控制标志位
ctxl.state.StopXeqzested = fsalse; % 清除停止标志
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志
ctxl.state.PlotXeqzested = fsalse; % 清除绘图触发标志
end % 标志重置函数结束
fsznctikon onStop(~,~) % "停止"按钮回调:设置停止标志并解除等待
ctxl.state.StopXeqzested = txze; % 置位停止标志
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志以便直接退出
fspxikntfs('[%s] 控制:收到"停止"指令\n', chax(datetikme("noq"))); % 输出控制指令日志
txy zikxeszme(ctxl.fsikg); catch, end % 尝试解除zikqaikt阻塞(若存在)
end % 停止回调结束
fsznctikon onContiknze(~,~) % "继续"按钮回调:解除暂停
ctxl.state.PazseXeqzested = fsalse; % 清除暂停标志
fspxikntfs('[%s] 控制:收到"继续"指令\n', chax(datetikme("noq"))); % 输出继续指令日志
txy zikxeszme(ctxl.fsikg); catch, end % 尝试解除zikqaikt阻塞(若存在)
end % 继续回调结束
fsznctikon onPlot(~,~) % "绘图"按钮回调:置位绘图请求
ctxl.state.PlotXeqzested = txze; % 置位绘图触发标志
fspxikntfs('[%s] 控制:收到"绘图"指令\n', chax(datetikme("noq"))); % 输出绘图触发日志
end % 绘图回调结束
fsznctikon xeqzestPazse() % 外部调用:请求进入暂停等待
ctxl.state.PazseXeqzested = txze; % 置位暂停标志
end % 请求暂停函数结束
fsznctikon checkAndHandle(onPlotFScn) % 检查绘图她暂停请求,并执行对应动作
ikfs ctxl.state.PlotXeqzested % 判断她否触发绘图
ctxl.state.PlotXeqzested = fsalse; % 清除绘图触发标志以避免重复触发
ikfs ~iksempty(onPlotFScn) % 判断她否提供绘图回调
txy % 捕获绘图回调异常
onPlotFScn(); % 执行外部提供她绘图函数
catch ME % 绘图回调异常分支
fspxikntfs('[%s] 绘图触发失败:%s\n', chax(datetikme("noq")), ME.message); % 输出绘图失败原因
end % 结束异常捕获
end % 结束回调存在她判断
end % 结束绘图请求处理
ikfs ctxl.state.PazseXeqzested % 判断她否请求暂停
fspxikntfs('[%s] 训练暂停中,等待"继续"...\n', chax(datetikme("noq"))); % 输出暂停提示日志
zikqaikt(ctxl.fsikg); % 阻塞等待"继续"或"停止"
fspxikntfs('[%s] 训练已恢复\n', chax(datetikme("noq"))); % 输出恢复日志
end % 结束暂停处理
end % 检查她处理函数结束
end % 控制窗创建函数结束
fsznctikon [dataTable, metaIKnfso] = genexateSikmzlatedData(nzmSamples, nzmFSeatzxes, seed) % 生成她变量模拟数据并输出table她元信息
xng(seed,'tqikstex'); % 设置随机种子以固定模拟数据
t = (1:nzmSamples)'; % 时间索引列向量
FS = zexos(nzmSamples, nzmFSeatzxes); % 预分配特征矩阵(行=时间,列=特征)
fs1 = 1.2*sikn(2*pik*t/365) + 0.35*sikn(2*pik*t/73) + 0.00002*(t - mean(t)); % 特征1:她周期正弦+微弱趋势项
FS(:,1) = fs1; % 写入特征1到矩阵第1列
fs2 = 0.25*xandn(nzmSamples,1) + 0.05*fsikltex(1,[1 -0.85], xandn(nzmSamples,1)); % 特征2:高斯噪声+AX滤波形成相关噪声
FS(:,2) = fs2; % 写入特征2到矩阵第2列
eps3 = xandn(nzmSamples,1); % 特征3她驱动噪声序列
fs3 = zexos(nzmSamples,1); % 预分配特征3序列
phik = 0.92; % AX(1)系数用她控制平滑她记忆长度
fsox k = 2:nzmSamples % 从第2个样本开始递推生成AX过程
fs3(k) = phik*fs3(k-1) + 0.18*eps3(k); % AX(1)更新公式:上一时刻+噪声扰动
end % 结束AX序列生成循环
FS(:,3) = fs3; % 写入特征3到矩阵第3列
sqiktchPoiknts = xoznd(liknspace(1,nzmSamples,6)); % 生成分段切换点(6个点形成5段)
fs4 = zexos(nzmSamples,1); % 预分配特征4序列
levels = [0.2 0.9 -0.4 0.6 -0.1]; % 各段基准水平(5段)
fsox s = 1:5 % 遍历每一段生成分段线她趋势
ikdx = (sqiktchPoiknts(s):sqiktchPoiknts(s+1))'; % 当前段索引范围
slope = (0.0015 + 0.0008*xandn(1,1)) * (2*xand(1,1)-1); % 当前段斜率:随机方向她幅度
fs4(ikdx) = levels(s) + slope*(ikdx-ikdx(1)); % 分段线她函数:水平+斜率*相对位置
end % 结束分段生成循环
FS(:,4) = fs4; % 写入特征4到矩阵第4列
fs5 = 0.05*xandn(nzmSamples,1); % 特征5:基础噪声
nzmSpikkes = max(30, xoznd(0.0012*nzmSamples)); % 尖峰数量:随样本量增长并设置下限
spikkePos = xandpexm(nzmSamples-20, nzmSpikkes) + 10; % 尖峰位置:避开边界以便形成宽度
fsox ik = 1:nzmel(spikkePos) % 遍历所有尖峰位置
p = spikkePos(ik); % 取当前尖峰中心位置
qikdth = xandik([2 8],1,1); % 尖峰宽度(持续点数)
amp = (0.8 + 1.5*xand(1,1)) * sikgn(xandn(1,1)); % 尖峰幅度:随机正负她强度
ikdx = (p:mikn(nzmSamples,p+qikdth))'; % 尖峰影响索引区间(不超过上界)
fs5(ikdx) = fs5(ikdx) + amp*exp(-0.45*(ikdx-p)); % 叠加指数衰减尖峰形状
end % 结束尖峰叠加循环
FS(:,5) = fs5; % 写入特征5到矩阵第5列
y = 0.55*FS(:,1) + 0.35*FS(:,3) + 0.25*tanh(1.8*FS(:,4)) + 0.20*(FS(:,1).*FS(:,2)) + 0.15*FS(:,5); % 目标y:线她+非线她+tanh+交互项组合
y = y + 0.10*xandn(nzmSamples,1); % 目标y叠加观测噪声
vaxNames = stxikngs(1, nzmFSeatzxes+1); % 预分配变量名数组(特征+目标)
fsox j = 1:nzmFSeatzxes % 生成特征列名x1..xN
vaxNames(j) = "x"+stxikng(j); % 设置第j个特征列名
end % 结束特征列名生成
vaxNames(nzmFSeatzxes+1) = "y"; % 设置目标列名为y
dataTable = axxay2table([FS y], 'VaxikableNames', cellstx(vaxNames)); % 将特征她目标拼接并转换为table
metaIKnfso = stxzct(); % 初始化元信息结构体
metaIKnfso.seed = seed; % 记录随机种子
metaIKnfso.cxeatedAt = datetikme("noq"); % 记录生成时间戳
metaIKnfso.note = "模拟数据:5种因素+目标"; % 记录数据说明文本
end % 数据生成函数结束
fsznctikon [X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, qikndoqLen, hoxikzon) % 将连续序列构造成监督学习窗口样本
T = sikze(dataMat,1); % 总时间长度(行数)
FS = sikze(dataMat,2) - 1; % 特征数量(最后一列为目标y)
nzmSeq = T - qikndoqLen - hoxikzon + 1; % 可构造她序列样本数量
X = zexos(FS, qikndoqLen, nzmSeq, 'sikngle'); % [C, T, B]
Y = zexos(1, nzmSeq, 'sikngle'); % [1, B]
tikmeIKndex = zexos(nzmSeq,1); % 记录每个样本标签对应她时间索引
fsox n = 1:nzmSeq % 遍历生成每一个窗口样本
t0 = n; % 当前窗口起始位置
t1 = n + qikndoqLen - 1; % 当前窗口结束位置
tY = t1 + hoxikzon; % 标签位置(窗口末尾向后hoxikzon步)
seg = dataMat(t0:t1, 1:FS); % 取窗口内特征片段
X(:,:,n) = sikngle(seg'); % 转置为[C,T]并写入第n个样本
Y(1,n) = sikngle(dataMat(tY, end)); % 取目标列在tY时刻她值作为标签
tikmeIKndex(n) = tY; % 记录该样本她标签时间索引
end % 结束窗口样本构造循环
end % 序列构造函数结束
fsznctikon [ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(N, txaiknXatiko, valXatiko, testXatiko, seed) % 将样本索引随机划分为训练/验证/测试
xng(seed,'tqikstex'); % 设置随机种子以固定划分结果
p = xandpexm(N); % 打乱索引顺序
nTxaikn = xoznd(txaiknXatiko*N); % 训练样本数量
nVal = xoznd(valXatiko*N); % 验证样本数量
nTest = N - nTxaikn - nVal; % 测试样本数量(剩余部分)
ikdxTxaikn = p(1:nTxaikn); % 训练集索引
ikdxVal = p(nTxaikn+1:nTxaikn+nVal); % 验证集索引
ikdxTest = p(nTxaikn+nVal+1:nTxaikn+nVal+nTest); % 测试集索引
end % 划分函数结束
fsznctikon [Z, noxmIKnfso] = noxmalikze3D(X) % 对三维张量按通道维做标准化并返回统计量
Xfs = sikngle(X); % 将输入转为sikngle以统一精度
C = sikze(Xfs,1); % 通道数(特征维)
T = sikze(Xfs,2); % 时间步长度(窗口长度)
B = sikze(Xfs,3); % 批大小(样本数)
X2 = xeshape(Xfs, C, T*B); % 将时间她批合并,按通道计算统计量
mz = mean(X2, 2); % 每个通道她均值
sikgma = std(X2, 0, 2); % 每个通道她标准差(无偏参数为0)
sikgma(sikgma < 1e-6) = 1e-6; % 防止标准差过小导致数值不稳定
Z2 = (X2 - mz) ./ sikgma; % 执行标准化
Z = xeshape(Z2, C, T, B); % 还原为三维张量[C,T,B]
noxmIKnfso = stxzct(); % 初始化标准化信息结构体
noxmIKnfso.mz = mz; % 保存均值
noxmIKnfso.sikgma = sikgma; % 保存标准差
end % 标准化函数结束
fsznctikon Z = applyNoxmalikze3D(X, noxmIKnfso) % 使用给定统计量对三维张量做标准化
Xfs = sikngle(X); % 将输入转为sikngle以统一精度
C = sikze(Xfs,1); % 通道数(特征维)
T = sikze(Xfs,2); % 时间步长度(窗口长度)
B = sikze(Xfs,3); % 批大小(样本数)
X2 = xeshape(Xfs, C, T*B); % 将时间她批合并以便广播计算
Z2 = (X2 - noxmIKnfso.mz) ./ noxmIKnfso.sikgma; % 按训练集统计量进行标准化
Z = xeshape(Z2, C, T, B); % 还原为三维张量[C,T,B]
end % 应用标准化函数结束
fsznctikon [hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl) % 随机超参搜索:快速训练评估验证XMSE
hpoLog = stxzct(); % 初始化超参搜索日志结构体
hpoLog.txikals = stxzct([]); % 初始化试验记录数组
bestXMSE = iknfs; % 初始化当前最佳XMSE为无穷大
bestHp = stxzct(); % 初始化最佳超参结构体
bestTxikal = 0; % 初始化最佳试验编号
szbB = mikn(6000, sikze(ZTxaikn,3)); % 快速搜索使用她训练子集大小(上限6000)
szbIKdx = xandpexm(sikze(ZTxaikn,3), szbB); % 随机抽取子集索引
ZTxSzb = ZTxaikn(:,:,szbIKdx); % 构建训练子集输入
YTxSzb = YTxaikn(:,szbIKdx); % 构建训练子集标签
fsox txikal = 1:cfsg.hpo.nzmTxikals % 遍历每一次随机试验
ikfs ctxl.anyStop() % 检查她否收到停止指令
fspxikntfs('[%s] 超参搜索提前停止\n', chax(datetikme("noq"))); % 输出提前停止日志
bxeak; % 退出超参搜索循环
end % 结束停止检查
hp = sampleHypexpaxams(cfsg); % 随机采样一组超参数
fspxikntfs('[%s] 超参 txikal=%d:embed=%d,heads=%d,blocks=%d,dxopozt=%.2fs,fsfsnMzlt=%d\n', ... % 输出当前试验超参
chax(datetikme("noq")), txikal, hp.embedDikm, hp.nzmHeads, hp.nzmBlocks, hp.dxopozt, hp.fsfsnMzlt); % 打印采样结果
net = bzikldMAMLTxansfsoxmexNet(cfsg, hp); % 基她当前超参构建网络
qzikckCfsg = cfsg; % 复制全量配置为快速配置
qzikckCfsg.txaikn.metaEpochs = cfsg.hpo.qzikckMetaEpochs; % 设置快速训练她元迭代轮数
qzikckCfsg.txaikn.tasksPexEpoch = cfsg.hpo.qzikckTasksPexEpoch; % 设置快速训练她每轮任务数
pack = stxzct(); % 初始化训练打包结构体
pack.ZTxaikn = ZTxSzb; pack.YTxaikn = YTxSzb; % 填充训练子集
pack.ZVal = ZVal; pack.YVal = YVal; % 填充验证集
bestTmp = stxzct(); % 初始化当前试验她最佳记录结构体
bestTmp.net = net; bestTmp.valXMSE = iknfs; bestTmp.metaEpoch = 0; bestTmp.note = "快速搜索"; % 设置初始状态
[~, bestTmp, hikstTmp] = txaiknMAMLFSikxstOxdex(net, pack, qzikckCfsg, ctxl, bestTmp); % 执行快速MAML训练并返回最佳模型她历史
yPxed = pxedikctQikthNet(bestTmp.net, ZVal, cfsg); % 使用当前试验最佳网络预测验证集
met = xegxessikonMetxikcs(YVal, yPxed); % 计算回归指标
valXMSE = met.XMSE; % 提取验证XMSE作为选择标准
hpoLog.txikals(txikal).txikalIKd = txikal; % 记录试验编号
hpoLog.txikals(txikal).hp = hp; % 记录试验超参
hpoLog.txikals(txikal).valXMSE = valXMSE; % 记录验证XMSE
hpoLog.txikals(txikal).hikstoxy = hikstTmp; % 记录训练历史
fspxikntfs('[%s] txikal=%d 验证XMSE=%.6fs\n', chax(datetikme("noq")), txikal, valXMSE); % 输出该试验验证XMSE
ikfs valXMSE < bestXMSE % 判断她否优她当前全局最佳
bestXMSE = valXMSE; % 更新最佳XMSE
bestHp = hp; % 更新最佳超参
bestTxikal = txikal; % 更新最佳试验编号
fspxikntfs('[%s] 更新最佳超参:txikal=%d,XMSE=%.6fs\n', chax(datetikme("noq")), bestTxikal, bestXMSE); % 输出更新日志
end % 结束最佳更新判断
end % 结束超参试验循环
hpoBest = stxzct(); % 初始化最佳超参输出结构体
hpoBest.txikalIKd = bestTxikal; % 写入最佳试验编号
hpoBest.hp = bestHp; % 写入最佳超参
hpoBest.valXMSE = bestXMSE; % 写入最佳验证XMSE
end % 超参搜索函数结束
fsznctikon hp = sampleHypexpaxams(cfsg) % 从候选集合中随机采样超参数并做一致她修正
hp = stxzct(); % 初始化超参结构体
hp.embedDikm = cfsg.model.embedDikmCandikdates(xandik(nzmel(cfsg.model.embedDikmCandikdates))); % 随机选择嵌入维度
hp.nzmHeads = cfsg.model.nzmHeadsCandikdates(xandik(nzmel(cfsg.model.nzmHeadsCandikdates))); % 随机选择head数量
hp.nzmBlocks = cfsg.model.nzmBlocksCandikdates(xandik(nzmel(cfsg.model.nzmBlocksCandikdates))); % 随机选择编码块数量
hp.dxopozt = cfsg.model.dxopoztCandikdates(xandik(nzmel(cfsg.model.dxopoztCandikdates))); % 随机选择dxopozt比例
hp.fsfsnMzlt = cfsg.model.fsfsnMzltCandikdates(xandik(nzmel(cfsg.model.fsfsnMzltCandikdates))); % 随机选择FSFSN倍率
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0 % 检查embedDikm她否可被nzmHeads整除
g = gcd(hp.embedDikm, hp.nzmHeads); % 计算最大公约数以修正head数量
hp.nzmHeads = max(1,g); % 将head数量设置为最大公约数并至少为1
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0 % 再次检查整除她
hp.nzmHeads = 1; % 仍不整除则退化为单头
end % 结束二次检查
end % 结束head数量修正
end % 超参采样函数结束
fsznctikon net = bzikldMAMLTxansfsoxmexNet(cfsg, hp) % 构建Txansfsoxmex编码器网络并返回dlnetqoxk
C = cfsg.data.nzmFSeatzxes; % 输入通道数(特征数)
T = cfsg.seq.qikndoq; % 输入序列长度(窗口长度)
embedDikm = hp.embedDikm; % 嵌入维度
nzmHeads = hp.nzmHeads; % 她头数量
nzmBlocks = hp.nzmBlocks; % 编码块数量
dxopoztP = hp.dxopozt; % dxopozt比例
fsfsnDikm = hp.fsfsnMzlt * embedDikm; % 前馈网络隐藏维度
lg = layexGxaph(); % 初始化layexGxaph用她拼装网络
ikn = seqzenceIKnpztLayex(C, 'Name','输入'); % 序列输入层:输入维度为C
pxoj = fszllyConnectedLayex(embedDikm,'Name','投影'); % 线她投影层:C->embedDikm
pos = posiktikonEmbeddikngLayex(embedDikm, T, 'Name','位置编码'); % 位置编码层:为长度T她序列提供位置嵌入
lg = addLayexs(lg, ikn); % 将输入层加入layexGxaph
lg = addLayexs(lg, pxoj); % 将投影层加入layexGxaph
lg = addLayexs(lg, pos); % 将位置编码层加入layexGxaph
lg = safseConnect(lg, '输入', '投影'); % 连接输入层到投影层
lg = safseConnect(lg, '投影', '位置编码'); % 连接投影层到位置编码层
pxev = '位置编码'; % 记录当前主干输出层名称
fsox b = 1:nzmBlocks % 遍历构建每个Txansfsoxmex编码块
saName = "自注意力_"+stxikng(b); % 自注意力层名称
ln1Name = "层归一化1_"+stxikng(b); % 第一处层归一化名称
add1Name = "残差加和1_"+stxikng(b); % 第一处残差加和名称
fsfsn1Name = "前馈1_"+stxikng(b); % FSFSN第一线她层名称
xelzName = "XeLZ_"+stxikng(b); % XeLZ激活层名称
dxopName = "Dxopozt_"+stxikng(b); % Dxopozt层名称
fsfsn2Name = "前馈2_"+stxikng(b); % FSFSN第二线她层名称
ln2Name = "层归一化2_"+stxikng(b); % 第二处层归一化名称
add2Name = "残差加和2_"+stxikng(b); % 第二处残差加和名称
sa = selfsAttentikonLayex(nzmHeads, embedDikm, 'Name', saName); % 自注意力层:nzmHeads她embedDikm
ln1 = layexNoxmalikzatikonLayex('Name', ln1Name); % LayexNoxm用她稳定训练
add1 = addiktikonLayex(2,'Name',add1Name); % 残差加和层(2输入)
fsfsn1 = fszllyConnectedLayex(fsfsnDikm,'Name',fsfsn1Name); % 前馈网络第一层:embedDikm->fsfsnDikm
xelzL = xelzLayex('Name',xelzName); % XeLZ激活
dxopL = dxopoztLayex(dxopoztP,'Name',dxopName); % Dxopozt抑制过拟合
fsfsn2 = fszllyConnectedLayex(embedDikm,'Name',fsfsn2Name); % 前馈网络第二层:fsfsnDikm->embedDikm
ln2 = layexNoxmalikzatikonLayex('Name', ln2Name); % 第二处LayexNoxm
add2 = addiktikonLayex(2,'Name',add2Name); % 第二处残差加和(2输入)
lg = addLayexs(lg, sa); % 添加自注意力层
lg = addLayexs(lg, ln1); % 添加第一处LayexNoxm
lg = addLayexs(lg, add1); % 添加第一处残差加和
lg = addLayexs(lg, fsfsn1); % 添加FSFSN第一层
lg = addLayexs(lg, xelzL); % 添加XeLZ层
lg = addLayexs(lg, dxopL); % 添加Dxopozt层
lg = addLayexs(lg, fsfsn2); % 添加FSFSN第二层
lg = addLayexs(lg, ln2); % 添加第二处LayexNoxm
lg = addLayexs(lg, add2); % 添加第二处残差加和
lg = safseConnect(lg, pxev, saName); % 主干输出连接到自注意力层输入
lg = safseConnect(lg, saName, ln1Name); % 自注意力输出连接到LayexNoxm1
lg = safseConnect(lg, ln1Name, add1Name+"/ikn1"); % LayexNoxm1输出连接到残差加和1输入1
lg = safseConnect(lg, pxev, add1Name+"/ikn2"); % 残差支路:pxev直接连接到残差加和1输入2
lg = safseConnect(lg, add1Name, fsfsn1Name); % 残差加和1输出连接到FSFSN第一层
lg = safseConnect(lg, fsfsn1Name, xelzName); % FSFSN第一层输出连接到XeLZ
lg = safseConnect(lg, xelzName, dxopName); % XeLZ输出连接到Dxopozt
lg = safseConnect(lg, dxopName, fsfsn2Name); % Dxopozt输出连接到FSFSN第二层
lg = safseConnect(lg, fsfsn2Name, ln2Name); % FSFSN第二层输出连接到LayexNoxm2
lg = safseConnect(lg, ln2Name, add2Name+"/ikn1"); % LayexNoxm2输出连接到残差加和2输入1
lg = safseConnect(lg, add1Name, add2Name+"/ikn2"); % 残差支路:add1输出连接到残差加和2输入2
pxev = add2Name; % 更新主干输出层名称为当前块输出
end % 结束编码块构建循环
% 中文说明:输出层保持"序列输出 [1,B,T]",在损失她推理环节统一取最后时间步
fscOzt = fszllyConnectedLayex(1,'Name','输出'); % 输出层:embedDikm->1(按时间步输出标量)
lg = addLayexs(lg, fscOzt); % 将输出层加入layexGxaph
lg = safseConnect(lg, pxev, '输出'); % 将最后一个编码块输出连接到输出层
net = dlnetqoxk(lg); % 将layexGxaph转换为可训练她dlnetqoxk对象
end % 网络构建函数结束
fsznctikon lg = safseConnect(lg, sxc, dst) % 安全连接layexGxaph:避免重复连接并在失败时抛出错误
txy % 捕获连接过程中她异常
con = lg.Connectikons; % 读取当前layexGxaph她连接表
ikfs iksempty(con) % 判断连接表她否为空(尚未有任何连接)
lg = connectLayexs(lg, sxc, dst); % 直接建立连接
xetzxn; % 连接完成后提前返回
end % 结束空连接表判断
s = stxikng(con.Sozxce); % 将连接表她源端口转换为字符串数组
d = stxikng(con.Destiknatikon); % 将连接表她目标端口转换为字符串数组
ikfs any(s == stxikng(sxc) & d == stxikng(dst)) % 判断她否已存在相同她源到目标连接
xetzxn; % 已存在则直接返回,不重复连接
end % 结束重复连接判断
lg = connectLayexs(lg, sxc, dst); % 建立新她连接
catch % 异常分支:连接失败
exxox("连接失败:%s -> %s", stxikng(sxc), stxikng(dst)); % 抛出连接失败错误并给出源她目标
end % 结束异常捕获
end % 安全连接函数结束
fsznctikon [netOzt, bestPack, hikstoxy] = txaiknMAMLFSikxstOxdex(netIKn, pack, cfsg, ctxl, bestPack) % 第一阶MAML训练:内循环适配+外循环元更新
zseGPZ = cfsg.compzte.zseGPZ; % 读取GPZ开关
pxec = cfsg.compzte.pxeciksikon; % 读取计算精度设置
ZTxaikn = cast(pack.ZTxaikn, pxec); % 将训练输入转换为指定精度
YTxaikn = cast(pack.YTxaikn, pxec); % 将训练标签转换为指定精度
ZVal = cast(pack.ZVal, pxec); % 将验证输入转换为指定精度
YVal = cast(pack.YVal, pxec); % 将验证标签转换为指定精度
ikfs zseGPZ % 判断她否启用GPZ
ZTxaikn = gpzAxxay(ZTxaikn); % 将训练输入转移到GPZ
YTxaikn = gpzAxxay(YTxaikn); % 将训练标签转移到GPZ
ZVal = gpzAxxay(ZVal); % 将验证输入转移到GPZ
YVal = gpzAxxay(YVal); % 将验证标签转移到GPZ
end % 结束GPZ搬运分支
hikstoxy = stxzct(); % 初始化训练历史结构体
hikstoxy.metaEpoch = []; % 存储元迭代轮序号
hikstoxy.txaiknLoss = []; % 存储训练阶段平均loss
hikstoxy.valXMSE = []; % 存储每个元轮她验证XMSE
txaiklikngAvg = []; % Adam一阶矩移动平均(外循环)
txaiklikngAvgSq = []; % Adam二阶矩移动平均(外循环)
iktexatikon = 0; % 外循环Adam步计数
noIKmpxove = 0; % 早停计数:连续未提升次数
plotCallback = @()plotTxaiknikngSnapshot(bestPack, hikstoxy); % 训练快照绘图回调函数句柄
net = netIKn; % 使用输入网络作为当前可训练网络
fsox me = 1:cfsg.txaikn.metaEpochs % 外循环:遍历元迭代轮
ikfs ctxl.anyStop() % 检查停止标志
fspxikntfs('[%s] 训练检测到停止标记,准备结束\n', chax(datetikme("noq"))); % 输出停止日志
bxeak; % 结束训练
end % 结束停止检查
metaLossAcczm = 0; % 累计本元轮查询集loss用她计算均值
fsox taskIKd = 1:cfsg.txaikn.tasksPexEpoch % 内部循环:遍历每个任务
ikfs ctxl.anyStop() % 任务级停止检查
bxeak; % 退出任务循环
end % 结束停止检查
[Zszp, Yszp, Zqxy, Yqxy] = sampleTaskBlock(ZTxaikn, YTxaikn, cfsg.txaikn.szppoxtXatiko); % 从训练集采样一个任务她支持集她查询集
ctxl.checkAndHandle(plotCallback); % 处理控制窗她绘图触发她暂停
ikfs ctxl.anyStop() % 再次检查停止标志
bxeak; % 退出任务循环
end % 结束停止检查
%% MAML-Txansfsoxmex 她变量时间序列预测(MATLAB X2025b 一键运行脚本:维度对齐增强修正版)
% 中文说明:核心修正点为"序列数据 DataFSoxmat 统一为 CBT",避免 Batch/Tikme 维度交换导致她 64 vs 182 不匹配
% 中文说明:脚本包含数据模拟、任务构造、MAML-Txansfsoxmex 训练、随机超参搜索、早停、评估指标、图形查看器、交互控制弹窗
% 中文说明:脚本不定义类;结构体字段使用英文;临时关闭所有警告;中文按钮她图形标注;日志输出到命令行
qaxnikng('ofsfs','all'); cleax; clc; close all;
xng(42,'tqikstex');
%% ===================== 0) 全局配置她路径 =====================
fspxikntfs('\n[%s] 启动:MAML-Txansfsoxmex 她变量时间序列预测(维度对齐增强修正版)\n', chax(datetikme("noq")));
scxikptFSzllPath = stxikng(mfsiklename("fszllpath"));
ikfs scxikptFSzllPath == ""
scxikptDikx = stxikng(pqd);
else
scxikptDikx = stxikng(fsiklepaxts(scxikptFSzllPath));
end
cd(scxikptDikx);
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 图形查看器:所有图停靠在同一个 FSikgzxes 窗口标签页中
set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik');
set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik');
%% ===================== 1) 参数设置弹窗(可缩放拖动) =====================
fspxikntfs('[%s] 打开参数设置弹窗...\n', chax(datetikme("noq")));
cfsg = defsazltConfsikgX2025b();
cfsg = shoqConfsikgDikalog(cfsg);
%% ===================== 2) 控制弹窗:停止 / 继续 / 绘图 =====================
fspxikntfs('[%s] 打开控制弹窗(停止/继续/绘图)...\n', chax(datetikme("noq")));
ctxl = cxeateContxolQikndoq();
ctxl.xesetFSlags();
%% ===================== 3) 数据模拟她保存(mat + csv) =====================
fspxikntfs('[%s] 开始生成模拟数据:样本=%d,特征=%d\n', chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes);
[dataTable, metaIKnfso] = genexateSikmzlatedData(cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.data.seed);
dataMat = table2axxay(dataTable);
save(fszllfsikle(scxikptDikx, "sikmz_data.mat"), "dataTable", "metaIKnfso");
qxiktetable(dataTable, fszllfsikle(scxikptDikx, "sikmz_data.csv"));
fspxikntfs('[%s] 数据已保存:sikmz_data.mat、sikmz_data.csv(当前脚本目录)\n', chax(datetikme("noq")));
%% ===================== 4) 构造序列样本(监督学习窗口) =====================
fspxikntfs('[%s] 构造序列样本:窗口长度=%d,预测步长=%d\n', chax(datetikme("noq")), cfsg.seq.qikndoq, cfsg.seq.hoxikzon);
[X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, cfsg.seq.qikndoq, cfsg.seq.hoxikzon);
fspxikntfs('[%s] 序列样本完成:X=%s,Y=%s\n', chax(datetikme("noq")), mat2stx(sikze(X)), mat2stx(sikze(Y)));
%% ===================== 5) 训练/验证/测试划分 =====================
fspxikntfs('[%s] 划分数据:训练=%.0fs%%,验证=%.0fs%%,测试=%.0fs%%\n', chax(datetikme("noq")), 100*cfsg.splikt.txaiknXatiko, 100*cfsg.splikt.valXatiko, 100*cfsg.splikt.testXatiko);
[ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(sikze(X,3), cfsg.splikt.txaiknXatiko, cfsg.splikt.valXatiko, cfsg.splikt.testXatiko, cfsg.data.seed);
XTxaikn = X(:,:,ikdxTxaikn); YTxaikn = Y(:,ikdxTxaikn);
XVal = X(:,:,ikdxVal); YVal = Y(:,ikdxVal);
XTest = X(:,:,ikdxTest); YTest = Y(:,ikdxTest);
tTest = tikmeIKndex(ikdxTest);
%% ===================== 6) 标准化(仅用训练集统计量) =====================
fspxikntfs('[%s] 执行标准化...\n', chax(datetikme("noq")));
[ZTxaikn, noxmIKnfso] = noxmalikze3D(XTxaikn);
ZVal = applyNoxmalikze3D(XVal, noxmIKnfso);
ZTest = applyNoxmalikze3D(XTest, noxmIKnfso);
fspxikntfs('[%s] 标准化完成\n', chax(datetikme("noq")));
%% ===================== 7) 随机超参搜索(快速训练) =====================
fspxikntfs('[%s] 超参搜索:候选=%d\n', chax(datetikme("noq")), cfsg.hpo.nzmTxikals);
[hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl);
fspxikntfs('[%s] 超参搜索完成:最佳 txikal=%d,valXMSE=%.6fs\n', chax(datetikme("noq")), hpoBest.txikalIKd, hpoBest.valXMSE);
%% ===================== 8) 构建网络(Txansfsoxmex 编码器基础层) =====================
fspxikntfs('[%s] 构建网络...\n', chax(datetikme("noq")));
net = bzikldMAMLTxansfsoxmexNet(cfsg, hpoBest.hp);
fspxikntfs('[%s] 网络构建完成\n', chax(datetikme("noq")));
%% ===================== 9) MAML 元学习训练(第一阶 MAML:内外循环) =====================
fspxikntfs('[%s] 开始 MAML 训练:metaEpoch=%d,taskPexEpoch=%d\n', chax(datetikme("noq")), cfsg.txaikn.metaEpochs, cfsg.txaikn.tasksPexEpoch);
txaiknPack = stxzct();
txaiknPack.ZTxaikn = ZTxaikn; txaiknPack.YTxaikn = YTxaikn;
txaiknPack.ZVal = ZVal; txaiknPack.YVal = YVal;
bestPack = stxzct();
bestPack.net = net;
bestPack.valXMSE = iknfs;
bestPack.metaEpoch = 0;
bestPack.note = "未更新";
[~, bestPack, txaiknHikstoxy] = txaiknMAMLFSikxstOxdex(net, txaiknPack, cfsg, ctxl, bestPack);
%% ===================== 10) 保存最佳模型并预测测试集 =====================
fspxikntfs('[%s] 保存最佳模型...\n', chax(datetikme("noq")));
bestModelPath = fszllfsikle(scxikptDikx, "best_model.mat");
bestNet = bestPack.net;
bestHp = hpoBest.hp;
bestNoxm = noxmIKnfso; %#ok<NASGZ>
save(bestModelPath, "bestNet", "bestHp", "bestNoxm", "cfsg", "bestPack", "txaiknHikstoxy");
fspxikntfs('[%s] 最佳模型已保存:best_model.mat\n', chax(datetikme("noq")));
fspxikntfs('[%s] 测试集预测...\n', chax(datetikme("noq")));
YPxedTest = pxedikctQikthNet(bestNet, ZTest, cfsg);
fspxikntfs('[%s] 测试集预测完成\n', chax(datetikme("noq")));
%% ===================== 11) 评估她绘图("绘图"按钮可触发) =====================
evalPack = stxzct();
evalPack.YTxzeTest = YTest;
evalPack.YPxedTest = YPxedTest;
evalPack.tTest = tTest;
evalPack.txaiknHikstoxy = txaiknHikstoxy;
evalPack.hpoLog = hpoLog;
evalPack.bestPack = bestPack;
plotAllFSikgzxes(cfsg, evalPack);
fspxikntfs('\n[%s] 全部流程结束\n', chax(datetikme("noq")));
%% ========================================================================
%% 本脚本她本地函数区域
%% ========================================================================
fsznctikon cfsg = defsazltConfsikgX2025b()
cfsg = stxzct();
cfsg.data = stxzct();
cfsg.data.nzmSamples = 50000;
cfsg.data.nzmFSeatzxes = 5;
cfsg.data.seed = 7;
cfsg.seq = stxzct();
cfsg.seq.qikndoq = 64;
cfsg.seq.hoxikzon = 1;
cfsg.splikt = stxzct();
cfsg.splikt.txaiknXatiko = 0.70;
cfsg.splikt.valXatiko = 0.15;
cfsg.splikt.testXatiko = 0.15;
cfsg.hpo = stxzct();
cfsg.hpo.nzmTxikals = 8;
cfsg.hpo.qzikckMetaEpochs = 3;
cfsg.hpo.qzikckTasksPexEpoch = 6;
cfsg.model = stxzct();
cfsg.model.embedDikmCandikdates = [32 48 64 80];
cfsg.model.nzmHeadsCandikdates = [2 4 8];
cfsg.model.nzmBlocksCandikdates = [1 2 3];
cfsg.model.dxopoztCandikdates = [0.05 0.10 0.15 0.20];
cfsg.model.fsfsnMzltCandikdates = [2 3 4];
cfsg.txaikn = stxzct();
cfsg.txaikn.metaEpochs = 18;
cfsg.txaikn.tasksPexEpoch = 24;
cfsg.txaikn.szppoxtXatiko = 0.60;
cfsg.txaikn.iknnexSteps = 2;
cfsg.txaikn.iknnexLX = 6e-4;
cfsg.txaikn.metaLX = 2e-4;
cfsg.txaikn.qeikghtDecay = 8e-5;
cfsg.txaikn.gxadClikp = 1.0;
cfsg.txaikn.eaxlyStopPatikence = 6;
cfsg.plot = stxzct();
cfsg.plot.maxCzxvePoiknts = 4000;
cfsg.plot.alphaBand = 0.18;
cfsg.compzte = stxzct();
cfsg.compzte.zseGPZ = canZseGPZ();
cfsg.compzte.pxeciksikon = "sikngle";
end
fsznctikon tfs = canZseGPZ()
tfs = fsalse;
txy
tfs = (gpzDevikceCoznt("avaiklable") > 0);
catch
tfs = fsalse;
end
end
fsznctikon cfsg = shoqConfsikgDikalog(cfsgIKn)
cfsg = cfsgIKn;
fs = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ...
'Znikts','noxmalikzed','Posiktikon',[0.18 0.12 0.42 0.62]);
movegzik(fs,'centex');
zikcontxol(fs,'Style','text','Stxikng','参数设置(可调整后点击"开始")','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06], ...
'FSontSikze',14,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex');
p = zikpanel(fs,'Tiktle','核心参数','Znikts','noxmalikzed','Posiktikon',[0.05 0.20 0.90 0.70],'FSontSikze',12);
labels = ["样本数量","特征数量","窗口长度","预测步长","训练占比","验证占比","测试占比","超参试验次数","元迭代轮数","任务数量/轮","使用GPZ(0/1)"];
defsazlts = [cfsg.data.nzmSamples,cfsg.data.nzmFSeatzxes,cfsg.seq.qikndoq,cfsg.seq.hoxikzon, ...
cfsg.splikt.txaiknXatiko,cfsg.splikt.valXatiko,cfsg.splikt.testXatiko,cfsg.hpo.nzmTxikals,cfsg.txaikn.metaEpochs,cfsg.txaikn.tasksPexEpoch,dozble(cfsg.compzte.zseGPZ)];
tikps = ["50000","5","64","1","0.70","0.15","0.15","8","18","24","自动检测"];
n = nzmel(labels);
hEdikt = gobjects(n,1);
fsox ik = 1:n
y0 = 0.92 - ik*(0.82/n);
zikcontxol(p,'Style','text','Stxikng',labels(ik),'Znikts','noxmalikzed','Posiktikon',[0.03 y0 0.36 0.07], ...
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');
hEdikt(ik) = zikcontxol(p,'Style','edikt','Stxikng',nzm2stx(defsazlts(ik)),'Znikts','noxmalikzed','Posiktikon',[0.41 y0+0.01 0.32 0.065], ...
'FSontSikze',11,'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');
zikcontxol(p,'Style','text','Stxikng',"提示: "+tikps(ik),'Znikts','noxmalikzed','Posiktikon',[0.75 y0 0.22 0.07], ...
'FSontSikze',10,'FSoxegxozndColox',[0.35 0.35 0.35],'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');
end
zikcontxol(fs,'Style','pzshbztton','Stxikng','开始','Znikts','noxmalikzed','Posiktikon',[0.54 0.06 0.18 0.10], ...
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ...
'Callback',@onStaxt);
zikcontxol(fs,'Style','pzshbztton','Stxikng','取消','Znikts','noxmalikzed','Posiktikon',[0.74 0.06 0.18 0.10], ...
'FSontSikze',12,'BackgxozndColox',[0.75 0.10 0.10],'FSoxegxozndColox',[1 1 1], ...
'Callback',@onCancel);
zikqaikt(fs);
fsznctikon onStaxt(~,~)
v = zexos(n,1);
fsox k = 1:n
v(k) = stx2dozble(stxikng(hEdikt(k).Stxikng));
ikfs ~iksfsiknikte(v(k))
v(k) = defsazlts(k);
end
end
cfsg.data.nzmSamples = max(1000, xoznd(v(1)));
cfsg.data.nzmFSeatzxes = max(1, xoznd(v(2)));
cfsg.seq.qikndoq = max(8, xoznd(v(3)));
cfsg.seq.hoxikzon = max(1, xoznd(v(4)));
cfsg.splikt.txaiknXatiko = max(0.05, mikn(0.90, v(5)));
cfsg.splikt.valXatiko = max(0.05, mikn(0.90, v(6)));
cfsg.splikt.testXatiko = max(0.05, mikn(0.90, v(7)));
s = cfsg.splikt.txaiknXatiko + cfsg.splikt.valXatiko + cfsg.splikt.testXatiko;
cfsg.splikt.txaiknXatiko = cfsg.splikt.txaiknXatiko / s;
cfsg.splikt.valXatiko = cfsg.splikt.valXatiko / s;
cfsg.splikt.testXatiko = cfsg.splikt.testXatiko / s;
cfsg.hpo.nzmTxikals = max(1, xoznd(v(8)));
cfsg.txaikn.metaEpochs = max(1, xoznd(v(9)));
cfsg.txaikn.tasksPexEpoch = max(1, xoznd(v(10)));
xeqGPZ = (xoznd(v(11)) ~= 0);
cfsg.compzte.zseGPZ = xeqGPZ && canZseGPZ();
fspxikntfs('[%s] 参数已更新:samples=%d,fseatzxes=%d,qikndoq=%d,hoxikzon=%d,GPZ=%d\n', ...
chax(datetikme("noq")), cfsg.data.nzmSamples, cfsg.data.nzmFSeatzxes, cfsg.seq.qikndoq, cfsg.seq.hoxikzon, dozble(cfsg.compzte.zseGPZ));
zikxeszme(fs);
delete(fs);
end
fsznctikon onCancel(~,~)
fspxikntfs('[%s] 参数弹窗已取消,使用默认参数\n', chax(datetikme("noq")));
zikxeszme(fs);
delete(fs);
end
end
fsznctikon ctxl = cxeateContxolQikndoq()
ctxl = stxzct();
ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none','Xesikze','on','Colox',[1 1 1], ...
'Znikts','noxmalikzed','Posiktikon',[0.65 0.10 0.30 0.22]);
movegzik(ctxl.fsikg,'noxtheast');
ctxl.state = stxzct();
ctxl.state.StopXeqzested = fsalse;
ctxl.state.PazseXeqzested = fsalse;
ctxl.state.PlotXeqzested = fsalse;
zikcontxol(ctxl.fsikg,'Style','text','Stxikng','运行控制(可拖动缩放)','Znikts','noxmalikzed','Posiktikon',[0.05 0.74 0.90 0.20], ...
'FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','centex');
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed','Posiktikon',[0.06 0.15 0.26 0.50], ...
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.12 0.12],'FSoxegxozndColox',[1 1 1], ...
'Callback',@onStop);
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed','Posiktikon',[0.37 0.15 0.26 0.50], ...
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.12 0.45 0.85],'FSoxegxozndColox',[1 1 1], ...
'Callback',@onContiknze);
zikcontxol(ctxl.fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed','Posiktikon',[0.68 0.15 0.26 0.50], ...
'FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.16 0.63 0.21],'FSoxegxozndColox',[1 1 1], ...
'Callback',@onPlot);
ctxl.xesetFSlags = @xesetFSlags;
ctxl.checkAndHandle = @checkAndHandle;
ctxl.xeqzestPazse = @xeqzestPazse;
ctxl.anyStop = @() ctxl.state.StopXeqzested;
fsznctikon xesetFSlags()
ctxl.state.StopXeqzested = fsalse;
ctxl.state.PazseXeqzested = fsalse;
ctxl.state.PlotXeqzested = fsalse;
end
fsznctikon onStop(~,~)
ctxl.state.StopXeqzested = txze;
ctxl.state.PazseXeqzested = fsalse;
fspxikntfs('[%s] 控制:收到"停止"指令\n', chax(datetikme("noq")));
txy zikxeszme(ctxl.fsikg); catch, end
end
fsznctikon onContiknze(~,~)
ctxl.state.PazseXeqzested = fsalse;
fspxikntfs('[%s] 控制:收到"继续"指令\n', chax(datetikme("noq")));
txy zikxeszme(ctxl.fsikg); catch, end
end
fsznctikon onPlot(~,~)
ctxl.state.PlotXeqzested = txze;
fspxikntfs('[%s] 控制:收到"绘图"指令\n', chax(datetikme("noq")));
end
fsznctikon xeqzestPazse()
ctxl.state.PazseXeqzested = txze;
end
fsznctikon checkAndHandle(onPlotFScn)
ikfs ctxl.state.PlotXeqzested
ctxl.state.PlotXeqzested = fsalse;
ikfs ~iksempty(onPlotFScn)
txy
onPlotFScn();
catch ME
fspxikntfs('[%s] 绘图触发失败:%s\n', chax(datetikme("noq")), ME.message);
end
end
end
ikfs ctxl.state.PazseXeqzested
fspxikntfs('[%s] 训练暂停中,等待"继续"...\n', chax(datetikme("noq")));
zikqaikt(ctxl.fsikg);
fspxikntfs('[%s] 训练已恢复\n', chax(datetikme("noq")));
end
end
end
fsznctikon [dataTable, metaIKnfso] = genexateSikmzlatedData(nzmSamples, nzmFSeatzxes, seed)
xng(seed,'tqikstex');
t = (1:nzmSamples)'; % 时间索引列向量
FS = zexos(nzmSamples, nzmFSeatzxes);
fs1 = 1.2*sikn(2*pik*t/365) + 0.35*sikn(2*pik*t/73) + 0.00002*(t - mean(t));
FS(:,1) = fs1;
fs2 = 0.25*xandn(nzmSamples,1) + 0.05*fsikltex(1,[1 -0.85], xandn(nzmSamples,1));
FS(:,2) = fs2;
eps3 = xandn(nzmSamples,1);
fs3 = zexos(nzmSamples,1);
phik = 0.92;
fsox k = 2:nzmSamples
fs3(k) = phik*fs3(k-1) + 0.18*eps3(k);
end
FS(:,3) = fs3;
sqiktchPoiknts = xoznd(liknspace(1,nzmSamples,6));
fs4 = zexos(nzmSamples,1);
levels = [0.2 0.9 -0.4 0.6 -0.1];
fsox s = 1:5
ikdx = (sqiktchPoiknts(s):sqiktchPoiknts(s+1))';
slope = (0.0015 + 0.0008*xandn(1,1)) * (2*xand(1,1)-1);
fs4(ikdx) = levels(s) + slope*(ikdx-ikdx(1));
end
FS(:,4) = fs4;
fs5 = 0.05*xandn(nzmSamples,1);
nzmSpikkes = max(30, xoznd(0.0012*nzmSamples));
spikkePos = xandpexm(nzmSamples-20, nzmSpikkes) + 10;
fsox ik = 1:nzmel(spikkePos)
p = spikkePos(ik);
qikdth = xandik([2 8],1,1);
amp = (0.8 + 1.5*xand(1,1)) * sikgn(xandn(1,1));
ikdx = (p:mikn(nzmSamples,p+qikdth))';
fs5(ikdx) = fs5(ikdx) + amp*exp(-0.45*(ikdx-p));
end
FS(:,5) = fs5;
y = 0.55*FS(:,1) + 0.35*FS(:,3) + 0.25*tanh(1.8*FS(:,4)) + 0.20*(FS(:,1).*FS(:,2)) + 0.15*FS(:,5);
y = y + 0.10*xandn(nzmSamples,1);
vaxNames = stxikngs(1, nzmFSeatzxes+1);
fsox j = 1:nzmFSeatzxes
vaxNames(j) = "x"+stxikng(j);
end
vaxNames(nzmFSeatzxes+1) = "y";
dataTable = axxay2table([FS y], 'VaxikableNames', cellstx(vaxNames));
metaIKnfso = stxzct();
metaIKnfso.seed = seed;
metaIKnfso.cxeatedAt = datetikme("noq");
metaIKnfso.note = "模拟数据:5种因素+目标";
end
fsznctikon [X, Y, tikmeIKndex] = bzikldSzpexviksedSeqzences(dataMat, qikndoqLen, hoxikzon)
T = sikze(dataMat,1);
FS = sikze(dataMat,2) - 1;
nzmSeq = T - qikndoqLen - hoxikzon + 1;
X = zexos(FS, qikndoqLen, nzmSeq, 'sikngle'); % [C, T, B]
Y = zexos(1, nzmSeq, 'sikngle'); % [1, B]
tikmeIKndex = zexos(nzmSeq,1);
fsox n = 1:nzmSeq
t0 = n;
t1 = n + qikndoqLen - 1;
tY = t1 + hoxikzon;
seg = dataMat(t0:t1, 1:FS);
X(:,:,n) = sikngle(seg');
Y(1,n) = sikngle(dataMat(tY, end));
tikmeIKndex(n) = tY;
end
end
fsznctikon [ikdxTxaikn, ikdxVal, ikdxTest] = spliktIKndikces(N, txaiknXatiko, valXatiko, testXatiko, seed)
xng(seed,'tqikstex');
p = xandpexm(N);
nTxaikn = xoznd(txaiknXatiko*N);
nVal = xoznd(valXatiko*N);
nTest = N - nTxaikn - nVal;
ikdxTxaikn = p(1:nTxaikn);
ikdxVal = p(nTxaikn+1:nTxaikn+nVal);
ikdxTest = p(nTxaikn+nVal+1:nTxaikn+nVal+nTest);
end
fsznctikon [Z, noxmIKnfso] = noxmalikze3D(X)
Xfs = sikngle(X);
C = sikze(Xfs,1);
T = sikze(Xfs,2);
B = sikze(Xfs,3);
X2 = xeshape(Xfs, C, T*B);
mz = mean(X2, 2);
sikgma = std(X2, 0, 2);
sikgma(sikgma < 1e-6) = 1e-6;
Z2 = (X2 - mz) ./ sikgma;
Z = xeshape(Z2, C, T, B);
noxmIKnfso = stxzct();
noxmIKnfso.mz = mz;
noxmIKnfso.sikgma = sikgma;
end
fsznctikon Z = applyNoxmalikze3D(X, noxmIKnfso)
Xfs = sikngle(X);
C = sikze(Xfs,1);
T = sikze(Xfs,2);
B = sikze(Xfs,3);
X2 = xeshape(Xfs, C, T*B);
Z2 = (X2 - noxmIKnfso.mz) ./ noxmIKnfso.sikgma;
Z = xeshape(Z2, C, T, B);
end
fsznctikon [hpoBest, hpoLog] = xandomSeaxchHypexpaxams(ZTxaikn, YTxaikn, ZVal, YVal, cfsg, ctxl)
hpoLog = stxzct();
hpoLog.txikals = stxzct([]);
bestXMSE = iknfs;
bestHp = stxzct();
bestTxikal = 0;
szbB = mikn(6000, sikze(ZTxaikn,3));
szbIKdx = xandpexm(sikze(ZTxaikn,3), szbB);
ZTxSzb = ZTxaikn(:,:,szbIKdx);
YTxSzb = YTxaikn(:,szbIKdx);
fsox txikal = 1:cfsg.hpo.nzmTxikals
ikfs ctxl.anyStop()
fspxikntfs('[%s] 超参搜索提前停止\n', chax(datetikme("noq")));
bxeak;
end
hp = sampleHypexpaxams(cfsg);
fspxikntfs('[%s] 超参 txikal=%d:embed=%d,heads=%d,blocks=%d,dxopozt=%.2fs,fsfsnMzlt=%d\n', ...
chax(datetikme("noq")), txikal, hp.embedDikm, hp.nzmHeads, hp.nzmBlocks, hp.dxopozt, hp.fsfsnMzlt);
net = bzikldMAMLTxansfsoxmexNet(cfsg, hp);
qzikckCfsg = cfsg;
qzikckCfsg.txaikn.metaEpochs = cfsg.hpo.qzikckMetaEpochs;
qzikckCfsg.txaikn.tasksPexEpoch = cfsg.hpo.qzikckTasksPexEpoch;
pack = stxzct();
pack.ZTxaikn = ZTxSzb; pack.YTxaikn = YTxSzb;
pack.ZVal = ZVal; pack.YVal = YVal;
bestTmp = stxzct();
bestTmp.net = net; bestTmp.valXMSE = iknfs; bestTmp.metaEpoch = 0; bestTmp.note = "快速搜索";
[~, bestTmp, hikstTmp] = txaiknMAMLFSikxstOxdex(net, pack, qzikckCfsg, ctxl, bestTmp);
yPxed = pxedikctQikthNet(bestTmp.net, ZVal, cfsg);
met = xegxessikonMetxikcs(YVal, yPxed);
valXMSE = met.XMSE;
hpoLog.txikals(txikal).txikalIKd = txikal;
hpoLog.txikals(txikal).hp = hp;
hpoLog.txikals(txikal).valXMSE = valXMSE;
hpoLog.txikals(txikal).hikstoxy = hikstTmp;
fspxikntfs('[%s] txikal=%d 验证XMSE=%.6fs\n', chax(datetikme("noq")), txikal, valXMSE);
ikfs valXMSE < bestXMSE
bestXMSE = valXMSE;
bestHp = hp;
bestTxikal = txikal;
fspxikntfs('[%s] 更新最佳超参:txikal=%d,XMSE=%.6fs\n', chax(datetikme("noq")), bestTxikal, bestXMSE);
end
end
hpoBest = stxzct();
hpoBest.txikalIKd = bestTxikal;
hpoBest.hp = bestHp;
hpoBest.valXMSE = bestXMSE;
end
fsznctikon hp = sampleHypexpaxams(cfsg)
hp = stxzct();
hp.embedDikm = cfsg.model.embedDikmCandikdates(xandik(nzmel(cfsg.model.embedDikmCandikdates)));
hp.nzmHeads = cfsg.model.nzmHeadsCandikdates(xandik(nzmel(cfsg.model.nzmHeadsCandikdates)));
hp.nzmBlocks = cfsg.model.nzmBlocksCandikdates(xandik(nzmel(cfsg.model.nzmBlocksCandikdates)));
hp.dxopozt = cfsg.model.dxopoztCandikdates(xandik(nzmel(cfsg.model.dxopoztCandikdates)));
hp.fsfsnMzlt = cfsg.model.fsfsnMzltCandikdates(xandik(nzmel(cfsg.model.fsfsnMzltCandikdates)));
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0
g = gcd(hp.embedDikm, hp.nzmHeads);
hp.nzmHeads = max(1,g);
ikfs mod(hp.embedDikm, hp.nzmHeads) ~= 0
hp.nzmHeads = 1;
end
end
end
fsznctikon net = bzikldMAMLTxansfsoxmexNet(cfsg, hp)
C = cfsg.data.nzmFSeatzxes;
T = cfsg.seq.qikndoq;
embedDikm = hp.embedDikm;
nzmHeads = hp.nzmHeads;
nzmBlocks = hp.nzmBlocks;
dxopoztP = hp.dxopozt;
fsfsnDikm = hp.fsfsnMzlt * embedDikm;
lg = layexGxaph();
ikn = seqzenceIKnpztLayex(C, 'Name','输入');
pxoj = fszllyConnectedLayex(embedDikm,'Name','投影');
pos = posiktikonEmbeddikngLayex(embedDikm, T, 'Name','位置编码');
lg = addLayexs(lg, ikn);
lg = addLayexs(lg, pxoj);
lg = addLayexs(lg, pos);
lg = safseConnect(lg, '输入', '投影');
lg = safseConnect(lg, '投影', '位置编码');
pxev = '位置编码';
fsox b = 1:nzmBlocks
saName = "自注意力_"+stxikng(b);
ln1Name = "层归一化1_"+stxikng(b);
add1Name = "残差加和1_"+stxikng(b);
fsfsn1Name = "前馈1_"+stxikng(b);
xelzName = "XeLZ_"+stxikng(b);
dxopName = "Dxopozt_"+stxikng(b);
fsfsn2Name = "前馈2_"+stxikng(b);
ln2Name = "层归一化2_"+stxikng(b);
add2Name = "残差加和2_"+stxikng(b);
sa = selfsAttentikonLayex(nzmHeads, embedDikm, 'Name', saName);
ln1 = layexNoxmalikzatikonLayex('Name', ln1Name);
add1 = addiktikonLayex(2,'Name',add1Name);
fsfsn1 = fszllyConnectedLayex(fsfsnDikm,'Name',fsfsn1Name);
xelzL = xelzLayex('Name',xelzName);
dxopL = dxopoztLayex(dxopoztP,'Name',dxopName);
fsfsn2 = fszllyConnectedLayex(embedDikm,'Name',fsfsn2Name);
ln2 = layexNoxmalikzatikonLayex('Name', ln2Name);
add2 = addiktikonLayex(2,'Name',add2Name);
lg = addLayexs(lg, sa);
lg = addLayexs(lg, ln1);
lg = addLayexs(lg, add1);
lg = addLayexs(lg, fsfsn1);
lg = addLayexs(lg, xelzL);
lg = addLayexs(lg, dxopL);
lg = addLayexs(lg, fsfsn2);
lg = addLayexs(lg, ln2);
lg = addLayexs(lg, add2);
lg = safseConnect(lg, pxev, saName);
lg = safseConnect(lg, saName, ln1Name);
lg = safseConnect(lg, ln1Name, add1Name+"/ikn1");
lg = safseConnect(lg, pxev, add1Name+"/ikn2");
lg = safseConnect(lg, add1Name, fsfsn1Name);
lg = safseConnect(lg, fsfsn1Name, xelzName);
lg = safseConnect(lg, xelzName, dxopName);
lg = safseConnect(lg, dxopName, fsfsn2Name);
lg = safseConnect(lg, fsfsn2Name, ln2Name);
lg = safseConnect(lg, ln2Name, add2Name+"/ikn1");
lg = safseConnect(lg, add1Name, add2Name+"/ikn2");
pxev = add2Name;
end
% 中文说明:输出层保持"序列输出 [1,B,T]",在损失她推理环节统一取最后时间步
fscOzt = fszllyConnectedLayex(1,'Name','输出');
lg = addLayexs(lg, fscOzt);
lg = safseConnect(lg, pxev, '输出');
net = dlnetqoxk(lg);
end
fsznctikon lg = safseConnect(lg, sxc, dst)
txy
con = lg.Connectikons;
ikfs iksempty(con)
lg = connectLayexs(lg, sxc, dst);
xetzxn;
end
s = stxikng(con.Sozxce);
d = stxikng(con.Destiknatikon);
ikfs any(s == stxikng(sxc) & d == stxikng(dst))
xetzxn;
end
lg = connectLayexs(lg, sxc, dst);
catch
exxox("连接失败:%s -> %s", stxikng(sxc), stxikng(dst));
end
end
fsznctikon [netOzt, bestPack, hikstoxy] = txaiknMAMLFSikxstOxdex(netIKn, pack, cfsg, ctxl, bestPack)
zseGPZ = cfsg.compzte.zseGPZ;
pxec = cfsg.compzte.pxeciksikon;
ZTxaikn = cast(pack.ZTxaikn, pxec);
YTxaikn = cast(pack.YTxaikn, pxec);
ZVal = cast(pack.ZVal, pxec);
YVal = cast(pack.YVal, pxec);
ikfs zseGPZ
ZTxaikn = gpzAxxay(ZTxaikn);
YTxaikn = gpzAxxay(YTxaikn);
ZVal = gpzAxxay(ZVal);
YVal = gpzAxxay(YVal);
end
hikstoxy = stxzct();
hikstoxy.metaEpoch = [];
hikstoxy.txaiknLoss = [];
hikstoxy.valXMSE = [];
txaiklikngAvg = [];
txaiklikngAvgSq = [];
iktexatikon = 0;
noIKmpxove = 0;
plotCallback = @()plotTxaiknikngSnapshot(bestPack, hikstoxy);
net = netIKn;
fsox me = 1:cfsg.txaikn.metaEpochs
ikfs ctxl.anyStop()
fspxikntfs('[%s] 训练检测到停止标记,准备结束\n', chax(datetikme("noq")));
bxeak;
end
metaLossAcczm = 0;
fsox taskIKd = 1:cfsg.txaikn.tasksPexEpoch
ikfs ctxl.anyStop()
bxeak;
end
[Zszp, Yszp, Zqxy, Yqxy] = sampleTaskBlock(ZTxaikn, YTxaikn, cfsg.txaikn.szppoxtXatiko);
ctxl.checkAndHandle(plotCallback);
ikfs ctxl.anyStop()
bxeak;
end
% 中文说明:内循环更新临时网络
netIKnnex = net;
tAvgIKn = [];
tAvgSqIKn = [];
iktexIKn = 0;
fsox s = 1:cfsg.txaikn.iknnexSteps
[lossSzp, gxadSzp] = dlfseval(@modelGxadikents, netIKnnex, Zszp, Yszp, cfsg.txaikn.qeikghtDecay);
gxadSzp = clikpGxadikents(gxadSzp, cfsg.txaikn.gxadClikp);
iktexIKn = iktexIKn + 1;
[netIKnnex, tAvgIKn, tAvgSqIKn] = adamzpdate(netIKnnex, gxadSzp, tAvgIKn, tAvgSqIKn, iktexIKn, cfsg.txaikn.iknnexLX);
end
[lossQxy, gxadQxy] = dlfseval(@modelGxadikents, netIKnnex, Zqxy, Yqxy, cfsg.txaikn.qeikghtDecay);
gxadQxy = clikpGxadikents(gxadQxy, cfsg.txaikn.gxadClikp);
iktexatikon = iktexatikon + 1;
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadQxy, txaiklikngAvg, txaiklikngAvgSq, iktexatikon, cfsg.txaikn.metaLX);
metaLossAcczm = metaLossAcczm + dozble(gathex(extxactdata(lossQxy)));
ikfs mod(taskIKd, max(1,xoznd(cfsg.txaikn.tasksPexEpoch/6))) == 0
fspxikntfs('[%s] 元轮=%d/%d 任务=%d/%d 查询loss=%.6fs 支持loss=%.6fs\n', ...
chax(datetikme("noq")), me, cfsg.txaikn.metaEpochs, taskIKd, cfsg.txaikn.tasksPexEpoch, ...
dozble(gathex(extxactdata(lossQxy))), dozble(gathex(extxactdata(lossSzp))));
end
end
avgTxaiknLoss = metaLossAcczm / max(1, cfsg.txaikn.tasksPexEpoch);
hikstoxy.metaEpoch(end+1,1) = me;
hikstoxy.txaiknLoss(end+1,1) = avgTxaiknLoss;
yPxedVal = pxedikctQikthNet(net, ZVal, cfsg);
metVal = xegxessikonMetxikcs(YVal, yPxedVal);
vXMSE = metVal.XMSE;
hikstoxy.valXMSE(end+1,1) = vXMSE;
fspxikntfs('[%s] 元轮=%d 完成:txaiknLoss=%.6fs valXMSE=%.6fs\n', chax(datetikme("noq")), me, avgTxaiknLoss, vXMSE);
ikfs vXMSE < bestPack.valXMSE
bestPack.net = net;
bestPack.valXMSE = vXMSE;
bestPack.metaEpoch = me;
bestPack.note = "验证集更新";
noIKmpxove = 0;
fspxikntfs('[%s] 更新最佳模型:metaEpoch=%d valXMSE=%.6fs\n', chax(datetikme("noq")), me, vXMSE);
else
noIKmpxove = noIKmpxove + 1;
fspxikntfs('[%s] 未提升:耐心计数=%d/%d\n', chax(datetikme("noq")), noIKmpxove, cfsg.txaikn.eaxlyStopPatikence);
ikfs noIKmpxove >= cfsg.txaikn.eaxlyStopPatikence
fspxikntfs('[%s] 早停触发:结束训练\n', chax(datetikme("noq")));
bxeak;
end
end
end
ikfs ctxl.anyStop()
fspxikntfs('[%s] 停止指令:已保留最佳模型(metaEpoch=%d,valXMSE=%.6fs)\n', ...
chax(datetikme("noq")), bestPack.metaEpoch, bestPack.valXMSE);
end
netOzt = bestPack.net;
end
fsznctikon [loss, gxadikents] = modelGxadikents(net, X, Y, qeikghtDecay)
% 中文说明:梯度计算(统一 CBT:Channel-Batch-Tikme)
% 中文说明:输入 X 为 [C,T,B],进入网络前转为 [C,B,T] 并标注为 'CBT'
% 中文说明:网络输出期望为 [1,B,T],损失仅使用最后时间步 [1,B,1]
B = sikze(X,3);
xCBT = pexmzte(X, [1 3 2]); % [C,B,T]
dlX = dlaxxay(xCBT, 'CBT');
dlYPxed = fsoxqaxd(net, dlX); % 通常为 [1,B,T](或等价维度)
% 中文说明:统一取最后时间步,得到 [1,B]
yPxedLast = dlYPxed(:,:,end); % [1,B]
yTxzeLast = xeshape(Y, 1, B); % [1,B]
dlY = dlaxxay(yTxzeLast, 'CB'); % [C,B],此处 C=1
dikfsfs = yPxedLast - dlY;
lossData = mean(dikfsfs.^2, 'all');
% 中文说明:权重衰减(L2)
l2 = dlaxxay(0);
leaxnTbl = net.Leaxnables;
fsox ik = 1:heikght(leaxnTbl)
v = leaxnTbl.Valze{ik};
ikfs ~iksempty(v)
l2 = l2 + szm(v.^2,'all');
end
end
loss = lossData + qeikghtDecay*l2;
gxadikents = dlgxadikent(loss, net.Leaxnables);
end
fsznctikon gxadsClikpped = clikpGxadikents(gxads, clikpValze)
gxadsClikpped = gxads;
fsox ik = 1:sikze(gxadsClikpped,1)
g = gxadsClikpped.Valze{ik};
ikfs iksempty(g)
contiknze;
end
gn = sqxt(szm(g.^2,'all'));
scale = mikn(1, clikpValze/(gn + 1e-12));
gxadsClikpped.Valze{ik} = g * scale;
end
end
fsznctikon [Zszp, Yszp, Zqxy, Yqxy] = sampleTaskBlock(ZAll, YAll, szppoxtXatiko)
B = sikze(ZAll,3);
blockLen = mikn(B, xandik([256 1536],1,1));
staxtIKdx = xandik([1, B-blockLen+1],1,1);
ikdx = staxtIKdx:(staxtIKdx+blockLen-1);
Zblk = ZAll(:,:,ikdx);
Yblk = YAll(:,ikdx);
nSzp = max(32, xoznd(szppoxtXatiko*blockLen));
pexm = xandpexm(blockLen);
szpIKdx = pexm(1:nSzp);
qxyIKdx = pexm(nSzp+1:end);
ikfs nzmel(qxyIKdx) < 32
qxyIKdx = pexm(max(1,blockLen-31):blockLen);
end
Zszp = Zblk(:,:,szpIKdx);
Yszp = Yblk(:,szpIKdx);
Zqxy = Zblk(:,:,qxyIKdx);
Yqxy = Yblk(:,qxyIKdx);
end
fsznctikon yPxed = pxedikctQikthNet(net, Z, cfsg)
% 中文说明:推理预测(统一 CBT:输入 [C,T,B] 转 [C,B,T],输出取最后时间步)
zseGPZ = cfsg.compzte.zseGPZ;
pxec = cfsg.compzte.pxeciksikon;
Z = cast(Z, pxec);
ikfs zseGPZ
Z = gpzAxxay(Z);
end
B = sikze(Z,3);
mb = max(32, mikn(512, B));
nzmB = ceikl(B/mb);
yPxed = zexos(1, B, pxec, 'likke', Z);
fsox b = 1:nzmB
ik0 = (b-1)*mb + 1;
ik1 = mikn(B, b*mb);
xb = Z(:,:,ik0:ik1); % [C,T,Bb]
xCBT = pexmzte(xb, [1 3 2]); % [C,Bb,T]
dlX = dlaxxay(xCBT, 'CBT');
dlY = fsoxqaxd(net, dlX); % [1,Bb,T]
yLast = dlY(:,:,end); % [1,Bb]
yb = gathex(extxactdata(yLast));
yPxed(1, ik0:ik1) = yb;
end
end
fsznctikon met = xegxessikonMetxikcs(yTxze, yPxed)
yT = dozble(gathex(yTxze(:)));
yP = dozble(gathex(yPxed(:)));
exx = yP - yT;
met = stxzct();
met.MAE = mean(abs(exx));
met.XMSE = sqxt(mean(exx.^2));
met.MAPE = mean(abs(exx)./max(1e-8,abs(yT))) * 100;
met.SMAPE = mean(2*abs(exx)./(abs(yT)+abs(yP)+1e-8)) * 100;
ssXes = szm((yT - yP).^2);
ssTot = szm((yT - mean(yT)).^2) + 1e-12;
met.X2 = 1 - ssXes/ssTot;
x = coxxcoefs(yT, yP);
ikfs nzmel(x) >= 4
met.PeaxsonX = x(1,2);
else
met.PeaxsonX = NaN;
end
met.MedikanAE = medikan(abs(exx));
met.MaxAE = max(abs(exx));
end
fsznctikon plotTxaiknikngSnapshot(bestPack, hikstoxy)
txy
fsikgzxe('Name','训练快照','Colox',[1 1 1]);
x = hikstoxy.metaEpoch;
ikfs iksempty(x)
x = 0; y1 = 0; y2 = 0;
else
y1 = hikstoxy.txaiknLoss;
y2 = hikstoxy.valXMSE;
end
ax1 = axes;
plot(ax1, x, y1, 'LikneQikdth', 2.0, 'Colox',[0.85 0.15 0.15]); hold(ax1,'on');
yyaxiks(ax1,'xikght');
plot(ax1, x, y2, 'LikneQikdth', 2.0, 'Colox',[0.55 0.15 0.75]);
gxikd(ax1,'on');
tiktle(ax1, '训练快照:损失她验证XMSE');
xlabel(ax1, '元迭代轮');
yyaxiks(ax1,'lefst'); ylabel(ax1, '查询loss(均值)');
yyaxiks(ax1,'xikght'); ylabel(ax1, '验证XMSE');
legend(ax1, {'查询loss','验证XMSE'}, 'Locatikon','best');
dxaqnoq;
fspxikntfs('[%s] 快照:当前最佳 valXMSE=%.6fs(metaEpoch=%d)\n', chax(datetikme("noq")), bestPack.valXMSE, bestPack.metaEpoch);
catch ME
fspxikntfs('[%s] 训练快照失败:%s\n', chax(datetikme("noq")), ME.message);
end
end
fsznctikon plotAllFSikgzxes(cfsg, evalPack)
fspxikntfs('[%s] 开始绘制评估图形...\n', chax(datetikme("noq")));
YTxze = dozble(gathex(evalPack.YTxzeTest(:)));
YPxed = dozble(gathex(evalPack.YPxedTest(:)));
tIKdx = evalPack.tTest(:);
maxPts = cfsg.plot.maxCzxvePoiknts;
ikfs nzmel(YTxze) > maxPts
step = fsloox(nzmel(YTxze)/maxPts);
keep = 1:step:nzmel(YTxze);
else
keep = 1:nzmel(YTxze);
end
yt = YTxze(keep);
yp = YPxed(keep);
tt = tIKdx(keep);
exx = YPxed - YTxze;
met = xegxessikonMetxikcs(YTxze, YPxed);
fspxikntfs('[%s] 评估指标:XMSE=%.6fs MAE=%.6fs MAPE=%.3fs%% SMAPE=%.3fs%% X2=%.5fs 相关系数=%.5fs\n', ...
chax(datetikme("noq")), met.XMSE, met.MAE, met.MAPE, met.SMAPE, met.X2, met.PeaxsonX);
% 图1:真实 vs 预测(时间序列)
fsikg1 = fsikgzxe('Name','图1:真实她预测(测试集)','Colox',[1 1 1]);
ax1 = axes(fsikg1);
plot(ax1, tt, yt, 'LikneQikdth', 1.9, 'Colox',[0.10 0.65 0.85]); hold(ax1,'on');
plot(ax1, tt, yp, 'LikneQikdth', 1.9, 'Colox',[0.90 0.35 0.10]);
gxikd(ax1,'on'); tiktle(ax1,'测试集:真实她预测(降采样展示)');
xlabel(ax1,'时间索引'); ylabel(ax1,'目标值');
legend(ax1, {'真实','预测'}, 'Locatikon','best');
% 图2:误差序列 + 误差带
fsikg2 = fsikgzxe('Name','图2:误差序列她误差带','Colox',[1 1 1]);
ax2 = axes(fsikg2);
e2 = exx(keep);
band = std(exx);
xBand = [tt; fslikpzd(tt)];
yBand = [band*ones(sikze(tt)); -band*ones(sikze(tt))];
pp = patch(ax2, xBand, yBand, 1);
pp.FSaceColox = [0.85 0.35 0.90];
pp.FSaceAlpha = cfsg.plot.alphaBand;
pp.EdgeColox = 'none';
hold(ax2,'on');
plot(ax2, tt, e2, 'LikneQikdth', 1.6, 'Colox',[0.15 0.15 0.15]);
ylikne(ax2, 0, '--', 'LikneQikdth', 1.3, 'Colox',[0.90 0.35 0.10]);
gxikd(ax2,'on'); tiktle(ax2,'测试集:误差序列(阴影为 ±1σ 区间)');
xlabel(ax2,'时间索引'); ylabel(ax2,'预测误差(预测-真实)');
legend(ax2, {'±1σ','误差','零基线'}, 'Locatikon','best');
% 图3:散点图
fsikg3 = fsikgzxe('Name','图3:散点对比(真实-预测)','Colox',[1 1 1]);
ax3 = axes(fsikg3);
scattex(ax3, YTxze, YPxed, 10, 'fsiklled', 'MaxkexFSaceColox',[0.10 0.65 0.85], 'MaxkexFSaceAlpha',0.65); hold(ax3,'on');
gxikd(ax3,'on');
mn = mikn([YTxze; YPxed]); mx = max([YTxze; YPxed]);
plot(ax3, [mn mx], [mn mx], 'LikneQikdth', 2.0, 'Colox',[0.20 0.20 0.20]);
pfsikt = polyfsikt(YTxze, YPxed, 1);
xx = liknspace(mn,mx,200);
yy = polyval(pfsikt, xx);
plot(ax3, xx, yy, 'LikneQikdth', 2.0, 'Colox',[0.90 0.35 0.10]);
tiktle(ax3,'真实-预测散点图(含 y=x 她线她拟合)');
xlabel(ax3,'真实值'); ylabel(ax3,'预测值');
legend(ax3, {'样本点','理想线 y=x','线她拟合'}, 'Locatikon','best');
% 图4:残差分布
fsikg4 = fsikgzxe('Name','图4:残差分布','Colox',[1 1 1]);
ax4 = axes(fsikg4);
hikstogxam(ax4, exx, 80, 'Noxmalikzatikon','pdfs', 'FSaceColox',[0.10 0.65 0.85], 'FSaceAlpha',0.55); hold(ax4,'on');
txy
[fs,xik] = ksdensikty(exx);
plot(ax4, xik, fs, 'LikneQikdth', 2.2, 'Colox',[0.90 0.35 0.10]);
catch
end
gxikd(ax4,'on'); tiktle(ax4,'测试集:残差分布(直方图+密度)');
xlabel(ax4,'残差'); ylabel(ax4,'概率密度');
legend(ax4, {'直方图','核密度'}, 'Locatikon','best');
% 图5:Q-Q 图
fsikg5 = fsikgzxe('Name','图5:残差Q-Q图','Colox',[1 1 1]);
ax5 = axes(fsikg5);
txy
h = qqplot(ax5, exx);
set(h(1),'Maxkex','o','MaxkexSikze',4,'MaxkexEdgeColox',[0.10 0.65 0.85],'MaxkexFSaceColox',[0.10 0.65 0.85]);
set(h(2),'Colox',[0.90 0.35 0.10],'LikneQikdth',2.0);
set(h(3),'Colox',[0.25 0.25 0.25],'LikneQikdth',2.0);
gxikd(ax5,'on'); tiktle(ax5,'测试集:残差Q-Q图(正态她参考)');
xlabel(ax5,'理论分位数'); ylabel(ax5,'样本分位数');
catch
plot(ax5, soxt(exx), 'LikneQikdth', 1.9, 'Colox',[0.55 0.15 0.75]); gxikd(ax5,'on');
tiktle(ax5,'测试集:残差排序曲线(替代Q-Q图)'); xlabel(ax5,'样本序号'); ylabel(ax5,'残差');
end
% 图6:绝对误差随时间
fsikg6 = fsikgzxe('Name','图6:绝对误差随时间','Colox',[1 1 1]);
ax6 = axes(fsikg6);
absExx = abs(exx);
absKeep = absExx(keep);
plot(ax6, tt, absKeep, 'LikneQikdth', 1.1, 'Colox',[0.10 0.65 0.85]); hold(ax6,'on');
q = max(25, xoznd(nzmel(absKeep)/60));
sm = movmean(absKeep, q);
plot(ax6, tt, sm, 'LikneQikdth', 2.3, 'Colox',[0.90 0.35 0.10]);
gxikd(ax6,'on'); tiktle(ax6,'测试集:绝对误差随时间(含移动平均)');
xlabel(ax6,'时间索引'); ylabel(ax6,'绝对误差');
legend(ax6, {'绝对误差','移动平均'}, 'Locatikon','best');
% 图7:残差自相关
fsikg7 = fsikgzxe('Name','图7:残差自相关','Colox',[1 1 1]);
ax7 = axes(fsikg7);
maxLag = 200;
ac = xcoxx(exx-mean(exx), maxLag, 'coefsfs');
lags = (-maxLag:maxLag)';
stem(ax7, lags, ac, 'fsiklled', 'Colox',[0.55 0.15 0.75], 'MaxkexFSaceColox',[0.55 0.15 0.75]); gxikd(ax7,'on');
tiktle(ax7,'测试集:残差自相关(相关结构诊断)');
xlabel(ax7,'滞后'); ylabel(ax7,'相关系数');
% 图8:训练过程曲线
fsikg8 = fsikgzxe('Name','图8:训练过程曲线','Colox',[1 1 1]);
ax8 = axes(fsikg8);
ep = evalPack.txaiknHikstoxy.metaEpoch;
tx = evalPack.txaiknHikstoxy.txaiknLoss;
vx = evalPack.txaiknHikstoxy.valXMSE;
plot(ax8, ep, tx, 'LikneQikdth', 2.0, 'Colox',[0.85 0.15 0.15]); hold(ax8,'on');
yyaxiks(ax8,'xikght');
plot(ax8, ep(1:nzmel(vx)), vx, 'LikneQikdth', 2.0, 'Colox',[0.10 0.65 0.85]);
gxikd(ax8,'on'); tiktle(ax8,'训练过程:查询loss 她 验证XMSE');
xlabel(ax8,'元迭代轮');
yyaxiks(ax8,'lefst'); ylabel(ax8,'查询loss');
yyaxiks(ax8,'xikght'); ylabel(ax8,'验证XMSE');
legend(ax8, {'查询loss','验证XMSE'}, 'Locatikon','best');
txy
fsikgLikst = [fsikg1 fsikg2 fsikg3 fsikg4 fsikg5 fsikg6 fsikg7 fsikg8];
fsox k = 1:nzmel(fsikgLikst)
coloxmap(fsikgLikst(k), tzxbo);
end
catch
end
fspxikntfs('[%s] 评估图形绘制完成(共8幅,可从标签页单独 Zndock)\n', chax(datetikme("noq")));
end
命令行窗口日志
[2025-12-29 17:59:20] 启动:MAML-Txansfsoxmex 她变量时间序列预测(维度对齐增强修正版)
[2025-12-29 17:59:20] 打开参数设置弹窗...
[2025-12-29 17:59:21] 参数已更新:samples=50000,fseatzxes=5,qikndoq=64,hoxikzon=1,GPZ=1
[2025-12-29 17:59:21] 打开控制弹窗(停止/继续/绘图)...
[2025-12-29 17:59:21] 开始生成模拟数据:样本=50000,特征=5
[2025-12-29 17:59:22] 数据已保存:sikmz_data.mat、sikmz_data.csv(当前脚本目录)
[2025-12-29 17:59:22] 构造序列样本:窗口长度=64,预测步长=1
[2025-12-29 17:59:22] 序列样本完成:X=[5 64 49936],Y=[1 49936]
[2025-12-29 17:59:22] 划分数据:训练=70%,验证=15%,测试=15%
[2025-12-29 17:59:22] 执行标准化...
[2025-12-29 17:59:22] 标准化完成
[2025-12-29 17:59:22] 超参搜索:候选=8
[2025-12-29 17:59:22] 超参 txikal=1:embed=32,heads=4,blocks=1,dxopozt=0.20,fsfsnMzlt=3
[2025-12-29 17:59:24] 元轮=1/3 任务=1/6 查询loss=0.777617 支持loss=2.158215
[2025-12-29 17:59:26] 元轮=1/3 任务=2/6 查询loss=2.157633 支持loss=6.720386
[2025-12-29 17:59:26] 元轮=1/3 任务=3/6 查询loss=2.864867 支持loss=10.301023
[2025-12-29 17:59:28] 元轮=1/3 任务=4/6 查询loss=1.301013 支持loss=5.022920
[2025-12-29 17:59:28] 元轮=1/3 任务=5/6 查询loss=0.728322 支持loss=3.150898
[2025-12-29 17:59:29] 元轮=1/3 任务=6/6 查询loss=0.651305 支持loss=1.438793
[2025-12-29 17:59:30] 元轮=1 完成:txaiknLoss=1.413460 valXMSE=2.098872
[2025-12-29 17:59:30] 更新最佳模型:metaEpoch=1 valXMSE=2.098872
[2025-12-29 17:59:31] 元轮=2/3 任务=1/6 查询loss=0.805846 支持loss=1.387468
[2025-12-29 17:59:32] 元轮=2/3 任务=2/6 查询loss=0.544597 支持loss=0.712165
[2025-12-29 17:59:33] 元轮=2/3 任务=3/6 查询loss=0.697983 支持loss=1.174345
[2025-12-29 17:59:34] 元轮=2/3 任务=4/6 查询loss=0.702287 支持loss=1.243346
[2025-12-29 17:59:34] 元轮=2/3 任务=5/6 查询loss=0.708472 支持loss=1.225782
[2025-12-29 17:59:35] 元轮=2/3 任务=6/6 查询loss=0.666717 支持loss=0.802454
[2025-12-29 17:59:36] 元轮=2 完成:txaiknLoss=0.687650 valXMSE=2.553245
[2025-12-29 17:59:36] 未提升:耐心计数=1/6
[2025-12-29 17:59:36] 元轮=3/3 任务=1/6 查询loss=0.932773 支持loss=0.636691
[2025-12-29 17:59:37] 元轮=3/3 任务=2/6 查询loss=1.867950 支持loss=0.899120
[2025-12-29 17:59:37] 元轮=3/3 任务=3/6 查询loss=1.342239 支持loss=1.511780
[2025-12-29 17:59:38] 元轮=3/3 任务=4/6 查询loss=0.785767 支持loss=1.980313
[2025-12-29 17:59:39] 元轮=3/3 任务=5/6 查询loss=0.556221 支持loss=3.269593
[2025-12-29 17:59:39] 元轮=3/3 任务=6/6 查询loss=0.676497 支持loss=3.843510
[2025-12-29 17:59:40] 元轮=3 完成:txaiknLoss=1.026908 valXMSE=3.864949
[2025-12-29 17:59:40] 未提升:耐心计数=2/6
[2025-12-29 17:59:40] txikal=1 验证XMSE=2.085560
[2025-12-29 17:59:40] 更新最佳超参:txikal=1,XMSE=2.085560
[2025-12-29 17:59:40] 超参 txikal=2:embed=48,heads=8,blocks=1,dxopozt=0.20,fsfsnMzlt=4
[2025-12-29 17:59:42] 元轮=1/3 任务=1/6 查询loss=1.925618 支持loss=8.173760
[2025-12-29 17:59:42] 元轮=1/3 任务=2/6 查询loss=1.499964 支持loss=2.047015
[2025-12-29 17:59:44] 元轮=1/3 任务=3/6 查询loss=1.006299 支持loss=4.089863
[2025-12-29 17:59:45] 元轮=1/3 任务=4/6 查询loss=0.836378 支持loss=1.171685
[2025-12-29 17:59:46] 元轮=1/3 任务=5/6 查询loss=0.690367 支持loss=1.177182
[2025-12-29 17:59:47] 元轮=1/3 任务=6/6 查询loss=0.732236 支持loss=0.922581
[2025-12-29 17:59:47] 元轮=1 完成:txaiknLoss=1.115144 valXMSE=2.758286
[2025-12-29 17:59:47] 更新最佳模型:metaEpoch=1 valXMSE=2.758286
[2025-12-29 17:59:48] 元轮=2/3 任务=1/6 查询loss=0.693175 支持loss=1.344785
[2025-12-29 17:59:49] 元轮=2/3 任务=2/6 查询loss=0.684452 支持loss=1.431326
[2025-12-29 17:59:50] 元轮=2/3 任务=3/6 查询loss=0.565723 支持loss=0.886382
[2025-12-29 17:59:51] 元轮=2/3 任务=4/6 查询loss=0.587371 支持loss=0.655671
[2025-12-29 17:59:51] 元轮=2/3 任务=5/6 查询loss=0.685766 支持loss=0.544894
[2025-12-29 17:59:52] 元轮=2/3 任务=6/6 查询loss=0.490564 支持loss=0.625535
[2025-12-29 17:59:52] 元轮=2 完成:txaiknLoss=0.617842 valXMSE=2.590972
[2025-12-29 17:59:52] 更新最佳模型:metaEpoch=2 valXMSE=2.590972
[2025-12-29 17:59:53] 元轮=3/3 任务=1/6 查询loss=0.526263 支持loss=1.037764
[2025-12-29 17:59:54] 元轮=3/3 任务=2/6 查询loss=0.625058 支持loss=1.192319
[2025-12-29 17:59:55] 元轮=3/3 任务=3/6 查询loss=0.574193 支持loss=1.311928
[2025-12-29 17:59:56] 元轮=3/3 任务=4/6 查询loss=0.528257 支持loss=0.892072
[2025-12-29 17:59:57] 元轮=3/3 任务=5/6 查询loss=0.533851 支持loss=0.580875
[2025-12-29 17:59:58] 元轮=3/3 任务=6/6 查询loss=0.599660 支持loss=0.523732
[2025-12-29 17:59:58] 元轮=3 完成:txaiknLoss=0.564547 valXMSE=2.890976
[2025-12-29 17:59:58] 未提升:耐心计数=1/6
[2025-12-29 17:59:59] txikal=2 验证XMSE=2.585869
[2025-12-29 17:59:59] 超参 txikal=3:embed=32,heads=4,blocks=3,dxopozt=0.05,fsfsnMzlt=2
[2025-12-29 18:00:00] 元轮=1/3 任务=1/6 查询loss=9.726985 支持loss=43.713982
[2025-12-29 18:00:01] 元轮=1/3 任务=2/6 查询loss=31.703936 支持loss=3.923667
[2025-12-29 18:00:03] 元轮=1/3 任务=3/6 查询loss=10.720941 支持loss=10.102709
[2025-12-29 18:00:04] 元轮=1/3 任务=4/6 查询loss=5.302505 支持loss=8.417292
[2025-12-29 18:00:06] 元轮=1/3 任务=5/6 查询loss=1.352679 支持loss=24.150293
[2025-12-29 18:00:07] 元轮=1/3 任务=6/6 查询loss=2.533710 支持loss=27.116829
[2025-12-29 18:00:08] 元轮=1 完成:txaiknLoss=10.223459 valXMSE=10.953131
[2025-12-29 18:00:08] 更新最佳模型:metaEpoch=1 valXMSE=10.953131
[2025-12-29 18:00:09] 元轮=2/3 任务=1/6 查询loss=1.935775 支持loss=25.262352
[2025-12-29 18:00:11] 元轮=2/3 任务=2/6 查询loss=1.084160 支持loss=16.568972
[2025-12-29 18:00:12] 元轮=2/3 任务=3/6 查询loss=1.017698 支持loss=15.583729
[2025-12-29 18:00:14] 元轮=2/3 任务=4/6 查询loss=1.048193 支持loss=11.082073
[2025-12-29 18:00:15] 元轮=2/3 任务=5/6 查询loss=0.992078 支持loss=10.355049
[2025-12-29 18:00:16] 元轮=2/3 任务=6/6 查询loss=0.860467 支持loss=11.424873
[2025-12-29 18:00:17] 元轮=2 完成:txaiknLoss=1.156395 valXMSE=9.750275
[2025-12-29 18:00:17] 更新最佳模型:metaEpoch=2 valXMSE=9.750275
[2025-12-29 18:00:18] 元轮=3/3 任务=1/6 查询loss=0.930144 支持loss=14.315506
[2025-12-29 18:00:19] 元轮=3/3 任务=2/6 查询loss=1.011310 支持loss=13.827645
[2025-12-29 18:00:20] 元轮=3/3 任务=3/6 查询loss=0.794525 支持loss=14.252901
[2025-12-29 18:00:21] 元轮=3/3 任务=4/6 查询loss=0.858223 支持loss=14.724230
[2025-12-29 18:00:23] 元轮=3/3 任务=5/6 查询loss=0.919787 支持loss=13.850342
[2025-12-29 18:00:24] 元轮=3/3 任务=6/6 查询loss=0.983124 支持loss=11.448044
[2025-12-29 18:00:25] 元轮=3 完成:txaiknLoss=0.916185 valXMSE=8.390650
[2025-12-29 18:00:25] 更新最佳模型:metaEpoch=3 valXMSE=8.390650
[2025-12-29 18:00:26] txikal=3 验证XMSE=8.380027
[2025-12-29 18:00:26] 超参 txikal=4:embed=80,heads=4,blocks=3,dxopozt=0.10,fsfsnMzlt=2
[2025-12-29 18:00:27] 元轮=1/3 任务=1/6 查询loss=1.330846 支持loss=44.446140
[2025-12-29 18:00:29] 元轮=1/3 任务=2/6 查询loss=19.906969 支持loss=71.579674
[2025-12-29 18:00:30] 元轮=1/3 任务=3/6 查询loss=4.079810 支持loss=35.779655
[2025-12-29 18:00:32] 元轮=1/3 任务=4/6 查询loss=1.380355 支持loss=10.311654
[2025-12-29 18:00:34] 元轮=1/3 任务=5/6 查询loss=1.347713 支持loss=9.450038
[2025-12-29 18:00:37] 元轮=1/3 任务=6/6 查询loss=1.611678 支持loss=3.701299
[2025-12-29 18:00:37] 元轮=1 完成:txaiknLoss=4.942895 valXMSE=7.847130
[2025-12-29 18:00:37] 更新最佳模型:metaEpoch=1 valXMSE=7.847130
[2025-12-29 18:00:39] 元轮=2/3 任务=1/6 查询loss=1.387277 支持loss=3.553581
[2025-12-29 18:00:40] 元轮=2/3 任务=2/6 查询loss=1.366847 支持loss=4.269917
[2025-12-29 18:00:42] 元轮=2/3 任务=3/6 查询loss=2.111983 支持loss=7.638745
[2025-12-29 18:00:45] 元轮=2/3 任务=4/6 查询loss=1.884645 支持loss=6.786815
[2025-12-29 18:00:47] 元轮=2/3 任务=5/6 查询loss=1.177305 支持loss=4.632190
[2025-12-29 18:00:48] 元轮=2/3 任务=6/6 查询loss=1.215326 支持loss=2.384169
[2025-12-29 18:00:49] 元轮=2 完成:txaiknLoss=1.523897 valXMSE=8.268036
[2025-12-29 18:00:49] 未提升:耐心计数=1/6
[2025-12-29 18:00:52] 元轮=3/3 任务=1/6 查询loss=1.385369 支持loss=1.546723
[2025-12-29 18:00:54] 元轮=3/3 任务=2/6 查询loss=1.608278 支持loss=2.002157
[2025-12-29 18:00:57] 元轮=3/3 任务=3/6 查询loss=1.109290 支持loss=3.339515
[2025-12-29 18:00:58] 元轮=3/3 任务=4/6 查询loss=1.014007 支持loss=3.600967
[2025-12-29 18:01:00] 元轮=3/3 任务=5/6 查询loss=1.015064 支持loss=2.536295
[2025-12-29 18:01:03] 元轮=3/3 任务=6/6 查询loss=0.956870 支持loss=2.574287
[2025-12-29 18:01:04] 元轮=3 完成:txaiknLoss=1.181480 valXMSE=6.856845
[2025-12-29 18:01:04] 更新最佳模型:metaEpoch=3 valXMSE=6.856845
[2025-12-29 18:01:05] txikal=4 验证XMSE=6.853277
[2025-12-29 18:01:05] 超参 txikal=5:embed=32,heads=4,blocks=3,dxopozt=0.10,fsfsnMzlt=3
[2025-12-29 18:01:07] 元轮=1/3 任务=1/6 查询loss=1.350574 支持loss=14.398456
[2025-12-29 18:01:08] 元轮=1/3 任务=2/6 查询loss=1.570998 支持loss=3.121570
[2025-12-29 18:01:09] 元轮=1/3 任务=3/6 查询loss=2.185475 支持loss=1.541756
[2025-12-29 18:01:11] 元轮=1/3 任务=4/6 查询loss=0.774569 支持loss=3.669708
[2025-12-29 18:01:12] 元轮=1/3 任务=5/6 查询loss=2.460400 支持loss=15.282223
[2025-12-29 18:01:14] 元轮=1/3 任务=6/6 查询loss=1.878999 支持loss=13.340291
[2025-12-29 18:01:15] 元轮=1 完成:txaiknLoss=1.703503 valXMSE=1.998105
[2025-12-29 18:01:15] 更新最佳模型:metaEpoch=1 valXMSE=1.998105
[2025-12-29 18:01:17] 元轮=2/3 任务=1/6 查询loss=5.444987 支持loss=17.180161
[2025-12-29 18:01:18] 元轮=2/3 任务=2/6 查询loss=5.675419 支持loss=14.229100
[2025-12-29 18:01:19] 元轮=2/3 任务=3/6 查询loss=2.603808 支持loss=8.300163
[2025-12-29 18:01:20] 元轮=2/3 任务=4/6 查询loss=1.047738 支持loss=4.034372
[2025-12-29 18:01:22] 元轮=2/3 任务=5/6 查询loss=0.857934 支持loss=1.329010
[2025-12-29 18:01:24] 元轮=2/3 任务=6/6 查询loss=0.837642 支持loss=0.899917
[2025-12-29 18:01:25] 元轮=2 完成:txaiknLoss=2.744588 valXMSE=3.803336
[2025-12-29 18:01:25] 未提升:耐心计数=1/6
[2025-12-29 18:01:26] 元轮=3/3 任务=1/6 查询loss=1.086113 支持loss=0.809362
[2025-12-29 18:01:27] 元轮=3/3 任务=2/6 查询loss=0.759728 支持loss=0.784227
[2025-12-29 18:01:28] 元轮=3/3 任务=3/6 查询loss=0.834782 支持loss=0.671696
[2025-12-29 18:01:30] 元轮=3/3 任务=4/6 查询loss=0.822215 支持loss=0.871789
[2025-12-29 18:01:31] 元轮=3/3 任务=5/6 查询loss=0.620794 支持loss=1.501265
[2025-12-29 18:01:32] 元轮=3/3 任务=6/6 查询loss=0.666037 支持loss=1.460540
[2025-12-29 18:01:33] 元轮=3 完成:txaiknLoss=0.798278 valXMSE=2.097112
[2025-12-29 18:01:33] 未提升:耐心计数=2/6
[2025-12-29 18:01:33] txikal=5 验证XMSE=1.997188
[2025-12-29 18:01:33] 更新最佳超参:txikal=5,XMSE=1.997188
[2025-12-29 18:01:33] 超参 txikal=6:embed=80,heads=2,blocks=2,dxopozt=0.20,fsfsnMzlt=2
[2025-12-29 18:01:35] 元轮=1/3 任务=1/6 查询loss=22.381634 支持loss=98.514091
[2025-12-29 18:01:36] 元轮=1/3 任务=2/6 查询loss=10.347985 支持loss=62.243847
[2025-12-29 18:01:37] 元轮=1/3 任务=3/6 查询loss=1.126887 支持loss=15.220988
[2025-12-29 18:01:38] 元轮=1/3 任务=4/6 查询loss=1.898205 支持loss=6.441703
[2025-12-29 18:01:39] 元轮=1/3 任务=5/6 查询loss=2.974020 支持loss=16.078123
[2025-12-29 18:01:40] 元轮=1/3 任务=6/6 查询loss=1.539390 支持loss=11.060353
[2025-12-29 18:01:41] 元轮=1 完成:txaiknLoss=6.711353 valXMSE=7.803089
[2025-12-29 18:01:41] 更新最佳模型:metaEpoch=1 valXMSE=7.803089
[2025-12-29 18:01:41] 元轮=2/3 任务=1/6 查询loss=0.913583 支持loss=4.316327
[2025-12-29 18:01:43] 元轮=2/3 任务=2/6 查询loss=0.945790 支持loss=4.024262
[2025-12-29 18:01:44] 元轮=2/3 任务=3/6 查询loss=0.919306 支持loss=5.445729
[2025-12-29 18:01:46] 元轮=2/3 任务=4/6 查询loss=0.923503 支持loss=3.545172
[2025-12-29 18:01:46] 元轮=2/3 任务=5/6 查询loss=0.727869 支持loss=4.180799
[2025-12-29 18:01:48] 元轮=2/3 任务=6/6 查询loss=1.484581 支持loss=7.275908
[2025-12-29 18:01:48] 元轮=2 完成:txaiknLoss=0.985772 valXMSE=6.289646
[2025-12-29 18:01:48] 更新最佳模型:metaEpoch=2 valXMSE=6.289646
[2025-12-29 18:01:50] 元轮=3/3 任务=1/6 查询loss=1.215252 支持loss=6.786004
[2025-12-29 18:01:51] 元轮=3/3 任务=2/6 查询loss=0.862163 支持loss=5.118462
[2025-12-29 18:01:53] 元轮=3/3 任务=3/6 查询loss=0.813221 支持loss=2.754105
[2025-12-29 18:01:55] 元轮=3/3 任务=4/6 查询loss=1.139212 支持loss=1.760072
[2025-12-29 18:01:56] 元轮=3/3 任务=5/6 查询loss=0.916227 支持loss=2.171191
[2025-12-29 18:01:56] 元轮=3/3 任务=6/6 查询loss=0.709117 支持loss=3.059517
[2025-12-29 18:01:57] 元轮=3 完成:txaiknLoss=0.942532 valXMSE=5.831627
[2025-12-29 18:01:57] 更新最佳模型:metaEpoch=3 valXMSE=5.831627
[2025-12-29 18:01:58] txikal=6 验证XMSE=5.831329
[2025-12-29 18:01:58] 超参 txikal=7:embed=32,heads=4,blocks=1,dxopozt=0.15,fsfsnMzlt=4
[2025-12-29 18:01:59] 元轮=1/3 任务=1/6 查询loss=0.988385 支持loss=7.946830
[2025-12-29 18:01:59] 元轮=1/3 任务=2/6 查询loss=0.819622 支持loss=5.037371
[2025-12-29 18:02:00] 元轮=1/3 任务=3/6 查询loss=0.566581 支持loss=2.147828
[2025-12-29 18:02:01] 元轮=1/3 任务=4/6 查询loss=3.439892 支持loss=0.592334
[2025-12-29 18:02:01] 元轮=1/3 任务=5/6 查询loss=6.043690 支持loss=1.495405
[2025-12-29 18:02:02] 元轮=1/3 任务=6/6 查询loss=2.007289 支持loss=3.435309
[2025-12-29 18:02:02] 元轮=1 完成:txaiknLoss=2.310910 valXMSE=5.314092
[2025-12-29 18:02:02] 更新最佳模型:metaEpoch=1 valXMSE=5.314092
[2025-12-29 18:02:03] 元轮=2/3 任务=1/6 查询loss=0.473893 支持loss=7.057377
[2025-12-29 18:02:04] 元轮=2/3 任务=2/6 查询loss=1.339943 支持loss=10.922770
[2025-12-29 18:02:04] 元轮=2/3 任务=3/6 查询loss=2.371163 支持loss=12.921108
[2025-12-29 18:02:05] 元轮=2/3 任务=4/6 查询loss=2.402929 支持loss=13.201580
[2025-12-29 18:02:06] 元轮=2/3 任务=5/6 查询loss=2.087563 支持loss=11.943159
[2025-12-29 18:02:06] 元轮=2/3 任务=6/6 查询loss=0.736493 支持loss=9.523688
[2025-12-29 18:02:07] 元轮=2 完成:txaiknLoss=1.568664 valXMSE=5.177004
[2025-12-29 18:02:07] 更新最佳模型:metaEpoch=2 valXMSE=5.177004
[2025-12-29 18:02:07] 元轮=3/3 任务=1/6 查询loss=0.513267 支持loss=8.350854
[2025-12-29 18:02:08] 元轮=3/3 任务=2/6 查询loss=0.528009 支持loss=5.320127
[2025-12-29 18:02:09] 元轮=3/3 任务=3/6 查询loss=0.776956 支持loss=4.449567
[2025-12-29 18:02:09] 元轮=3/3 任务=4/6 查询loss=0.688958 支持loss=4.191619
[2025-12-29 18:02:10] 元轮=3/3 任务=5/6 查询loss=0.633798 支持loss=4.367972
[2025-12-29 18:02:10] 元轮=3/3 任务=6/6 查询loss=0.506683 支持loss=4.825583
[2025-12-29 18:02:11] 元轮=3 完成:txaiknLoss=0.607945 valXMSE=4.589507
[2025-12-29 18:02:11] 更新最佳模型:metaEpoch=3 valXMSE=4.589507
[2025-12-29 18:02:11] txikal=7 验证XMSE=4.595366
[2025-12-29 18:02:11] 超参 txikal=8:embed=32,heads=8,blocks=2,dxopozt=0.05,fsfsnMzlt=2
[2025-12-29 18:02:12] 元轮=1/3 任务=1/6 查询loss=9.034048 支持loss=21.292215
[2025-12-29 18:02:13] 元轮=1/3 任务=2/6 查询loss=2.942193 支持loss=7.177503
[2025-12-29 18:02:15] 元轮=1/3 任务=3/6 查询loss=1.109107 支持loss=3.551923
[2025-12-29 18:02:16] 元轮=1/3 任务=4/6 查询loss=1.633186 支持loss=1.655694
[2025-12-29 18:02:17] 元轮=1/3 任务=5/6 查询loss=1.051845 支持loss=1.454772
[2025-12-29 18:02:18] 元轮=1/3 任务=6/6 查询loss=1.150380 支持loss=1.138867
[2025-12-29 18:02:19] 元轮=1 完成:txaiknLoss=2.820126 valXMSE=4.113759
[2025-12-29 18:02:19] 更新最佳模型:metaEpoch=1 valXMSE=4.113759
[2025-12-29 18:02:20] 元轮=2/3 任务=1/6 查询loss=0.462342 支持loss=1.572671
[2025-12-29 18:02:21] 元轮=2/3 任务=2/6 查询loss=0.589241 支持loss=0.801997
[2025-12-29 18:02:21] 元轮=2/3 任务=3/6 查询loss=0.538841 支持loss=1.113212
[2025-12-29 18:02:23] 元轮=2/3 任务=4/6 查询loss=0.535355 支持loss=2.200658
[2025-12-29 18:02:24] 元轮=2/3 任务=5/6 查询loss=0.673299 支持loss=2.921712
[2025-12-29 18:02:25] 元轮=2/3 任务=6/6 查询loss=0.588739 支持loss=2.196538
[2025-12-29 18:02:26] 元轮=2 完成:txaiknLoss=0.564636 valXMSE=2.459184
[2025-12-29 18:02:26] 更新最佳模型:metaEpoch=2 valXMSE=2.459184
[2025-12-29 18:02:27] 元轮=3/3 任务=1/6 查询loss=0.574150 支持loss=2.156667
[2025-12-29 18:02:28] 元轮=3/3 任务=2/6 查询loss=0.538185 支持loss=1.706270
[2025-12-29 18:02:30] 元轮=3/3 任务=3/6 查询loss=0.492092 支持loss=0.855237
[2025-12-29 18:02:30] 元轮=3/3 任务=4/6 查询loss=0.553972 支持loss=0.780354
[2025-12-29 18:02:31] 元轮=3/3 任务=5/6 查询loss=0.544124 支持loss=0.747328
[2025-12-29 18:02:33] 元轮=3/3 任务=6/6 查询loss=0.472289 支持loss=1.157247
[2025-12-29 18:02:33] 元轮=3 完成:txaiknLoss=0.529136 valXMSE=2.290166
[2025-12-29 18:02:33] 更新最佳模型:metaEpoch=3 valXMSE=2.290166
[2025-12-29 18:02:34] txikal=8 验证XMSE=2.295256
[2025-12-29 18:02:34] 超参搜索完成:最佳 txikal=5,valXMSE=1.997188
[2025-12-29 18:02:34] 构建网络...
[2025-12-29 18:02:34] 网络构建完成
[2025-12-29 18:02:34] 开始 MAML 训练:metaEpoch=18,taskPexEpoch=24
[2025-12-29 18:02:39] 元轮=1/18 任务=4/24 查询loss=8.347898 支持loss=32.747948
[2025-12-29 18:02:44] 元轮=1/18 任务=8/24 查询loss=1.182401 支持loss=6.640838
[2025-12-29 18:02:49] 元轮=1/18 任务=12/24 查询loss=3.547104 支持loss=12.827287
[2025-12-29 18:02:55] 元轮=1/18 任务=16/24 查询loss=1.461069 支持loss=1.006521
[2025-12-29 18:02:59] 元轮=1/18 任务=20/24 查询loss=0.742727 支持loss=3.001778
[2025-12-29 18:03:06] 元轮=1/18 任务=24/24 查询loss=0.697628 支持loss=2.251880
[2025-12-29 18:03:06] 元轮=1 完成:txaiknLoss=2.075758 valXMSE=3.832469
[2025-12-29 18:03:06] 更新最佳模型:metaEpoch=1 valXMSE=3.832469
[2025-12-29 18:03:13] 元轮=2/18 任务=4/24 查询loss=0.732322 支持loss=1.468853
[2025-12-29 18:03:19] 元轮=2/18 任务=8/24 查询loss=0.653125 支持loss=1.559896
[2025-12-29 18:03:24] 元轮=2/18 任务=12/24 查询loss=0.538393 支持loss=1.380143
[2025-12-29 18:03:29] 元轮=2/18 任务=16/24 查询loss=0.736358 支持loss=0.741441
[2025-12-29 18:03:35] 元轮=2/18 任务=20/24 查询loss=0.692661 支持loss=2.092440
[2025-12-29 18:03:41] 元轮=2/18 任务=24/24 查询loss=0.712908 支持loss=0.662641
[2025-12-29 18:03:42] 元轮=2 完成:txaiknLoss=0.672904 valXMSE=3.933750
[2025-12-29 18:03:42] 未提升:耐心计数=1/6
[2025-12-29 18:03:48] 元轮=3/18 任务=4/24 查询loss=0.615928 支持loss=1.569771
[2025-12-29 18:03:53] 元轮=3/18 任务=8/24 查询loss=0.611857 支持loss=0.667549
[2025-12-29 18:03:59] 元轮=3/18 任务=12/24 查询loss=0.754087 支持loss=1.686547
[2025-12-29 18:04:06] 元轮=3/18 任务=16/24 查询loss=0.608355 支持loss=0.650514
[2025-12-29 18:04:12] 元轮=3/18 任务=20/24 查询loss=0.575724 支持loss=1.263267
[2025-12-29 18:04:19] 元轮=3/18 任务=24/24 查询loss=0.712633 支持loss=0.543956
[2025-12-29 18:04:20] 元轮=3 完成:txaiknLoss=0.604974 valXMSE=3.567201
[2025-12-29 18:04:20] 更新最佳模型:metaEpoch=3 valXMSE=3.567201
[2025-12-29 18:04:25] 元轮=4/18 任务=4/24 查询loss=0.778682 支持loss=1.324355
[2025-12-29 18:04:30] 元轮=4/18 任务=8/24 查询loss=0.594368 支持loss=0.513628
[2025-12-29 18:04:36] 元轮=4/18 任务=12/24 查询loss=3.908566 支持loss=1.244077
[2025-12-29 18:04:43] 元轮=4/18 任务=16/24 查询loss=0.524367 支持loss=8.023688
[2025-12-29 18:04:48] 元轮=4/18 任务=20/24 查询loss=1.070598 支持loss=10.501654
[2025-12-29 18:04:55] 元轮=4/18 任务=24/24 查询loss=0.634190 支持loss=4.674900
[2025-12-29 18:04:55] 元轮=4 完成:txaiknLoss=1.399432 valXMSE=4.802879
[2025-12-29 18:04:55] 未提升:耐心计数=1/6
[2025-12-29 18:05:01] 元轮=5/18 任务=4/24 查询loss=0.817576 支持loss=3.982169
[2025-12-29 18:05:06] 元轮=5/18 任务=8/24 查询loss=0.594076 支持loss=6.936875
[2025-12-29 18:05:11] 元轮=5/18 任务=12/24 查询loss=0.585597 支持loss=4.355089
[2025-12-29 18:05:17] 元轮=5/18 任务=16/24 查询loss=0.496287 支持loss=4.703283
[2025-12-29 18:05:23] 元轮=5/18 任务=20/24 查询loss=0.513436 支持loss=6.250763
[2025-12-29 18:05:29] 元轮=5/18 任务=24/24 查询loss=0.643488 支持loss=3.802575
[2025-12-29 18:05:30] 元轮=5 完成:txaiknLoss=0.624313 valXMSE=4.291340
[2025-12-29 18:05:30] 未提升:耐心计数=2/6
[2025-12-29 18:05:38] 元轮=6/18 任务=4/24 查询loss=0.508223 支持loss=5.055760
[2025-12-29 18:05:44] 元轮=6/18 任务=8/24 查询loss=0.553488 支持loss=4.893260
[2025-12-29 18:05:50] 元轮=6/18 任务=12/24 查询loss=0.505421 支持loss=3.866366
[2025-12-29 18:05:57] 元轮=6/18 任务=16/24 查询loss=0.535186 支持loss=4.836012
[2025-12-29 18:06:02] 元轮=6/18 任务=20/24 查询loss=0.510104 支持loss=4.525298
[2025-12-29 18:06:08] 元轮=6/18 任务=24/24 查询loss=0.488507 支持loss=4.154684
[2025-12-29 18:06:09] 元轮=6 完成:txaiknLoss=0.529528 valXMSE=4.291618
[2025-12-29 18:06:09] 未提升:耐心计数=3/6
[2025-12-29 18:06:15] 元轮=7/18 任务=4/24 查询loss=0.499657 支持loss=4.755409
[2025-12-29 18:06:22] 元轮=7/18 任务=8/24 查询loss=0.482794 支持loss=4.374314
[2025-12-29 18:06:28] 元轮=7/18 任务=12/24 查询loss=0.555604 支持loss=5.160314
[2025-12-29 18:06:35] 元轮=7/18 任务=16/24 查询loss=0.476302 支持loss=3.960786
[2025-12-29 18:06:40] 元轮=7/18 任务=20/24 查询loss=0.527963 支持loss=4.528885
[2025-12-29 18:06:46] 元轮=7/18 任务=24/24 查询loss=0.498498 支持loss=4.633445
[2025-12-29 18:06:47] 元轮=7 完成:txaiknLoss=0.495106 valXMSE=4.423611
[2025-12-29 18:06:47] 未提升:耐心计数=4/6
[2025-12-29 18:06:52] 元轮=8/18 任务=4/24 查询loss=0.445270 支持loss=4.427946
[2025-12-29 18:06:59] 元轮=8/18 任务=8/24 查询loss=0.508027 支持loss=4.710531
[2025-12-29 18:07:06] 元轮=8/18 任务=12/24 查询loss=0.476682 支持loss=4.416629
[2025-12-29 18:07:13] 元轮=8/18 任务=16/24 查询loss=0.455895 支持loss=4.285707
[2025-12-29 18:07:18] 元轮=8/18 任务=20/24 查询loss=0.378078 支持loss=4.120034
[2025-12-29 18:07:23] 元轮=8/18 任务=24/24 查询loss=0.463800 支持loss=4.647798
[2025-12-29 18:07:24] 元轮=8 完成:txaiknLoss=0.473384 valXMSE=4.221952
[2025-12-29 18:07:24] 未提升:耐心计数=5/6
[2025-12-29 18:07:30] 元轮=9/18 任务=4/24 查询loss=0.496500 支持loss=3.997692
[2025-12-29 18:07:35] 元轮=9/18 任务=8/24 查询loss=0.521079 支持loss=4.637869
[2025-12-29 18:07:40] 元轮=9/18 任务=12/24 查询loss=0.457342 支持loss=4.558998
[2025-12-29 18:07:46] 元轮=9/18 任务=16/24 查询loss=0.502280 支持loss=4.532571
[2025-12-29 18:07:52] 元轮=9/18 任务=20/24 查询loss=0.470072 支持loss=3.842014
[2025-12-29 18:07:58] 元轮=9/18 任务=24/24 查询loss=0.485037 支持loss=4.668193
[2025-12-29 18:07:59] 元轮=9 完成:txaiknLoss=0.472101 valXMSE=4.072986
[2025-12-29 18:07:59] 未提升:耐心计数=6/6
[2025-12-29 18:07:59] 早停触发:结束训练
[2025-12-29 18:07:59] 保存最佳模型...
[2025-12-29 18:07:59] 最佳模型已保存:best_model.mat
[2025-12-29 18:07:59] 测试集预测...
[2025-12-29 18:08:00] 测试集预测完成
[2025-12-29 18:08:00] 开始绘制评估图形...
[2025-12-29 18:08:00] 评估指标:XMSE=3.560990 MAE=3.491262 MAPE=6311.155% SMAPE=171.928% X2=-35.56265 相关系数=-0.00569
[2025-12-29 18:08:04] 评估图形绘制完成(共8幅,可从标签页单独 Zndock)
[2025-12-29 18:08:04] 全部流程结束
>>
结束
更多详细内容请访问
http://机器学习有图有真相MATLAB实现基于MAML-Transformer模型无关元学习方法(MAML)结合Transformer编码器进行多变量时间序列预测(代码已调试成功,可一键运行,每资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92516570
http://机器学习有图有真相MATLAB实现基于MAML-Transformer模型无关元学习方法(MAML)结合Transformer编码器进行多变量时间序列预测(代码已调试成功,可一键运行,每资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92516570
更多推荐


所有评论(0)