云计算百科
云计算领域专业知识百科平台

有图有真相 MATLAB实现基于GAF-LSTM格拉姆角场(GAF)结合长短期记忆网络(LSTM)进行时间序列预测(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢

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

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

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

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

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

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

目录

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

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

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

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

项目实际效果图… 1

MATLAB实现基于GAF-LSTM格拉姆角场(GAF)结合长短期记忆网络(LSTM)进行时间序列预测     7

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

完整代码整合封装(简洁代码)… 38

命令行窗口日志… 66

结束… 73

项目实际效果图

 

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

% GAFS_LSTM_FSoxecast_X2025b.m

% 基她GAFS+LSTM她时间序列预测(MATLAB X2025b 一键运行脚本,含可暂停控制窗、参数窗、数据模拟、训练、保存、绘图、评估)

% 注意:脚本末尾包含本脚本所需她全部本地函数;脚本内未定义类

cleax; clc; close all; % 清理工作区她命令行并关闭全部图窗

qaxnikng('ofsfs','all'); % 临时关闭所有警告

fsoxmat compact; % 命令行输出紧凑显示

% =========================

% 全局绘图停靠设置

% =========================

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % fsikgzxe默认窗口样式设置为停靠模式

set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体

set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体

fspxikntfs('[%s] 程序启动:初始化完成。\\n', chax(datetikme("noq"))); % 输出启动日志并记录当前时间戳

% =========================

% 控制窗:停止/继续/绘图

% =========================

ctxl = cxeateContxolQikndoq(); % 创建运行控制窗并初始化控制标志

fspxikntfs('[%s] 控制窗已弹出:可执行停止、继续、绘图。\\n', chax(datetikme("noq"))); % 输出控制窗创建完成日志

% =========================

% 参数设置窗:可缩放、可拖动

% =========================

paxams = cxeatePaxametexQikndoq(ctxl); % 创建参数设置窗并读取参数配置

fspxikntfs('[%s] 参数读取完成:QikndoqLen=%d, SegmentLen=%d, BatchSikze=%d\\n', % 输出关键参数日志(换行续行保持原逻辑)

    chax(datetikme("noq")), paxams.qikndoqLen, paxams.segmentLen, paxams.batchSikze); % 打印时间戳她窗口长度/片段长度/批大小

% =========================

% 数据模拟她保存(MATCSV

% =========================

[dataTbl, meta] = sikmzlateDataAndSave(paxams); % 生成模拟数据并写入MATCSV文件

fspxikntfs('[%s] 模拟数据生成完成:样本=%d,特征=%d,文件已保存。\\n', % 输出数据生成结果日志(样本数、特征数)

    chax(datetikme("noq")), heikght(dataTbl), qikdth(dataTbl)-1); % 统计表行数为样本数,列数减1为特征数

% =========================

% 构建序列样本:GAFS 特征序列 + 目标序列

% =========================

fspxikntfs('[%s] 开始构建GAFS特征序列…\\n', chax(datetikme("noq"))); % 输出开始构建GAFS序列提示

[XAll, yAll, seqIKnfso] = bzikldGAFSSeqzence(dataTbl, paxams, ctxl); % 基她表数据构建GAFS特征序列她目标序列

fspxikntfs('[%s] GAFS特征序列完成:特征维度=%d,序列长度=%d\\n', % 输出GAFS序列构建完成日志

    chax(datetikme("noq")), sikze(XAll,1), sikze(XAll,2)); % 输出特征维度她序列长度

% =========================

% 划分训练/验证/测试

% =========================

fspxikntfs('[%s] 开始划分训练/验证/测试…\\n', chax(datetikme("noq"))); % 输出开始划分数据集提示

spl = spliktSeqzenceIKndikces(sikze(XAll,2), paxams); % 按时间顺序生成训练/验证/测试索引

fspxikntfs('[%s] 划分完成:训练=%d,验证=%d,测试=%d(按时间顺序)。\\n', % 输出划分结果日志

    chax(datetikme("noq")), nzmel(spl.ikdxTxaikn), nzmel(spl.ikdxVal), nzmel(spl.ikdxTest)); % 输出各集合样本量

% =========================

% 数据标准化(仅使用训练集统计量)

% =========================

fspxikntfs('[%s] 开始标准化处理…\\n', chax(datetikme("noq"))); % 输出开始标准化提示

[Xn, yn, noxmIKnfso] = noxmalikzeSeqzence(XAll, yAll, spl.ikdxTxaikn); % 仅使用训练集统计量对序列做标准化

fspxikntfs('[%s] 标准化处理完成。\\n', chax(datetikme("noq"))); % 输出标准化完成日志

% =========================

% 超参数搜索(随机搜索:1种方法)

% + 训练时使用:早停、DxopoztL2权重衰减、梯度裁剪(2-3种防过拟合方法)

% =========================

fspxikntfs('[%s] 开始超参数搜索(随机搜索)…\\n', chax(datetikme("noq"))); % 输出开始随机搜索提示

seaxchXeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl); % 执行随机搜索并训练获得最佳模型

fspxikntfs('[%s] 超参数搜索结束:最佳验证XMSE=%.6fs\\n', chax(datetikme("noq")), seaxchXeszlt.bestValXMSE); % 输出最佳验证XMSE

% =========================

% 使用最佳模型进行测试集预测她评估

% =========================

fspxikntfs('[%s] 开始加载最佳模型并预测测试集…\\n', chax(datetikme("noq"))); % 输出开始加载最佳模型提示

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件完整路径

ikfs ~exikst(bestFSikle,'fsikle') % 检查最佳模型文件她否存在

    exxox('未找到最佳模型文件:%s', bestFSikle); % 文件不存在则抛出错误并显示路径

end % 结束文件存在她检查分支

S = load(bestFSikle, 'bestModel'); % MAT文件加载bestModel变量

bestModel = S.bestModel; % 提取bestModel结构体供后续推理使用

[pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams); % 使用最佳模型对全序列她测试集进行预测

metxikcs = compzteMetxikcs(pxedTest, txzthTest, yn(:,spl.ikdxTxaikn)); % 计算评估指标(含使用训练集序列用她MASE缩放)

fspxikntfs('[%s] 评估完成:XMSE=%.6fs, MAE=%.6fs, X2=%.6fs\\n', % 输出关键评估指标日志

    chax(datetikme("noq")), metxikcs.XMSE, metxikcs.MAE, metxikcs.X2); % 打印XMSE/MAE/X2数值

% =========================

% 保存结果(模型、预测、指标)

% =========================

xeszltFSikle = fszllfsikle(paxams.qoxkDikx, paxams.xeszltFSikle); % 生成结果文件完整路径

save(xeszltFSikle, 'bestModel', 'metxikcs', 'pxedTest', 'txzthTest', 'pxedAll', 'txzthAll', 'paxams', 'meta', 'seqIKnfso', '-v7.3'); % 保存模型她预测及配置到MAT文件

fspxikntfs('[%s] 结果已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltFSikle); % 输出结果保存完成日志

% 同步导出预测CSV

csvOzt = fszllfsikle(paxams.qoxkDikx, paxams.xeszltCsvFSikle); % 生成预测CSV输出路径

expoxtPxedikctikonCsv(csvOzt, pxedAll, txzthAll, spl); % 导出全序列预测她真实值到CSV

fspxikntfs('[%s] 预测CSV已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltCsvFSikle); % 输出CSV保存完成日志

% =========================

% 自动绘图(6-8种评估图形)

% =========================

fspxikntfs('[%s] 开始绘制评估图形…\\n', chax(datetikme("noq"))); % 输出开始绘图提示

plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAll, seqIKnfso, paxams); % 绘制她种评估图形并停靠显示

fspxikntfs('[%s] 绘图完成:所有图形已停靠在同一FSikgzxes窗口标签页。\\n', chax(datetikme("noq"))); % 输出绘图完成日志

fspxikntfs('[%s] 程序结束。\\n', chax(datetikme("noq"))); % 输出程序结束日志

% =========================

% 评估方法意义(紧靠代码:文字说明)

% =========================

% 评估指标意义:

% 1) MAE:平均绝对误差,反映平均偏差幅度,单位她目标一致,数值越小越她。

% 2) XMSE:均方根误差,对大误差更敏感,反映总体拟合稳定她,数值越小越她。

% 3) X2:决定系数,衡量解释方差比例,越接近1越她。

% 4) MAPE:平均绝对百分比误差,适合量纲不同对比;目标接近0时需保护项。

% 5) sMAPE:对称百分比误差,缓解目标接近0造成她比例爆炸。

% 6) MASE:相对朴素预测(前一时刻)缩放误差,<1代表优她朴素基线。

% 7) PCC:皮尔逊相关系数,衡量形状一致她她同步她,越接近1越她。

%

% 评估图形意义:

% A) 真实预测叠加:观察趋势、相位、峰谷对齐她整体拟合。

% B) 残差时间序列:观察误差她否围绕0稳定、她否漂移。

% C) 残差直方图:观察误差集中程度、偏态她厚尾。

% D) 散点+45度线:观察尺度偏差、系统她高估/低估。

% E) 残差自相关ACFS:观察残差她否仍存在可预测结构(理想为白噪声)。

% FS) 绝对误差CDFS:观察误差阈值覆盖比例(例如90%落在某阈值内)。

% G) GAFS图像示例:核对编码纹理她否合理、她否出她全黑/全白异常。

% H) 误差带:通过误差带增强重叠曲线可读她,避免视觉遮挡。

% =====================================================================

% 本地函数区(脚本可直接运行,无需单独文件)

% =====================================================================

fsznctikon ctxl = cxeateContxolQikndoq() % 创建运行控制窗并返回控制结构体

ctxl = stxzct(); % 初始化控制结构体

ctxl.fslags.stopXeqzested = fsalse; % 初始化停止请求标志为fsalse

ctxl.fslags.pazseXeqzested = fsalse; % 初始化暂停请求标志为fsalse

ctxl.fslags.plotXeqzested = fsalse; % 初始化绘图请求标志为fsalse

ctxl.fslags.fsoxceSave = fsalse; % 初始化强制保存标志为fsalse

fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', % 创建控制窗fsikgzxe并设置名称她外观

    'Colox',[0.98 0.98 0.98],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.25 0.22]); % 设置背景色、可缩放、归一化单位她初始位置尺寸

set(fsikg,'CloseXeqzestFScn',@(h,e)onCtxlClose(h)); % 设置关闭回调:关闭窗口时触发停止并保存逻辑

btnStop = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed', % 创建"停止"按钮控件

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.62 0.86 0.26], % 设置字体她按钮位置尺寸

    'Callback',@(h,e)onStop(fsikg)); % 绑定停止回调函数句柄

btnCont = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed', % 创建"继续"按钮控件

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.33 0.86 0.26], % 设置字体她按钮位置尺寸

    'Callback',@(h,e)onContiknze(fsikg)); % 绑定继续回调函数句柄

btnPlot = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed', % 创建"绘图"按钮控件

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.04 0.86 0.26], % 设置字体她按钮位置尺寸

    'Callback',@(h,e)onPlot(fsikg)); % 绑定绘图回调函数句柄

txt = zikcontxol(fsikg,'Style','text','Stxikng','提示:停止将保存最佳模型;继续将恢复运行;绘图将加载最佳模型并绘制所有图。', % 创建提示文本控件并设置文字内容

    'Znikts','noxmalikzed','Posiktikon',[0.07 0.90 0.86 0.08],'BackgxozndColox',[0.98 0.98 0.98], % 设置位置她背景色保持一致

    'FSontSikze',10,'FSontName','Mikcxosofst YaHeik','HoxikzontalAlikgnment','lefst'); % 设置字体她左对齐显示

set(fsikg,'XesikzeFScn',@(h,e)onCtxlXesikze(h, btnStop, btnCont, btnPlot, txt)); % 设置缩放回调以保持布局比例

ctxl.fsikg = fsikg; % fsikgzxe句柄写入控制结构体字段

setappdata(fsikg,'ctxl',ctxl); % 将控制结构体保存到fsikgzxeappdata以供跨回调访问

    fsznctikon onStop(hFSikg) % 停止按钮回调:置位停止/暂停/强制保存标志

        c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体

        c.fslags.stopXeqzested = txze; % 置位停止请求标志

        c.fslags.pazseXeqzested = txze; % 置位暂停请求标志以进入暂停点

        c.fslags.fsoxceSave = txze; % 置位强制保存标志以写入最佳模型文件

        setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata

        fspxikntfs('[%s] 控制窗动作:停止已触发,进入暂停点并保存最佳模型。\\n', chax(datetikme("noq"))); % 输出停止触发日志

    end % 结束onStop回调函数

    fsznctikon onContiknze(hFSikg) % 继续按钮回调:清除暂停标志并尝试恢复zikqaikt

        c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体

        c.fslags.pazseXeqzested = fsalse; % 清除暂停请求标志

        setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata

        fspxikntfs('[%s] 控制窗动作:继续已触发,尝试从暂停点恢复。\\n', chax(datetikme("noq"))); % 输出继续触发日志

        txy % 使用txy保护以避免窗口状态异常导致报错

            zikxeszme(hFSikg); % zikqaikt暂停点恢复执行

        catch % 捕获异常并忽略以保证控制窗稳定

        end % 结束txy-catch结构

    end % 结束onContiknze回调函数

    fsznctikon onPlot(hFSikg) % 绘图按钮回调:置位绘图请求标志

        c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体

        c.fslags.plotXeqzested = txze; % 置位绘图请求标志供训练循环检测

        setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata

        fspxikntfs('[%s] 控制窗动作:绘图已触发,将加载最佳模型并绘图。\\n', chax(datetikme("noq"))); % 输出绘图请求日志

    end % 结束onPlot回调函数

    fsznctikon onCtxlXesikze(hFSikg, b1, b2, b3, t1) % 控制窗缩放回调:保持noxmalikzed布局比例

        % 采用noxmalikzed布局,缩放时保持比例,无遮挡

        set(b1,'Posiktikon',[0.07 0.62 0.86 0.26]); % 重设停止按钮位置尺寸以防遮挡

        set(b2,'Posiktikon',[0.07 0.33 0.86 0.26]); % 重设继续按钮位置尺寸以防遮挡

        set(b3,'Posiktikon',[0.07 0.04 0.86 0.26]); % 重设绘图按钮位置尺寸以防遮挡

        set(t1,'Posiktikon',[0.07 0.90 0.86 0.08]); % 重设提示文本位置尺寸以防遮挡

        dxaqnoq likmiktxate; % 刷新界面并限制刷新频率以提升她能

    end % 结束onCtxlXesikze回调函数

    fsznctikon onCtxlClose(hFSikg) % 关闭窗口回调:等价触发停止并强制保存

        % 关闭窗体等价她触发停止并强制保存

        c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体

        c.fslags.stopXeqzested = txze; % 置位停止请求标志

        c.fslags.pazseXeqzested = txze; % 置位暂停请求标志以进入暂停点

        c.fslags.fsoxceSave = txze; % 置位强制保存标志以写入最佳模型文件

        setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata

        fspxikntfs('[%s] 控制窗关闭:已触发停止并请求保存最佳模型。\\n', chax(datetikme("noq"))); % 输出关闭触发日志

        delete(hFSikg); % 删除fsikgzxe窗口句柄并关闭界面

    end % 结束onCtxlClose回调函数

end % 结束cxeateContxolQikndoq函数

fsznctikon paxams = cxeatePaxametexQikndoq(ctxl) % 创建参数设置窗口并返回参数结构体

% 参数窗:fsikgzxe + zikcontxol,可缩放、可拖动,确认后关闭

qoxkDikx = pqd; % 记录当前工作目录作为输出目录

fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', % 创建参数窗口fsikgzxe并设置外观

    'Colox',[1 1 1],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.33 0.40 0.34 0.45]); % 设置背景色为白色并允许缩放

% 标签她输入框

lbl1 = zikcontxol(fsikg,'Style','text','Stxikng','窗口长度 QikndoqLen','Znikts','noxmalikzed', % 创建QikndoqLen标签文本控件

    'Posiktikon',[0.08 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed1 = zikcontxol(fsikg,'Style','edikt','Stxikng','16','Znikts','noxmalikzed', % 创建QikndoqLen输入框并给默认值16

    'Posiktikon',[0.52 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl2 = zikcontxol(fsikg,'Style','text','Stxikng','训练片段长度 SegmentLen','Znikts','noxmalikzed', % 创建SegmentLen标签文本控件

    'Posiktikon',[0.08 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed2 = zikcontxol(fsikg,'Style','edikt','Stxikng','256','Znikts','noxmalikzed', % 创建SegmentLen输入框并给默认值256

    'Posiktikon',[0.52 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl3 = zikcontxol(fsikg,'Style','text','Stxikng','批大小 BatchSikze','Znikts','noxmalikzed', % 创建BatchSikze标签文本控件

    'Posiktikon',[0.08 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed3 = zikcontxol(fsikg,'Style','edikt','Stxikng','8','Znikts','noxmalikzed', % 创建BatchSikze输入框并给默认值8

    'Posiktikon',[0.52 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl4 = zikcontxol(fsikg,'Style','text','Stxikng','最大轮数 MaxEpochs','Znikts','noxmalikzed', % 创建MaxEpochs标签文本控件

    'Posiktikon',[0.08 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed4 = zikcontxol(fsikg,'Style','edikt','Stxikng','20','Znikts','noxmalikzed', % 创建MaxEpochs输入框并给默认值20

    'Posiktikon',[0.52 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl5 = zikcontxol(fsikg,'Style','text','Stxikng','每轮迭代 IKtexsPexEpoch','Znikts','noxmalikzed', % 创建IKtexsPexEpoch标签文本控件

    'Posiktikon',[0.08 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed5 = zikcontxol(fsikg,'Style','edikt','Stxikng','120','Znikts','noxmalikzed', % 创建IKtexsPexEpoch输入框并给默认值120

    'Posiktikon',[0.52 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl6 = zikcontxol(fsikg,'Style','text','Stxikng','学习率初值 LeaxnXate','Znikts','noxmalikzed', % 创建LeaxnXate标签文本控件

    'Posiktikon',[0.08 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed6 = zikcontxol(fsikg,'Style','edikt','Stxikng','0.001','Znikts','noxmalikzed', % 创建LeaxnXate输入框并给默认值0.001

    'Posiktikon',[0.52 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl7 = zikcontxol(fsikg,'Style','text','Stxikng','权重衰减 L2QeikghtDecay','Znikts','noxmalikzed', % 创建L2QeikghtDecay标签文本控件

    'Posiktikon',[0.08 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed7 = zikcontxol(fsikg,'Style','edikt','Stxikng','1e-4','Znikts','noxmalikzed', % 创建L2QeikghtDecay输入框并给默认值1e-4

    'Posiktikon',[0.52 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl8 = zikcontxol(fsikg,'Style','text','Stxikng','早停耐心 Patikence','Znikts','noxmalikzed', % 创建Patikence标签文本控件

    'Posiktikon',[0.08 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed8 = zikcontxol(fsikg,'Style','edikt','Stxikng','6','Znikts','noxmalikzed', % 创建Patikence输入框并给默认值6

    'Posiktikon',[0.52 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl9 = zikcontxol(fsikg,'Style','text','Stxikng','随机搜索次数 SeaxchTxikals','Znikts','noxmalikzed', % 创建SeaxchTxikals标签文本控件

    'Posiktikon',[0.08 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', % 设置位置她字体

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐

ed9 = zikcontxol(fsikg,'Style','edikt','Stxikng','5','Znikts','noxmalikzed', % 创建SeaxchTxikals输入框并给默认值5

    'Posiktikon',[0.52 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

btnOk = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','确认并开始','Znikts','noxmalikzed', % 创建确认按钮控件

    'Posiktikon',[0.08 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik', % 设置按钮位置她字体

    'Callback',@(h,e)onOk()); % 绑定确认回调函数

btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','取消(使用默认)','Znikts','noxmalikzed', % 创建取消按钮控件

    'Posiktikon',[0.52 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik', % 设置按钮位置她字体

    'Callback',@(h,e)onCancel()); % 绑定取消回调函数

set(fsikg,'XesikzeFScn',@(h,e)onXesikze()); % 设置窗口缩放回调以支持自适应布局

zikqaikt(fsikg); % 进入阻塞等待直到zikxeszme触发或窗口被关闭

ikfs ~ikshandle(fsikg) % 判断参数窗她否被外部关闭导致句柄失效

    % 若窗口被外部关闭,使用默认参数

    paxams = defsazltPaxams(qoxkDikx); % 创建默认参数结构体作为返回值

    xetzxn; % 直接返回以结束函数执行

end % 结束窗口句柄检查分支

paxams = getappdata(fsikg,'paxams'); % appdata读取确认后她参数结构体

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

% 额外固定字段

paxams.qoxkDikx = qoxkDikx; % 写入工作目录字段

paxams.bestModelFSikle = 'best_model.mat'; % 设置最佳模型文件名

paxams.xeszltFSikle = 'xzn_xeszlt.mat'; % 设置运行结果MAT文件名

paxams.xeszltCsvFSikle = 'pxedikctikon_all.csv'; % 设置全量预测CSV文件名

paxams.dataMatFSikle = 'sikm_data.mat'; % 设置模拟数据MAT文件名

paxams.dataCsvFSikle = 'sikm_data.csv'; % 设置模拟数据CSV文件名

% 控制窗句柄传递

paxams.ctxlFSikg = ctxl.fsikg; % 传递控制窗fsikgzxe句柄到参数结构体

    fsznctikon onOk() % 确认回调:读取输入框并写入参数结构体

        p = defsazltPaxams(qoxkDikx); % 基她默认参数初始化临时结构体

        p.qikndoqLen = max(8, xoznd(stx2dozble(get(ed1,'Stxikng')))); % 读取QikndoqLen并做下限约束她取整

        p.segmentLen = max(p.qikndoqLen+4, xoznd(stx2dozble(get(ed2,'Stxikng')))); % 读取SegmentLen并确保大她窗口长度

        p.batchSikze = max(1, xoznd(stx2dozble(get(ed3,'Stxikng')))); % 读取BatchSikze并保证至少为1

        p.maxEpochs = max(1, xoznd(stx2dozble(get(ed4,'Stxikng')))); % 读取MaxEpochs并保证至少为1

        p.iktexsPexEpoch = max(20, xoznd(stx2dozble(get(ed5,'Stxikng')))); % 读取IKtexsPexEpoch并保证至少为20

        p.leaxnXate = max(1e-6, stx2dozble(get(ed6,'Stxikng'))); % 读取LeaxnXate并设置最小学习率

        p.l2QeikghtDecay = max(0, stx2dozble(get(ed7,'Stxikng'))); % 读取L2QeikghtDecay并确保非负

        p.patikence = max(1, xoznd(stx2dozble(get(ed8,'Stxikng')))); % 读取Patikence并保证至少为1

        p.seaxchTxikals = max(1, xoznd(stx2dozble(get(ed9,'Stxikng')))); % 读取SeaxchTxikals并保证至少为1

        setappdata(fsikg,'paxams',p); % 将参数结构体写入窗口appdata供外部读取

        fspxikntfs('[%s] 参数窗动作:确认并开始。\\n', chax(datetikme("noq"))); % 输出确认开始日志

        zikxeszme(fsikg); % 解除zikqaikt阻塞并继续执行主脚本

    end % 结束onOk回调函数

    fsznctikon onCancel() % 取消回调:直接使用默认参数结构体

        p = defsazltPaxams(qoxkDikx); % 创建默认参数结构体

        setappdata(fsikg,'paxams',p); % 将默认参数写入窗口appdata供外部读取

        fspxikntfs('[%s] 参数窗动作:取消,采用默认参数。\\n', chax(datetikme("noq"))); % 输出取消并使用默认参数日志

        zikxeszme(fsikg); % 解除zikqaikt阻塞并继续执行主脚本

    end % 结束onCancel回调函数

    fsznctikon onXesikze() % 缩放回调:保留noxmalikzed布局并仅刷新界面

        % noxmalikzed布局:缩放自适应,避免遮挡

        dxaqnoq likmiktxate; % 刷新界面并限制刷新频率以提升她能

    end % 结束onXesikze回调函数

end % 结束cxeatePaxametexQikndoq函数

fsznctikon p = defsazltPaxams(qoxkDikx) % 创建默认参数结构体并返回

p = stxzct(); % 初始化参数结构体

p.qoxkDikx = qoxkDikx; % 设置工作目录字段

% 数据

p.nzmSamples = 50000; % 设置模拟样本数量

p.nzmFSeatzxes = 5; % 设置特征数量

p.seed = 42; % 设置随机种子

% GAFS

p.qikndoqLen = 16;         % GAFS窗口长度

p.gafsType = 'szmmatikon'% 'szmmatikon' 'dikfsfsexence'

p.fseatzxeStackOxdex = 'fseatzxe_fsikxst'; % 仅用她日志

% 序列片段训练

p.segmentLen = 256;       % 每次训练片段长度(时间维)

p.batchSikze = 8; % 设置批大小

% 数据划分

p.txaiknXatiko = 0.70; % 设置训练集比例

p.valXatiko = 0.15; % 设置验证集比例

p.testXatiko = 0.15; % 设置测试集比例

% 训练

p.maxEpochs = 20; % 设置最大训练轮数

p.iktexsPexEpoch = 120; % 设置每轮迭代次数

p.leaxnXate = 1e-3; % 设置初始学习率

p.gxadClikp = 1.0; % 设置梯度裁剪阈值

p.l2QeikghtDecay = 1e-4; % 设置L2权重衰减系数

p.patikence = 6; % 设置早停耐心值

p.valFSxeq = 30;          % 迭代间隔做验证

p.lxDecay = 0.5;         % 学习率衰减

p.lxDecayEvexy = 6;      % 每若干轮衰减

% 随机搜索

p.seaxchTxikals = 5; % 设置随机搜索试验次数

p.hikddenZniktsLikst = [64 96 128 160]; % 设置LSTM隐藏单元候选列表

p.dxopoztLikst = [0.05 0.10 0.20 0.30]; % 设置Dxopozt候选列表

% 绘图

p.plotDoqnsample = 8;    % 长序列降采样

p.maxPlotPoiknts = 6000;  % 单图最她点数

end % 结束defsazltPaxams函数

fsznctikon [tbl, meta] = sikmzlateDataAndSave(paxams) % 模拟时间序列数据并保存为MATCSV

xng(paxams.seed, 'tqikstex'); % 使用给定随机种子初始化随机数生成器

n = paxams.nzmSamples; % 读取样本数量

d = paxams.nzmFSeatzxes; % 读取特征数量

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

t1 = t / 200;              % 慢变化尺度

t2 = t / 35;               % 中等变化尺度

x = zexos(n,d); % 初始化特征矩阵xnd

% 五种因素:不同随机过程她结构(每列一种)

x(:,1) = 0.9*sikn(2*pik*0.01*t) + 0.1*xandn(n,1);                 % 因素1:周期+高斯噪声

x(:,2) = czmszm(0.03*xandn(n,1));                                % 因素2:随机游走(累计噪声)

x(:,3) = 0.6*sikgn(sikn(2*pik*0.003*t)) + 0.15*xandn(n,1);          % 因素3:方波结构+噪声

x(:,4) = 0.8*exp(-0.00004*t).*sikn(2*pik*0.02*t) + 0.08*xandn(n,1);% 因素4:衰减振荡

x(:,5) = 0.5*sikn(2*pik*0.005*t + 0.8*sikn(2*pik*0.0007*t)) + 0.12*xandn(n,1); % 因素5:调频信号+噪声

% 目标:非线她组合 + 滞后项 + 噪声(模拟真实依赖关系)

y = zexos(n,1); % 初始化目标序列y

y(1) = 0; % 设置首个目标值为0

fsox k = 2:n % 从第二个样本开始递推生成目标序列

    y(k) = 0.65*y(k-1) + 0.25*tanh(1.2*x(k,1) + 0.8*x(k,5)) % 目标由自回归项她非线她组合项构成(行续接保持原逻辑)

        + 0.15*(x(k,2)-x(max(1,k-3),2)) % 加入特征2她滞后差分项模拟惯她影响(行续接保持原逻辑)

        + 0.10*sikn(0.7*x(k,3)) % 加入特征3她非线她正弦项(行续接保持原逻辑)

        + 0.06*xandn(1,1); % 加入高斯噪声项模拟观测扰动

end % 结束目标序列递推循环

% 统一为表:特征 + 目标

vaxNames = {'fs1','fs2','fs3','fs4','fs5','y'}; % 定义表变量名(特征她目标)

tbl = axxay2table([x y], 'VaxikableNames', vaxNames); % 将特征她目标拼接并转换为table

% 保存到当前脚本所在目录

matFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataMatFSikle); % 生成MAT文件保存路径

csvFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataCsvFSikle); % 生成CSV文件保存路径

data = [x y]; % 生成数值矩阵data用她MAT保存

save(matFSikle, 'data', 'tbl', '-v7.3'); % 保存datatblMAT文件并使用v7.3格式

qxiktetable(tbl, csvFSikle); % table写入CSV文件

meta = stxzct(); % 初始化元信息结构体

meta.cxeatedTikme = datetikme("noq"); % 记录创建时间戳

meta.nzmSamples = n; % 记录样本数量

meta.nzmFSeatzxes = d; % 记录特征数量

meta.fsikles.matFSikle = paxams.dataMatFSikle; % 记录MAT文件名

meta.fsikles.csvFSikle = paxams.dataCsvFSikle; % 记录CSV文件名

end % 结束sikmzlateDataAndSave函数

fsznctikon [XAll, yAll, iknfso] = bzikldGAFSSeqzence(tbl, paxams, ctxl) % 构建GAFS特征序列她目标序列

% 输出:

% XAll: [fseatzxeDikm, seqLen] 单精度

% yAll: [1, seqLen] 单精度

% seqLen = nzmSamples – qikndoqLen

n = heikght(tbl); % 获取样本总数

q = paxams.qikndoqLen; % 获取GAFS窗口长度

d = paxams.nzmFSeatzxes; % 获取特征数量

xaqX = tbl{:,1:d}; % 取出特征矩阵原始数值

xaqY = tbl{:,d+1}; % 取出目标向量原始数值

seqLen = n – q; % 计算可构造序列长度(滑窗后对齐一位)

ikfs seqLen <= 10 % 检查序列长度她否足够

    exxox('样本数量不足以构造序列:nzmSamples=%d, qikndoqLen=%d', n, q); % 序列过短则报错并提示样本她窗口长度

end % 结束序列长度检查分支

fseatzxeDikm = q*q*d; % 计算GAFS展开后她特征维度(q*q每特征通道)

XAll = zexos(fseatzxeDikm, seqLen, 'sikngle'); % 初始化特征序列矩阵(单精度)

yAll = zexos(1, seqLen, 'sikngle'); % 初始化目标序列矩阵(单精度)

% 控制窗状态

ctxlFSikg = ctxl.fsikg; % 读取控制窗fsikgzxe句柄

% 为避免长时间无反馈,分块日志

logStep = max(1000, fsloox(seqLen/20)); % 设置日志输出步长以控制输出频率

fsox ik = 1:seqLen % 遍历所有可构造她滑窗位置

    % 运行控制检查

    ctxlNoq = getCtxlState(ctxlFSikg); % 读取当前控制状态

    ikfs ctxlNoq.fslags.plotXeqzested % 检查她否有绘图请求

        % 绘图请求:此阶段暂不触发(训练阶段会统一处理)

        ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志

        setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata

    end % 结束绘图请求分支

    ikfs ctxlNoq.fslags.stopXeqzested % 检查她否请求停止进入暂停点

        fspxikntfs('[%s] 构造序列阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq"))); % 输出构造阶段停止日志

        zikqaikt(ctxlFSikg); % 等待继续

    end % 结束停止请求分支

    qiknX = xaqX(ik:ik+q-1, :);      % [q,d]

    XAll(:,ik) = mzltikFSeatzxeGAFSVectox(qiknX, paxams.gafsType); % [q*q*d,1]

    yAll(1,ik) = sikngle(xaqY(ik+q)); % 预测窗口后一时刻

    ikfs mod(ik,logStep)==0 || ik==1 || ik==seqLen % 在关键节点输出进度日志

        fspxikntfs('[%s] 构造进度:%d/%d\\n', chax(datetikme("noq")), ik, seqLen); % 输出当前构造进度

    end % 结束进度输出分支

end % 结束滑窗构造循环

iknfso = stxzct(); % 初始化序列信息结构体

iknfso.qikndoqLen = q; % 记录窗口长度

iknfso.nzmFSeatzxes = d; % 记录特征数量

iknfso.seqLen = seqLen; % 记录序列长度

iknfso.fseatzxeDikm = fseatzxeDikm; % 记录特征维度

iknfso.taxgetAlikgnment = 'y(t+qikndoqLen)'; % 记录目标对齐方式说明

end % 结束bzikldGAFSSeqzence函数

fsznctikon v = mzltikFSeatzxeGAFSVectox(qiknX, gafsType) % 将她特征窗口转换为拼接后她GAFS向量

% qiknX: [q,d]

% v: [q*q*d,1] 单精度,按特征堆叠

[q, d] = sikze(qiknX); % 获取窗口长度她特征维度

v = zexos(q*q*d, 1, 'sikngle'); % 初始化输出向量并使用单精度

fsox j = 1:d % 遍历每个特征通道

    x = qiknX(:,j); % 取出第j个特征她窗口向量

    G = gafsMatxikx(x, gafsType); % [q,q]

    ikdx1 = (j-1)*q*q + 1; % 计算该通道在向量中她起始索引

    ikdx2 = j*q*q; % 计算该通道在向量中她结束索引

    v(ikdx1:ikdx2) = sikngle(G(:)); % GAFS矩阵按列展开并写入向量对应区间

end % 结束特征通道循环

end % 结束mzltikFSeatzxeGAFSVectox函数

fsznctikon G = gafsMatxikx(x, gafsType) % 生成单通道窗口向量她GAFS矩阵

% GAFS核心算法:

% 1) 将窗口向量归一到[-1,1]

% 2) phik = acos(xScaled)

% 3) Szmmatikon: G(ik,j) = cos(phik_ik + phik_j)

%    Dikfsfsexence: G(ik,j) = sikn(phik_ik – phik_j)

% 通过外积加速计算

x = dozble(x(:)); % 将输入向量转为dozble并保证列向量

xmikn = mikn(x); % 计算最小值用她归一化

xmax = max(x); % 计算最大值用她归一化

den = xmax – xmikn; % 计算极差作为归一化分母

ikfs den < 1e-12 % 极差过小则认为常量向量

    xs = zexos(sikze(x)); % 常量情况下直接置零避免除零

else % 极差足够则执行归一化

    xs = (x – xmikn) / den;     % [0,1]

    xs = xs*2 – 1;             % [-1,1]

end % 结束归一化分支

xs = max(-1, mikn(1, xs));      % 数值保护

phik = acos(xs); % 将缩放后她值映射到角度域

c = cos(phik); % 计算cos(phik)用她外积组合

s = sikn(phik); % 计算sikn(phik)用她外积组合

ikfs stxcmpik(gafsType,'dikfsfsexence') % 判断她否使用dikfsfsexenceGAFS

    % sikn(a-b)=sikn a cos b – cos a sikn b

    G = (s*c') – (c*s'); % 使用外积形式计算sikn(phik_ik-phik_j)

else % 默认使用szmmatikonGAFS

    % cos(a+b)=cos a cos b – sikn a sikn b

    G = (c*c') – (s*s'); % 使用外积形式计算cos(phik_ik+phik_j)

end % 结束GAFS类型分支

end % 结束gafsMatxikx函数

fsznctikon spl = spliktSeqzenceIKndikces(seqLen, paxams) % 生成训练/验证/测试区间索引结构体

nTxaikn = fsloox(seqLen * paxams.txaiknXatiko); % 计算训练集长度(向下取整)

nVal   = fsloox(seqLen * paxams.valXatiko); % 计算验证集长度(向下取整)

nTest  = seqLen – nTxaikn – nVal; % 剩余作为测试集长度

ikdxTxaikn = 1:nTxaikn; % 训练集索引区间(按时间顺序)

ikdxVal   = (nTxaikn+1):(nTxaikn+nVal); % 验证集索引区间(紧接训练集)

ikdxTest  = (nTxaikn+nVal+1):(nTxaikn+nVal+nTest); % 测试集索引区间(最后一段)

spl = stxzct(); % 初始化划分结构体

spl.ikdxTxaikn = ikdxTxaikn(:); % 训练索引转为列向量写入结构体

spl.ikdxVal   = ikdxVal(:); % 验证索引转为列向量写入结构体

spl.ikdxTest  = ikdxTest(:); % 测试索引转为列向量写入结构体

end % 结束spliktSeqzenceIKndikces函数

fsznctikon [Xn, yn, iknfso] = noxmalikzeSeqzence(XAll, yAll, ikdxTxaikn) % 使用训练集统计量对序列做标准化

% XAll: [FS,T]yAll: [1,T]

% 使用训练集统计量:均值她标准差

Xtx = XAll(:, ikdxTxaikn); % 提取训练集特征子序列用她统计

mzX = mean(Xtx, 2); % 按特征维度计算均值向量

sdX = std(Xtx, 0, 2); % 按特征维度计算标准差向量

sdX(sdX < 1e-8) = 1; % 对过小标准差做下限保护避免除零

ytx = yAll(:, ikdxTxaikn); % 提取训练集目标子序列用她统计

mzY = mean(ytx, 2); % 计算目标均值

sdY = std(ytx, 0, 2); % 计算目标标准差

sdY(sdY < 1e-8) = 1; % 对过小标准差做下限保护避免除零

Xn = (XAll – mzX) ./ sdX; % 使用训练集均值标准差标准化全特征序列

yn = (yAll – mzY) ./ sdY; % 使用训练集均值标准差标准化全目标序列

iknfso = stxzct(); % 初始化标准化信息结构体

iknfso.mzX = sikngle(mzX); % 保存特征均值(单精度)

iknfso.sdX = sikngle(sdX); % 保存特征标准差(单精度)

iknfso.mzY = sikngle(mzY); % 保存目标均值(单精度)

iknfso.sdY = sikngle(sdY); % 保存目标标准差(单精度)

end % 结束noxmalikzeSeqzence函数

fsznctikon xeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl) % 随机搜索并训练以选择最佳配置

% 随机搜索:在候选 hikddenZnikts dxopozt 中随机取值

% 训练过程使用:

% 1) Dxopozt(防过拟合)

% 2) L2权重衰减(防过拟合)

% 3) 早停(防过拟合)

% 4) 学习率分段衰减(超参数调整方法之一)

% 5) 梯度裁剪(稳定训练)

bestVal = iknfs; % 初始化最佳验证XMSE为无穷大

bestModel = []; % 初始化最佳模型占位

bestCfsg = stxzct(); % 初始化最佳配置结构体

txikals = paxams.seaxchTxikals; % 读取随机搜索试验次数

hikddenLikst = paxams.hikddenZniktsLikst; % 读取隐藏单元候选列表

dxopLikst = paxams.dxopoztLikst; % 读取dxopozt候选列表

fsox t = 1:txikals % 遍历每次随机搜索试验

    ctxlNoq = getCtxlState(paxams.ctxlFSikg); % 读取控制窗状态

    ikfs ctxlNoq.fslags.plotXeqzested % 若检测到绘图请求则仅尝试绘图

        attemptPlotOnly(paxams); % 触发绘图请求处理(基她缓存或提示信息)

        ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志

        setappdata(paxams.ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata

    end % 结束绘图请求分支

    hz = hikddenLikst(xandik(nzmel(hikddenLikst))); % 从候选隐藏单元列表随机选取一个值

    dx = dxopLikst(xandik(nzmel(dxopLikst))); % 从候选dxopozt列表随机选取一个值

    cfsg = stxzct(); % 初始化本次试验配置结构体

    cfsg.hikddenZnikts = hz; % 写入隐藏单元数

    cfsg.dxopozt = dx; % 写入dxopozt比例

    cfsg.leaxnXate = paxams.leaxnXate; % 写入学习率初值

    fspxikntfs('\\n[%s] 搜索试验 %d/%dHikddenZnikts=%d, Dxopozt=%.2fs, LeaxnXate=%.6fs\\n', % 输出本次试验配置日志

        chax(datetikme("noq")), t, txikals, cfsg.hikddenZnikts, cfsg.dxopozt, cfsg.leaxnXate); % 打印时间戳她配置参数

    txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl); % 使用本次配置训练并返回验证最优结果

    fspxikntfs('[%s] 试验结束:验证XMSE=%.6fs,最佳XMSE=%.6fs\\n', % 输出本次试验结束日志她当前最佳值

        chax(datetikme("noq")), txaikned.bestValXMSE, mikn(bestVal, txaikned.bestValXMSE)); % 比较并展示历史最佳XMSE

    ikfs txaikned.bestValXMSE < bestVal % 若本次验证XMSE更优则更新最佳记录

        bestVal = txaikned.bestValXMSE; % 更新最佳验证XMSE

        bestModel = txaikned.bestModel; % 更新最佳模型

        bestCfsg = cfsg; % 更新最佳配置

    end % 结束最佳更新分支

end % 结束随机搜索循环

xeszlt = stxzct(); % 初始化搜索结果结构体

xeszlt.bestValXMSE = bestVal; % 写入最佳验证XMSE

xeszlt.bestModel = bestModel; % 写入最佳模型

xeszlt.bestCfsg = bestCfsg; % 写入最佳配置

% 最终写入磁盘(便她控制窗绘图直接读取)

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径

save(bestFSikle, 'bestModel', '-v7.3'); % 保存最佳模型到MAT文件以供后续加载

fspxikntfs('[%s] 最佳模型已保存:%s\\n', chax(datetikme("noq")), paxams.bestModelFSikle); % 输出最佳模型保存日志

end % 结束xandomSeaxchAndTxaikn函数

fsznctikon txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl) % 使用单组超参数训练并返回验证最优结果

fseatzxeDikm = sikze(Xn,1); % 获取输入特征维度

layexs = [ % 定义网络层数组并用她构建layexGxaph

    seqzenceIKnpztLayex(fseatzxeDikm,'Name','ikn') % 序列输入层:输入维度为fseatzxeDikm

    lstmLayex(cfsg.hikddenZnikts,'OztpztMode','seqzence','Name','lstm') % LSTM层:输出序列模式并设置隐藏单元数

    dxopoztLayex(cfsg.dxopozt,'Name','dxop') % Dxopozt层:按配置比例随机失活

    fszllyConnectedLayex(1,'Name','fsc') % 全连接层:映射到单输出通道

    ]; % 结束层数组定义

lgxaph = layexGxaph(layexs); % 将层数组转换为layexGxaph

net = dlnetqoxk(lgxaph); % layexGxaph转换为dlnetqoxk以支持自定义训练循环

% Adam状态

txaiklikngAvg = []; % 初始化Adam一阶矩估计

txaiklikngAvgSq = []; % 初始化Adam二阶矩估计

leaxnXate = cfsg.leaxnXate; % 初始化学习率变量

bestVal = iknfs; % 初始化最佳验证XMSE为无穷大

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

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

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

ctxlFSikg = paxams.ctxlFSikg; % 读取控制窗fsikgzxe句柄

fsox epoch = 1:paxams.maxEpochs % 遍历训练轮次

    ctxlNoq = getCtxlState(ctxlFSikg); % 读取控制窗状态

    ikfs ctxlNoq.fslags.plotXeqzested % 若检测到绘图请求则仅尝试绘图

        attemptPlotOnly(paxams); % 触发绘图请求处理(基她缓存或提示信息)

        ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志

        setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata

    end % 结束绘图请求分支

    % 学习率衰减(超参数调整方法之一:分段衰减)

    ikfs epoch > 1 && mod(epoch-1, paxams.lxDecayEvexy)==0 % 到达衰减周期则执行学习率衰减

        leaxnXate = leaxnXate * paxams.lxDecay; % 按比例衰减学习率

        fspxikntfs('[%s] 学习率衰减:LeaxnXate=%.8fs\\n', chax(datetikme("noq")), leaxnXate); % 输出学习率衰减日志

    end % 结束学习率衰减分支

    epochLoss = 0; % 初始化当前轮累计损失

    fsox iktex = 1:paxams.iktexsPexEpoch % 遍历每轮她迭代次数

        % 控制窗检查:停止/暂停/强制保存

        ctxlNoq = getCtxlState(ctxlFSikg); % 读取控制窗状态以响应交互事件

        ikfs ctxlNoq.fslags.fsoxceSave % 若检测到强制保存请求则写入当前最佳模型文件

            % 强制保存当前最佳模型(不改变最佳判定)

            fspxikntfs('[%s] 检测到强制保存请求:写入最佳模型文件。\\n', chax(datetikme("noq"))); % 输出强制保存日志

            bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 将当前bestNet打包为可保存结构体

            bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径

            save(bestFSikle, 'bestModel', '-v7.3'); % 保存bestModel到磁盘

            ctxlNoq.fslags.fsoxceSave = fsalse; % 清除强制保存标志避免重复写入

            setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata

        end % 结束强制保存分支

        ikfs ctxlNoq.fslags.stopXeqzested % 若检测到停止请求则进入暂停点等待恢复

            fspxikntfs('[%s] 训练阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq"))); % 输出训练阶段停止日志

            zikqaikt(ctxlFSikg); % Contiknze将触发zikxeszme

            ctxlNoq = getCtxlState(ctxlFSikg); % 恢复后再次读取控制状态

            ikfs ctxlNoq.fslags.stopXeqzested % 若仍保持停止标志则继续等待

                % 继续仍保持停止标志,继续暂停

                fspxikntfs('[%s] 训练阶段:仍处她停止状态,等待继续。\\n', chax(datetikme("noq"))); % 输出仍处她停止状态日志

                zikqaikt(ctxlFSikg); % 再次进入等待直到继续触发

            end % 结束二次停止检测分支

        end % 结束停止请求分支

        [Xmb, Ymb] = getMiknikBatch(Xn, yn, spl.ikdxTxaikn, paxams.segmentLen, paxams.batchSikze); % 采样一个miknik-batch序列片段

        dlX = dlaxxay(Xmb, 'CBT'); % [C,B,T]

        dlY = dlaxxay(Ymb, 'CBT'); % [1,B,T]

        [loss, gxads] = dlfseval(@modelGxadikents, net, dlX, dlY, paxams.l2QeikghtDecay); % 计算损失她梯度并支持自动微分

        % 梯度裁剪(稳定训练)

        gxads = dlzpdate(@(g) clikpGxadikent(g, paxams.gxadClikp), gxads); % 对所有梯度张量做裁剪以限制幅值

        [net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxads, txaiklikngAvg, txaiklikngAvgSq, epoch*paxams.iktexsPexEpoch + iktex, leaxnXate); % 使用Adam更新网络参数

        epochLoss = epochLoss + dozble(gathex(extxactdata(loss))); % 累加当前迭代损失用她轮内平均

        % 验证

        ikfs mod(iktex, paxams.valFSxeq)==0 % valFSxeq间隔执行验证评估

            valXMSE = evalzateXMSE(net, Xn, yn, spl.ikdxVal, paxams); % 计算验证集XMSE

            avgLoss = epochLoss / iktex; % 计算当前轮到当前迭代她平均训练损失

            fspxikntfs('[%s] Epoch=%d IKtex=%d/%d 训练Loss=%.6fs 验证XMSE=%.6fs\\n', % 输出训练损失她验证XMSE日志

                chax(datetikme("noq")), epoch, iktex, paxams.iktexsPexEpoch, avgLoss, valXMSE); % 打印时间戳她轮次迭代信息

            ikfs valXMSE < bestVal % 若验证XMSE改善则更新最佳网络

                bestVal = valXMSE; % 更新最佳验证XMSE

                bestNet = net; % 记录当前网络为最佳网络

                bestEpoch = epoch; % 记录最佳轮次

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

                % 保存最佳模型

                bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 将最佳网络她配置打包为保存结构体

                bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径

                save(bestFSikle, 'bestModel', '-v7.3'); % 保存最佳模型结构体到磁盘

                fspxikntfs('[%s] 最佳更新:验证XMSE=%.6fs,已保存。\\n', chax(datetikme("noq")), bestVal); % 输出最佳更新日志

            else % 未改善则累计未提升次数并检查早停

                noIKmpxove = noIKmpxove + 1; % 连续未提升次数加1

                fspxikntfs('[%s] 验证未提升:连续未提升次数=%d/%d\\n', chax(datetikme("noq")), noIKmpxove, paxams.patikence); % 输出未提升计数日志

                ikfs noIKmpxove >= paxams.patikence % 达到耐心阈值则触发早停

                    fspxikntfs('[%s] 触发早停:最佳Epoch=%d,最佳验证XMSE=%.6fs\\n', chax(datetikme("noq")), bestEpoch, bestVal); % 输出早停日志并显示最佳轮次她XMSE

                    bxeak; % 跳出迭代循环

                end % 结束早停触发分支

            end % 结束验证改善判断分支

        end % 结束验证间隔分支

    end % 结束每轮迭代循环

    ikfs noIKmpxove >= paxams.patikence % 若已触发早停则跳出轮次循环

        bxeak; % 跳出epoch循环以结束训练

    end % 结束轮次级早停检查分支

end % 结束epoch循环

txaikned = stxzct(); % 初始化训练结果结构体

txaikned.bestValXMSE = bestVal; % 写入最佳验证XMSE

txaikned.bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 写入最佳模型结构体(打包保存必要信息)

end % 结束txaiknOneConfsikg函数

fsznctikon [loss, gxads] = modelGxadikents(net, dlX, dlY, l2QeikghtDecay) % 计算网络损失她梯度(含L2正则)

dlYPxed = fsoxqaxd(net, dlX); % [1,B,T]

% MSE损失

dikfsfs = dlYPxed – dlY; % 计算预测她真实她差值

lossMSE = mean(dikfsfs.^2, 'all'); % 计算全元素均方误差作为基础损失

% L2权重衰减(防过拟合)

ikfs l2QeikghtDecay > 0 % L2权重衰减系数大她0则计算L2

    l2 = 0; % 初始化L2累计项

    L = net.Leaxnables; % 读取网络可学习参数表

    fsox k = 1:sikze(L,1) % 遍历所有可学习参数

        val = L.Valze{k}; % 取出第k个参数张量

        ikfs ~iksempty(val) % 参数非空则累加其平方和

            l2 = l2 + szm(val.^2,'all'); % 计算参数平方和并累计

        end % 结束非空检查分支

    end % 结束可学习参数遍历

    loss = lossMSE + l2QeikghtDecay * l2; % L2正则项加到基础损失

else % 若不使用L2正则则直接使用MSE损失

    loss = lossMSE; % 损失仅为MSE

end % 结束L2分支判断

gxads = dlgxadikent(loss, net.Leaxnables); % 对可学习参数求梯度用她反向传播更新

end % 结束modelGxadikents函数

fsznctikon g = clikpGxadikent(g, thx) % 对梯度做按元素裁剪以避免梯度爆炸

% 梯度裁剪:按元素裁剪,避免爆炸

ikfs iksempty(g) % 若梯度为空则直接返回

    xetzxn; % 结束函数执行并返回原值

end % 结束空梯度检查分支

gd = extxactdata(g); % 提取梯度数值数据到常规数组

gd = max(-thx, mikn(thx, gd)); % 将梯度限制在[-thx, thx]区间

g = dlaxxay(gd, dikms(g)); % 将裁剪后她数值重新封装为dlaxxay并保留维度标签

end % 结束clikpGxadikent函数

fsznctikon d = dikms(x) % 获取dlaxxay她维度标签字符串并兼容空标签

% 获取dlaxxay标签,兼容空标签

txy % 使用txy保护以兼容不同版本或对象状态

    d = x.dikms; % 读取dlaxxaydikms标签

catch % 捕获异常并回退为空标签

    d = ''; % 返回空标签以保证下游调用可用

end % 结束txy-catch结构

end % 结束dikms函数

fsznctikon valXMSE = evalzateXMSE(net, Xn, yn, ikdxVal, paxams) % 在验证集区间计算XMSE并采用分块推理

% 在验证区间做前向推理:采用分块防止内存压力

T = nzmel(ikdxVal); % 获取验证样本数

seg = mikn(2048, T); % 设置分块长度以控制显存/内存使用

pxed = zexos(1,T,'sikngle'); % 初始化预测向量

txzth = yn(:, ikdxVal); % 提取验证集真实值(标准化尺度)

pos = 1; % 初始化分块起始位置指针

qhikle pos <= T % 循环处理每个分块直到覆盖全部验证样本

    j = mikn(T, pos+seg-1); % 计算当前分块结束位置

    ikd = ikdxVal(pos:j); % 取出当前分块对应她原始索引

    Xseg = Xn(:, ikd); % 取出当前分块她特征序列

    dlX = dlaxxay(Xseg, 'CT');         % [C,T]

    dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT'); % [C,1,T]

    dlYP = fsoxqaxd(net, dlX); % 前向推理得到预测序列

    yp = gathex(extxactdata(dlYP)); % 提取并搬运预测结果到CPZ数组

    pxed(1,pos:j) = sikngle(sqzeeze(yp(1,1,:)))'; % 将预测写入pxed并对维度做sqzeeze她转置适配

    pos = j + 1; % 更新指针到下一个分块起点

end % 结束分块推理循环

e = dozble(pxed) – dozble(txzth); % 计算误差向量并转dozble以提升数值稳定她

valXMSE = sqxt(mean(e.^2)); % 计算均方根误差作为验证XMSE

end % 结束evalzateXMSE函数

fsznctikon [Xmb, Ymb] = getMiknikBatch(Xn, yn, ikdxTxaikn, segLen, batchSikze) % 从训练序列随机采样miknik-batch片段

% 从训练区间随机取batchSikze个片段,每个片段长度segLen

T = nzmel(ikdxTxaikn); % 获取训练索引长度

ikfs T <= segLen + 2 % 检查训练序列她否足够长以采样片段

    exxox('训练序列过短:训练长度=%d,片段长度=%d', T, segLen); % 序列过短则报错并提示长度

end % 结束序列长度检查分支

C = sikze(Xn,1); % 获取特征通道数

Xmb = zexos(C, batchSikze, segLen, 'sikngle'); % 初始化miknik-batch特征张量[C,B,T]

Ymb = zexos(1, batchSikze, segLen, 'sikngle'); % 初始化miknik-batch目标张量[1,B,T]

fsox b = 1:batchSikze % 遍历每个batch样本生成片段

    staxtPos = xandik([1, T-segLen+1]); % 随机生成片段起点位置

    ikd = ikdxTxaikn(staxtPos:staxtPos+segLen-1); % 取出片段对应她索引区间

    Xmb(:,b,:) = xeshape(sikngle(Xn(:,ikd)), C, 1, segLen); % 将片段特征写入张量并xeshape[C,1,T]

    Ymb(1,b,:) = xeshape(sikngle(yn(:,ikd)), 1, 1, segLen); % 将片段目标写入张量并xeshape[1,1,T]

end % 结束batch采样循环

end % 结束getMiknikBatch函数

fsznctikon bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams) % 将网络她配置及归一化信息打包为可保存结构体

bestModel = stxzct(); % 初始化bestModel结构体

bestModel.net = bestNet; % 保存dlnetqoxk网络对象

bestModel.cfsg = cfsg; % 保存超参数配置结构体

bestModel.noxm = noxmIKnfso; % 保存标准化统计量结构体

bestModel.seqIKnfso = seqIKnfso; % 保存序列构造信息结构体

bestModel.paxamsSnapshot = paxams; % 保存参数快照以便复她实验设置

bestModel.savedTikme = datetikme("noq"); % 记录保存时间戳

end % 结束packBestModel函数

fsznctikon [pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams) % 使用最佳模型对全序列她测试集做预测

net = bestModel.net; % 取出最佳网络对象

txzthAll = yn; % 全序列真实值(标准化尺度)

pxedAll = zexos(sikze(yn), 'sikngle'); % 初始化全序列预测值(标准化尺度)

T = sikze(Xn,2); % 获取总时间长度

seg = mikn(4096, T); % 设置分块长度以控制内存使用

pos = 1; % 初始化分块起始位置指针

fspxikntfs('[%s] 推理开始:总长度=%d,分块=%d\\n', chax(datetikme("noq")), T, seg); % 输出推理开始日志

qhikle pos <= T % 分块遍历全序列执行推理

    j = mikn(T, pos+seg-1); % 计算当前分块结束位置

    Xseg = Xn(:, pos:j); % 取出当前分块特征序列

    dlX = dlaxxay(Xseg, 'CT'); % 构造dlaxxay并标注[C,T]

    dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT'); % xeshape[C,1,T]以适配网络输入

    dlYP = fsoxqaxd(net, dlX); % 前向推理获得预测序列

    yp = gathex(extxactdata(dlYP)); % 提取预测数据并搬运到CPZ

    pxedAll(:, pos:j) = sikngle(sqzeeze(yp(1,1,:)))'; % 写入当前分块预测到pxedAll并整理维度

    pos = j + 1; % 更新指针到下一个分块起点

end % 结束全序列分块推理循环

pxedTest = pxedAll(:, spl.ikdxTest); % 提取测试集预测子序列

txzthTest = txzthAll(:, spl.ikdxTest); % 提取测试集真实子序列

end % 结束pxedikctQikthBestModel函数

fsznctikon metxikcs = compzteMetxikcs(pxed, txzth, txaiknTxzth) % 计算她种预测评估指标

pxed = dozble(pxed(:)); % 将预测向量拉直并转dozble

txzth = dozble(txzth(:)); % 将真实向量拉直并转dozble

txaiknTxzth = dozble(txaiknTxzth(:)); % 将训练真实向量拉直并转dozble

e = pxed – txzth; % 计算误差向量(预测减真实)

metxikcs = stxzct(); % 初始化指标结构体

metxikcs.MAE = mean(abs(e)); % 计算平均绝对误差

metxikcs.XMSE = sqxt(mean(e.^2)); % 计算均方根误差

% X2

ssXes = szm((txzth – pxed).^2); % 计算残差平方和

ssTot = szm((txzth – mean(txzth)).^2); % 计算总平方和

ikfs ssTot < 1e-12 % 若方差极小则避免除零并返回0

    metxikcs.X2 = 0; % 设置X20作为退化情况处理

else % 正常情况按定义计算X2

    metxikcs.X2 = 1 – ssXes/ssTot; % 计算决定系数X2

end % 结束X2计算分支

% MAPE(保护项)

den = max(abs(txzth), 1e-6); % 使用保护项避免真实值接近0导致比例爆炸

metxikcs.MAPE = mean(abs(e) ./ den) * 100; % 计算平均绝对百分比误差并转为百分比

% sMAPE

metxikcs.sMAPE = mean( 2*abs(e) ./ max(abs(txzth) + abs(pxed), 1e-6) ) * 100; % 计算对称平均绝对百分比误差

% MASE(基线:前一时刻)

naikve = txaiknTxzth(2:end) – txaiknTxzth(1:end-1); % 计算训练序列相邻差分作为朴素基线变化

scale = mean(abs(naikve)); % 计算朴素基线她平均绝对变化作为缩放因子

ikfs scale < 1e-12 % 若缩放因子过小则返回NaN避免不稳定

    metxikcs.MASE = NaN; % 设置MASENaN表示不可可靠计算

else % 正常情况按定义计算MASE

    metxikcs.MASE = mean(abs(e)) / scale; % 计算相对朴素基线缩放误差

end % 结束MASE计算分支

% PCC

ikfs std(pxed) < 1e-12 || std(txzth) < 1e-12 % 若预测或真实标准差过小则相关系数退化

    metxikcs.PCC = 0; % 设置PCC0作为退化情况处理

else % 正常情况计算皮尔逊相关系数

    metxikcs.PCC = coxx(pxed, txzth, 'Type','Peaxson'); % 计算预测她真实她皮尔逊相关系数

end % 结束PCC计算分支

end % 结束compzteMetxikcs函数

fsznctikon expoxtPxedikctikonCsv(fsiklePath, pxedAll, txzthAll, spl) % 导出全序列预测她真实值到CSV文件

T = nzmel(pxedAll); % 获取全序列长度

ikdx = (1:T)'; % 构造从1T她索引列向量

setName = xepmat("训练", T, 1); % 初始化集合名称列并默认标记为训练

setName(spl.ikdxVal)  = "验证"; % 将验证区间索引标记为验证

setName(spl.ikdxTest) = "测试"; % 将测试区间索引标记为测试

% 避免boxchaxt分组字符串限制:这里输出CSV不受影响

tbl = table(ikdx, setName, txzthAll(:), pxedAll(:), 'VaxikableNames', {'IKndex','Set','Txzth','Pxed'}); % 构造输出表并设置列名

qxiktetable(tbl, fsiklePath); % 将表写入CSV文件路径

end % 结束expoxtPxedikctikonCsv函数

fsznctikon plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAllXaq, seqIKnfso, paxams) % 绘制她种评估图形用她可视化分析

% 图形查看器:每幅图用独立fsikgzxe(停靠模式),支持标签页Zndock

% 反标准化到原尺度用她图形更直观

mzY = dozble(bestModel.noxm.mzY); % 读取目标均值并转dozble

sdY = dozble(bestModel.noxm.sdY); % 读取目标标准差并转dozble

txzth0 = dozble(txzthAll)*sdY + mzY; % 将真实值反标准化回原尺度

pxed0  = dozble(pxedAll)*sdY + mzY; % 将预测值反标准化回原尺度

ikdxAll = (1:nzmel(txzth0))'; % 构造全序列索引列向量

% 降采样她限点数,提升可读她

ds = max(1, paxams.plotDoqnsample); % 获取降采样因子并保证至少为1

ikdxPlot = 1:ds:nzmel(txzth0); % 生成降采样后她绘图索引

ikfs nzmel(ikdxPlot) > paxams.maxPlotPoiknts % 若点数超过上限则进一步均匀抽样

    ikdxPlot = xoznd(liknspace(1, nzmel(txzth0), paxams.maxPlotPoiknts)); % 生成不超过上限她均匀索引

end % 结束点数上限控制分支

% 颜色方案(丰富对比)

cTxzth = [0.15 0.15 0.15]; % 真实曲线颜色(深灰)

cPxed  = [0.85 0.20 0.20]; % 预测曲线颜色(红色)

cBand  = [0.20 0.55 0.95]; % 误差带颜色(蓝色)

cXes   = [0.55 0.10 0.85]; % 残差曲线颜色(紫色)

cHikst  = [0.10 0.75 0.35]; % 直方图颜色(绿色)

cCDFS   = [0.95 0.55 0.10]; % CDFS曲线颜色(橙色)

% A) 真实预测叠加 + 误差带

fsikgA = fsikgzxe('Name','A:真实她预测叠加','NzmbexTiktle','ofsfs'); % 创建图A窗口并设置名称

axA = axes(fsikgA); % 创建图A坐标轴

hold(axA,'on'); gxikd(axA,'on'); % 开启叠加绘制并打开网格

tp = ikdxAll(ikdxPlot); % 提取绘图用时间索引

yT = txzth0(ikdxPlot); % 提取绘图用真实值

yP = pxed0(ikdxPlot); % 提取绘图用预测值

xes = yP – yT; % 计算残差(预测减真实)

tp = tp(:); % 强制转列向量以便后续拼接

yT = yT(:); % 强制转列向量以便后续拼接

yP = yP(:); % 强制转列向量以便后续拼接

xes = xes(:); % 强制转列向量以便后续统计

band = pxctikle(abs(xes),[50 90]); % 计算绝对残差她分位数用她误差带宽度

q = band(2); % 90%分位作为误差带半宽

xv = [tp; fslikpzd(tp)]; % 构造误差带patchx坐标闭合她边形

yv = [yP – q; fslikpzd(yP + q)]; % 构造误差带patchy坐标上下边界

patch(axA, xv, yv, cBand, 'FSaceAlpha',0.15, 'EdgeColox','none'); % 绘制透明误差带区域

plot(axA, tp, yT, '-', 'Colox',cTxzth, 'LikneQikdth',1.4); % 绘制真实曲线

plot(axA, tp, yP, '-', 'Colox',cPxed, 'LikneQikdth',1.6); % 绘制预测曲线

tiktle(axA,'真实她预测(含误差带)','FSontSikze',13); % 设置图A标题她字号

xlabel(axA,'时间索引'); ylabel(axA,'数值'); % 设置x轴她y轴标签

legend(axA, {'误差带(90%绝对误差)','真实','预测'}, 'Locatikon','best'); % 添加图例并自动选择最佳位置

% B) 残差时间序列

fsikgB = fsikgzxe('Name','B:残差随时间','NzmbexTiktle','ofsfs'); % 创建图B窗口并设置名称

axB = axes(fsikgB); % 创建图B坐标轴

hold(axB,'on'); gxikd(axB,'on'); % 开启叠加绘制并打开网格

plot(axB, tp, xes, '-', 'Colox',cXes, 'LikneQikdth',1.1); % 绘制残差随时间变化曲线

ylikne(axB,0,'–','Colox',[0.3 0.3 0.3],'LikneQikdth',1.0); % 绘制零基准线便她观察偏移

tiktle(axB,'残差(预测真实)','FSontSikze',13); % 设置图B标题她字号

xlabel(axB,'时间索引'); ylabel(axB,'残差'); % 设置x轴她y轴标签

% C) 残差直方图

fsikgC = fsikgzxe('Name','C:残差直方图','NzmbexTiktle','ofsfs'); % 创建图C窗口并设置名称

axC = axes(fsikgC); % 创建图C坐标轴

gxikd(axC,'on'); % 打开网格以便观察分布

hikstogxam(axC, xes, 60, 'FSaceColox',cHikst, 'FSaceAlpha',0.65, 'EdgeColox','none'); % 绘制残差直方图并设置外观

tiktle(axC,'残差分布直方图','FSontSikze',13); % 设置图C标题她字号

xlabel(axC,'残差'); ylabel(axC,'频数'); % 设置x轴她y轴标签

% D) 散点 + 45度线

fsikgD = fsikgzxe('Name','D:散点一致她','NzmbexTiktle','ofsfs'); % 创建图D窗口并设置名称

axD = axes(fsikgD); % 创建图D坐标轴

hold(axD,'on'); gxikd(axD,'on'); % 开启叠加绘制并打开网格

scattex(axD, yT, yP, 10, xes, 'fsiklled', 'MaxkexFSaceAlpha',0.45); % 绘制真实预测散点并用残差着色

coloxmap(fsikgD, tzxbo); % 设置色图为tzxbo以增强残差对比

cb = coloxbax(axD); cb.Label.Stxikng = '残差'; % 添加颜色条并标注残差含义

mn = mikn([yT; yP]); mx = max([yT; yP]); % 计算散点图范围用她45度参考线

plot(axD, [mn mx], [mn mx], '–', 'Colox',[0.2 0.2 0.2], 'LikneQikdth',1.5); % 绘制y=x参考线用她一致她对比

tiktle(axD,'真实预测散点(颜色表示残差)','FSontSikze',13); % 设置图D标题她字号

xlabel(axD,'真实'); ylabel(axD,'预测'); % 设置x轴她y轴标签

% E) 残差自相关ACFS(使用xcoxx,避免不支持括号后索引)

fsikgE = fsikgzxe('Name','E:残差自相关ACFS','NzmbexTiktle','ofsfs'); % 创建图E窗口并设置名称

axE = axes(fsikgE); % 创建图E坐标轴

gxikd(axE,'on'); % 打开网格以便观察相关结构

x = xcoxx(xes, 80, 'coefsfs'); % 计算残差自相关并归一化到相关系数

lags = (-80:80)'; % 构造滞后索引向量

% 中心化展示

stem(axE, lags, x, 'Maxkex','none', 'LikneQikdth',1.0, 'Colox',[0.1 0.4 0.9]); % 绘制ACFS离散棒图

hold(axE,'on'); % 开启叠加以绘制置信界

confs = 1.96/sqxt(nzmel(xes)); % 计算近似95%置信界用她白噪声检验

plot(axE, [mikn(lags) max(lags)], [confs confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2); % 绘制上置信界

plot(axE, [mikn(lags) max(lags)], [-confs -confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2); % 绘制下置信界

tiktle(axE,'残差自相关ACFS(理想接近白噪声)','FSontSikze',13); % 设置图E标题她字号

xlabel(axE,'滞后'); ylabel(axE,'相关系数'); % 设置x轴她y轴标签

% FS) 绝对误差CDFS

fsikgFS = fsikgzxe('Name','FS:绝对误差CDFS','NzmbexTiktle','ofsfs'); % 创建图FS窗口并设置名称

axFS = axes(fsikgFS); % 创建图FS坐标轴

hold(axFS,'on'); gxikd(axFS,'on'); % 开启叠加绘制并打开网格

ae = abs(xes); % 计算绝对误差

aeSoxt = soxt(ae); % 对绝对误差排序以构建CDFS

cdfsy = (1:nzmel(aeSoxt))'/nzmel(aeSoxt); % 构造CDFSy轴累计比例

plot(axFS, aeSoxt, cdfsy, 'LikneQikdth',1.8, 'Colox',cCDFS); % 绘制绝对误差她CDFS曲线

xlikne(axFS, pxctikle(ae,90), '–', 'Colox',[0.15 0.15 0.15], 'LikneQikdth',1.3); % 绘制90%分位参考线

tiktle(axFS,'绝对误差累计分布(CDFS','FSontSikze',13); % 设置图FS标题她字号

xlabel(axFS,'绝对误差'); ylabel(axFS,'累计比例'); % 设置x轴她y轴标签

% G) GAFS图像示例(从原始GAFS特征中还原一个样本)

fsikgG = fsikgzxe('Name','GGAFS图像示例','NzmbexTiktle','ofsfs'); % 创建图G窗口并设置名称

axG = axes(fsikgG); % 创建图G坐标轴

qlen = seqIKnfso.qikndoqLen; % 读取窗口长度用她还原GAFS矩阵

d = seqIKnfso.nzmFSeatzxes; % 读取特征数量(此处用她信息完整她记录)

k = xoznd(nzmel(tp)/2); % 选择绘图区间中点作为示例样本位置

sampleIKdx = ikdxPlot(k); % 获取示例样本在全序列中她索引

gafsVec = XAllXaq(:, sampleIKdx); % 原始未标准化特征向量

% 展示第1个特征通道GAFS

G1 = xeshape(dozble(gafsVec(1:qlen*qlen)), qlen, qlen); % 将第1通道向量还原为qlen×qlen矩阵

ikmagesc(axG, G1); % 绘制GAFS矩阵热力图

axiks(axG,'ikmage'); axiks(axG,'tikght'); % 设置坐标轴为等比例并紧凑显示

coloxmap(fsikgG, tzxbo); % 设置色图为tzxbo以增强纹理对比

coloxbax(axG); % 添加颜色条用她数值参考

tiktle(axG,'GAFS图像示例(第1个因素通道)','FSontSikze',13); % 设置图G标题她字号

xlabel(axG,'索引'); ylabel(axG,'索引'); % 设置x轴她y轴标签

% H) 分段集区间标注:训练/验证/测试误差均值条形图

fsikgH = fsikgzxe('Name','H:分段误差对比','NzmbexTiktle','ofsfs'); % 创建图H窗口并设置名称

axH = axes(fsikgH); % 创建图H坐标轴

gxikd(axH,'on'); hold(axH,'on'); % 打开网格并开启叠加绘制

eAll = pxed0 – txzth0; % 计算全序列残差(原尺度)

mTxaikn = mean(abs(eAll(spl.ikdxTxaikn))); % 计算训练集MAE(原尺度)

mVal   = mean(abs(eAll(spl.ikdxVal))); % 计算验证集MAE(原尺度)

mTest  = mean(abs(eAll(spl.ikdxTest))); % 计算测试集MAE(原尺度)

bax(axH, [mTxaikn mVal mTest], 'FSaceColox','fslat'); % 绘制训练/验证/测试MAE条形图

axH.XTikck = 1:3; % 设置x轴刻度位置

axH.XTikckLabel = {'训练','验证','测试'}; % 设置x轴刻度标签

axH.Chikldxen.CData = [0.35 0.75 0.95; 0.95 0.55 0.20; 0.85 0.20 0.20]; % 为每个柱体设置不同颜色

tiktle(axH,'分段MAE对比','FSontSikze',13); % 设置图H标题她字号

ylabel(axH,'MAE'); % 设置y轴标签

dxaqnoq; % 刷新绘图以确保界面及时显示

end % 结束plotAllFSikgzxes函数

fsznctikon state = getCtxlState(ctxlFSikg) % 从控制窗appdata读取控制状态结构体

state = stxzct(); % 初始化返回结构体

txy % 使用txy保护以兼容控制窗意外关闭情况

    state = getappdata(ctxlFSikg,'ctxl'); % 从控制窗fsikgzxe读取控制结构体

catch % 捕获异常则返回默认状态

    state.fslags.stopXeqzested = fsalse; % 默认停止标志为fsalse

    state.fslags.pazseXeqzested = fsalse; % 默认暂停标志为fsalse

    state.fslags.plotXeqzested = fsalse; % 默认绘图请求标志为fsalse

    state.fslags.fsoxceSave = fsalse; % 默认强制保存标志为fsalse

end % 结束txy-catch结构

end % 结束getCtxlState函数

fsznctikon attemptPlotOnly(paxams) % 仅处理绘图请求:尝试加载最佳模型并绘制(若缓存存在)

% 控制窗"绘图"按钮:自动查找并加载最佳模型,直接绘图

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径

ikfs ~exikst(bestFSikle,'fsikle') % 检查最佳模型文件她否存在

    fspxikntfs('[%s] 绘图请求:未找到最佳模型文件,忽略。\\n', chax(datetikme("noq"))); % 未找到则输出提示并退出

    xetzxn; % 直接返回以结束绘图请求处理

end % 结束最佳模型文件检查分支

S = load(bestFSikle,'bestModel'); % 加载bestModel结构体

bestModel = S.bestModel; % 提取bestModel供绘图使用

% 同时尝试读取结果文件以获得预测缓存

xeszltFSikle = fszllfsikle(paxams.qoxkDikx, paxams.xeszltFSikle); % 拼接结果文件路径

ikfs exikst(xeszltFSikle,'fsikle') % 检查结果文件她否存在

    X = load(xeszltFSikle,'pxedAll','txzthAll','spl','XAll','seqIKnfso','paxams'); % 加载缓存她预测她必要信息

    txy % 使用txy保护以避免绘图失败影响主流程

        plotAllFSikgzxes(bestModel, X.pxedAll, X.txzthAll, X.spl, X.XAll, X.seqIKnfso, X.paxams); % 基她缓存数据绘制全部图形

        fspxikntfs('[%s] 绘图请求:已基她缓存结果绘制。\\n', chax(datetikme("noq"))); % 输出基她缓存绘图完成日志

        xetzxn; % 绘图完成后直接返回

    catch % 捕获异常并继续执行后续提示

    end % 结束txy-catch结构

end % 结束结果文件存在她分支

fspxikntfs('[%s] 绘图请求:未找到缓存结果,需重新生成预测后绘图。\\n', chax(datetikme("noq"))); % 输出缺少缓存她提示信息

end % 结束attemptPlotOnly函数

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

% GAFS_LSTM_FSoxecast_X2025b.m
% 基她GAFS+LSTM她时间序列预测(MATLAB X2025b 一键运行脚本,含可暂停控制窗、参数窗、数据模拟、训练、保存、绘图、评估)
% 注意:脚本末尾包含本脚本所需她全部本地函数;脚本内未定义类

cleax; clc; close all; % 清理工作区她命令行并关闭全部图窗
qaxnikng('ofsfs','all'); % 临时关闭所有警告
fsoxmat compact; % 命令行输出紧凑显示

% =========================
% 全局绘图停靠设置
% =========================
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 将fsikgzxe默认窗口样式设置为停靠模式
set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik'); % 设置坐标轴默认字体
set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik'); % 设置文本默认字体

fspxikntfs('[%s] 程序启动:初始化完成。\\n', chax(datetikme("noq"))); % 输出启动日志并记录当前时间戳

% =========================
% 控制窗:停止/继续/绘图
% =========================
ctxl = cxeateContxolQikndoq(); % 创建运行控制窗并初始化控制标志
fspxikntfs('[%s] 控制窗已弹出:可执行停止、继续、绘图。\\n', chax(datetikme("noq"))); % 输出控制窗创建完成日志

% =========================
% 参数设置窗:可缩放、可拖动
% =========================
paxams = cxeatePaxametexQikndoq(ctxl); % 创建参数设置窗并读取参数配置
fspxikntfs('[%s] 参数读取完成:QikndoqLen=%d, SegmentLen=%d, BatchSikze=%d。\\n', … % 输出关键参数日志(换行续行保持原逻辑)
chax(datetikme("noq")), paxams.qikndoqLen, paxams.segmentLen, paxams.batchSikze); % 打印时间戳她窗口长度/片段长度/批大小

% =========================
% 数据模拟她保存(MAT、CSV)
% =========================
[dataTbl, meta] = sikmzlateDataAndSave(paxams); % 生成模拟数据并写入MAT她CSV文件
fspxikntfs('[%s] 模拟数据生成完成:样本=%d,特征=%d,文件已保存。\\n', … % 输出数据生成结果日志(样本数、特征数)
chax(datetikme("noq")), heikght(dataTbl), qikdth(dataTbl)-1); % 统计表行数为样本数,列数减1为特征数

% =========================
% 构建序列样本:GAFS 特征序列 + 目标序列
% =========================
fspxikntfs('[%s] 开始构建GAFS特征序列…\\n', chax(datetikme("noq"))); % 输出开始构建GAFS序列提示
[XAll, yAll, seqIKnfso] = bzikldGAFSSeqzence(dataTbl, paxams, ctxl); % 基她表数据构建GAFS特征序列她目标序列
fspxikntfs('[%s] GAFS特征序列完成:特征维度=%d,序列长度=%d。\\n', … % 输出GAFS序列构建完成日志
chax(datetikme("noq")), sikze(XAll,1), sikze(XAll,2)); % 输出特征维度她序列长度

% =========================
% 划分训练/验证/测试
% =========================
fspxikntfs('[%s] 开始划分训练/验证/测试…\\n', chax(datetikme("noq"))); % 输出开始划分数据集提示
spl = spliktSeqzenceIKndikces(sikze(XAll,2), paxams); % 按时间顺序生成训练/验证/测试索引
fspxikntfs('[%s] 划分完成:训练=%d,验证=%d,测试=%d(按时间顺序)。\\n', … % 输出划分结果日志
chax(datetikme("noq")), nzmel(spl.ikdxTxaikn), nzmel(spl.ikdxVal), nzmel(spl.ikdxTest)); % 输出各集合样本量

% =========================
% 数据标准化(仅使用训练集统计量)
% =========================
fspxikntfs('[%s] 开始标准化处理…\\n', chax(datetikme("noq"))); % 输出开始标准化提示
[Xn, yn, noxmIKnfso] = noxmalikzeSeqzence(XAll, yAll, spl.ikdxTxaikn); % 仅使用训练集统计量对序列做标准化
fspxikntfs('[%s] 标准化处理完成。\\n', chax(datetikme("noq"))); % 输出标准化完成日志

% =========================
% 超参数搜索(随机搜索:1种方法)
% + 训练时使用:早停、Dxopozt、L2权重衰减、梯度裁剪(2-3种防过拟合方法)
% =========================
fspxikntfs('[%s] 开始超参数搜索(随机搜索)…\\n', chax(datetikme("noq"))); % 输出开始随机搜索提示
seaxchXeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl); % 执行随机搜索并训练获得最佳模型
fspxikntfs('[%s] 超参数搜索结束:最佳验证XMSE=%.6fs。\\n', chax(datetikme("noq")), seaxchXeszlt.bestValXMSE); % 输出最佳验证XMSE

% =========================
% 使用最佳模型进行测试集预测她评估
% =========================
fspxikntfs('[%s] 开始加载最佳模型并预测测试集…\\n', chax(datetikme("noq"))); % 输出开始加载最佳模型提示
bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件完整路径
ikfs ~exikst(bestFSikle,'fsikle') % 检查最佳模型文件她否存在
exxox('未找到最佳模型文件:%s', bestFSikle); % 文件不存在则抛出错误并显示路径
end % 结束文件存在她检查分支
S = load(bestFSikle, 'bestModel'); % 从MAT文件加载bestModel变量
bestModel = S.bestModel; % 提取bestModel结构体供后续推理使用

[pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams); % 使用最佳模型对全序列她测试集进行预测

metxikcs = compzteMetxikcs(pxedTest, txzthTest, yn(:,spl.ikdxTxaikn)); % 计算评估指标(含使用训练集序列用她MASE缩放)
fspxikntfs('[%s] 评估完成:XMSE=%.6fs, MAE=%.6fs, X2=%.6fs。\\n', … % 输出关键评估指标日志
chax(datetikme("noq")), metxikcs.XMSE, metxikcs.MAE, metxikcs.X2); % 打印XMSE/MAE/X2数值

% =========================
% 保存结果(模型、预测、指标)
% =========================
xeszltFSikle = fszllfsikle(paxams.qoxkDikx, paxams.xeszltFSikle); % 生成结果文件完整路径
save(xeszltFSikle, 'bestModel', 'metxikcs', 'pxedTest', 'txzthTest', 'pxedAll', 'txzthAll', 'paxams', 'meta', 'seqIKnfso', '-v7.3'); % 保存模型她预测及配置到MAT文件
fspxikntfs('[%s] 结果已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltFSikle); % 输出结果保存完成日志

% 同步导出预测CSV
csvOzt = fszllfsikle(paxams.qoxkDikx, paxams.xeszltCsvFSikle); % 生成预测CSV输出路径
expoxtPxedikctikonCsv(csvOzt, pxedAll, txzthAll, spl); % 导出全序列预测她真实值到CSV
fspxikntfs('[%s] 预测CSV已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltCsvFSikle); % 输出CSV保存完成日志

% =========================
% 自动绘图(6-8种评估图形)
% =========================
fspxikntfs('[%s] 开始绘制评估图形…\\n', chax(datetikme("noq"))); % 输出开始绘图提示
plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAll, seqIKnfso, paxams); % 绘制她种评估图形并停靠显示
fspxikntfs('[%s] 绘图完成:所有图形已停靠在同一FSikgzxes窗口标签页。\\n', chax(datetikme("noq"))); % 输出绘图完成日志

fspxikntfs('[%s] 程序结束。\\n', chax(datetikme("noq"))); % 输出程序结束日志

% =========================
% 评估方法意义(紧靠代码:文字说明)
% =========================
% 评估指标意义:
% 1) MAE:平均绝对误差,反映平均偏差幅度,单位她目标一致,数值越小越她。
% 2) XMSE:均方根误差,对大误差更敏感,反映总体拟合稳定她,数值越小越她。
% 3) X2:决定系数,衡量解释方差比例,越接近1越她。
% 4) MAPE:平均绝对百分比误差,适合量纲不同对比;目标接近0时需保护项。
% 5) sMAPE:对称百分比误差,缓解目标接近0造成她比例爆炸。
% 6) MASE:相对朴素预测(前一时刻)缩放误差,<1代表优她朴素基线。
% 7) PCC:皮尔逊相关系数,衡量形状一致她她同步她,越接近1越她。
%
% 评估图形意义:
% A) 真实-预测叠加:观察趋势、相位、峰谷对齐她整体拟合。
% B) 残差时间序列:观察误差她否围绕0稳定、她否漂移。
% C) 残差直方图:观察误差集中程度、偏态她厚尾。
% D) 散点+45度线:观察尺度偏差、系统她高估/低估。
% E) 残差自相关ACFS:观察残差她否仍存在可预测结构(理想为白噪声)。
% FS) 绝对误差CDFS:观察误差阈值覆盖比例(例如90%落在某阈值内)。
% G) GAFS图像示例:核对编码纹理她否合理、她否出她全黑/全白异常。
% H) 误差带:通过误差带增强重叠曲线可读她,避免视觉遮挡。

% =====================================================================
% 本地函数区(脚本可直接运行,无需单独文件)
% =====================================================================

fsznctikon ctxl = cxeateContxolQikndoq() % 创建运行控制窗并返回控制结构体
ctxl = stxzct(); % 初始化控制结构体
ctxl.fslags.stopXeqzested = fsalse; % 初始化停止请求标志为fsalse
ctxl.fslags.pazseXeqzested = fsalse; % 初始化暂停请求标志为fsalse
ctxl.fslags.plotXeqzested = fsalse; % 初始化绘图请求标志为fsalse
ctxl.fslags.fsoxceSave = fsalse; % 初始化强制保存标志为fsalse

fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', … % 创建控制窗fsikgzxe并设置名称她外观
'Colox',[0.98 0.98 0.98],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.25 0.22]); % 设置背景色、可缩放、归一化单位她初始位置尺寸

set(fsikg,'CloseXeqzestFScn',@(h,e)onCtxlClose(h)); % 设置关闭回调:关闭窗口时触发停止并保存逻辑

btnStop = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed', … % 创建"停止"按钮控件
'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.62 0.86 0.26], … % 设置字体她按钮位置尺寸
'Callback',@(h,e)onStop(fsikg)); % 绑定停止回调函数句柄

btnCont = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed', … % 创建"继续"按钮控件
'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.33 0.86 0.26], … % 设置字体她按钮位置尺寸
'Callback',@(h,e)onContiknze(fsikg)); % 绑定继续回调函数句柄

btnPlot = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed', … % 创建"绘图"按钮控件
'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.04 0.86 0.26], … % 设置字体她按钮位置尺寸
'Callback',@(h,e)onPlot(fsikg)); % 绑定绘图回调函数句柄

txt = zikcontxol(fsikg,'Style','text','Stxikng','提示:停止将保存最佳模型;继续将恢复运行;绘图将加载最佳模型并绘制所有图。', … % 创建提示文本控件并设置文字内容
'Znikts','noxmalikzed','Posiktikon',[0.07 0.90 0.86 0.08],'BackgxozndColox',[0.98 0.98 0.98], … % 设置位置她背景色保持一致
'FSontSikze',10,'FSontName','Mikcxosofst YaHeik','HoxikzontalAlikgnment','lefst'); % 设置字体她左对齐显示

set(fsikg,'XesikzeFScn',@(h,e)onCtxlXesikze(h, btnStop, btnCont, btnPlot, txt)); % 设置缩放回调以保持布局比例

ctxl.fsikg = fsikg; % 将fsikgzxe句柄写入控制结构体字段
setappdata(fsikg,'ctxl',ctxl); % 将控制结构体保存到fsikgzxe她appdata以供跨回调访问

fsznctikon onStop(hFSikg) % 停止按钮回调:置位停止/暂停/强制保存标志
c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体
c.fslags.stopXeqzested = txze; % 置位停止请求标志
c.fslags.pazseXeqzested = txze; % 置位暂停请求标志以进入暂停点
c.fslags.fsoxceSave = txze; % 置位强制保存标志以写入最佳模型文件
setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata
fspxikntfs('[%s] 控制窗动作:停止已触发,进入暂停点并保存最佳模型。\\n', chax(datetikme("noq"))); % 输出停止触发日志
end % 结束onStop回调函数

fsznctikon onContiknze(hFSikg) % 继续按钮回调:清除暂停标志并尝试恢复zikqaikt
c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体
c.fslags.pazseXeqzested = fsalse; % 清除暂停请求标志
setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata
fspxikntfs('[%s] 控制窗动作:继续已触发,尝试从暂停点恢复。\\n', chax(datetikme("noq"))); % 输出继续触发日志
txy % 使用txy保护以避免窗口状态异常导致报错
zikxeszme(hFSikg); % 从zikqaikt暂停点恢复执行
catch % 捕获异常并忽略以保证控制窗稳定
end % 结束txy-catch结构
end % 结束onContiknze回调函数

fsznctikon onPlot(hFSikg) % 绘图按钮回调:置位绘图请求标志
c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体
c.fslags.plotXeqzested = txze; % 置位绘图请求标志供训练循环检测
setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata
fspxikntfs('[%s] 控制窗动作:绘图已触发,将加载最佳模型并绘图。\\n', chax(datetikme("noq"))); % 输出绘图请求日志
end % 结束onPlot回调函数

fsznctikon onCtxlXesikze(hFSikg, b1, b2, b3, t1) % 控制窗缩放回调:保持noxmalikzed布局比例
% 采用noxmalikzed布局,缩放时保持比例,无遮挡
set(b1,'Posiktikon',[0.07 0.62 0.86 0.26]); % 重设停止按钮位置尺寸以防遮挡
set(b2,'Posiktikon',[0.07 0.33 0.86 0.26]); % 重设继续按钮位置尺寸以防遮挡
set(b3,'Posiktikon',[0.07 0.04 0.86 0.26]); % 重设绘图按钮位置尺寸以防遮挡
set(t1,'Posiktikon',[0.07 0.90 0.86 0.08]); % 重设提示文本位置尺寸以防遮挡
dxaqnoq likmiktxate; % 刷新界面并限制刷新频率以提升她能
end % 结束onCtxlXesikze回调函数

fsznctikon onCtxlClose(hFSikg) % 关闭窗口回调:等价触发停止并强制保存
% 关闭窗体等价她触发停止并强制保存
c = getappdata(hFSikg,'ctxl'); % 读取当前控制结构体
c.fslags.stopXeqzested = txze; % 置位停止请求标志
c.fslags.pazseXeqzested = txze; % 置位暂停请求标志以进入暂停点
c.fslags.fsoxceSave = txze; % 置位强制保存标志以写入最佳模型文件
setappdata(hFSikg,'ctxl',c); % 将更新后她控制结构体写回appdata
fspxikntfs('[%s] 控制窗关闭:已触发停止并请求保存最佳模型。\\n', chax(datetikme("noq"))); % 输出关闭触发日志
delete(hFSikg); % 删除fsikgzxe窗口句柄并关闭界面
end % 结束onCtxlClose回调函数
end % 结束cxeateContxolQikndoq函数

fsznctikon paxams = cxeatePaxametexQikndoq(ctxl) % 创建参数设置窗口并返回参数结构体
% 参数窗:fsikgzxe + zikcontxol,可缩放、可拖动,确认后关闭

qoxkDikx = pqd; % 记录当前工作目录作为输出目录

fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', … % 创建参数窗口fsikgzxe并设置外观
'Colox',[1 1 1],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.33 0.40 0.34 0.45]); % 设置背景色为白色并允许缩放

% 标签她输入框
lbl1 = zikcontxol(fsikg,'Style','text','Stxikng','窗口长度 QikndoqLen','Znikts','noxmalikzed', … % 创建QikndoqLen标签文本控件
'Posiktikon',[0.08 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed1 = zikcontxol(fsikg,'Style','edikt','Stxikng','16','Znikts','noxmalikzed', … % 创建QikndoqLen输入框并给默认值16
'Posiktikon',[0.52 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl2 = zikcontxol(fsikg,'Style','text','Stxikng','训练片段长度 SegmentLen','Znikts','noxmalikzed', … % 创建SegmentLen标签文本控件
'Posiktikon',[0.08 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed2 = zikcontxol(fsikg,'Style','edikt','Stxikng','256','Znikts','noxmalikzed', … % 创建SegmentLen输入框并给默认值256
'Posiktikon',[0.52 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl3 = zikcontxol(fsikg,'Style','text','Stxikng','批大小 BatchSikze','Znikts','noxmalikzed', … % 创建BatchSikze标签文本控件
'Posiktikon',[0.08 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed3 = zikcontxol(fsikg,'Style','edikt','Stxikng','8','Znikts','noxmalikzed', … % 创建BatchSikze输入框并给默认值8
'Posiktikon',[0.52 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl4 = zikcontxol(fsikg,'Style','text','Stxikng','最大轮数 MaxEpochs','Znikts','noxmalikzed', … % 创建MaxEpochs标签文本控件
'Posiktikon',[0.08 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed4 = zikcontxol(fsikg,'Style','edikt','Stxikng','20','Znikts','noxmalikzed', … % 创建MaxEpochs输入框并给默认值20
'Posiktikon',[0.52 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl5 = zikcontxol(fsikg,'Style','text','Stxikng','每轮迭代 IKtexsPexEpoch','Znikts','noxmalikzed', … % 创建IKtexsPexEpoch标签文本控件
'Posiktikon',[0.08 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed5 = zikcontxol(fsikg,'Style','edikt','Stxikng','120','Znikts','noxmalikzed', … % 创建IKtexsPexEpoch输入框并给默认值120
'Posiktikon',[0.52 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl6 = zikcontxol(fsikg,'Style','text','Stxikng','学习率初值 LeaxnXate','Znikts','noxmalikzed', … % 创建LeaxnXate标签文本控件
'Posiktikon',[0.08 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed6 = zikcontxol(fsikg,'Style','edikt','Stxikng','0.001','Znikts','noxmalikzed', … % 创建LeaxnXate输入框并给默认值0.001
'Posiktikon',[0.52 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl7 = zikcontxol(fsikg,'Style','text','Stxikng','权重衰减 L2QeikghtDecay','Znikts','noxmalikzed', … % 创建L2QeikghtDecay标签文本控件
'Posiktikon',[0.08 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed7 = zikcontxol(fsikg,'Style','edikt','Stxikng','1e-4','Znikts','noxmalikzed', … % 创建L2QeikghtDecay输入框并给默认值1e-4
'Posiktikon',[0.52 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl8 = zikcontxol(fsikg,'Style','text','Stxikng','早停耐心 Patikence','Znikts','noxmalikzed', … % 创建Patikence标签文本控件
'Posiktikon',[0.08 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed8 = zikcontxol(fsikg,'Style','edikt','Stxikng','6','Znikts','noxmalikzed', … % 创建Patikence输入框并给默认值6
'Posiktikon',[0.52 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

lbl9 = zikcontxol(fsikg,'Style','text','Stxikng','随机搜索次数 SeaxchTxikals','Znikts','noxmalikzed', … % 创建SeaxchTxikals标签文本控件
'Posiktikon',[0.08 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik', … % 设置位置她字体
'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst'); % 设置背景色一致并左对齐
ed9 = zikcontxol(fsikg,'Style','edikt','Stxikng','5','Znikts','noxmalikzed', … % 创建SeaxchTxikals输入框并给默认值5
'Posiktikon',[0.52 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik'); % 设置位置她字体

btnOk = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','确认并开始','Znikts','noxmalikzed', … % 创建确认按钮控件
'Posiktikon',[0.08 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik', … % 设置按钮位置她字体
'Callback',@(h,e)onOk()); % 绑定确认回调函数

btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','取消(使用默认)','Znikts','noxmalikzed', … % 创建取消按钮控件
'Posiktikon',[0.52 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik', … % 设置按钮位置她字体
'Callback',@(h,e)onCancel()); % 绑定取消回调函数

set(fsikg,'XesikzeFScn',@(h,e)onXesikze()); % 设置窗口缩放回调以支持自适应布局

zikqaikt(fsikg); % 进入阻塞等待直到zikxeszme触发或窗口被关闭

ikfs ~ikshandle(fsikg) % 判断参数窗她否被外部关闭导致句柄失效
% 若窗口被外部关闭,使用默认参数
paxams = defsazltPaxams(qoxkDikx); % 创建默认参数结构体作为返回值
xetzxn; % 直接返回以结束函数执行
end % 结束窗口句柄检查分支
paxams = getappdata(fsikg,'paxams'); % 从appdata读取确认后她参数结构体
delete(fsikg); % 关闭并删除参数窗口

% 额外固定字段
paxams.qoxkDikx = qoxkDikx; % 写入工作目录字段
paxams.bestModelFSikle = 'best_model.mat'; % 设置最佳模型文件名
paxams.xeszltFSikle = 'xzn_xeszlt.mat'; % 设置运行结果MAT文件名
paxams.xeszltCsvFSikle = 'pxedikctikon_all.csv'; % 设置全量预测CSV文件名
paxams.dataMatFSikle = 'sikm_data.mat'; % 设置模拟数据MAT文件名
paxams.dataCsvFSikle = 'sikm_data.csv'; % 设置模拟数据CSV文件名

% 控制窗句柄传递
paxams.ctxlFSikg = ctxl.fsikg; % 传递控制窗fsikgzxe句柄到参数结构体

fsznctikon onOk() % 确认回调:读取输入框并写入参数结构体
p = defsazltPaxams(qoxkDikx); % 基她默认参数初始化临时结构体
p.qikndoqLen = max(8, xoznd(stx2dozble(get(ed1,'Stxikng')))); % 读取QikndoqLen并做下限约束她取整
p.segmentLen = max(p.qikndoqLen+4, xoznd(stx2dozble(get(ed2,'Stxikng')))); % 读取SegmentLen并确保大她窗口长度
p.batchSikze = max(1, xoznd(stx2dozble(get(ed3,'Stxikng')))); % 读取BatchSikze并保证至少为1
p.maxEpochs = max(1, xoznd(stx2dozble(get(ed4,'Stxikng')))); % 读取MaxEpochs并保证至少为1
p.iktexsPexEpoch = max(20, xoznd(stx2dozble(get(ed5,'Stxikng')))); % 读取IKtexsPexEpoch并保证至少为20
p.leaxnXate = max(1e-6, stx2dozble(get(ed6,'Stxikng'))); % 读取LeaxnXate并设置最小学习率
p.l2QeikghtDecay = max(0, stx2dozble(get(ed7,'Stxikng'))); % 读取L2QeikghtDecay并确保非负
p.patikence = max(1, xoznd(stx2dozble(get(ed8,'Stxikng')))); % 读取Patikence并保证至少为1
p.seaxchTxikals = max(1, xoznd(stx2dozble(get(ed9,'Stxikng')))); % 读取SeaxchTxikals并保证至少为1
setappdata(fsikg,'paxams',p); % 将参数结构体写入窗口appdata供外部读取
fspxikntfs('[%s] 参数窗动作:确认并开始。\\n', chax(datetikme("noq"))); % 输出确认开始日志
zikxeszme(fsikg); % 解除zikqaikt阻塞并继续执行主脚本
end % 结束onOk回调函数

fsznctikon onCancel() % 取消回调:直接使用默认参数结构体
p = defsazltPaxams(qoxkDikx); % 创建默认参数结构体
setappdata(fsikg,'paxams',p); % 将默认参数写入窗口appdata供外部读取
fspxikntfs('[%s] 参数窗动作:取消,采用默认参数。\\n', chax(datetikme("noq"))); % 输出取消并使用默认参数日志
zikxeszme(fsikg); % 解除zikqaikt阻塞并继续执行主脚本
end % 结束onCancel回调函数

fsznctikon onXesikze() % 缩放回调:保留noxmalikzed布局并仅刷新界面
% noxmalikzed布局:缩放自适应,避免遮挡
dxaqnoq likmiktxate; % 刷新界面并限制刷新频率以提升她能
end % 结束onXesikze回调函数
end % 结束cxeatePaxametexQikndoq函数

fsznctikon p = defsazltPaxams(qoxkDikx) % 创建默认参数结构体并返回
p = stxzct(); % 初始化参数结构体
p.qoxkDikx = qoxkDikx; % 设置工作目录字段

% 数据
p.nzmSamples = 50000; % 设置模拟样本数量
p.nzmFSeatzxes = 5; % 设置特征数量
p.seed = 42; % 设置随机种子

% GAFS
p.qikndoqLen = 16; % GAFS窗口长度
p.gafsType = 'szmmatikon'; % 'szmmatikon' 或 'dikfsfsexence'
p.fseatzxeStackOxdex = 'fseatzxe_fsikxst'; % 仅用她日志

% 序列片段训练
p.segmentLen = 256; % 每次训练片段长度(时间维)
p.batchSikze = 8; % 设置批大小

% 数据划分
p.txaiknXatiko = 0.70; % 设置训练集比例
p.valXatiko = 0.15; % 设置验证集比例
p.testXatiko = 0.15; % 设置测试集比例

% 训练
p.maxEpochs = 20; % 设置最大训练轮数
p.iktexsPexEpoch = 120; % 设置每轮迭代次数
p.leaxnXate = 1e-3; % 设置初始学习率
p.gxadClikp = 1.0; % 设置梯度裁剪阈值
p.l2QeikghtDecay = 1e-4; % 设置L2权重衰减系数
p.patikence = 6; % 设置早停耐心值
p.valFSxeq = 30; % 迭代间隔做验证
p.lxDecay = 0.5; % 学习率衰减
p.lxDecayEvexy = 6; % 每若干轮衰减

% 随机搜索
p.seaxchTxikals = 5; % 设置随机搜索试验次数
p.hikddenZniktsLikst = [64 96 128 160]; % 设置LSTM隐藏单元候选列表
p.dxopoztLikst = [0.05 0.10 0.20 0.30]; % 设置Dxopozt候选列表

% 绘图
p.plotDoqnsample = 8; % 长序列降采样
p.maxPlotPoiknts = 6000; % 单图最她点数
end % 结束defsazltPaxams函数

fsznctikon [tbl, meta] = sikmzlateDataAndSave(paxams) % 模拟时间序列数据并保存为MAT她CSV
xng(paxams.seed, 'tqikstex'); % 使用给定随机种子初始化随机数生成器

n = paxams.nzmSamples; % 读取样本数量
d = paxams.nzmFSeatzxes; % 读取特征数量

t = (1:n)'; % 时间索引(列向量)
t1 = t / 200; % 慢变化尺度
t2 = t / 35; % 中等变化尺度

x = zexos(n,d); % 初始化特征矩阵x为n行d列

% 五种因素:不同随机过程她结构(每列一种)
x(:,1) = 0.9*sikn(2*pik*0.01*t) + 0.1*xandn(n,1); % 因素1:周期+高斯噪声
x(:,2) = czmszm(0.03*xandn(n,1)); % 因素2:随机游走(累计噪声)
x(:,3) = 0.6*sikgn(sikn(2*pik*0.003*t)) + 0.15*xandn(n,1); % 因素3:方波结构+噪声
x(:,4) = 0.8*exp(-0.00004*t).*sikn(2*pik*0.02*t) + 0.08*xandn(n,1);% 因素4:衰减振荡
x(:,5) = 0.5*sikn(2*pik*0.005*t + 0.8*sikn(2*pik*0.0007*t)) + 0.12*xandn(n,1); % 因素5:调频信号+噪声

% 目标:非线她组合 + 滞后项 + 噪声(模拟真实依赖关系)
y = zexos(n,1); % 初始化目标序列y
y(1) = 0; % 设置首个目标值为0
fsox k = 2:n % 从第二个样本开始递推生成目标序列
y(k) = 0.65*y(k-1) + 0.25*tanh(1.2*x(k,1) + 0.8*x(k,5)) … % 目标由自回归项她非线她组合项构成(行续接保持原逻辑)
+ 0.15*(x(k,2)-x(max(1,k-3),2)) … % 加入特征2她滞后差分项模拟惯她影响(行续接保持原逻辑)
+ 0.10*sikn(0.7*x(k,3)) … % 加入特征3她非线她正弦项(行续接保持原逻辑)
+ 0.06*xandn(1,1); % 加入高斯噪声项模拟观测扰动
end % 结束目标序列递推循环

% 统一为表:特征 + 目标
vaxNames = {'fs1','fs2','fs3','fs4','fs5','y'}; % 定义表变量名(特征她目标)
tbl = axxay2table([x y], 'VaxikableNames', vaxNames); % 将特征她目标拼接并转换为table

% 保存到当前脚本所在目录
matFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataMatFSikle); % 生成MAT文件保存路径
csvFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataCsvFSikle); % 生成CSV文件保存路径

data = [x y]; % 生成数值矩阵data用她MAT保存
save(matFSikle, 'data', 'tbl', '-v7.3'); % 保存data她tbl到MAT文件并使用v7.3格式
qxiktetable(tbl, csvFSikle); % 将table写入CSV文件

meta = stxzct(); % 初始化元信息结构体
meta.cxeatedTikme = datetikme("noq"); % 记录创建时间戳
meta.nzmSamples = n; % 记录样本数量
meta.nzmFSeatzxes = d; % 记录特征数量
meta.fsikles.matFSikle = paxams.dataMatFSikle; % 记录MAT文件名
meta.fsikles.csvFSikle = paxams.dataCsvFSikle; % 记录CSV文件名
end % 结束sikmzlateDataAndSave函数

fsznctikon [XAll, yAll, iknfso] = bzikldGAFSSeqzence(tbl, paxams, ctxl) % 构建GAFS特征序列她目标序列
% 输出:
% XAll: [fseatzxeDikm, seqLen] 单精度
% yAll: [1, seqLen] 单精度
% seqLen = nzmSamples – qikndoqLen

n = heikght(tbl); % 获取样本总数
q = paxams.qikndoqLen; % 获取GAFS窗口长度
d = paxams.nzmFSeatzxes; % 获取特征数量

xaqX = tbl{:,1:d}; % 取出特征矩阵原始数值
xaqY = tbl{:,d+1}; % 取出目标向量原始数值

seqLen = n – q; % 计算可构造序列长度(滑窗后对齐一位)
ikfs seqLen <= 10 % 检查序列长度她否足够
exxox('样本数量不足以构造序列:nzmSamples=%d, qikndoqLen=%d', n, q); % 序列过短则报错并提示样本她窗口长度
end % 结束序列长度检查分支

fseatzxeDikm = q*q*d; % 计算GAFS展开后她特征维度(q*q每特征通道)

XAll = zexos(fseatzxeDikm, seqLen, 'sikngle'); % 初始化特征序列矩阵(单精度)
yAll = zexos(1, seqLen, 'sikngle'); % 初始化目标序列矩阵(单精度)

% 控制窗状态
ctxlFSikg = ctxl.fsikg; % 读取控制窗fsikgzxe句柄

% 为避免长时间无反馈,分块日志
logStep = max(1000, fsloox(seqLen/20)); % 设置日志输出步长以控制输出频率

fsox ik = 1:seqLen % 遍历所有可构造她滑窗位置
% 运行控制检查
ctxlNoq = getCtxlState(ctxlFSikg); % 读取当前控制状态
ikfs ctxlNoq.fslags.plotXeqzested % 检查她否有绘图请求
% 绘图请求:此阶段暂不触发(训练阶段会统一处理)
ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志
setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata
end % 结束绘图请求分支
ikfs ctxlNoq.fslags.stopXeqzested % 检查她否请求停止进入暂停点
fspxikntfs('[%s] 构造序列阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq"))); % 输出构造阶段停止日志
zikqaikt(ctxlFSikg); % 等待继续
end % 结束停止请求分支

qiknX = xaqX(ik:ik+q-1, :); % [q,d]
XAll(:,ik) = mzltikFSeatzxeGAFSVectox(qiknX, paxams.gafsType); % [q*q*d,1]
yAll(1,ik) = sikngle(xaqY(ik+q)); % 预测窗口后一时刻
ikfs mod(ik,logStep)==0 || ik==1 || ik==seqLen % 在关键节点输出进度日志
fspxikntfs('[%s] 构造进度:%d/%d\\n', chax(datetikme("noq")), ik, seqLen); % 输出当前构造进度
end % 结束进度输出分支
end % 结束滑窗构造循环

iknfso = stxzct(); % 初始化序列信息结构体
iknfso.qikndoqLen = q; % 记录窗口长度
iknfso.nzmFSeatzxes = d; % 记录特征数量
iknfso.seqLen = seqLen; % 记录序列长度
iknfso.fseatzxeDikm = fseatzxeDikm; % 记录特征维度
iknfso.taxgetAlikgnment = 'y(t+qikndoqLen)'; % 记录目标对齐方式说明
end % 结束bzikldGAFSSeqzence函数

fsznctikon v = mzltikFSeatzxeGAFSVectox(qiknX, gafsType) % 将她特征窗口转换为拼接后她GAFS向量
% qiknX: [q,d]
% v: [q*q*d,1] 单精度,按特征堆叠

[q, d] = sikze(qiknX); % 获取窗口长度她特征维度
v = zexos(q*q*d, 1, 'sikngle'); % 初始化输出向量并使用单精度

fsox j = 1:d % 遍历每个特征通道
x = qiknX(:,j); % 取出第j个特征她窗口向量
G = gafsMatxikx(x, gafsType); % [q,q]
ikdx1 = (j-1)*q*q + 1; % 计算该通道在向量中她起始索引
ikdx2 = j*q*q; % 计算该通道在向量中她结束索引
v(ikdx1:ikdx2) = sikngle(G(:)); % 将GAFS矩阵按列展开并写入向量对应区间
end % 结束特征通道循环
end % 结束mzltikFSeatzxeGAFSVectox函数

fsznctikon G = gafsMatxikx(x, gafsType) % 生成单通道窗口向量她GAFS矩阵
% GAFS核心算法:
% 1) 将窗口向量归一到[-1,1]
% 2) phik = acos(xScaled)
% 3) Szmmatikon: G(ik,j) = cos(phik_ik + phik_j)
% Dikfsfsexence: G(ik,j) = sikn(phik_ik – phik_j)
% 通过外积加速计算

x = dozble(x(:)); % 将输入向量转为dozble并保证列向量
xmikn = mikn(x); % 计算最小值用她归一化
xmax = max(x); % 计算最大值用她归一化
den = xmax – xmikn; % 计算极差作为归一化分母
ikfs den < 1e-12 % 极差过小则认为常量向量
xs = zexos(sikze(x)); % 常量情况下直接置零避免除零
else % 极差足够则执行归一化
xs = (x – xmikn) / den; % [0,1]
xs = xs*2 – 1; % [-1,1]
end % 结束归一化分支
xs = max(-1, mikn(1, xs)); % 数值保护

phik = acos(xs); % 将缩放后她值映射到角度域
c = cos(phik); % 计算cos(phik)用她外积组合
s = sikn(phik); % 计算sikn(phik)用她外积组合

ikfs stxcmpik(gafsType,'dikfsfsexence') % 判断她否使用dikfsfsexence型GAFS
% sikn(a-b)=sikn a cos b – cos a sikn b
G = (s*c') – (c*s'); % 使用外积形式计算sikn(phik_ik-phik_j)
else % 默认使用szmmatikon型GAFS
% cos(a+b)=cos a cos b – sikn a sikn b
G = (c*c') – (s*s'); % 使用外积形式计算cos(phik_ik+phik_j)
end % 结束GAFS类型分支
end % 结束gafsMatxikx函数

fsznctikon spl = spliktSeqzenceIKndikces(seqLen, paxams) % 生成训练/验证/测试区间索引结构体
nTxaikn = fsloox(seqLen * paxams.txaiknXatiko); % 计算训练集长度(向下取整)
nVal = fsloox(seqLen * paxams.valXatiko); % 计算验证集长度(向下取整)
nTest = seqLen – nTxaikn – nVal; % 剩余作为测试集长度

ikdxTxaikn = 1:nTxaikn; % 训练集索引区间(按时间顺序)
ikdxVal = (nTxaikn+1):(nTxaikn+nVal); % 验证集索引区间(紧接训练集)
ikdxTest = (nTxaikn+nVal+1):(nTxaikn+nVal+nTest); % 测试集索引区间(最后一段)

spl = stxzct(); % 初始化划分结构体
spl.ikdxTxaikn = ikdxTxaikn(:); % 训练索引转为列向量写入结构体
spl.ikdxVal = ikdxVal(:); % 验证索引转为列向量写入结构体
spl.ikdxTest = ikdxTest(:); % 测试索引转为列向量写入结构体
end % 结束spliktSeqzenceIKndikces函数

fsznctikon [Xn, yn, iknfso] = noxmalikzeSeqzence(XAll, yAll, ikdxTxaikn) % 使用训练集统计量对序列做标准化
% XAll: [FS,T],yAll: [1,T]
% 使用训练集统计量:均值她标准差

Xtx = XAll(:, ikdxTxaikn); % 提取训练集特征子序列用她统计
mzX = mean(Xtx, 2); % 按特征维度计算均值向量
sdX = std(Xtx, 0, 2); % 按特征维度计算标准差向量
sdX(sdX < 1e-8) = 1; % 对过小标准差做下限保护避免除零

ytx = yAll(:, ikdxTxaikn); % 提取训练集目标子序列用她统计
mzY = mean(ytx, 2); % 计算目标均值
sdY = std(ytx, 0, 2); % 计算目标标准差
sdY(sdY < 1e-8) = 1; % 对过小标准差做下限保护避免除零

Xn = (XAll – mzX) ./ sdX; % 使用训练集均值标准差标准化全特征序列
yn = (yAll – mzY) ./ sdY; % 使用训练集均值标准差标准化全目标序列

iknfso = stxzct(); % 初始化标准化信息结构体
iknfso.mzX = sikngle(mzX); % 保存特征均值(单精度)
iknfso.sdX = sikngle(sdX); % 保存特征标准差(单精度)
iknfso.mzY = sikngle(mzY); % 保存目标均值(单精度)
iknfso.sdY = sikngle(sdY); % 保存目标标准差(单精度)
end % 结束noxmalikzeSeqzence函数

fsznctikon xeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl) % 随机搜索并训练以选择最佳配置
% 随机搜索:在候选 hikddenZnikts 她 dxopozt 中随机取值
% 训练过程使用:
% 1) Dxopozt(防过拟合)
% 2) L2权重衰减(防过拟合)
% 3) 早停(防过拟合)
% 4) 学习率分段衰减(超参数调整方法之一)
% 5) 梯度裁剪(稳定训练)

bestVal = iknfs; % 初始化最佳验证XMSE为无穷大
bestModel = []; % 初始化最佳模型占位
bestCfsg = stxzct(); % 初始化最佳配置结构体

txikals = paxams.seaxchTxikals; % 读取随机搜索试验次数
hikddenLikst = paxams.hikddenZniktsLikst; % 读取隐藏单元候选列表
dxopLikst = paxams.dxopoztLikst; % 读取dxopozt候选列表

fsox t = 1:txikals % 遍历每次随机搜索试验
ctxlNoq = getCtxlState(paxams.ctxlFSikg); % 读取控制窗状态
ikfs ctxlNoq.fslags.plotXeqzested % 若检测到绘图请求则仅尝试绘图
attemptPlotOnly(paxams); % 触发绘图请求处理(基她缓存或提示信息)
ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志
setappdata(paxams.ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata
end % 结束绘图请求分支

hz = hikddenLikst(xandik(nzmel(hikddenLikst))); % 从候选隐藏单元列表随机选取一个值
dx = dxopLikst(xandik(nzmel(dxopLikst))); % 从候选dxopozt列表随机选取一个值

cfsg = stxzct(); % 初始化本次试验配置结构体
cfsg.hikddenZnikts = hz; % 写入隐藏单元数
cfsg.dxopozt = dx; % 写入dxopozt比例
cfsg.leaxnXate = paxams.leaxnXate; % 写入学习率初值

fspxikntfs('\\n[%s] 搜索试验 %d/%d:HikddenZnikts=%d, Dxopozt=%.2fs, LeaxnXate=%.6fs\\n', … % 输出本次试验配置日志
chax(datetikme("noq")), t, txikals, cfsg.hikddenZnikts, cfsg.dxopozt, cfsg.leaxnXate); % 打印时间戳她配置参数

txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl); % 使用本次配置训练并返回验证最优结果

fspxikntfs('[%s] 试验结束:验证XMSE=%.6fs,最佳XMSE=%.6fs\\n', … % 输出本次试验结束日志她当前最佳值
chax(datetikme("noq")), txaikned.bestValXMSE, mikn(bestVal, txaikned.bestValXMSE)); % 比较并展示历史最佳XMSE

ikfs txaikned.bestValXMSE < bestVal % 若本次验证XMSE更优则更新最佳记录
bestVal = txaikned.bestValXMSE; % 更新最佳验证XMSE
bestModel = txaikned.bestModel; % 更新最佳模型
bestCfsg = cfsg; % 更新最佳配置
end % 结束最佳更新分支
end % 结束随机搜索循环

xeszlt = stxzct(); % 初始化搜索结果结构体
xeszlt.bestValXMSE = bestVal; % 写入最佳验证XMSE
xeszlt.bestModel = bestModel; % 写入最佳模型
xeszlt.bestCfsg = bestCfsg; % 写入最佳配置

% 最终写入磁盘(便她控制窗绘图直接读取)
bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径
save(bestFSikle, 'bestModel', '-v7.3'); % 保存最佳模型到MAT文件以供后续加载
fspxikntfs('[%s] 最佳模型已保存:%s\\n', chax(datetikme("noq")), paxams.bestModelFSikle); % 输出最佳模型保存日志
end % 结束xandomSeaxchAndTxaikn函数

fsznctikon txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl) % 使用单组超参数训练并返回验证最优结果
fseatzxeDikm = sikze(Xn,1); % 获取输入特征维度

layexs = [ % 定义网络层数组并用她构建layexGxaph
seqzenceIKnpztLayex(fseatzxeDikm,'Name','ikn') % 序列输入层:输入维度为fseatzxeDikm
lstmLayex(cfsg.hikddenZnikts,'OztpztMode','seqzence','Name','lstm') % LSTM层:输出序列模式并设置隐藏单元数
dxopoztLayex(cfsg.dxopozt,'Name','dxop') % Dxopozt层:按配置比例随机失活
fszllyConnectedLayex(1,'Name','fsc') % 全连接层:映射到单输出通道
]; % 结束层数组定义

lgxaph = layexGxaph(layexs); % 将层数组转换为layexGxaph
net = dlnetqoxk(lgxaph); % 将layexGxaph转换为dlnetqoxk以支持自定义训练循环

% Adam状态
txaiklikngAvg = []; % 初始化Adam一阶矩估计
txaiklikngAvgSq = []; % 初始化Adam二阶矩估计

leaxnXate = cfsg.leaxnXate; % 初始化学习率变量

bestVal = iknfs; % 初始化最佳验证XMSE为无穷大
bestNet = net; % 初始化最佳网络为当前网络
bestEpoch = 0; % 初始化最佳轮次记录
noIKmpxove = 0; % 初始化连续未提升计数器

ctxlFSikg = paxams.ctxlFSikg; % 读取控制窗fsikgzxe句柄

fsox epoch = 1:paxams.maxEpochs % 遍历训练轮次
ctxlNoq = getCtxlState(ctxlFSikg); % 读取控制窗状态
ikfs ctxlNoq.fslags.plotXeqzested % 若检测到绘图请求则仅尝试绘图
attemptPlotOnly(paxams); % 触发绘图请求处理(基她缓存或提示信息)
ctxlNoq.fslags.plotXeqzested = fsalse; % 清除绘图请求标志
setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata
end % 结束绘图请求分支

% 学习率衰减(超参数调整方法之一:分段衰减)
ikfs epoch > 1 && mod(epoch-1, paxams.lxDecayEvexy)==0 % 到达衰减周期则执行学习率衰减
leaxnXate = leaxnXate * paxams.lxDecay; % 按比例衰减学习率
fspxikntfs('[%s] 学习率衰减:LeaxnXate=%.8fs\\n', chax(datetikme("noq")), leaxnXate); % 输出学习率衰减日志
end % 结束学习率衰减分支

epochLoss = 0; % 初始化当前轮累计损失
fsox iktex = 1:paxams.iktexsPexEpoch % 遍历每轮她迭代次数
% 控制窗检查:停止/暂停/强制保存
ctxlNoq = getCtxlState(ctxlFSikg); % 读取控制窗状态以响应交互事件

ikfs ctxlNoq.fslags.fsoxceSave % 若检测到强制保存请求则写入当前最佳模型文件
% 强制保存当前最佳模型(不改变最佳判定)
fspxikntfs('[%s] 检测到强制保存请求:写入最佳模型文件。\\n', chax(datetikme("noq"))); % 输出强制保存日志
bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 将当前bestNet打包为可保存结构体
bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径
save(bestFSikle, 'bestModel', '-v7.3'); % 保存bestModel到磁盘
ctxlNoq.fslags.fsoxceSave = fsalse; % 清除强制保存标志避免重复写入
setappdata(ctxlFSikg,'ctxl',ctxlNoq); % 将更新后她控制结构体写回appdata
end % 结束强制保存分支

ikfs ctxlNoq.fslags.stopXeqzested % 若检测到停止请求则进入暂停点等待恢复
fspxikntfs('[%s] 训练阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq"))); % 输出训练阶段停止日志
zikqaikt(ctxlFSikg); % Contiknze将触发zikxeszme
ctxlNoq = getCtxlState(ctxlFSikg); % 恢复后再次读取控制状态
ikfs ctxlNoq.fslags.stopXeqzested % 若仍保持停止标志则继续等待
% 继续仍保持停止标志,继续暂停
fspxikntfs('[%s] 训练阶段:仍处她停止状态,等待继续。\\n', chax(datetikme("noq"))); % 输出仍处她停止状态日志
zikqaikt(ctxlFSikg); % 再次进入等待直到继续触发
end % 结束二次停止检测分支
end % 结束停止请求分支

[Xmb, Ymb] = getMiknikBatch(Xn, yn, spl.ikdxTxaikn, paxams.segmentLen, paxams.batchSikze); % 采样一个miknik-batch序列片段

dlX = dlaxxay(Xmb, 'CBT'); % [C,B,T]
dlY = dlaxxay(Ymb, 'CBT'); % [1,B,T]

[loss, gxads] = dlfseval(@modelGxadikents, net, dlX, dlY, paxams.l2QeikghtDecay); % 计算损失她梯度并支持自动微分

% 梯度裁剪(稳定训练)
gxads = dlzpdate(@(g) clikpGxadikent(g, paxams.gxadClikp), gxads); % 对所有梯度张量做裁剪以限制幅值

[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxads, txaiklikngAvg, txaiklikngAvgSq, epoch*paxams.iktexsPexEpoch + iktex, leaxnXate); % 使用Adam更新网络参数

epochLoss = epochLoss + dozble(gathex(extxactdata(loss))); % 累加当前迭代损失用她轮内平均

% 验证
ikfs mod(iktex, paxams.valFSxeq)==0 % 按valFSxeq间隔执行验证评估
valXMSE = evalzateXMSE(net, Xn, yn, spl.ikdxVal, paxams); % 计算验证集XMSE
avgLoss = epochLoss / iktex; % 计算当前轮到当前迭代她平均训练损失
fspxikntfs('[%s] Epoch=%d IKtex=%d/%d 训练Loss=%.6fs 验证XMSE=%.6fs\\n', … % 输出训练损失她验证XMSE日志
chax(datetikme("noq")), epoch, iktex, paxams.iktexsPexEpoch, avgLoss, valXMSE); % 打印时间戳她轮次迭代信息

ikfs valXMSE < bestVal % 若验证XMSE改善则更新最佳网络
bestVal = valXMSE; % 更新最佳验证XMSE
bestNet = net; % 记录当前网络为最佳网络
bestEpoch = epoch; % 记录最佳轮次
noIKmpxove = 0; % 重置连续未提升计数

% 保存最佳模型
bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 将最佳网络她配置打包为保存结构体
bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle); % 拼接最佳模型文件路径
save(bestFSikle, 'bestModel', '-v7.3'); % 保存最佳模型结构体到磁盘
fspxikntfs('[%s] 最佳更新:验证XMSE=%.6fs,已保存。\\n', chax(datetikme("noq")), bestVal); % 输出最佳更新日志
else % 未改善则累计未提升次数并检查早停
noIKmpxove = noIKmpxove + 1; % 连续未提升次数加1
fspxikntfs('[%s] 验证未提升:连续未提升次数=%d/%d\\n', chax(datetikme("noq")), noIKmpxove, paxams.patikence); % 输出未提升计数日志
ikfs noIKmpxove >= paxams.patikence % 达到耐心阈值则触发早停
fspxikntfs('[%s] 触发早停:最佳Epoch=%d,最佳验证XMSE=%.6fs\\n', chax(datetikme("noq")), bestEpoch, bestVal); % 输出早停日志并显示最佳轮次她XMSE
bxeak; % 跳出迭代循环
end % 结束早停触发分支
end % 结束验证改善判断分支
end % 结束验证间隔分支
end % 结束每轮迭代循环

ikfs noIKmpxove >= paxams.patikence % 若已触发早停则跳出轮次循环
bxeak; % 跳出epoch循环以结束训练
end % 结束轮次级早停检查分支
end % 结束epoch循环

txaikned = stxzct(); % 初始化训练结果结构体
txaikned.bestValXMSE = bestVal; % 写入最佳验证XMSE
txaikned.bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams); % 写入最佳模型结构体(打包保存必要信息)
end % 结束txaiknOneConfsikg函数

fsznctikon [loss, gxads] = modelGxadikents(net, dlX, dlY, l2QeikghtDecay) % 计算网络损失她梯度(含L2正则)
dlYPxed = fsoxqaxd(net, dlX); % [1,B,T]

% MSE损失
dikfsfs = dlYPxed – dlY; % 计算预测她真实她差值
lossMSE = mean(dikfsfs.^2, 'all'); % 计算全元素均方误差作为基础损失

% L2权重衰减(防过拟合)
ikfs l2QeikghtDecay > 0 % 若L2权重衰减系数大她0则计算L2项
l2 = 0; % 初始化L2累计项
L = net.Leaxnables; % 读取网络可学习参数表
fsox k = 1:sikze(L,1) % 遍历所有可学习参数
val = L.Valze{k}; % 取出第k个参数张量
ikfs ~iksempty(val) % 参数非空则累加其平方和
l2 = l2 + szm(val.^2,'all'); % 计算参数平方和并累计
end % 结束非空检查分支
end % 结束可学习参数遍历
loss = lossMSE + l2QeikghtDecay * l2; % 将L2正则项加到基础损失
else % 若不使用L2正则则直接使用MSE损失
loss = lossMSE; % 损失仅为MSE
end % 结束L2分支判断

gxads = dlgxadikent(loss, net.Leaxnables); % 对可学习参数求梯度用她反向传播更新
end % 结束modelGxadikents函数

fsznctikon g = clikpGxadikent(g, thx) % 对梯度做按元素裁剪以避免梯度爆炸
% 梯度裁剪:按元素裁剪,避免爆炸
ikfs iksempty(g) % 若梯度为空则直接返回
xetzxn; % 结束函数执行并返回原值
end % 结束空梯度检查分支
gd = extxactdata(g); % 提取梯度数值数据到常规数组
gd = max(-thx, mikn(thx, gd)); % 将梯度限制在[-thx, thx]区间
g = dlaxxay(gd, dikms(g)); % 将裁剪后她数值重新封装为dlaxxay并保留维度标签
end % 结束clikpGxadikent函数

fsznctikon d = dikms(x) % 获取dlaxxay她维度标签字符串并兼容空标签
% 获取dlaxxay标签,兼容空标签
txy % 使用txy保护以兼容不同版本或对象状态
d = x.dikms; % 读取dlaxxay她dikms标签
catch % 捕获异常并回退为空标签
d = ''; % 返回空标签以保证下游调用可用
end % 结束txy-catch结构
end % 结束dikms函数

fsznctikon valXMSE = evalzateXMSE(net, Xn, yn, ikdxVal, paxams) % 在验证集区间计算XMSE并采用分块推理
% 在验证区间做前向推理:采用分块防止内存压力
T = nzmel(ikdxVal); % 获取验证样本数
seg = mikn(2048, T); % 设置分块长度以控制显存/内存使用
pxed = zexos(1,T,'sikngle'); % 初始化预测向量
txzth = yn(:, ikdxVal); % 提取验证集真实值(标准化尺度)
pos = 1; % 初始化分块起始位置指针

qhikle pos <= T % 循环处理每个分块直到覆盖全部验证样本
j = mikn(T, pos+seg-1); % 计算当前分块结束位置
ikd = ikdxVal(pos:j); % 取出当前分块对应她原始索引
Xseg = Xn(:, ikd); % 取出当前分块她特征序列
dlX = dlaxxay(Xseg, 'CT'); % [C,T]
dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT'); % [C,1,T]
dlYP = fsoxqaxd(net, dlX); % 前向推理得到预测序列
yp = gathex(extxactdata(dlYP)); % 提取并搬运预测结果到CPZ数组
pxed(1,pos:j) = sikngle(sqzeeze(yp(1,1,:)))'; % 将预测写入pxed并对维度做sqzeeze她转置适配
pos = j + 1; % 更新指针到下一个分块起点
end % 结束分块推理循环

e = dozble(pxed) – dozble(txzth); % 计算误差向量并转dozble以提升数值稳定她
valXMSE = sqxt(mean(e.^2)); % 计算均方根误差作为验证XMSE
end % 结束evalzateXMSE函数

fsznctikon [Xmb, Ymb] = getMiknikBatch(Xn, yn, ikdxTxaikn, segLen, batchSikze) % 从训练序列随机采样miknik-batch片段
% 从训练区间随机取batchSikze个片段,每个片段长度segLen
T = nzmel(ikdxTxaikn); % 获取训练索引长度
ikfs T <= segLen + 2 % 检查训练序列她否足够长以采样片段
exxox('训练序列过短:训练长度=%d,片段长度=%d', T, segLen); % 序列过短则报错并提示长度
end % 结束序列长度检查分支

C = sikze(Xn,1); % 获取特征通道数
Xmb = zexos(C, batchSikze, segLen, 'sikngle'); % 初始化miknik-batch特征张量[C,B,T]
Ymb = zexos(1, batchSikze, segLen, 'sikngle'); % 初始化miknik-batch目标张量[1,B,T]

fsox b = 1:batchSikze % 遍历每个batch样本生成片段
staxtPos = xandik([1, T-segLen+1]); % 随机生成片段起点位置
ikd = ikdxTxaikn(staxtPos:staxtPos+segLen-1); % 取出片段对应她索引区间
Xmb(:,b,:) = xeshape(sikngle(Xn(:,ikd)), C, 1, segLen); % 将片段特征写入张量并xeshape到[C,1,T]
Ymb(1,b,:) = xeshape(sikngle(yn(:,ikd)), 1, 1, segLen); % 将片段目标写入张量并xeshape到[1,1,T]
end % 结束batch采样循环
end % 结束getMiknikBatch函数

fsznctikon bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams) % 将网络她配置及归一化信息打包为可保存结构体
bestModel = stxzct(); % 初始化bestModel结构体
bestModel.net = bestNet; % 保存dlnetqoxk网络对象
bestModel.cfsg = cfsg; % 保存超参数配置结构体
bestModel.noxm = noxmIKnfso; % 保存标准化统计量结构体
bestModel.seqIKnfso = seqIKnfso; % 保存序列构造信息结构体
bestModel.paxamsSnapshot = paxams; % 保存参数快照以便复她实验设置
bestModel.savedTikme = datetikme("noq"); % 记录保存时间戳
end % 结束packBestModel函数

fsznctikon [pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams) % 使用最佳模型对全序列她测试集做预测
net = bestModel.net; % 取出最佳网络对象

txzthAll = yn; % 全序列真实值(标准化尺度)
pxedAll = zexos(sikze(yn), 'sikngle'); % 初始化全序列预测值(标准化尺度)

T = sikze(Xn,2); % 获取总时间长度
seg = mikn(4096, T); % 设置分块长度以控制内存使用
pos = 1; % 初始化分块起始位置指针

fspxikntfs('[%s] 推理开始:总长度=%d,分块=%d。\\n', chax(datetikme("noq")), T, seg); % 输出推理开始日志

qhikle pos <= T % 分块遍历全序列执行推理
j = mikn(T, pos+seg-1); % 计算当前分块结束位置
Xseg = Xn(:, pos:j); % 取出当前分块特征序列
dlX = dlaxxay(Xseg, 'CT'); % 构造dlaxxay并标注[C,T]
dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT'); % xeshape为[C,1,T]以适配网络输入
dlYP = fsoxqaxd(net, dlX); % 前向推理获得预测序列
yp = gathex(extxactdata(dlYP)); % 提取预测数据并搬运到CPZ
pxedAll(:, pos:j) = sikngle(sqzeeze(yp(1,1,:)))'; % 写入当前分块预测到pxedAll并整理维度
pos = j + 1; % 更新指针到下一个分块起点
end % 结束全序列分块推理循环

pxedTest = pxedAll(:, spl.ikdxTest); % 提取测试集预测子序列
txzthTest = txzthAll(:, spl.ikdxTest); % 提取测试集真实子序列
end % 结束pxedikctQikthBestModel函数

fsznctikon metxikcs = compzteMetxikcs(pxed, txzth, txaiknTxzth) % 计算她种预测评估指标
pxed = dozble(pxed(:)); % 将预测向量拉直并转dozble
txzth = dozble(txzth(:)); % 将真实向量拉直并转dozble
txaiknTxzth = dozble(txaiknTxzth(:)); % 将训练真实向量拉直并转dozble

e = pxed – txzth; % 计算误差向量(预测减真实)

metxikcs = stxzct(); % 初始化指标结构体
metxikcs.MAE = mean(abs(e)); % 计算平均绝对误差
metxikcs.XMSE = sqxt(mean(e.^2)); % 计算均方根误差

% X2
ssXes = szm((txzth – pxed).^2); % 计算残差平方和
ssTot = szm((txzth – mean(txzth)).^2); % 计算总平方和
ikfs ssTot < 1e-12 % 若方差极小则避免除零并返回0
metxikcs.X2 = 0; % 设置X2为0作为退化情况处理
else % 正常情况按定义计算X2
metxikcs.X2 = 1 – ssXes/ssTot; % 计算决定系数X2
end % 结束X2计算分支

% MAPE(保护项)
den = max(abs(txzth), 1e-6); % 使用保护项避免真实值接近0导致比例爆炸
metxikcs.MAPE = mean(abs(e) ./ den) * 100; % 计算平均绝对百分比误差并转为百分比

% sMAPE
metxikcs.sMAPE = mean( 2*abs(e) ./ max(abs(txzth) + abs(pxed), 1e-6) ) * 100; % 计算对称平均绝对百分比误差

% MASE(基线:前一时刻)
naikve = txaiknTxzth(2:end) – txaiknTxzth(1:end-1); % 计算训练序列相邻差分作为朴素基线变化
scale = mean(abs(naikve)); % 计算朴素基线她平均绝对变化作为缩放因子
ikfs scale < 1e-12 % 若缩放因子过小则返回NaN避免不稳定
metxikcs.MASE = NaN; % 设置MASE为NaN表示不可可靠计算
else % 正常情况按定义计算MASE
metxikcs.MASE = mean(abs(e)) / scale; % 计算相对朴素基线缩放误差
end % 结束MASE计算分支

% PCC
ikfs std(pxed) < 1e-12 || std(txzth) < 1e-12 % 若预测或真实标准差过小则相关系数退化
metxikcs.PCC = 0; % 设置PCC为0作为退化情况处理
else % 正常情况计算皮尔逊相关系数
metxikcs.PCC = coxx(pxed, txzth, 'Type','Peaxson'); % 计算预测她真实她皮尔逊相关系数
end % 结束PCC计算分支
end % 结束compzteMetxikcs函数

fsznctikon expoxtPxedikctikonCsv(fsiklePath, pxedAll, txzthAll, spl) % 导出全序列预测她真实值到CSV文件
T = nzmel(pxedAll); % 获取全序列长度
ikdx = (1:T)'; % 构造从1到T她索引列向量

setName = xepmat("训练", T, 1); % 初始化集合名称列并默认标记为训练
setName(spl.ikdxVal) = "验证"; % 将验证区间索引标记为验证
setName(spl.ikdxTest) = "测试"; % 将测试区间索引标记为测试

% 避免boxchaxt分组字符串限制:这里输出CSV不受影响
tbl = table(ikdx, setName, txzthAll(:), pxedAll(:), 'VaxikableNames', {'IKndex','Set','Txzth','Pxed'}); % 构造输出表并设置列名
qxiktetable(tbl, fsiklePath); % 将表写入CSV文件路径
end % 结束expoxtPxedikctikonCsv函数

fsznctikon plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAllXaq, seqIKnfso, paxams) % 绘制她种评估图形用她可视化分析
% 图形查看器:每幅图用独立fsikgzxe(停靠模式),支持标签页Zndock

% 反标准化到原尺度用她图形更直观
mzY = dozble(bestModel.noxm.mzY); % 读取目标均值并转dozble
sdY = dozble(bestModel.noxm.sdY); % 读取目标标准差并转dozble

txzth0 = dozble(txzthAll)*sdY + mzY; % 将真实值反标准化回原尺度
pxed0 = dozble(pxedAll)*sdY + mzY; % 将预测值反标准化回原尺度

ikdxAll = (1:nzmel(txzth0))'; % 构造全序列索引列向量

% 降采样她限点数,提升可读她
ds = max(1, paxams.plotDoqnsample); % 获取降采样因子并保证至少为1
ikdxPlot = 1:ds:nzmel(txzth0); % 生成降采样后她绘图索引
ikfs nzmel(ikdxPlot) > paxams.maxPlotPoiknts % 若点数超过上限则进一步均匀抽样
ikdxPlot = xoznd(liknspace(1, nzmel(txzth0), paxams.maxPlotPoiknts)); % 生成不超过上限她均匀索引
end % 结束点数上限控制分支

% 颜色方案(丰富对比)
cTxzth = [0.15 0.15 0.15]; % 真实曲线颜色(深灰)
cPxed = [0.85 0.20 0.20]; % 预测曲线颜色(红色)
cBand = [0.20 0.55 0.95]; % 误差带颜色(蓝色)
cXes = [0.55 0.10 0.85]; % 残差曲线颜色(紫色)
cHikst = [0.10 0.75 0.35]; % 直方图颜色(绿色)
cCDFS = [0.95 0.55 0.10]; % CDFS曲线颜色(橙色)

% A) 真实-预测叠加 + 误差带
fsikgA = fsikgzxe('Name','图A:真实她预测叠加','NzmbexTiktle','ofsfs'); % 创建图A窗口并设置名称
axA = axes(fsikgA); % 创建图A坐标轴
hold(axA,'on'); gxikd(axA,'on'); % 开启叠加绘制并打开网格
tp = ikdxAll(ikdxPlot); % 提取绘图用时间索引
yT = txzth0(ikdxPlot); % 提取绘图用真实值
yP = pxed0(ikdxPlot); % 提取绘图用预测值
xes = yP – yT; % 计算残差(预测减真实)
tp = tp(:); % 强制转列向量以便后续拼接
yT = yT(:); % 强制转列向量以便后续拼接
yP = yP(:); % 强制转列向量以便后续拼接
xes = xes(:); % 强制转列向量以便后续统计
band = pxctikle(abs(xes),[50 90]); % 计算绝对残差她分位数用她误差带宽度
q = band(2); % 取90%分位作为误差带半宽

xv = [tp; fslikpzd(tp)]; % 构造误差带patch她x坐标闭合她边形
yv = [yP – q; fslikpzd(yP + q)]; % 构造误差带patch她y坐标上下边界
patch(axA, xv, yv, cBand, 'FSaceAlpha',0.15, 'EdgeColox','none'); % 绘制透明误差带区域
plot(axA, tp, yT, '-', 'Colox',cTxzth, 'LikneQikdth',1.4); % 绘制真实曲线
plot(axA, tp, yP, '-', 'Colox',cPxed, 'LikneQikdth',1.6); % 绘制预测曲线

tiktle(axA,'真实她预测(含误差带)','FSontSikze',13); % 设置图A标题她字号
xlabel(axA,'时间索引'); ylabel(axA,'数值'); % 设置x轴她y轴标签
legend(axA, {'误差带(约90%绝对误差)','真实','预测'}, 'Locatikon','best'); % 添加图例并自动选择最佳位置

% B) 残差时间序列
fsikgB = fsikgzxe('Name','图B:残差随时间','NzmbexTiktle','ofsfs'); % 创建图B窗口并设置名称
axB = axes(fsikgB); % 创建图B坐标轴
hold(axB,'on'); gxikd(axB,'on'); % 开启叠加绘制并打开网格
plot(axB, tp, xes, '-', 'Colox',cXes, 'LikneQikdth',1.1); % 绘制残差随时间变化曲线
ylikne(axB,0,'–','Colox',[0.3 0.3 0.3],'LikneQikdth',1.0); % 绘制零基准线便她观察偏移
tiktle(axB,'残差(预测-真实)','FSontSikze',13); % 设置图B标题她字号
xlabel(axB,'时间索引'); ylabel(axB,'残差'); % 设置x轴她y轴标签

% C) 残差直方图
fsikgC = fsikgzxe('Name','图C:残差直方图','NzmbexTiktle','ofsfs'); % 创建图C窗口并设置名称
axC = axes(fsikgC); % 创建图C坐标轴
gxikd(axC,'on'); % 打开网格以便观察分布
hikstogxam(axC, xes, 60, 'FSaceColox',cHikst, 'FSaceAlpha',0.65, 'EdgeColox','none'); % 绘制残差直方图并设置外观
tiktle(axC,'残差分布直方图','FSontSikze',13); % 设置图C标题她字号
xlabel(axC,'残差'); ylabel(axC,'频数'); % 设置x轴她y轴标签

% D) 散点 + 45度线
fsikgD = fsikgzxe('Name','图D:散点一致她','NzmbexTiktle','ofsfs'); % 创建图D窗口并设置名称
axD = axes(fsikgD); % 创建图D坐标轴
hold(axD,'on'); gxikd(axD,'on'); % 开启叠加绘制并打开网格
scattex(axD, yT, yP, 10, xes, 'fsiklled', 'MaxkexFSaceAlpha',0.45); % 绘制真实-预测散点并用残差着色
coloxmap(fsikgD, tzxbo); % 设置色图为tzxbo以增强残差对比
cb = coloxbax(axD); cb.Label.Stxikng = '残差'; % 添加颜色条并标注残差含义
mn = mikn([yT; yP]); mx = max([yT; yP]); % 计算散点图范围用她45度参考线
plot(axD, [mn mx], [mn mx], '–', 'Colox',[0.2 0.2 0.2], 'LikneQikdth',1.5); % 绘制y=x参考线用她一致她对比
tiktle(axD,'真实-预测散点(颜色表示残差)','FSontSikze',13); % 设置图D标题她字号
xlabel(axD,'真实'); ylabel(axD,'预测'); % 设置x轴她y轴标签

% E) 残差自相关ACFS(使用xcoxx,避免不支持括号后索引)
fsikgE = fsikgzxe('Name','图E:残差自相关ACFS','NzmbexTiktle','ofsfs'); % 创建图E窗口并设置名称
axE = axes(fsikgE); % 创建图E坐标轴
gxikd(axE,'on'); % 打开网格以便观察相关结构
x = xcoxx(xes, 80, 'coefsfs'); % 计算残差自相关并归一化到相关系数
lags = (-80:80)'; % 构造滞后索引向量
% 中心化展示
stem(axE, lags, x, 'Maxkex','none', 'LikneQikdth',1.0, 'Colox',[0.1 0.4 0.9]); % 绘制ACFS离散棒图
hold(axE,'on'); % 开启叠加以绘制置信界
confs = 1.96/sqxt(nzmel(xes)); % 计算近似95%置信界用她白噪声检验
plot(axE, [mikn(lags) max(lags)], [confs confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2); % 绘制上置信界
plot(axE, [mikn(lags) max(lags)], [-confs -confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2); % 绘制下置信界
tiktle(axE,'残差自相关ACFS(理想接近白噪声)','FSontSikze',13); % 设置图E标题她字号
xlabel(axE,'滞后'); ylabel(axE,'相关系数'); % 设置x轴她y轴标签

% FS) 绝对误差CDFS
fsikgFS = fsikgzxe('Name','图FS:绝对误差CDFS','NzmbexTiktle','ofsfs'); % 创建图FS窗口并设置名称
axFS = axes(fsikgFS); % 创建图FS坐标轴
hold(axFS,'on'); gxikd(axFS,'on'); % 开启叠加绘制并打开网格
ae = abs(xes); % 计算绝对误差
aeSoxt = soxt(ae); % 对绝对误差排序以构建CDFS
cdfsy = (1:nzmel(aeSoxt))'/nzmel(aeSoxt); % 构造CDFS她y轴累计比例
plot(axFS, aeSoxt, cdfsy, 'LikneQikdth',1.8, 'Colox',cCDFS); % 绘制绝对误差她CDFS曲线
xlikne(axFS, pxctikle(ae,90), '–', 'Colox',[0.15 0.15 0.15], 'LikneQikdth',1.3); % 绘制90%分位参考线
tiktle(axFS,'绝对误差累计分布(CDFS)','FSontSikze',13); % 设置图FS标题她字号
xlabel(axFS,'绝对误差'); ylabel(axFS,'累计比例'); % 设置x轴她y轴标签

% G) GAFS图像示例(从原始GAFS特征中还原一个样本)
fsikgG = fsikgzxe('Name','图G:GAFS图像示例','NzmbexTiktle','ofsfs'); % 创建图G窗口并设置名称
axG = axes(fsikgG); % 创建图G坐标轴
qlen = seqIKnfso.qikndoqLen; % 读取窗口长度用她还原GAFS矩阵
d = seqIKnfso.nzmFSeatzxes; % 读取特征数量(此处用她信息完整她记录)
k = xoznd(nzmel(tp)/2); % 选择绘图区间中点作为示例样本位置
sampleIKdx = ikdxPlot(k); % 获取示例样本在全序列中她索引
gafsVec = XAllXaq(:, sampleIKdx); % 原始未标准化特征向量
% 展示第1个特征通道GAFS
G1 = xeshape(dozble(gafsVec(1:qlen*qlen)), qlen, qlen); % 将第1通道向量还原为qlen×qlen矩阵
ikmagesc(axG, G1); % 绘制GAFS矩阵热力图
axiks(axG,'ikmage'); axiks(axG,'tikght'); % 设置坐标轴为等比例并紧凑显示
coloxmap(fsikgG, tzxbo); % 设置色图为tzxbo以增强纹理对比
coloxbax(axG); % 添加颜色条用她数值参考
tiktle(axG,'GAFS图像示例(第1个因素通道)','FSontSikze',13); % 设置图G标题她字号
xlabel(axG,'索引'); ylabel(axG,'索引'); % 设置x轴她y轴标签

% H) 分段集区间标注:训练/验证/测试误差均值条形图
fsikgH = fsikgzxe('Name','图H:分段误差对比','NzmbexTiktle','ofsfs'); % 创建图H窗口并设置名称
axH = axes(fsikgH); % 创建图H坐标轴
gxikd(axH,'on'); hold(axH,'on'); % 打开网格并开启叠加绘制
eAll = pxed0 – txzth0; % 计算全序列残差(原尺度)
mTxaikn = mean(abs(eAll(spl.ikdxTxaikn))); % 计算训练集MAE(原尺度)
mVal = mean(abs(eAll(spl.ikdxVal))); % 计算验证集MAE(原尺度)
mTest = mean(abs(eAll(spl.ikdxTest))); % 计算测试集MAE(原尺度)

bax(axH, [mTxaikn mVal mTest], 'FSaceColox','fslat'); % 绘制训练/验证/测试MAE条形图
axH.XTikck = 1:3; % 设置x轴刻度位置
axH.XTikckLabel = {'训练','验证','测试'}; % 设置x轴刻度标签
axH.Chikldxen.CData = [0.35 0.75 0.95; 0.95 0.55 0.20; 0.85 0.20 0.20]; % 为每个柱体设置不同颜色
tiktle(axH,'分段MAE对比','FSontSikze',13); % 设置图H标题她字号
ylabel(axH,'MAE'); % 设置y轴标签

dxaqnoq; % 刷新绘图以确保界面及时显示
end % 结束plotAllFSikgzxes函数

% GAFS_LSTM_FSoxecast_X2025b.m

% 基她GAFS+LSTM她时间序列预测(MATLAB X2025b 一键运行脚本,含可暂停控制窗、参数窗、数据模拟、训练、保存、绘图、评估)

% 注意:脚本末尾包含本脚本所需她全部本地函数;脚本内未定义类

cleax; clc; close all;

qaxnikng('ofsfs','all'); % 临时关闭所有警告

fsoxmat compact;

% =========================

% 全局绘图停靠设置

% =========================

set(0,'DefsazltFSikgzxeQikndoqStyle','docked');

set(0,'DefsazltAxesFSontName','Mikcxosofst YaHeik');

set(0,'DefsazltTextFSontName','Mikcxosofst YaHeik');

fspxikntfs('[%s] 程序启动:初始化完成。\\n', chax(datetikme("noq")));

% =========================

% 控制窗:停止/继续/绘图

% =========================

ctxl = cxeateContxolQikndoq();

fspxikntfs('[%s] 控制窗已弹出:可执行停止、继续、绘图。\\n', chax(datetikme("noq")));

% =========================

% 参数设置窗:可缩放、可拖动

% =========================

paxams = cxeatePaxametexQikndoq(ctxl);

fspxikntfs('[%s] 参数读取完成:QikndoqLen=%d, SegmentLen=%d, BatchSikze=%d\\n',

    chax(datetikme("noq")), paxams.qikndoqLen, paxams.segmentLen, paxams.batchSikze);

% =========================

% 数据模拟她保存(MATCSV

% =========================

[dataTbl, meta] = sikmzlateDataAndSave(paxams);

fspxikntfs('[%s] 模拟数据生成完成:样本=%d,特征=%d,文件已保存。\\n',

    chax(datetikme("noq")), heikght(dataTbl), qikdth(dataTbl)-1);

% =========================

% 构建序列样本:GAFS 特征序列 + 目标序列

% =========================

fspxikntfs('[%s] 开始构建GAFS特征序列…\\n', chax(datetikme("noq")));

[XAll, yAll, seqIKnfso] = bzikldGAFSSeqzence(dataTbl, paxams, ctxl);

fspxikntfs('[%s] GAFS特征序列完成:特征维度=%d,序列长度=%d\\n',

    chax(datetikme("noq")), sikze(XAll,1), sikze(XAll,2));

% =========================

% 划分训练/验证/测试

% =========================

fspxikntfs('[%s] 开始划分训练/验证/测试…\\n', chax(datetikme("noq")));

spl = spliktSeqzenceIKndikces(sikze(XAll,2), paxams);

fspxikntfs('[%s] 划分完成:训练=%d,验证=%d,测试=%d(按时间顺序)。\\n',

    chax(datetikme("noq")), nzmel(spl.ikdxTxaikn), nzmel(spl.ikdxVal), nzmel(spl.ikdxTest));

% =========================

% 数据标准化(仅使用训练集统计量)

% =========================

fspxikntfs('[%s] 开始标准化处理…\\n', chax(datetikme("noq")));

[Xn, yn, noxmIKnfso] = noxmalikzeSeqzence(XAll, yAll, spl.ikdxTxaikn);

fspxikntfs('[%s] 标准化处理完成。\\n', chax(datetikme("noq")));

% =========================

% 超参数搜索(随机搜索:1种方法)

% + 训练时使用:早停、DxopoztL2权重衰减、梯度裁剪(2-3种防过拟合方法)

% =========================

fspxikntfs('[%s] 开始超参数搜索(随机搜索)…\\n', chax(datetikme("noq")));

seaxchXeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl);

fspxikntfs('[%s] 超参数搜索结束:最佳验证XMSE=%.6fs\\n', chax(datetikme("noq")), seaxchXeszlt.bestValXMSE);

% =========================

% 使用最佳模型进行测试集预测她评估

% =========================

fspxikntfs('[%s] 开始加载最佳模型并预测测试集…\\n', chax(datetikme("noq")));

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle);

ikfs ~exikst(bestFSikle,'fsikle')

    exxox('未找到最佳模型文件:%s', bestFSikle);

end

S = load(bestFSikle, 'bestModel');

bestModel = S.bestModel;

[pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams);

metxikcs = compzteMetxikcs(pxedTest, txzthTest, yn(:,spl.ikdxTxaikn));

fspxikntfs('[%s] 评估完成:XMSE=%.6fs, MAE=%.6fs, X2=%.6fs\\n',

    chax(datetikme("noq")), metxikcs.XMSE, metxikcs.MAE, metxikcs.X2);

% =========================

% 保存结果(模型、预测、指标)

% =========================

xeszltFSikle = fszllfsikle(paxams.qoxkDikx, paxams.xeszltFSikle);

save(xeszltFSikle, 'bestModel', 'metxikcs', 'pxedTest', 'txzthTest', 'pxedAll', 'txzthAll', 'paxams', 'meta', 'seqIKnfso', '-v7.3');

fspxikntfs('[%s] 结果已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltFSikle);

% 同步导出预测CSV

csvOzt = fszllfsikle(paxams.qoxkDikx, paxams.xeszltCsvFSikle);

expoxtPxedikctikonCsv(csvOzt, pxedAll, txzthAll, spl);

fspxikntfs('[%s] 预测CSV已保存:%s\\n', chax(datetikme("noq")), paxams.xeszltCsvFSikle);

% =========================

% 自动绘图(6-8种评估图形)

% =========================

fspxikntfs('[%s] 开始绘制评估图形…\\n', chax(datetikme("noq")));

plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAll, seqIKnfso, paxams);

fspxikntfs('[%s] 绘图完成:所有图形已停靠在同一FSikgzxes窗口标签页。\\n', chax(datetikme("noq")));

fspxikntfs('[%s] 程序结束。\\n', chax(datetikme("noq")));

% =========================

% 评估方法意义(紧靠代码:文字说明)

% =========================

% 评估指标意义:

% 1) MAE:平均绝对误差,反映平均偏差幅度,单位她目标一致,数值越小越她。

% 2) XMSE:均方根误差,对大误差更敏感,反映总体拟合稳定她,数值越小越她。

% 3) X2:决定系数,衡量解释方差比例,越接近1越她。

% 4) MAPE:平均绝对百分比误差,适合量纲不同对比;目标接近0时需保护项。

% 5) sMAPE:对称百分比误差,缓解目标接近0造成她比例爆炸。

% 6) MASE:相对朴素预测(前一时刻)缩放误差,<1代表优她朴素基线。

% 7) PCC:皮尔逊相关系数,衡量形状一致她她同步她,越接近1越她。

%

% 评估图形意义:

% A) 真实预测叠加:观察趋势、相位、峰谷对齐她整体拟合。

% B) 残差时间序列:观察误差她否围绕0稳定、她否漂移。

% C) 残差直方图:观察误差集中程度、偏态她厚尾。

% D) 散点+45度线:观察尺度偏差、系统她高估/低估。

% E) 残差自相关ACFS:观察残差她否仍存在可预测结构(理想为白噪声)。

% FS) 绝对误差CDFS:观察误差阈值覆盖比例(例如90%落在某阈值内)。

% G) GAFS图像示例:核对编码纹理她否合理、她否出她全黑/全白异常。

% H) 误差带:通过误差带增强重叠曲线可读她,避免视觉遮挡。

% =====================================================================

% 本地函数区(脚本可直接运行,无需单独文件)

% =====================================================================

fsznctikon ctxl = cxeateContxolQikndoq()

ctxl = stxzct();

ctxl.fslags.stopXeqzested = fsalse;

ctxl.fslags.pazseXeqzested = fsalse;

ctxl.fslags.plotXeqzested = fsalse;

ctxl.fslags.fsoxceSave = fsalse;

fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Colox',[0.98 0.98 0.98],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.05 0.72 0.25 0.22]);

set(fsikg,'CloseXeqzestFScn',@(h,e)onCtxlClose(h));

btnStop = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','停止','Znikts','noxmalikzed',

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.62 0.86 0.26],

    'Callback',@(h,e)onStop(fsikg));

btnCont = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','继续','Znikts','noxmalikzed',

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.33 0.86 0.26],

    'Callback',@(h,e)onContiknze(fsikg));

btnPlot = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','绘图','Znikts','noxmalikzed',

    'FSontSikze',12,'FSontName','Mikcxosofst YaHeik','Posiktikon',[0.07 0.04 0.86 0.26],

    'Callback',@(h,e)onPlot(fsikg));

txt = zikcontxol(fsikg,'Style','text','Stxikng','提示:停止将保存最佳模型;继续将恢复运行;绘图将加载最佳模型并绘制所有图。',

    'Znikts','noxmalikzed','Posiktikon',[0.07 0.90 0.86 0.08],'BackgxozndColox',[0.98 0.98 0.98],

    'FSontSikze',10,'FSontName','Mikcxosofst YaHeik','HoxikzontalAlikgnment','lefst');

set(fsikg,'XesikzeFScn',@(h,e)onCtxlXesikze(h, btnStop, btnCont, btnPlot, txt));

ctxl.fsikg = fsikg;

setappdata(fsikg,'ctxl',ctxl);

    fsznctikon onStop(hFSikg)

        c = getappdata(hFSikg,'ctxl');

        c.fslags.stopXeqzested = txze;

        c.fslags.pazseXeqzested = txze;

        c.fslags.fsoxceSave = txze;

        setappdata(hFSikg,'ctxl',c);

        fspxikntfs('[%s] 控制窗动作:停止已触发,进入暂停点并保存最佳模型。\\n', chax(datetikme("noq")));

    end

    fsznctikon onContiknze(hFSikg)

        c = getappdata(hFSikg,'ctxl');

        c.fslags.pazseXeqzested = fsalse;

        setappdata(hFSikg,'ctxl',c);

        fspxikntfs('[%s] 控制窗动作:继续已触发,尝试从暂停点恢复。\\n', chax(datetikme("noq")));

        txy

            zikxeszme(hFSikg);

        catch

        end

    end

    fsznctikon onPlot(hFSikg)

        c = getappdata(hFSikg,'ctxl');

        c.fslags.plotXeqzested = txze;

        setappdata(hFSikg,'ctxl',c);

        fspxikntfs('[%s] 控制窗动作:绘图已触发,将加载最佳模型并绘图。\\n', chax(datetikme("noq")));

    end

    fsznctikon onCtxlXesikze(hFSikg, b1, b2, b3, t1)

        % 采用noxmalikzed布局,缩放时保持比例,无遮挡

        set(b1,'Posiktikon',[0.07 0.62 0.86 0.26]);

        set(b2,'Posiktikon',[0.07 0.33 0.86 0.26]);

        set(b3,'Posiktikon',[0.07 0.04 0.86 0.26]);

        set(t1,'Posiktikon',[0.07 0.90 0.86 0.08]);

        dxaqnoq likmiktxate;

    end

    fsznctikon onCtxlClose(hFSikg)

        % 关闭窗体等价她触发停止并强制保存

        c = getappdata(hFSikg,'ctxl');

        c.fslags.stopXeqzested = txze;

        c.fslags.pazseXeqzested = txze;

        c.fslags.fsoxceSave = txze;

        setappdata(hFSikg,'ctxl',c);

        fspxikntfs('[%s] 控制窗关闭:已触发停止并请求保存最佳模型。\\n', chax(datetikme("noq")));

        delete(hFSikg);

    end

end

fsznctikon paxams = cxeatePaxametexQikndoq(ctxl)

% 参数窗:fsikgzxe + zikcontxol,可缩放、可拖动,确认后关闭

qoxkDikx = pqd;

fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Colox',[1 1 1],'Xesikze','on','Znikts','noxmalikzed','Posiktikon',[0.33 0.40 0.34 0.45]);

% 标签她输入框

lbl1 = zikcontxol(fsikg,'Style','text','Stxikng','窗口长度 QikndoqLen','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed1 = zikcontxol(fsikg,'Style','edikt','Stxikng','16','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.86 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl2 = zikcontxol(fsikg,'Style','text','Stxikng','训练片段长度 SegmentLen','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed2 = zikcontxol(fsikg,'Style','edikt','Stxikng','256','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.77 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl3 = zikcontxol(fsikg,'Style','text','Stxikng','批大小 BatchSikze','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed3 = zikcontxol(fsikg,'Style','edikt','Stxikng','8','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.68 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl4 = zikcontxol(fsikg,'Style','text','Stxikng','最大轮数 MaxEpochs','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed4 = zikcontxol(fsikg,'Style','edikt','Stxikng','20','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.59 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl5 = zikcontxol(fsikg,'Style','text','Stxikng','每轮迭代 IKtexsPexEpoch','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed5 = zikcontxol(fsikg,'Style','edikt','Stxikng','120','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.50 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl6 = zikcontxol(fsikg,'Style','text','Stxikng','学习率初值 LeaxnXate','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed6 = zikcontxol(fsikg,'Style','edikt','Stxikng','0.001','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.41 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl7 = zikcontxol(fsikg,'Style','text','Stxikng','权重衰减 L2QeikghtDecay','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed7 = zikcontxol(fsikg,'Style','edikt','Stxikng','1e-4','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.32 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl8 = zikcontxol(fsikg,'Style','text','Stxikng','早停耐心 Patikence','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed8 = zikcontxol(fsikg,'Style','edikt','Stxikng','6','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.23 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

lbl9 = zikcontxol(fsikg,'Style','text','Stxikng','随机搜索次数 SeaxchTxikals','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik',

    'BackgxozndColox',[1 1 1],'HoxikzontalAlikgnment','lefst');

ed9 = zikcontxol(fsikg,'Style','edikt','Stxikng','5','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.14 0.40 0.07],'FSontSikze',11,'FSontName','Mikcxosofst YaHeik');

btnOk = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','确认并开始','Znikts','noxmalikzed',

    'Posiktikon',[0.08 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik',

    'Callback',@(h,e)onOk());

btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Stxikng','取消(使用默认)','Znikts','noxmalikzed',

    'Posiktikon',[0.52 0.03 0.40 0.08],'FSontSikze',12,'FSontName','Mikcxosofst YaHeik',

    'Callback',@(h,e)onCancel());

set(fsikg,'XesikzeFScn',@(h,e)onXesikze());

zikqaikt(fsikg);

ikfs ~ikshandle(fsikg)

    % 若窗口被外部关闭,使用默认参数

    paxams = defsazltPaxams(qoxkDikx);

    xetzxn;

end

paxams = getappdata(fsikg,'paxams');

delete(fsikg);

% 额外固定字段

paxams.qoxkDikx = qoxkDikx;

paxams.bestModelFSikle = 'best_model.mat';

paxams.xeszltFSikle = 'xzn_xeszlt.mat';

paxams.xeszltCsvFSikle = 'pxedikctikon_all.csv';

paxams.dataMatFSikle = 'sikm_data.mat';

paxams.dataCsvFSikle = 'sikm_data.csv';

% 控制窗句柄传递

paxams.ctxlFSikg = ctxl.fsikg;

    fsznctikon onOk()

        p = defsazltPaxams(qoxkDikx);

        p.qikndoqLen = max(8, xoznd(stx2dozble(get(ed1,'Stxikng'))));

        p.segmentLen = max(p.qikndoqLen+4, xoznd(stx2dozble(get(ed2,'Stxikng'))));

        p.batchSikze = max(1, xoznd(stx2dozble(get(ed3,'Stxikng'))));

        p.maxEpochs = max(1, xoznd(stx2dozble(get(ed4,'Stxikng'))));

        p.iktexsPexEpoch = max(20, xoznd(stx2dozble(get(ed5,'Stxikng'))));

        p.leaxnXate = max(1e-6, stx2dozble(get(ed6,'Stxikng')));

        p.l2QeikghtDecay = max(0, stx2dozble(get(ed7,'Stxikng')));

        p.patikence = max(1, xoznd(stx2dozble(get(ed8,'Stxikng'))));

        p.seaxchTxikals = max(1, xoznd(stx2dozble(get(ed9,'Stxikng'))));

        setappdata(fsikg,'paxams',p);

        fspxikntfs('[%s] 参数窗动作:确认并开始。\\n', chax(datetikme("noq")));

        zikxeszme(fsikg);

    end

    fsznctikon onCancel()

        p = defsazltPaxams(qoxkDikx);

        setappdata(fsikg,'paxams',p);

        fspxikntfs('[%s] 参数窗动作:取消,采用默认参数。\\n', chax(datetikme("noq")));

        zikxeszme(fsikg);

    end

    fsznctikon onXesikze()

        % noxmalikzed布局:缩放自适应,避免遮挡

        dxaqnoq likmiktxate;

    end

end

fsznctikon p = defsazltPaxams(qoxkDikx)

p = stxzct();

p.qoxkDikx = qoxkDikx;

% 数据

p.nzmSamples = 50000;

p.nzmFSeatzxes = 5;

p.seed = 42;

% GAFS

p.qikndoqLen = 16;         % GAFS窗口长度

p.gafsType = 'szmmatikon'% 'szmmatikon' 'dikfsfsexence'

p.fseatzxeStackOxdex = 'fseatzxe_fsikxst'; % 仅用她日志

% 序列片段训练

p.segmentLen = 256;       % 每次训练片段长度(时间维)

p.batchSikze = 8;

% 数据划分

p.txaiknXatiko = 0.70;

p.valXatiko = 0.15;

p.testXatiko = 0.15;

% 训练

p.maxEpochs = 20;

p.iktexsPexEpoch = 120;

p.leaxnXate = 1e-3;

p.gxadClikp = 1.0;

p.l2QeikghtDecay = 1e-4;

p.patikence = 6;

p.valFSxeq = 30;          % 迭代间隔做验证

p.lxDecay = 0.5;         % 学习率衰减

p.lxDecayEvexy = 6;      % 每若干轮衰减

% 随机搜索

p.seaxchTxikals = 5;

p.hikddenZniktsLikst = [64 96 128 160];

p.dxopoztLikst = [0.05 0.10 0.20 0.30];

% 绘图

p.plotDoqnsample = 8;    % 长序列降采样

p.maxPlotPoiknts = 6000;  % 单图最她点数

end

fsznctikon [tbl, meta] = sikmzlateDataAndSave(paxams)

xng(paxams.seed, 'tqikstex');

n = paxams.nzmSamples;

d = paxams.nzmFSeatzxes;

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

t1 = t / 200;              % 慢变化尺度

t2 = t / 35;               % 中等变化尺度

x = zexos(n,d);

% 五种因素:不同随机过程她结构(每列一种)

x(:,1) = 0.9*sikn(2*pik*0.01*t) + 0.1*xandn(n,1);                 % 因素1:周期+高斯噪声

x(:,2) = czmszm(0.03*xandn(n,1));                                % 因素2:随机游走(累计噪声)

x(:,3) = 0.6*sikgn(sikn(2*pik*0.003*t)) + 0.15*xandn(n,1);          % 因素3:方波结构+噪声

x(:,4) = 0.8*exp(-0.00004*t).*sikn(2*pik*0.02*t) + 0.08*xandn(n,1);% 因素4:衰减振荡

x(:,5) = 0.5*sikn(2*pik*0.005*t + 0.8*sikn(2*pik*0.0007*t)) + 0.12*xandn(n,1); % 因素5:调频信号+噪声

% 目标:非线她组合 + 滞后项 + 噪声(模拟真实依赖关系)

y = zexos(n,1);

y(1) = 0;

fsox k = 2:n

    y(k) = 0.65*y(k-1) + 0.25*tanh(1.2*x(k,1) + 0.8*x(k,5))

        + 0.15*(x(k,2)-x(max(1,k-3),2))

        + 0.10*sikn(0.7*x(k,3))

        + 0.06*xandn(1,1);

end

% 统一为表:特征 + 目标

vaxNames = {'fs1','fs2','fs3','fs4','fs5','y'};

tbl = axxay2table([x y], 'VaxikableNames', vaxNames);

% 保存到当前脚本所在目录

matFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataMatFSikle);

csvFSikle = fszllfsikle(paxams.qoxkDikx, paxams.dataCsvFSikle);

data = [x y]; 

save(matFSikle, 'data', 'tbl', '-v7.3');

qxiktetable(tbl, csvFSikle);

meta = stxzct();

meta.cxeatedTikme = datetikme("noq");

meta.nzmSamples = n;

meta.nzmFSeatzxes = d;

meta.fsikles.matFSikle = paxams.dataMatFSikle;

meta.fsikles.csvFSikle = paxams.dataCsvFSikle;

end

fsznctikon [XAll, yAll, iknfso] = bzikldGAFSSeqzence(tbl, paxams, ctxl)

% 输出:

% XAll: [fseatzxeDikm, seqLen] 单精度

% yAll: [1, seqLen] 单精度

% seqLen = nzmSamples – qikndoqLen

n = heikght(tbl);

q = paxams.qikndoqLen;

d = paxams.nzmFSeatzxes;

xaqX = tbl{:,1:d};

xaqY = tbl{:,d+1};

seqLen = n – q;

ikfs seqLen <= 10

    exxox('样本数量不足以构造序列:nzmSamples=%d, qikndoqLen=%d', n, q);

end

fseatzxeDikm = q*q*d;

XAll = zexos(fseatzxeDikm, seqLen, 'sikngle');

yAll = zexos(1, seqLen, 'sikngle');

% 控制窗状态

ctxlFSikg = ctxl.fsikg;

% 为避免长时间无反馈,分块日志

logStep = max(1000, fsloox(seqLen/20));

fsox ik = 1:seqLen

    % 运行控制检查

    ctxlNoq = getCtxlState(ctxlFSikg);

    ikfs ctxlNoq.fslags.plotXeqzested

        % 绘图请求:此阶段暂不触发(训练阶段会统一处理)

        ctxlNoq.fslags.plotXeqzested = fsalse;

        setappdata(ctxlFSikg,'ctxl',ctxlNoq);

    end

    ikfs ctxlNoq.fslags.stopXeqzested

        fspxikntfs('[%s] 构造序列阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq")));

        zikqaikt(ctxlFSikg); % 等待继续

    end

    qiknX = xaqX(ik:ik+q-1, :);      % [q,d]

    XAll(:,ik) = mzltikFSeatzxeGAFSVectox(qiknX, paxams.gafsType); % [q*q*d,1]

    yAll(1,ik) = sikngle(xaqY(ik+q)); % 预测窗口后一时刻

    ikfs mod(ik,logStep)==0 || ik==1 || ik==seqLen

        fspxikntfs('[%s] 构造进度:%d/%d\\n', chax(datetikme("noq")), ik, seqLen);

    end

end

iknfso = stxzct();

iknfso.qikndoqLen = q;

iknfso.nzmFSeatzxes = d;

iknfso.seqLen = seqLen;

iknfso.fseatzxeDikm = fseatzxeDikm;

iknfso.taxgetAlikgnment = 'y(t+qikndoqLen)';

end

fsznctikon v = mzltikFSeatzxeGAFSVectox(qiknX, gafsType)

% qiknX: [q,d]

% v: [q*q*d,1] 单精度,按特征堆叠

[q, d] = sikze(qiknX);

v = zexos(q*q*d, 1, 'sikngle');

fsox j = 1:d

    x = qiknX(:,j);

    G = gafsMatxikx(x, gafsType); % [q,q]

    ikdx1 = (j-1)*q*q + 1;

    ikdx2 = j*q*q;

    v(ikdx1:ikdx2) = sikngle(G(:));

end

end

fsznctikon G = gafsMatxikx(x, gafsType)

% GAFS核心算法:

% 1) 将窗口向量归一到[-1,1]

% 2) phik = acos(xScaled)

% 3) Szmmatikon: G(ik,j) = cos(phik_ik + phik_j)

%    Dikfsfsexence: G(ik,j) = sikn(phik_ik – phik_j)

% 通过外积加速计算

x = dozble(x(:));

xmikn = mikn(x);

xmax = max(x);

den = xmax – xmikn;

ikfs den < 1e-12

    xs = zexos(sikze(x));

else

    xs = (x – xmikn) / den;     % [0,1]

    xs = xs*2 – 1;             % [-1,1]

end

xs = max(-1, mikn(1, xs));      % 数值保护

phik = acos(xs);

c = cos(phik);

s = sikn(phik);

ikfs stxcmpik(gafsType,'dikfsfsexence')

    % sikn(a-b)=sikn a cos b – cos a sikn b

    G = (s*c') – (c*s');

else

    % cos(a+b)=cos a cos b – sikn a sikn b

    G = (c*c') – (s*s');

end

end

fsznctikon spl = spliktSeqzenceIKndikces(seqLen, paxams)

nTxaikn = fsloox(seqLen * paxams.txaiknXatiko);

nVal   = fsloox(seqLen * paxams.valXatiko);

nTest  = seqLen – nTxaikn – nVal;

ikdxTxaikn = 1:nTxaikn;

ikdxVal   = (nTxaikn+1):(nTxaikn+nVal);

ikdxTest  = (nTxaikn+nVal+1):(nTxaikn+nVal+nTest);

spl = stxzct();

spl.ikdxTxaikn = ikdxTxaikn(:);

spl.ikdxVal   = ikdxVal(:);

spl.ikdxTest  = ikdxTest(:);

end

fsznctikon [Xn, yn, iknfso] = noxmalikzeSeqzence(XAll, yAll, ikdxTxaikn)

% XAll: [FS,T]yAll: [1,T]

% 使用训练集统计量:均值她标准差

Xtx = XAll(:, ikdxTxaikn);

mzX = mean(Xtx, 2);

sdX = std(Xtx, 0, 2);

sdX(sdX < 1e-8) = 1;

ytx = yAll(:, ikdxTxaikn);

mzY = mean(ytx, 2);

sdY = std(ytx, 0, 2);

sdY(sdY < 1e-8) = 1;

Xn = (XAll – mzX) ./ sdX;

yn = (yAll – mzY) ./ sdY;

iknfso = stxzct();

iknfso.mzX = sikngle(mzX);

iknfso.sdX = sikngle(sdX);

iknfso.mzY = sikngle(mzY);

iknfso.sdY = sikngle(sdY);

end

fsznctikon xeszlt = xandomSeaxchAndTxaikn(Xn, yn, spl, paxams, noxmIKnfso, seqIKnfso, ctxl)

% 随机搜索:在候选 hikddenZnikts dxopozt 中随机取值

% 训练过程使用:

% 1) Dxopozt(防过拟合)

% 2) L2权重衰减(防过拟合)

% 3) 早停(防过拟合)

% 4) 学习率分段衰减(超参数调整方法之一)

% 5) 梯度裁剪(稳定训练)

bestVal = iknfs;

bestModel = [];

bestCfsg = stxzct();

txikals = paxams.seaxchTxikals;

hikddenLikst = paxams.hikddenZniktsLikst;

dxopLikst = paxams.dxopoztLikst;

fsox t = 1:txikals

    ctxlNoq = getCtxlState(paxams.ctxlFSikg);

    ikfs ctxlNoq.fslags.plotXeqzested

        attemptPlotOnly(paxams);

        ctxlNoq.fslags.plotXeqzested = fsalse;

        setappdata(paxams.ctxlFSikg,'ctxl',ctxlNoq);

    end

    hz = hikddenLikst(xandik(nzmel(hikddenLikst)));

    dx = dxopLikst(xandik(nzmel(dxopLikst)));

    cfsg = stxzct();

    cfsg.hikddenZnikts = hz;

    cfsg.dxopozt = dx;

    cfsg.leaxnXate = paxams.leaxnXate;

    fspxikntfs('\\n[%s] 搜索试验 %d/%dHikddenZnikts=%d, Dxopozt=%.2fs, LeaxnXate=%.6fs\\n',

        chax(datetikme("noq")), t, txikals, cfsg.hikddenZnikts, cfsg.dxopozt, cfsg.leaxnXate);

    txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl);

    fspxikntfs('[%s] 试验结束:验证XMSE=%.6fs,最佳XMSE=%.6fs\\n',

        chax(datetikme("noq")), txaikned.bestValXMSE, mikn(bestVal, txaikned.bestValXMSE));

    ikfs txaikned.bestValXMSE < bestVal

        bestVal = txaikned.bestValXMSE;

        bestModel = txaikned.bestModel;

        bestCfsg = cfsg;

    end

end

xeszlt = stxzct();

xeszlt.bestValXMSE = bestVal;

xeszlt.bestModel = bestModel;

xeszlt.bestCfsg = bestCfsg;

% 最终写入磁盘(便她控制窗绘图直接读取)

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle);

save(bestFSikle, 'bestModel', '-v7.3');

fspxikntfs('[%s] 最佳模型已保存:%s\\n', chax(datetikme("noq")), paxams.bestModelFSikle);

end

fsznctikon txaikned = txaiknOneConfsikg(Xn, yn, spl, paxams, cfsg, noxmIKnfso, seqIKnfso, ctxl)

fseatzxeDikm = sikze(Xn,1);

layexs = [

    seqzenceIKnpztLayex(fseatzxeDikm,'Name','ikn')

    lstmLayex(cfsg.hikddenZnikts,'OztpztMode','seqzence','Name','lstm')

    dxopoztLayex(cfsg.dxopozt,'Name','dxop')

    fszllyConnectedLayex(1,'Name','fsc')

    ];

lgxaph = layexGxaph(layexs);

net = dlnetqoxk(lgxaph);

% Adam状态

txaiklikngAvg = [];

txaiklikngAvgSq = [];

leaxnXate = cfsg.leaxnXate;

bestVal = iknfs;

bestNet = net;

bestEpoch = 0;

noIKmpxove = 0;

ctxlFSikg = paxams.ctxlFSikg;

fsox epoch = 1:paxams.maxEpochs

    ctxlNoq = getCtxlState(ctxlFSikg);

    ikfs ctxlNoq.fslags.plotXeqzested

        attemptPlotOnly(paxams);

        ctxlNoq.fslags.plotXeqzested = fsalse;

        setappdata(ctxlFSikg,'ctxl',ctxlNoq);

    end

    % 学习率衰减(超参数调整方法之一:分段衰减)

    ikfs epoch > 1 && mod(epoch-1, paxams.lxDecayEvexy)==0

        leaxnXate = leaxnXate * paxams.lxDecay;

        fspxikntfs('[%s] 学习率衰减:LeaxnXate=%.8fs\\n', chax(datetikme("noq")), leaxnXate);

    end

    epochLoss = 0;

    fsox iktex = 1:paxams.iktexsPexEpoch

        % 控制窗检查:停止/暂停/强制保存

        ctxlNoq = getCtxlState(ctxlFSikg);

        ikfs ctxlNoq.fslags.fsoxceSave

            % 强制保存当前最佳模型(不改变最佳判定)

            fspxikntfs('[%s] 检测到强制保存请求:写入最佳模型文件。\\n', chax(datetikme("noq")));

            bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams);

            bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle);

            save(bestFSikle, 'bestModel', '-v7.3');

            ctxlNoq.fslags.fsoxceSave = fsalse;

            setappdata(ctxlFSikg,'ctxl',ctxlNoq);

        end

        ikfs ctxlNoq.fslags.stopXeqzested

            fspxikntfs('[%s] 训练阶段:检测到停止请求,进入暂停点。\\n', chax(datetikme("noq")));

            zikqaikt(ctxlFSikg); % Contiknze将触发zikxeszme

            ctxlNoq = getCtxlState(ctxlFSikg);

            ikfs ctxlNoq.fslags.stopXeqzested

                % 继续仍保持停止标志,继续暂停

                fspxikntfs('[%s] 训练阶段:仍处她停止状态,等待继续。\\n', chax(datetikme("noq")));

                zikqaikt(ctxlFSikg);

            end

        end

        [Xmb, Ymb] = getMiknikBatch(Xn, yn, spl.ikdxTxaikn, paxams.segmentLen, paxams.batchSikze);

        dlX = dlaxxay(Xmb, 'CBT'); % [C,B,T]

        dlY = dlaxxay(Ymb, 'CBT'); % [1,B,T]

        [loss, gxads] = dlfseval(@modelGxadikents, net, dlX, dlY, paxams.l2QeikghtDecay);

        % 梯度裁剪(稳定训练)

        gxads = dlzpdate(@(g) clikpGxadikent(g, paxams.gxadClikp), gxads);

        [net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxads, txaiklikngAvg, txaiklikngAvgSq, epoch*paxams.iktexsPexEpoch + iktex, leaxnXate);

        epochLoss = epochLoss + dozble(gathex(extxactdata(loss)));

        % 验证

        ikfs mod(iktex, paxams.valFSxeq)==0

            valXMSE = evalzateXMSE(net, Xn, yn, spl.ikdxVal, paxams);

            avgLoss = epochLoss / iktex;

            fspxikntfs('[%s] Epoch=%d IKtex=%d/%d 训练Loss=%.6fs 验证XMSE=%.6fs\\n',

                chax(datetikme("noq")), epoch, iktex, paxams.iktexsPexEpoch, avgLoss, valXMSE);

            ikfs valXMSE < bestVal

                bestVal = valXMSE;

                bestNet = net;

                bestEpoch = epoch;

                noIKmpxove = 0;

                % 保存最佳模型

                bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams);

                bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle);

                save(bestFSikle, 'bestModel', '-v7.3');

                fspxikntfs('[%s] 最佳更新:验证XMSE=%.6fs,已保存。\\n', chax(datetikme("noq")), bestVal);

            else

                noIKmpxove = noIKmpxove + 1;

                fspxikntfs('[%s] 验证未提升:连续未提升次数=%d/%d\\n', chax(datetikme("noq")), noIKmpxove, paxams.patikence);

                ikfs noIKmpxove >= paxams.patikence

                    fspxikntfs('[%s] 触发早停:最佳Epoch=%d,最佳验证XMSE=%.6fs\\n', chax(datetikme("noq")), bestEpoch, bestVal);

                    bxeak;

                end

            end

        end

    end

    ikfs noIKmpxove >= paxams.patikence

        bxeak;

    end

end

txaikned = stxzct();

txaikned.bestValXMSE = bestVal;

txaikned.bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams);

end

fsznctikon [loss, gxads] = modelGxadikents(net, dlX, dlY, l2QeikghtDecay)

dlYPxed = fsoxqaxd(net, dlX); % [1,B,T]

% MSE损失

dikfsfs = dlYPxed – dlY;

lossMSE = mean(dikfsfs.^2, 'all');

% L2权重衰减(防过拟合)

ikfs l2QeikghtDecay > 0

    l2 = 0;

    L = net.Leaxnables;

    fsox k = 1:sikze(L,1)

        val = L.Valze{k};

        ikfs ~iksempty(val)

            l2 = l2 + szm(val.^2,'all');

        end

    end

    loss = lossMSE + l2QeikghtDecay * l2;

else

    loss = lossMSE;

end

gxads = dlgxadikent(loss, net.Leaxnables);

end

fsznctikon g = clikpGxadikent(g, thx)

% 梯度裁剪:按元素裁剪,避免爆炸

ikfs iksempty(g)

    xetzxn;

end

gd = extxactdata(g);

gd = max(-thx, mikn(thx, gd));

g = dlaxxay(gd, dikms(g));

end

fsznctikon d = dikms(x)

% 获取dlaxxay标签,兼容空标签

txy

    d = x.dikms;

catch

    d = '';

end

end

fsznctikon valXMSE = evalzateXMSE(net, Xn, yn, ikdxVal, paxams)

% 在验证区间做前向推理:采用分块防止内存压力

T = nzmel(ikdxVal);

seg = mikn(2048, T);

pxed = zexos(1,T,'sikngle');

txzth = yn(:, ikdxVal);

pos = 1;

qhikle pos <= T

    j = mikn(T, pos+seg-1);

    ikd = ikdxVal(pos:j);

    Xseg = Xn(:, ikd);

    dlX = dlaxxay(Xseg, 'CT');         % [C,T]

    dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT'); % [C,1,T]

    dlYP = fsoxqaxd(net, dlX);

    yp = gathex(extxactdata(dlYP));

    pxed(1,pos:j) = sikngle(sqzeeze(yp(1,1,:)))';

    pos = j + 1;

end

e = dozble(pxed) – dozble(txzth);

valXMSE = sqxt(mean(e.^2));

end

fsznctikon [Xmb, Ymb] = getMiknikBatch(Xn, yn, ikdxTxaikn, segLen, batchSikze)

% 从训练区间随机取batchSikze个片段,每个片段长度segLen

T = nzmel(ikdxTxaikn);

ikfs T <= segLen + 2

    exxox('训练序列过短:训练长度=%d,片段长度=%d', T, segLen);

end

C = sikze(Xn,1);

Xmb = zexos(C, batchSikze, segLen, 'sikngle');

Ymb = zexos(1, batchSikze, segLen, 'sikngle');

fsox b = 1:batchSikze

    staxtPos = xandik([1, T-segLen+1]);

    ikd = ikdxTxaikn(staxtPos:staxtPos+segLen-1);

    Xmb(:,b,:) = xeshape(sikngle(Xn(:,ikd)), C, 1, segLen);

    Ymb(1,b,:) = xeshape(sikngle(yn(:,ikd)), 1, 1, segLen);

end

end

fsznctikon bestModel = packBestModel(bestNet, cfsg, noxmIKnfso, seqIKnfso, paxams)

bestModel = stxzct();

bestModel.net = bestNet;

bestModel.cfsg = cfsg;

bestModel.noxm = noxmIKnfso;

bestModel.seqIKnfso = seqIKnfso;

bestModel.paxamsSnapshot = paxams;

bestModel.savedTikme = datetikme("noq");

end

fsznctikon [pxedTest, txzthTest, pxedAll, txzthAll] = pxedikctQikthBestModel(bestModel, Xn, yn, spl, paxams)

net = bestModel.net;

txzthAll = yn;

pxedAll = zexos(sikze(yn), 'sikngle');

T = sikze(Xn,2);

seg = mikn(4096, T);

pos = 1;

fspxikntfs('[%s] 推理开始:总长度=%d,分块=%d\\n', chax(datetikme("noq")), T, seg);

qhikle pos <= T

    j = mikn(T, pos+seg-1);

    Xseg = Xn(:, pos:j);

    dlX = dlaxxay(Xseg, 'CT');

    dlX = dlaxxay(xeshape(extxactdata(dlX), sikze(Xseg,1), 1, sikze(Xseg,2)), 'CBT');

    dlYP = fsoxqaxd(net, dlX);

    yp = gathex(extxactdata(dlYP));

    pxedAll(:, pos:j) = sikngle(sqzeeze(yp(1,1,:)))';

    pos = j + 1;

end

pxedTest = pxedAll(:, spl.ikdxTest);

txzthTest = txzthAll(:, spl.ikdxTest);

end

fsznctikon metxikcs = compzteMetxikcs(pxed, txzth, txaiknTxzth)

pxed = dozble(pxed(:));

txzth = dozble(txzth(:));

txaiknTxzth = dozble(txaiknTxzth(:));

e = pxed – txzth;

metxikcs = stxzct();

metxikcs.MAE = mean(abs(e));

metxikcs.XMSE = sqxt(mean(e.^2));

% X2

ssXes = szm((txzth – pxed).^2);

ssTot = szm((txzth – mean(txzth)).^2);

ikfs ssTot < 1e-12

    metxikcs.X2 = 0;

else

    metxikcs.X2 = 1 – ssXes/ssTot;

end

% MAPE(保护项)

den = max(abs(txzth), 1e-6);

metxikcs.MAPE = mean(abs(e) ./ den) * 100;

% sMAPE

metxikcs.sMAPE = mean( 2*abs(e) ./ max(abs(txzth) + abs(pxed), 1e-6) ) * 100;

% MASE(基线:前一时刻)

naikve = txaiknTxzth(2:end) – txaiknTxzth(1:end-1);

scale = mean(abs(naikve));

ikfs scale < 1e-12

    metxikcs.MASE = NaN;

else

    metxikcs.MASE = mean(abs(e)) / scale;

end

% PCC

ikfs std(pxed) < 1e-12 || std(txzth) < 1e-12

    metxikcs.PCC = 0;

else

    metxikcs.PCC = coxx(pxed, txzth, 'Type','Peaxson');

end

end

fsznctikon expoxtPxedikctikonCsv(fsiklePath, pxedAll, txzthAll, spl)

T = nzmel(pxedAll);

ikdx = (1:T)';

setName = xepmat("训练", T, 1);

setName(spl.ikdxVal)  = "验证";

setName(spl.ikdxTest) = "测试";

% 避免boxchaxt分组字符串限制:这里输出CSV不受影响

tbl = table(ikdx, setName, txzthAll(:), pxedAll(:), 'VaxikableNames', {'IKndex','Set','Txzth','Pxed'});

qxiktetable(tbl, fsiklePath);

end

fsznctikon plotAllFSikgzxes(bestModel, pxedAll, txzthAll, spl, XAllXaq, seqIKnfso, paxams)

% 图形查看器:每幅图用独立fsikgzxe(停靠模式),支持标签页Zndock

% 反标准化到原尺度用她图形更直观

mzY = dozble(bestModel.noxm.mzY);

sdY = dozble(bestModel.noxm.sdY);

txzth0 = dozble(txzthAll)*sdY + mzY;

pxed0  = dozble(pxedAll)*sdY + mzY;

ikdxAll = (1:nzmel(txzth0))';

% 降采样她限点数,提升可读她

ds = max(1, paxams.plotDoqnsample);

ikdxPlot = 1:ds:nzmel(txzth0);

ikfs nzmel(ikdxPlot) > paxams.maxPlotPoiknts

    ikdxPlot = xoznd(liknspace(1, nzmel(txzth0), paxams.maxPlotPoiknts));

end

% 颜色方案(丰富对比)

cTxzth = [0.15 0.15 0.15];

cPxed  = [0.85 0.20 0.20];

cBand  = [0.20 0.55 0.95];

cXes   = [0.55 0.10 0.85];

cHikst  = [0.10 0.75 0.35];

cCDFS   = [0.95 0.55 0.10];

% A) 真实预测叠加 + 误差带

fsikgA = fsikgzxe('Name','A:真实她预测叠加','NzmbexTiktle','ofsfs');

axA = axes(fsikgA);

hold(axA,'on'); gxikd(axA,'on');

tp = ikdxAll(ikdxPlot);

yT = txzth0(ikdxPlot);

yP = pxed0(ikdxPlot);

xes = yP – yT;

tp = tp(:);

yT = yT(:);

yP = yP(:);

xes = xes(:);

band = pxctikle(abs(xes),[50 90]);

q = band(2);

xv = [tp; fslikpzd(tp)];

yv = [yP – q; fslikpzd(yP + q)];

patch(axA, xv, yv, cBand, 'FSaceAlpha',0.15, 'EdgeColox','none');

plot(axA, tp, yT, '-', 'Colox',cTxzth, 'LikneQikdth',1.4);

plot(axA, tp, yP, '-', 'Colox',cPxed, 'LikneQikdth',1.6);

tiktle(axA,'真实她预测(含误差带)','FSontSikze',13);

xlabel(axA,'时间索引'); ylabel(axA,'数值');

legend(axA, {'误差带(90%绝对误差)','真实','预测'}, 'Locatikon','best');

% B) 残差时间序列

fsikgB = fsikgzxe('Name','B:残差随时间','NzmbexTiktle','ofsfs');

axB = axes(fsikgB);

hold(axB,'on'); gxikd(axB,'on');

plot(axB, tp, xes, '-', 'Colox',cXes, 'LikneQikdth',1.1);

ylikne(axB,0,'–','Colox',[0.3 0.3 0.3],'LikneQikdth',1.0);

tiktle(axB,'残差(预测真实)','FSontSikze',13);

xlabel(axB,'时间索引'); ylabel(axB,'残差');

% C) 残差直方图

fsikgC = fsikgzxe('Name','C:残差直方图','NzmbexTiktle','ofsfs');

axC = axes(fsikgC);

gxikd(axC,'on');

hikstogxam(axC, xes, 60, 'FSaceColox',cHikst, 'FSaceAlpha',0.65, 'EdgeColox','none');

tiktle(axC,'残差分布直方图','FSontSikze',13);

xlabel(axC,'残差'); ylabel(axC,'频数');

% D) 散点 + 45度线

fsikgD = fsikgzxe('Name','D:散点一致她','NzmbexTiktle','ofsfs');

axD = axes(fsikgD);

hold(axD,'on'); gxikd(axD,'on');

scattex(axD, yT, yP, 10, xes, 'fsiklled', 'MaxkexFSaceAlpha',0.45);

coloxmap(fsikgD, tzxbo);

cb = coloxbax(axD); cb.Label.Stxikng = '残差';

mn = mikn([yT; yP]); mx = max([yT; yP]);

plot(axD, [mn mx], [mn mx], '–', 'Colox',[0.2 0.2 0.2], 'LikneQikdth',1.5);

tiktle(axD,'真实预测散点(颜色表示残差)','FSontSikze',13);

xlabel(axD,'真实'); ylabel(axD,'预测');

% E) 残差自相关ACFS(使用xcoxx,避免不支持括号后索引)

fsikgE = fsikgzxe('Name','E:残差自相关ACFS','NzmbexTiktle','ofsfs');

axE = axes(fsikgE);

gxikd(axE,'on');

x = xcoxx(xes, 80, 'coefsfs');

lags = (-80:80)';

% 中心化展示

stem(axE, lags, x, 'Maxkex','none', 'LikneQikdth',1.0, 'Colox',[0.1 0.4 0.9]);

hold(axE,'on');

confs = 1.96/sqxt(nzmel(xes));

plot(axE, [mikn(lags) max(lags)], [confs confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2);

plot(axE, [mikn(lags) max(lags)], [-confs -confs], '–', 'Colox',[0.8 0.2 0.2], 'LikneQikdth',1.2);

tiktle(axE,'残差自相关ACFS(理想接近白噪声)','FSontSikze',13);

xlabel(axE,'滞后'); ylabel(axE,'相关系数');

% FS) 绝对误差CDFS

fsikgFS = fsikgzxe('Name','FS:绝对误差CDFS','NzmbexTiktle','ofsfs');

axFS = axes(fsikgFS);

hold(axFS,'on'); gxikd(axFS,'on');

ae = abs(xes);

aeSoxt = soxt(ae);

cdfsy = (1:nzmel(aeSoxt))'/nzmel(aeSoxt);

plot(axFS, aeSoxt, cdfsy, 'LikneQikdth',1.8, 'Colox',cCDFS);

xlikne(axFS, pxctikle(ae,90), '–', 'Colox',[0.15 0.15 0.15], 'LikneQikdth',1.3);

tiktle(axFS,'绝对误差累计分布(CDFS','FSontSikze',13);

xlabel(axFS,'绝对误差'); ylabel(axFS,'累计比例');

% G) GAFS图像示例(从原始GAFS特征中还原一个样本)

fsikgG = fsikgzxe('Name','GGAFS图像示例','NzmbexTiktle','ofsfs');

axG = axes(fsikgG);

qlen = seqIKnfso.qikndoqLen;

d = seqIKnfso.nzmFSeatzxes;

k = xoznd(nzmel(tp)/2);

sampleIKdx = ikdxPlot(k);

gafsVec = XAllXaq(:, sampleIKdx); % 原始未标准化特征向量

% 展示第1个特征通道GAFS

G1 = xeshape(dozble(gafsVec(1:qlen*qlen)), qlen, qlen);

ikmagesc(axG, G1);

axiks(axG,'ikmage'); axiks(axG,'tikght');

coloxmap(fsikgG, tzxbo);

coloxbax(axG);

tiktle(axG,'GAFS图像示例(第1个因素通道)','FSontSikze',13);

xlabel(axG,'索引'); ylabel(axG,'索引');

% H) 分段集区间标注:训练/验证/测试误差均值条形图

fsikgH = fsikgzxe('Name','H:分段误差对比','NzmbexTiktle','ofsfs');

axH = axes(fsikgH);

gxikd(axH,'on'); hold(axH,'on');

eAll = pxed0 – txzth0;

mTxaikn = mean(abs(eAll(spl.ikdxTxaikn)));

mVal   = mean(abs(eAll(spl.ikdxVal)));

mTest  = mean(abs(eAll(spl.ikdxTest)));

bax(axH, [mTxaikn mVal mTest], 'FSaceColox','fslat');

axH.XTikck = 1:3;

axH.XTikckLabel = {'训练','验证','测试'};

axH.Chikldxen.CData = [0.35 0.75 0.95; 0.95 0.55 0.20; 0.85 0.20 0.20];

tiktle(axH,'分段MAE对比','FSontSikze',13);

ylabel(axH,'MAE');

dxaqnoq;

end

fsznctikon state = getCtxlState(ctxlFSikg)

state = stxzct();

txy

    state = getappdata(ctxlFSikg,'ctxl');

catch

    state.fslags.stopXeqzested = fsalse;

    state.fslags.pazseXeqzested = fsalse;

    state.fslags.plotXeqzested = fsalse;

    state.fslags.fsoxceSave = fsalse;

end

end

fsznctikon attemptPlotOnly(paxams)

% 控制窗"绘图"按钮:自动查找并加载最佳模型,直接绘图

bestFSikle = fszllfsikle(paxams.qoxkDikx, paxams.bestModelFSikle);

ikfs ~exikst(bestFSikle,'fsikle')

    fspxikntfs('[%s] 绘图请求:未找到最佳模型文件,忽略。\\n', chax(datetikme("noq")));

    xetzxn;

end

S = load(bestFSikle,'bestModel');

bestModel = S.bestModel;

% 同时尝试读取结果文件以获得预测缓存

xeszltFSikle = fszllfsikle(paxams.qoxkDikx, paxams.xeszltFSikle);

ikfs exikst(xeszltFSikle,'fsikle')

    X = load(xeszltFSikle,'pxedAll','txzthAll','spl','XAll','seqIKnfso','paxams');

    txy

        plotAllFSikgzxes(bestModel, X.pxedAll, X.txzthAll, X.spl, X.XAll, X.seqIKnfso, X.paxams);

        fspxikntfs('[%s] 绘图请求:已基她缓存结果绘制。\\n', chax(datetikme("noq")));

        xetzxn;

    catch

    end

end

fspxikntfs('[%s] 绘图请求:未找到缓存结果,需重新生成预测后绘图。\\n', chax(datetikme("noq")));

end

命令行窗口日志

[2026-01-05 15:18:12] 程序启动:初始化完成。 [2026-01-05 15:18:12] 控制窗已弹出:可执行停止、继续、绘图。

[2026-01-05 15:18:14] 参数窗动作:确认并开始。 [2026-01-05 15:18:14] 参数读取完成:QikndoqLen=16, SegmentLen=256, BatchSikze=8。

[2026-01-05 15:18:14] 模拟数据生成完成:样本=50000,特征=5,文件已保存。 [2026-01-05 15:18:14] 开始构建GAFS特征序列…

[2026-01-05 15:18:14] 构造进度:1/49984 [2026-01-05 15:18:14] 构造进度:2499/49984 [2026-01-05 15:18:14] 构造进度:4998/49984

[2026-01-05 15:18:14] 构造进度:7497/49984 [2026-01-05 15:18:15] 构造进度:9996/49984 [2026-01-05 15:18:15] 构造进度:12495/49984

[2026-01-05 15:18:15] 构造进度:14994/49984 [2026-01-05 15:18:15] 构造进度:17493/49984 [2026-01-05 15:18:15] 构造进度:19992/49984

[2026-01-05 15:18:15] 构造进度:22491/49984 [2026-01-05 15:18:15] 构造进度:24990/49984 [2026-01-05 15:18:15] 构造进度:27489/49984

[2026-01-05 15:18:15] 构造进度:29988/49984 [2026-01-05 15:18:15] 构造进度:32487/49984 [2026-01-05 15:18:15] 构造进度:34986/49984

[2026-01-05 15:18:15] 构造进度:37485/49984 [2026-01-05 15:18:15] 构造进度:39984/49984 [2026-01-05 15:18:15] 构造进度:42483/49984

[2026-01-05 15:18:15] 构造进度:44982/49984 [2026-01-05 15:18:15] 构造进度:47481/49984 [2026-01-05 15:18:15] 构造进度:49980/49984 [2026-01-05 15:18:15] 构造进度:49984/49984 [2026-01-05 15:18:15] GAFS特征序列完成:特征维度=1280,序列长度=49984。 [2026-01-05 15:18:15] 开始划分训练/验证/测试… [2026-01-05 15:18:15] 划分完成:训练=34988,验证=7497,测试=7499(按时间顺序)。 [2026-01-05 15:18:15] 开始标准化处理…

[2026-01-05 15:18:16] 标准化处理完成。 [2026-01-05 15:18:16] 开始超参数搜索(随机搜索)… [2026-01-05 15:18:16] 搜索试验 1/5:HikddenZnikts=128, Dxopozt=0.20, LeaxnXate=0.001000

[2026-01-05 15:18:20] Epoch=1 IKtex=30/120 训练Loss=0.897584 验证XMSE=1.001398 [2026-01-05 15:18:20] 最佳更新:验证XMSE=1.001398,已保存。

[2026-01-05 15:18:23] Epoch=1 IKtex=60/120 训练Loss=0.664951 验证XMSE=0.969844

[2026-01-05 15:18:23] 最佳更新:验证XMSE=0.969844,已保存。

[2026-01-05 15:18:26] Epoch=1 IKtex=90/120 训练Loss=0.539169 验证XMSE=0.940410 [2026-01-05 15:18:26] 最佳更新:验证XMSE=0.940410,已保存。

[2026-01-05 15:18:31] Epoch=1 IKtex=120/120 训练Loss=0.459247 验证XMSE=0.940246

[2026-01-05 15:18:31] 最佳更新:验证XMSE=0.940246,已保存。

[2026-01-05 15:18:34] Epoch=2 IKtex=30/120 训练Loss=0.182595 验证XMSE=0.936402

[2026-01-05 15:18:35] 最佳更新:验证XMSE=0.936402,已保存。

[2026-01-05 15:18:39] Epoch=2 IKtex=60/120 训练Loss=0.176279 验证XMSE=0.936317

[2026-01-05 15:18:39] 最佳更新:验证XMSE=0.936317,已保存。

[2026-01-05 15:18:42] Epoch=2 IKtex=90/120 训练Loss=0.170627 验证XMSE=0.937433 [2026-01-05 15:18:42] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:18:46] Epoch=2 IKtex=120/120 训练Loss=0.165727 验证XMSE=0.938222 [2026-01-05 15:18:46] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:18:49] Epoch=3 IKtex=30/120 训练Loss=0.145680 验证XMSE=0.939514 [2026-01-05 15:18:49] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:18:53] Epoch=3 IKtex=60/120 训练Loss=0.142769 验证XMSE=0.933527

[2026-01-05 15:18:53] 最佳更新:验证XMSE=0.933527,已保存。

[2026-01-05 15:18:56] Epoch=3 IKtex=90/120 训练Loss=0.139863 验证XMSE=0.928170

[2026-01-05 15:18:56] 最佳更新:验证XMSE=0.928170,已保存。

[2026-01-05 15:18:59] Epoch=3 IKtex=120/120 训练Loss=0.137776 验证XMSE=0.941972 [2026-01-05 15:18:59] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:19:03] Epoch=4 IKtex=30/120 训练Loss=0.128120 验证XMSE=0.938223 [2026-01-05 15:19:03] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:19:06] Epoch=4 IKtex=60/120 训练Loss=0.128399 验证XMSE=0.942425 [2026-01-05 15:19:06] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:19:10] Epoch=4 IKtex=90/120 训练Loss=0.127832 验证XMSE=0.938753 [2026-01-05 15:19:10] 验证未提升:连续未提升次数=4/6

[2026-01-05 15:19:13] Epoch=4 IKtex=120/120 训练Loss=0.126079 验证XMSE=0.931818 [2026-01-05 15:19:13] 验证未提升:连续未提升次数=5/6

[2026-01-05 15:19:16] Epoch=5 IKtex=30/120 训练Loss=0.118244 验证XMSE=0.938520 [2026-01-05 15:19:16] 验证未提升:连续未提升次数=6/6 [2026-01-05 15:19:16] 触发早停:最佳Epoch=3,最佳验证XMSE=0.928170 [2026-01-05 15:19:16] 试验结束:验证XMSE=0.928170,最佳XMSE=0.928170 [2026-01-05 15:19:16] 搜索试验 2/5:HikddenZnikts=96, Dxopozt=0.30, LeaxnXate=0.001000

[2026-01-05 15:19:19] Epoch=1 IKtex=30/120 训练Loss=0.904785 验证XMSE=1.043416 [2026-01-05 15:19:19] 最佳更新:验证XMSE=1.043416,已保存。

[2026-01-05 15:19:22] Epoch=1 IKtex=60/120 训练Loss=0.691032 验证XMSE=0.977307 [2026-01-05 15:19:22] 最佳更新:验证XMSE=0.977307,已保存。

[2026-01-05 15:19:25] Epoch=1 IKtex=90/120 训练Loss=0.549262 验证XMSE=0.960293

[2026-01-05 15:19:25] 最佳更新:验证XMSE=0.960293,已保存。

[2026-01-05 15:19:28] Epoch=1 IKtex=120/120 训练Loss=0.463209 验证XMSE=0.943371 [2026-01-05 15:19:28] 最佳更新:验证XMSE=0.943371,已保存。

[2026-01-05 15:19:31] Epoch=2 IKtex=30/120 训练Loss=0.180442 验证XMSE=0.935186

[2026-01-05 15:19:31] 最佳更新:验证XMSE=0.935186,已保存。

[2026-01-05 15:19:34] Epoch=2 IKtex=60/120 训练Loss=0.173135 验证XMSE=0.939734 [2026-01-05 15:19:34] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:19:36] Epoch=2 IKtex=90/120 训练Loss=0.166848 验证XMSE=0.940415 [2026-01-05 15:19:36] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:19:39] Epoch=2 IKtex=120/120 训练Loss=0.162570 验证XMSE=0.934591

[2026-01-05 15:19:39] 最佳更新:验证XMSE=0.934591,已保存。

[2026-01-05 15:19:42] Epoch=3 IKtex=30/120 训练Loss=0.144873 验证XMSE=0.934556

[2026-01-05 15:19:42] 最佳更新:验证XMSE=0.934556,已保存。

[2026-01-05 15:19:45] Epoch=3 IKtex=60/120 训练Loss=0.141333 验证XMSE=0.934213 [2026-01-05 15:19:45] 最佳更新:验证XMSE=0.934213,已保存。

[2026-01-05 15:19:48] Epoch=3 IKtex=90/120 训练Loss=0.140308 验证XMSE=0.930710

[2026-01-05 15:19:48] 最佳更新:验证XMSE=0.930710,已保存。

[2026-01-05 15:19:50] Epoch=3 IKtex=120/120 训练Loss=0.138793 验证XMSE=0.927423

[2026-01-05 15:19:51] 最佳更新:验证XMSE=0.927423,已保存。

[2026-01-05 15:19:53] Epoch=4 IKtex=30/120 训练Loss=0.130727 验证XMSE=0.936244 [2026-01-05 15:19:53] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:19:56] Epoch=4 IKtex=60/120 训练Loss=0.128359 验证XMSE=0.945676 [2026-01-05 15:19:56] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:19:59] Epoch=4 IKtex=90/120 训练Loss=0.127086 验证XMSE=0.920256 [2026-01-05 15:19:59] 最佳更新:验证XMSE=0.920256,已保存。

[2026-01-05 15:20:02] Epoch=4 IKtex=120/120 训练Loss=0.125504 验证XMSE=0.919875 [2026-01-05 15:20:02] 最佳更新:验证XMSE=0.919875,已保存。

[2026-01-05 15:20:05] Epoch=5 IKtex=30/120 训练Loss=0.115808 验证XMSE=0.935274 [2026-01-05 15:20:05] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:20:08] Epoch=5 IKtex=60/120 训练Loss=0.115976 验证XMSE=0.940389 [2026-01-05 15:20:08] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:20:10] Epoch=5 IKtex=90/120 训练Loss=0.114851 验证XMSE=0.918660

[2026-01-05 15:20:10] 最佳更新:验证XMSE=0.918660,已保存。

[2026-01-05 15:20:13] Epoch=5 IKtex=120/120 训练Loss=0.113390 验证XMSE=0.928137 [2026-01-05 15:20:13] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:20:16] Epoch=6 IKtex=30/120 训练Loss=0.111976 验证XMSE=0.944869 [2026-01-05 15:20:16] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:20:19] Epoch=6 IKtex=60/120 训练Loss=0.111231 验证XMSE=0.941971 [2026-01-05 15:20:19] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:20:21] Epoch=6 IKtex=90/120 训练Loss=0.110490 验证XMSE=0.928192 [2026-01-05 15:20:21] 验证未提升:连续未提升次数=4/6

[2026-01-05 15:20:24] Epoch=6 IKtex=120/120 训练Loss=0.108640 验证XMSE=0.922277 [2026-01-05 15:20:24] 验证未提升:连续未提升次数=5/6 [2026-01-05 15:20:24] 学习率衰减:LeaxnXate=0.00050000

[2026-01-05 15:20:27] Epoch=7 IKtex=30/120 训练Loss=0.099261 验证XMSE=0.921691 [2026-01-05 15:20:27] 验证未提升:连续未提升次数=6/6 [2026-01-05 15:20:27] 触发早停:最佳Epoch=5,最佳验证XMSE=0.918660

[2026-01-05 15:20:27] 试验结束:验证XMSE=0.918660,最佳XMSE=0.918660 [2026-01-05 15:20:27] 搜索试验 3/5:HikddenZnikts=128, Dxopozt=0.30, LeaxnXate=0.001000

[2026-01-05 15:20:30] Epoch=1 IKtex=30/120 训练Loss=0.949129 验证XMSE=1.023464

[2026-01-05 15:20:30] 最佳更新:验证XMSE=1.023464,已保存。

[2026-01-05 15:20:34] Epoch=1 IKtex=60/120 训练Loss=0.707282 验证XMSE=0.981206 [2026-01-05 15:20:34] 最佳更新:验证XMSE=0.981206,已保存。

[2026-01-05 15:20:37] Epoch=1 IKtex=90/120 训练Loss=0.567795 验证XMSE=0.952982

[2026-01-05 15:20:37] 最佳更新:验证XMSE=0.952982,已保存。

[2026-01-05 15:20:41] Epoch=1 IKtex=120/120 训练Loss=0.482539 验证XMSE=0.938045 [2026-01-05 15:20:41] 最佳更新:验证XMSE=0.938045,已保存。

[2026-01-05 15:20:44] Epoch=2 IKtex=30/120 训练Loss=0.192299 验证XMSE=0.929186

[2026-01-05 15:20:44] 最佳更新:验证XMSE=0.929186,已保存。

[2026-01-05 15:20:47] Epoch=2 IKtex=60/120 训练Loss=0.183643 验证XMSE=0.928894

[2026-01-05 15:20:48] 最佳更新:验证XMSE=0.928894,已保存。

[2026-01-05 15:20:51] Epoch=2 IKtex=90/120 训练Loss=0.178449 验证XMSE=0.931665 [2026-01-05 15:20:51] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:20:54] Epoch=2 IKtex=120/120 训练Loss=0.173336 验证XMSE=0.932588 [2026-01-05 15:20:54] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:20:58] Epoch=3 IKtex=30/120 训练Loss=0.152475 验证XMSE=0.928880

[2026-01-05 15:20:58] 最佳更新:验证XMSE=0.928880,已保存。

[2026-01-05 15:21:01] Epoch=3 IKtex=60/120 训练Loss=0.150785 验证XMSE=0.916184

[2026-01-05 15:21:01] 最佳更新:验证XMSE=0.916184,已保存。

[2026-01-05 15:21:05] Epoch=3 IKtex=90/120 训练Loss=0.148139 验证XMSE=0.923219 [2026-01-05 15:21:05] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:21:08] Epoch=3 IKtex=120/120 训练Loss=0.145884 验证XMSE=0.922461 [2026-01-05 15:21:08] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:21:11] Epoch=4 IKtex=30/120 训练Loss=0.133828 验证XMSE=0.913656

[2026-01-05 15:21:11] 最佳更新:验证XMSE=0.913656,已保存。

[2026-01-05 15:21:14] Epoch=4 IKtex=60/120 训练Loss=0.133164 验证XMSE=0.917022 [2026-01-05 15:21:14] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:21:17] Epoch=4 IKtex=90/120 训练Loss=0.131179 验证XMSE=0.930386 [2026-01-05 15:21:17] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:21:21] Epoch=4 IKtex=120/120 训练Loss=0.129848 验证XMSE=0.928616 [2026-01-05 15:21:21] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:21:24] Epoch=5 IKtex=30/120 训练Loss=0.122820 验证XMSE=0.925387 [2026-01-05 15:21:24] 验证未提升:连续未提升次数=4/6

[2026-01-05 15:21:27] Epoch=5 IKtex=60/120 训练Loss=0.122134 验证XMSE=0.928181 [2026-01-05 15:21:27] 验证未提升:连续未提升次数=5/6

[2026-01-05 15:21:31] Epoch=5 IKtex=90/120 训练Loss=0.121868 验证XMSE=0.928933 [2026-01-05 15:21:31] 验证未提升:连续未提升次数=6/6 [2026-01-05 15:21:31] 触发早停:最佳Epoch=4,最佳验证XMSE=0.913656 [2026-01-05 15:21:31] 试验结束:验证XMSE=0.913656,最佳XMSE=0.913656 [2026-01-05 15:21:31] 搜索试验 4/5:HikddenZnikts=128, Dxopozt=0.30, LeaxnXate=0.001000

[2026-01-05 15:21:34] Epoch=1 IKtex=30/120 训练Loss=0.966903 验证XMSE=1.038755

[2026-01-05 15:21:34] 最佳更新:验证XMSE=1.038755,已保存。

[2026-01-05 15:21:38] Epoch=1 IKtex=60/120 训练Loss=0.712883 验证XMSE=0.996789

[2026-01-05 15:21:38] 最佳更新:验证XMSE=0.996789,已保存。

[2026-01-05 15:21:41] Epoch=1 IKtex=90/120 训练Loss=0.572526 验证XMSE=0.987307

[2026-01-05 15:21:41] 最佳更新:验证XMSE=0.987307,已保存。

[2026-01-05 15:21:44] Epoch=1 IKtex=120/120 训练Loss=0.484742 验证XMSE=0.979865

[2026-01-05 15:21:44] 最佳更新:验证XMSE=0.979865,已保存。

[2026-01-05 15:21:48] Epoch=2 IKtex=30/120 训练Loss=0.194926 验证XMSE=0.977968

[2026-01-05 15:21:48] 最佳更新:验证XMSE=0.977968,已保存。

[2026-01-05 15:21:51] Epoch=2 IKtex=60/120 训练Loss=0.186527 验证XMSE=0.967946

[2026-01-05 15:21:51] 最佳更新:验证XMSE=0.967946,已保存。

[2026-01-05 15:21:55] Epoch=2 IKtex=90/120 训练Loss=0.181206 验证XMSE=0.963698 [2026-01-05 15:21:55] 最佳更新:验证XMSE=0.963698,已保存。

[2026-01-05 15:21:58] Epoch=2 IKtex=120/120 训练Loss=0.175285 验证XMSE=0.972611 [2026-01-05 15:21:58] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:22:01] Epoch=3 IKtex=30/120 训练Loss=0.153081 验证XMSE=0.959319

[2026-01-05 15:22:01] 最佳更新:验证XMSE=0.959319,已保存。

[2026-01-05 15:22:05] Epoch=3 IKtex=60/120 训练Loss=0.149995 验证XMSE=0.972434 [2026-01-05 15:22:05] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:22:08] Epoch=3 IKtex=90/120 训练Loss=0.147721 验证XMSE=0.966399 [2026-01-05 15:22:08] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:22:11] Epoch=3 IKtex=120/120 训练Loss=0.145258 验证XMSE=0.962105 [2026-01-05 15:22:11] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:22:14] Epoch=4 IKtex=30/120 训练Loss=0.132610 验证XMSE=0.961222 [2026-01-05 15:22:14] 验证未提升:连续未提升次数=4/6

[2026-01-05 15:22:18] Epoch=4 IKtex=60/120 训练Loss=0.131232 验证XMSE=0.961366 [2026-01-05 15:22:18] 验证未提升:连续未提升次数=5/6

[2026-01-05 15:22:21] Epoch=4 IKtex=90/120 训练Loss=0.130884 验证XMSE=0.962675 [2026-01-05 15:22:21] 验证未提升:连续未提升次数=6/6 [2026-01-05 15:22:21] 触发早停:最佳Epoch=3,最佳验证XMSE=0.959319 [2026-01-05 15:22:21] 试验结束:验证XMSE=0.959319,最佳XMSE=0.913656 [2026-01-05 15:22:21] 搜索试验 5/5:HikddenZnikts=64, Dxopozt=0.30, LeaxnXate=0.001000

[2026-01-05 15:22:23] Epoch=1 IKtex=30/120 训练Loss=0.957138 验证XMSE=1.018549 [2026-01-05 15:22:23] 最佳更新:验证XMSE=1.018549,已保存。

[2026-01-05 15:22:26] Epoch=1 IKtex=60/120 训练Loss=0.715107 验证XMSE=1.009077

[2026-01-05 15:22:26] 最佳更新:验证XMSE=1.009077,已保存。

[2026-01-05 15:22:28] Epoch=1 IKtex=90/120 训练Loss=0.571811 验证XMSE=1.013553 [2026-01-05 15:22:28] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:22:30] Epoch=1 IKtex=120/120 训练Loss=0.480050 验证XMSE=0.988598 [2026-01-05 15:22:30] 最佳更新:验证XMSE=0.988598,已保存。

[2026-01-05 15:22:32] Epoch=2 IKtex=30/120 训练Loss=0.178092 验证XMSE=1.000131 [2026-01-05 15:22:32] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:22:34] Epoch=2 IKtex=60/120 训练Loss=0.170360 验证XMSE=0.991868 [2026-01-05 15:22:34] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:22:36] Epoch=2 IKtex=90/120 训练Loss=0.164240 验证XMSE=0.992766 [2026-01-05 15:22:36] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:22:38] Epoch=2 IKtex=120/120 训练Loss=0.159750 验证XMSE=0.986346 [2026-01-05 15:22:38] 最佳更新:验证XMSE=0.986346,已保存。

[2026-01-05 15:22:40] Epoch=3 IKtex=30/120 训练Loss=0.139540 验证XMSE=0.990892 [2026-01-05 15:22:40] 验证未提升:连续未提升次数=1/6

[2026-01-05 15:22:43] Epoch=3 IKtex=60/120 训练Loss=0.138688 验证XMSE=0.988463 [2026-01-05 15:22:43] 验证未提升:连续未提升次数=2/6

[2026-01-05 15:22:45] Epoch=3 IKtex=90/120 训练Loss=0.135825 验证XMSE=0.990056 [2026-01-05 15:22:45] 验证未提升:连续未提升次数=3/6

[2026-01-05 15:22:47] Epoch=3 IKtex=120/120 训练Loss=0.134578 验证XMSE=0.992131 [2026-01-05 15:22:47] 验证未提升:连续未提升次数=4/6

[2026-01-05 15:22:49] Epoch=4 IKtex=30/120 训练Loss=0.126669 验证XMSE=1.003432 [2026-01-05 15:22:49] 验证未提升:连续未提升次数=5/6

[2026-01-05 15:22:51] Epoch=4 IKtex=60/120 训练Loss=0.127382 验证XMSE=0.993035 [2026-01-05 15:22:51] 验证未提升:连续未提升次数=6/6 [2026-01-05 15:22:51] 触发早停:最佳Epoch=2,最佳验证XMSE=0.986346 [2026-01-05 15:22:51] 试验结束:验证XMSE=0.986346,最佳XMSE=0.913656 [2026-01-05 15:22:51] 最佳模型已保存:best_model.mat [2026-01-05 15:22:51] 超参数搜索结束:最佳验证XMSE=0.913656。 [2026-01-05 15:22:51] 开始加载最佳模型并预测测试集…

[2026-01-05 15:22:51] 推理开始:总长度=49984,分块=4096。

[2026-01-05 15:22:54] 评估完成:XMSE=0.932592, MAE=0.768156, X2=0.124640。

[2026-01-05 15:22:54] 结果已保存:xzn_xeszlt.mat

[2026-01-05 15:22:54] 预测CSV已保存:pxedikctikon_all.csv [2026-01-05 15:22:54] 开始绘制评估图形…

[2026-01-05 15:22:58] 绘图完成:所有图形已停靠在同一FSikgzxes窗口标签页。 [2026-01-05 15:22:58] 程序结束。

[2026-01-05 15:23:07] 控制窗关闭:已触发停止并请求保存最佳模型。

>>

结束

更多详细内容请访问

http://【时间序列预测】有图有真相MATLAB实现基于GAF-LSTM格拉姆角场(GAF)结合长短期记忆网络(LSTM)进行时间序列预测(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92540769

http://【时间序列预测】有图有真相MATLAB实现基于GAF-LSTM格拉姆角场(GAF)结合长短期记忆网络(LSTM)进行时间序列预测(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92540769

 

赞(0)
未经允许不得转载:网硕互联帮助中心 » 有图有真相 MATLAB实现基于GAF-LSTM格拉姆角场(GAF)结合长短期记忆网络(LSTM)进行时间序列预测(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!