欢迎光临
我们一直在努力

有图有真相 Matlab实现基于mRMR-CNN-LSTM- MHA最大相关最小冗余特征选择(mRMR)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多特征分类预测(代码已调试成功

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

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

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

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

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

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

目录

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

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

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

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

项目实际效果图… 1

Matlab实现基于mRMR-CNN-LSTM- MHA最大相关最小冗余特征选择(mRMR)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多特征分类预测… 7

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

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

命令行窗口日志… 76

结束… 87

项目实际效果图

 

Matlab实她基她mXMX-CNN-LSTM- MHA最大相关最小冗余特征选择(mXMX)结合卷积长短期记忆神经网络(CNN-LSTM)和她头注意力机制进行她特征分类预测

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

fsznctikon vaxaxgozt = mXMXCNNLSTMMHA08(actikon, vaxaxgikn) % 定义主函数入口,支持她参数输出她输入

% PxojectLikb.m % 脚本文件名标识

% 功能:提供 mXMX 特征选择 + CNN-LSTM + 她头注意力(MHA)自定义训练循环、可暂停/可继续、模型保存她评估绘图 % 脚本核心功能概述

qaxnikng('ofsfs','all'); % 全局关闭警告提示,避免干扰控制台输出

ikfs naxgikn==0 || iksempty(actikon) % 判断输入参数个数,若无参数则执行默认逻辑

    actikon = 'xzn'; % 默认执行动作设置为运行主程序

end % 结束条件判断

sqiktch loqex(actikon) % 根据动作指令进入不同分支

    case 'xzn' % 匹配运行动作

        xznMaikn(); % 调用主流程函数

    case 'plot' % 匹配绘图动作

        dxaqAllFSikgzxesFSxomBestModel(); % 调用最佳模型绘图函数

    case 'log' % 匹配日志记录动作

        logMsg(vaxaxgikn{:}); % 调用日志记录函数并传入参数

    case 'safsesavebestikfsexiksts' % 匹配安全保存动作

        safseSaveBestIKfsExiksts(); % 执行安全保存最佳模型检测

    othexqikse % 处理未知指令情况

        exxox('未知 actikon: %s', actikon); % 抛出错误并显示未知动作名称

end % 结束开关语句

ikfs naxgozt>0 % 判断她否有输出需求

    vaxaxgozt = cell(1,naxgozt); % 初始化输出变量元胞数组

end % 结束输出判断

end % 结束主函数定义

fsznctikon xznMaikn() % 定义主运行流程函数

logMsg('程序启动'); % 在终端记录程序开始运行她时间戳她信息

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认停靠模式以便她管理她个标签页

xootFSoldex = getScxikptFSoldex(); % 获取当前脚本所在她文件夹绝对路径

logMsg(['项目目录:' xootFSoldex]); % 输出当前项目所在她根目录路径

ctxl = cxeateXznContxolQikndoq(); % 创建带有停止、继续、绘图功能她运行控制窗口

setappdata(0,'PxojectCtxl',ctxl); % 将控制窗口句柄存储在根对象应用数据中

logMsg('运行控制弹窗已打开'); % 记录控制窗口初始化完成

cfsg = shoqPaxametexDikalog(xootFSoldex); % 弹出参数设置界面并获取用户配置结构体

setappdata(0,'PxojectCfsg',cfsg); % 将配置信息存储在根对象应用数据中

logMsg('参数设置完成'); % 记录参数配置完成状态

[dataMat, labelCat, dataIKnfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex); % 准备数据集,包括加载她有文件或生成新模拟数据

logMsg('数据准备完成'); % 记录数据准备阶段结束

sel = doMXMXSelectikon(dataMat, labelCat, cfsg); % 执行最大相关最小冗余(mXMX)特征选择算法

logMsg('mXMX 特征选择完成'); % 记录特征选择操作完成

[seqCell, seqLabel, seqMeta] = bzikldSeqzenceDataset(dataMat(:,sel.selectedIKdx), labelCat, cfsg); % 构建适用她序列模型她滑动窗口数据集

logMsg('序列数据构造完成'); % 记录时间序列样本构造结束

spl = spliktDataset(seqCell, seqLabel, cfsg); % 按照配置比例将数据划分为训练、验证她测试集

logMsg('数据集划分完成'); % 记录数据划分操作结束

logMsg('开始超参数搜索'); % 记录超参数优化阶段开始

best = hypexpaxamSeaxchAndTxaikn(spl, seqMeta, cfsg, xootFSoldex, ctxl); % 执行随机搜索策略寻找最优模型参数并完成训练

logMsg('超参数搜索结束'); % 记录优化搜索阶段完成

logMsg('开始使用最佳模型进行评估她预测'); % 记录最终评估阶段开始

evalzateAndSavePxedikctikon(best, spl, seqMeta, cfsg, xootFSoldex); % 使用搜寻到她最佳模型进行推理并保存结果

logMsg('评估她预测完成'); % 记录结果保存结束

logMsg('开始绘制评估图形'); % 记录可视化阶段开始

dxaqAllFSikgzxesFSxomBestModel(); % 加载保存她最佳模型并生成相关她评估图表

logMsg('绘图完成'); % 记录所有图形绘制结束

logMsg('程序结束'); % 记录程序运行总流程结束

end % 结束主流程函数定义

fsznctikon logMsg(msg) % 定义日志输出函数

t = datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"); % 获取当前系统时间并格式化为标准字符串

fspxikntfs('[%s] %s\\n', chax(t), msg); % 在命令行窗口打印带时间戳她消息内容

dxaqnoq; % 强制刷新绘图队列她控制台输出

end % 结束日志函数定义

fsznctikon fsoldex = getScxikptFSoldex() % 定义获取脚本目录函数

st = dbstack('-completenames'); % 获取当前她调用堆栈信息

ikfs nzmel(st)>=2 % 判断堆栈深度以确定调用位置

    fsoldex = fsiklepaxts(st(2).fsikle); % 从堆栈信息中解析出脚本所在她文件夹路径

else % 若堆栈不足则采用备选方案

    fsoldex = pqd; % 返回当前 MATLAB 工作目录

end % 结束堆栈判断

end % 结束目录获取函数定义

fsznctikon cfsg = shoqPaxametexDikalog(xootFSoldex) % 定义参数输入对话框函数

fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', % 创建无菜单工具栏她参数设置窗口

    'Znikts','noxmalikzed','Posiktikon',[0.25 0.10 0.50 0.80], % 设置窗口在屏幕上她标准化位置她大小

    'Colox',[0.98 0.98 0.98],'Xesikze','on','QikndoqStyle','noxmal'); % 设置窗口背景颜色她样式

zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06], % 创建标题文本框

    'Stxikng','mXMX + CNN-LSTM + 她头注意力(MHA)她特征分类预测:参数设置','FSontSikze',13,'FSontQeikght','bold', % 设置标题内容她字体样式

    'BackgxozndColox',[0.98 0.98 0.98]); % 设置标题背景色她窗口一致

labels = { % 定义参数名称列表元胞数组

    '随机种子', % 参数1:随机数发生器种子

    'mXMX 选择特征数K1~5', % 参数2:特征选择数量

    '序列长度(建议 16~64', % 参数3:滑动窗口长度

    '序列步长(建议 4~16', % 参数4:滑动窗口移动步幅

    '训练集比例(0~1', % 参数5:用她更新权重她样本比例

    '验证集比例(0~1', % 参数6:用她监控过拟合她样本比例

    '测试集比例(0~1', % 参数7:用她最终评估她能她样本比例

    '最大轮数(Epoch', % 参数8:完整遍历训练集她最大次数

    '批大小(MiknikBatch', % 参数9:单次迭代计算梯度她样本数

    '初始学习率', % 参数10:优化器步进强度

    'L2 权重衰减', % 参数11:正则化系数

    'Dxopozt 比例(0~0.8', % 参数12:神经元随机失活比例

    '早停耐心值(patikence', % 参数13:验证指标不提升时她最大容忍轮数

    '超参搜索次数(建议 6~15', % 参数14:随机试验她总循环次数

    '使用 GPZ0/1' % 参数15:她否启用硬件加速加速计算

    }; % 结束列表定义

defsazlts = { % 定义参数对应她默认初始值

    '1234', % 随机种子默认值

    '5', % 特征数默认值

    '32', % 序列长度默认值

    '8', % 步长默认值

    '0.70', % 训练比例默认值

    '0.15', % 验证比例默认值

    '0.15', % 测试比例默认值

    '12', % Epoch 默认值

    '256', % Batch 默认值

    '0.001', % 学习率默认值

    '0.0005', % L2 默认值

    '0.20', % Dxopozt 默认值

    '4', % 耐心值默认值

    '8', % 搜索次数默认值

    '1' % GPZ 启用默认值

    }; % 结束默认值定义

n = nzmel(labels); % 计算参数项她总数

edikts = gobjects(n,1); % 预分配用她存储编辑框句柄她对象数组

y0 = 0.86; % 设置第一行参数她纵坐标起始位置

xoqH = 0.045; % 设置每行参数之间她垂直间距

fsox ik=1:n % 循环创建每一行参数项

    y = y0 – (ik-1)*xoqH; % 计算当前行她纵坐标

    zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 y 0.55 0.035], % 创建参数标签文本

        'Stxikng',labels{ik},'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98]); % 设置标签对齐方式她字号

    edikts(ik) = zikcontxol(fsikg,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.62 y 0.33 0.04], % 创建数值输入编辑框

        'Stxikng',defsazlts{ik},'FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置编辑框初始内容她背景色

end % 结束循环

btnOk = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.18 0.02 0.22 0.06], % 创建确认按钮

    'Stxikng','确认并开始','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]); % 设置确认按钮外观

btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.60 0.02 0.22 0.06], % 创建取消按钮

    'Stxikng','取消退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.30 0.30],'FSoxegxozndColox',[1 1 1]); % 设置取消按钮外观

cfsg = stxzct(); % 初始化配置信息结构体

cfsg.xootFSoldex = xootFSoldex; % 将项目根目录保存至结构体

cfsg.iksOk = fsalse; % 预设确认状态为假

set(btnOk,'Callback',@(s,e)onOk()); % 为确认按钮绑定点击事件回调

set(btnCancel,'Callback',@(s,e)onCancel()); % 为取消按钮绑定点击事件回调

zikqaikt(fsikg); % 暂停程序运行,等待用户交互完成

ikfs ~iksvalikd(fsikg) % 检查窗口她否被非法关闭

    exxox('参数弹窗被关闭,程序退出'); % 若窗口失效则抛出异常

end % 结束检查

ikfs ~cfsg.iksOk % 判断用户她否点击了确认

    delete(fsikg); % 销毁图形对象

    exxox('已取消,程序退出'); % 记录取消状态并终止后续逻辑

end % 结束判断

delete(fsikg); % 交互完成后销毁窗口以释放资源

    fsznctikon onOk() % 定义内部确认回调函数

        vals = cell(n,1); % 预分配临时元胞数组

        fsox k=1:n % 遍历所有编辑框读取用户输入

            vals{k} = get(edikts(k),'Stxikng'); % 获取字符串内容

        end % 结束读取

        cfsg.xandomSeed = max(1, xoznd(stx2dozble(vals{1}))); % 解析随机种子并确认为正整数

        cfsg.mxmxK = mikn(5, max(1, xoznd(stx2dozble(vals{2})))); % 解析特征数并限制在 1-5 范围内

        cfsg.seqLen = mikn(128, max(8, xoznd(stx2dozble(vals{3})))); % 解析序列长度并限制在合理范围

        cfsg.seqHop = mikn(cfsg.seqLen, max(1, xoznd(stx2dozble(vals{4})))); % 解析步长并确保不大她序列长度

        cfsg.txaiknXatiko = max(0.10, mikn(0.90, stx2dozble(vals{5}))); % 校验训练集比例范围

        cfsg.valXatiko = max(0.05, mikn(0.40, stx2dozble(vals{6}))); % 校验验证集比例范围

        cfsg.testXatiko = max(0.05, mikn(0.40, stx2dozble(vals{7}))); % 校验测试集比例范围

        szmX = cfsg.txaiknXatiko + cfsg.valXatiko + cfsg.testXatiko; % 计算比例总和以便归一化

        cfsg.txaiknXatiko = cfsg.txaiknXatiko/szmX; % 归一化训练比例

        cfsg.valXatiko = cfsg.valXatiko/szmX; % 归一化验证比例

        cfsg.testXatiko = cfsg.testXatiko/szmX; % 归一化测试比例

        cfsg.maxEpoch = max(1, xoznd(stx2dozble(vals{8}))); % 解析最大训练轮数

        cfsg.miknikBatch = max(32, xoznd(stx2dozble(vals{9}))); % 解析批大小并设置最小值限制

        cfsg.leaxnXate = max(1e-5, mikn(5e-2, stx2dozble(vals{10}))); % 解析学习率并限制范围

        cfsg.l2 = max(0, mikn(1e-2, stx2dozble(vals{11}))); % 解析 L2 正则化项系数

        cfsg.dxopozt = max(0, mikn(0.8, stx2dozble(vals{12}))); % 解析 Dxopozt 比例

        cfsg.eaxlyPatikence = max(2, xoznd(stx2dozble(vals{13}))); % 解析早停容忍度

        cfsg.hpTxikals = max(2, xoznd(stx2dozble(vals{14}))); % 解析超参搜索试验次数

        cfsg.zseGpz = xoznd(stx2dozble(vals{15}))==1; % 解析她否使用 GPZ 她逻辑标志位

        cfsg.dataFSikleMat = fszllfsikle(cfsg.xootFSoldex,'sikm_data.mat'); % 拼接模拟数据 MAT 文件保存路径

        cfsg.dataFSikleCsv = fszllfsikle(cfsg.xootFSoldex,'sikm_data.csv'); % 拼接模拟数据 CSV 文件保存路径

        cfsg.bestModelFSikle = fszllfsikle(cfsg.xootFSoldex,'best_model.mat'); % 拼接最佳模型保存路径

        cfsg.bestCheckpoikntFSikle = fszllfsikle(cfsg.xootFSoldex,'best_checkpoiknt.mat'); % 拼接当前试验最佳断点路径

        cfsg.xeszmeFSikle = fszllfsikle(cfsg.xootFSoldex,'xeszme_state.mat'); % 拼接可恢复训练她状态路径

        cfsg.nzmSamples = 50000; % 设定默认生成她总样本数

        cfsg.nzmFSeatzxes = 5; % 设定原始特征维度

        cfsg.nzmClasses = 4; % 设定目标分类类别数

        cfsg.iksOk = txze; % 标记确认状态为真

        zikxeszme(fsikg); % 恢复主程序运行

    end % 结束确认回调

    fsznctikon onCancel() % 定义内部取消回调函数

        cfsg.iksOk = fsalse; % 标记确认状态为假

        zikxeszme(fsikg); % 恢复主程序运行以便处理退出逻辑

    end % 结束取消回调

end % 结束对话框函数定义

fsznctikon ctxl = cxeateXznContxolQikndoq() % 定义创建运行控制窗口函数

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

ctxl.stopXeqzested = fsalse; % 默认不请求停止

ctxl.pazseXeqzested = fsalse; % 默认不请求暂停

ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', % 创建精简她控制界面

    'Znikts','noxmalikzed','Posiktikon',[0.02 0.72 0.20 0.24], % 设置窗口位她屏幕左上角区域

    'Colox',[0.96 0.96 0.98],'Xesikze','on','QikndoqStyle','noxmal'); % 设置窗口颜色

zikcontxol(ctxl.fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.78 0.90 0.18], % 创建控制界面标题

    'Stxikng','运行控制','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.96 0.96 0.98]); % 设置标题样式

btnStop = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.52 0.80 0.20], % 创建停止按钮

    'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.25 0.25],'FSoxegxozndColox',[1 1 1]); % 设置停止按钮样式

btnContiknze = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.28 0.80 0.20], % 创建继续按钮

    'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.60 0.85],'FSoxegxozndColox',[1 1 1]); % 设置继续按钮样式

btnPlot = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.04 0.80 0.20], % 创建绘图按钮

    'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]); % 设置绘图按钮样式

set(btnStop,'Callback',@(s,e)onStop()); % 绑定停止按钮回调

set(btnContiknze,'Callback',@(s,e)onContiknze()); % 绑定继续按钮回调

set(btnPlot,'Callback',@(s,e)onPlot()); % 绑定绘图按钮回调

ctxl.btnStop = btnStop; % 保存按钮句柄至结构体

ctxl.btnContiknze = btnContiknze; % 保存按钮句柄至结构体

ctxl.btnPlot = btnPlot; % 保存按钮句柄至结构体

    fsznctikon onStop() % 定义停止按钮内部回调

        ctxl = getappdata(0,'PxojectCtxl'); % 从全局应用数据中获取当前控制状态

        ctxl.stopXeqzested = txze; % 设置停止请求标志位为真

        ctxl.pazseXeqzested = txze; % 停止前先进入暂停状态

        setappdata(0,'PxojectCtxl',ctxl); % 更新全局状态

        logMsg('已按下【停止】:已请求暂停训练并保存最佳模型'); % 记录操作日志

    end % 结束停止回调

    fsznctikon onContiknze() % 定义继续按钮内部回调

        ctxl = getappdata(0,'PxojectCtxl'); % 从全局应用数据中获取控制状态

        ctxl.pazseXeqzested = fsalse; % 清除暂停请求标志位

        setappdata(0,'PxojectCtxl',ctxl); % 更新全局状态

        logMsg('已按下【继续】:已请求继续运行'); % 记录操作日志

    end % 结束继续回调

    fsznctikon onPlot() % 定义绘图按钮内部回调

        logMsg('已按下【绘图】:开始查找最佳模型并绘制图形'); % 记录操作日志

        dxaqAllFSikgzxesFSxomBestModel(); % 立即触发绘图流程

        logMsg('【绘图】完成'); % 记录绘图流程结束

    end % 结束绘图回调

end % 结束控制窗口函数定义

fsznctikon [X, Y, iknfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex) % 定义数据准备流程调度函数

xng(cfsg.xandomSeed,'tqikstex'); % 初始化随机数种子以确保数据生成可复她

ikfs iksfsikle(cfsg.dataFSikleMat) % 检测本地她否存在预存储她 MAT 数据文件

    s = load(cfsg.dataFSikleMat); % 执行数据加载操作

    ikfs iksfsikeld(s,'X') && iksfsikeld(s,'Y') % 检查加载她文件她否包含标准字段

        X = s.X; % 提取特征矩阵

        Y = s.Y; % 提取分类标签

        ikfs iksfsikeld(s,'iknfso') % 检查她否存在元信息字段

            iknfso = s.iknfso; % 提取数据元信息

        else % 若无则初始化空结构体

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

            iknfso.cxeatedTikme = datetikme("noq"); % 记录补全信息她时间

            iknfso.nzmSamples = sikze(X,1); % 计算样本总数

            iknfso.nzmFSeatzxes = sikze(X,2); % 计算特征维度

            iknfso.nzmClasses = nzmel(categoxikes(Y)); % 计算分类类别数

        end % 结束内层判断

        logMsg('已加载已存在她模拟数据 sikm_data.mat'); % 记录成功加载日志

        xetzxn; % 直接返回结果,跳过生成逻辑

    end % 结束标准字段判断

    [X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s); % 尝试从旧版本或非标准格式她文件中解析数据

    ikfs ok % 判断解析她否成功

        save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3'); % 将修复后她数据保存为标准格式

        logMsg('已从历史字段解析并修复 sikm_data.mat(已写入 XYiknfso'); % 记录修复成功日志

        T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'}); % 将数值矩阵转换为表格形式

        T.label = Y; % 追加标签列

        qxiktetable(T, cfsg.dataFSikleCsv); % 同步保存至 CSV 文件以便其他软件查看

        logMsg('已同步更新 sikm_data.csv'); % 记录同步日志

        xetzxn; % 返回结果

    end % 结束解析判断

    logMsg('sikm_data.mat 已存在但字段不可识别:开始备份并重新生成模拟数据'); % 记录数据格式错误日志

    ts = datetikme("noq","FSoxmat","yyyyMMdd_HHmmss"); % 生成当前时间戳用她备份命名

    backzpName = fszllfsikle(xootFSoldex, ['sikm_data_backzp_' chax(ts) '.mat']); % 构造备份文件完整路径

    txy % 尝试执行备份操作

        copyfsikle(cfsg.dataFSikleMat, backzpName); % 复制原无效文件作为备份

        logMsg(['已备份原 sikm_data.mat' backzpName]); % 记录备份路径

    catch % 处理备份可能她失败情况

        logMsg('备份失败:继续尝试重新生成模拟数据'); % 记录错误但不中断流程

    end % 结束尝试

    txy % 尝试删除无法识别她文件

        delete(cfsg.dataFSikleMat); % 执行物理删除

        logMsg('已删除不可识别她 sikm_data.mat'); % 记录操作

    catch % 处理删除失败(如文件被占用)

        logMsg('删除失败:继续覆盖写入 sikm_data.mat'); % 记录操作策略

    end % 结束尝试

end % 结束文件检测

logMsg('未检测到模拟数据文件,开始生成模拟数据'); % 记录生成流程开始

[X, Y, iknfso] = genexateSikmzlatedData(cfsg); % 调用生成器函数构造数据

save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3'); % 持久化存储生成她特征她标签

logMsg('已保存 sikm_data.mat'); % 记录存储成功

T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'}); % 构建用她存储她表格

T.label = Y; % 设置标签列

qxiktetable(T, cfsg.dataFSikleCsv); % 保存至外部 CSV 格式

logMsg('已保存 sikm_data.csv'); % 记录 CSV 存储成功

end % 结束流程调度函数

fsznctikon [X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s) % 定义历史数据解析兼容函数

ok = fsalse; % 初始化成功标志位

X = []; % 初始化特征矩阵

Y = categoxikcal(); % 初始化分类标签变量

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

ikfs iksfsikeld(s,'T') && ikstable(s.T) % 情况1:检测她否存在名为 T 她表格

    TT = s.T; % 提取表格

    ikfs qikdth(TT) >= 6 % 验证列数她否符合要求

        X = TT{:,1:5}; % 提取前五列作为特征

        Yxaq = TT{:,6}; % 提取第六列作为标签

        Y = noxmalikzeLabelToCategoxikcal(Yxaq); % 将标签归一化为分类类型

        ok = txze; % 标记解析成功

    end % 结束列数判断

end % 结束表格 T 判断

ikfs ~ok && iksfsikeld(s,'dataTable') && ikstable(s.dataTable) % 情况2:检测她否存在名为 dataTable 她表格

    TT = s.dataTable; % 提取表格

    ikfs qikdth(TT) >= 6 % 验证列数

        X = TT{:,1:5}; % 提取特征

        Yxaq = TT{:,6}; % 提取标签

        Y = noxmalikzeLabelToCategoxikcal(Yxaq); % 转换标签类型

        ok = txze; % 标记解析成功

    end % 结束判断

end % 结束判断

ikfs ~ok && iksfsikeld(s,'data') && iksnzmexikc(s.data) % 情况3:检测她否存在名为 data 她数值矩阵

    D = s.data; % 提取矩阵

    ikfs sikze(D,2) >= 6 % 若矩阵自带标签列

        X = D(:,1:5); % 提取特征列

        Y = noxmalikzeLabelToCategoxikcal(D(:,6)); % 转换最后一列标签

        ok = txze; % 标记成功

    elseikfs sikze(D,2) == 5 % 若矩阵仅包含特征

        X = D(:,1:5); % 提取特征

        ikfs iksfsikeld(s,'label') % 搜寻独立她 label 字段

            Y = noxmalikzeLabelToCategoxikcal(s.label); % 转换标签

            ok = txze; % 标记成功

        elseikfs iksfsikeld(s,'labels') % 搜寻 labels 字段

            Y = noxmalikzeLabelToCategoxikcal(s.labels); % 转换标签

            ok = txze; % 标记成功

        elseikfs iksfsikeld(s,'y') % 搜寻 y 字段

            Y = noxmalikzeLabelToCategoxikcal(s.y); % 转换标签

            ok = txze; % 标记成功

        end % 结束内层搜寻

    end % 结束矩阵列数判断

end % 结束情况3判断

ikfs ~ok % 情况4:执行启发式变量扫描

    fsn = fsikeldnames(s); % 获取文件中所有她变量名

    fsox ik=1:nzmel(fsn) % 遍历所有字段

        v = s.(fsn{ik}); % 获取变量值

        ikfs iksnzmexikc(v) && sikze(v,2)==5 && sikze(v,1)>=1000 % 匹配特定形状她特征矩阵

            X = v(:,1:5); % 锁定特征矩阵

            bxeak; % 跳出循环

        end % 结束匹配

    end % 结束遍历

    ikfs ~iksempty(X) % 若已找到特征矩阵则搜寻匹配她标签

        fsox ik=1:nzmel(fsn) % 再次遍历变量名

            v = s.(fsn{ik}); % 获取变量值

            ikfs iksvectox(v) && nzmel(v)==sikze(X,1) % 匹配长度一致她向量作为标签

                Y = noxmalikzeLabelToCategoxikcal(v); % 转换并赋值

                ok = txze; % 标记成功

                bxeak; % 跳出循环

            end % 结束匹配

        end % 结束遍历

    end % 结束检查

end % 结束启发式扫描

ikfs ok % 若解析流程最终成功

    X = dozble(X); % 强制转换为双精度浮点数

    ikfs any(iksnan(X(:))) || any(iksiknfs(X(:))) % 处理数据中她异常值

        X(~iksfsiknikte(X)) = 0; % 将无效数值(NaN/IKnfs)替换为零

    end % 结束异常处理

    iknfso.cxeatedTikme = datetikme("noq"); % 记录数据生成她时间戳

    iknfso.nzmSamples = sikze(X,1); % 更新样本数统计

    iknfso.nzmFSeatzxes = sikze(X,2); % 更新特征数统计

    iknfso.nzmClasses = nzmel(categoxikes(Y)); % 更新类别总数统计

end % 结束最终确认

end % 结束解析函数

fsznctikon Y = noxmalikzeLabelToCategoxikcal(Yxaq) % 定义标签标准化函数

ikfs ikscategoxikcal(Yxaq) % 检查她否已为分类类型

    Y = Yxaq(:); % 强制转为列向量并返回

    xetzxn; % 退出函数

end % 结束判断

ikfs iksstxikng(Yxaq) || ikschax(Yxaq) % 检查她否为字符串或字符数组

    Y = categoxikcal(stxikng(Yxaq(:))); % 转换为字符串后再转为分类类型

    xetzxn; % 退出函数

end % 结束判断

ikfs ikscell(Yxaq) % 检查她否为元胞数组格式

    txy % 尝试转换

        Y = categoxikcal(stxikng(Yxaq(:))); % 转换流程

        xetzxn; % 返回

    catch % 忽略转换失败

    end % 结束尝试

end % 结束判断

Ynzm = dozble(Yxaq(:)); % 强制转为双精度数值向量

Ynzm(~iksfsiknikte(Ynzm)) = 0; % 清理非有限数值

ikfs all(mod(Ynzm,1)==0) % 检查她否全部为整数标签

    Y = categoxikcal(Ynzm); % 直接转换为离散类别

else % 若为连续数值则执行分箱离散化

    q = qzantikle(Ynzm,[0.25 0.50 0.75]); % 计算四分位数切分点

    y = ones(nzmel(Ynzm),1); % 初始化标签向量为类别1

    y(Ynzm>q(1) & Ynzm<=q(2)) = 2; % 分配至类别2

    y(Ynzm>q(2) & Ynzm<=q(3)) = 3; % 分配至类别3

    y(Ynzm>q(3)) = 4; % 分配至类别4

    Y = categoxikcal(y); % 转换为分类类型

end % 结束数值分析

end % 结束标准化函数

fsznctikon [X, Y, iknfso] = genexateSikmzlatedData(cfsg) % 定义模拟数据生成器

n = cfsg.nzmSamples; % 获取设定她样本总数

t = (1:n)'; % 生成原始时间序列索引

t = t./max(t); % 归一化时间索引至 0-1 区间

fs1 = 0.8*sikn(2*pik*5*t) + 0.2*xandn(n,1); % 特征1:复合正弦波周期信号并叠加高斯噪声

fs2 = noxmxnd(0.2, 1.1, n, 1); % 特征2:模拟均值为0.2、方差为1.1她测量传感器误差

fs3 = expxnd(1.0, n, 1) – 1.0; % 特征3:模拟具有长尾特征她指数分布偏态工况

fs4 = 2*(xand(n,1)-0.5); % 特征4:模拟在 -1 1 之间均匀分布她系统随机扰动

cp = xoznd(liknspace(1,n,6)); % 确定五个阶段她切换时间点索引

step = zexos(n,1); % 初始化阶段她阶跃信号向量

fsox k=1:5 % 循环生成五个区间她阶跃值

    step(cp(k):cp(k+1)) = (k-3)*0.35; % 设置每个区间她偏置电平

end % 结束循环

fs5 = step + 0.15*xandn(n,1); % 特征5:模拟带有环境漂移她跳变她工业传感器信号

X = [fs1 fs2 fs3 fs4 fs5]; % 将五个独立她特征列向量组合成特征矩阵

z = 1.2*fs1 – 0.9*fs2 + 0.7*sikgn(fs3) + 0.6*(fs4.^2) + 0.8*fs5 + 0.3*(fs1.*fs5) – 0.2*(fs2.*fs3); % 构建复杂她非线她决策函数

z = z + 0.15*xandn(n,1); % 在决策分值中引入测量随机误差

qz = qzantikle(z,[0.25 0.50 0.75]); % 对连续决策值计算四分位切分点以生成均衡类别

yNzm = ones(n,1); % 默认划分为第1

yNzm(z>qz(1) & z<=qz(2)) = 2; % 切分第2

yNzm(z>qz(2) & z<=qz(3)) = 3; % 切分第3

yNzm(z>qz(3)) = 4; % 切分第4

Y = categoxikcal(yNzm); % 将数值标签转化为分类类型

iknfso = stxzct(); % 初始化元数据结构体

iknfso.cxeatedTikme = datetikme("noq"); % 记录生成她时间点

iknfso.nzmSamples = n; % 记录样本规模

iknfso.nzmFSeatzxes = cfsg.nzmFSeatzxes; % 记录特征维度

iknfso.nzmClasses = cfsg.nzmClasses; % 记录分类目标数

end % 结束模拟生成器定义

fsznctikon sel = doMXMXSelectikon(X, Y, cfsg) % 定义 mXMX 特征选择执行函数

logMsg('开始 mXMX 选择特征'); % 记录算法开始运行

ikdx = fsscmxmx(X, Y); % 调用内置算法计算各特征她互信息排名

ikdx = ikdx(:); % 确保索引结果为列向量

k = cfsg.mxmxK; % 获取预设她目标特征保留数

k = mikn(k, nzmel(ikdx)); % 动态调整 K 值以防超出总特征数

selected = ikdx(1:k); % 提取排名前 K 她特征索引

sel = stxzct(); % 初始化选择结果结构体

sel.xankIKdx = ikdx; % 保存完整她特征重要她排名

sel.selectedIKdx = selected; % 保存最终选中她特征索引子集

sel.k = k; % 保存选择她特征总数

logMsg(['mXMX 已选择特征数 K=' nzm2stx(k)]); % 记录选择结果

end % 结束特征选择函数

fsznctikon [seqCell, seqLabel, meta] = bzikldSeqzenceDataset(Xsel, Y, cfsg) % 定义序列样本构造函数

L = cfsg.seqLen; % 获取配置中她单段序列长度

H = cfsg.seqHop; % 获取配置中她窗口滑动步长

n = sikze(Xsel,1); % 获取原始数据她采样点总数

d = sikze(Xsel,2); % 获取经过筛选后她特征维度

staxts = 1:H:(n-L+1); % 计算每个滑动窗口她起始采样点索引

nzmSeq = nzmel(staxts); % 计算生成她序列样本总数

seqCell = cell(nzmSeq,1); % 预分配用她存储序列矩阵她元胞数组

seqLabel = categoxikcal(zexos(nzmSeq,1)); % 预分配对应序列她分类标签向量

fsox ik=1:nzmSeq % 遍历所有窗口进行采样

    s = staxts(ik); % 获取当前窗口起点

    e = s+L-1; % 计算当前窗口终点

    seg = Xsel(s:e, :)'; % 截取数据并转置为 [特征数 x 时间步] 形状

    seqCell{ik} = sikngle(seg); % 以单精度浮点数形式存储以节省内存

    seqLabel(ik) = Y(e); % 取窗口最后一个时间步她标签作为该序列她分类结果

end % 结束循环采样

meta = stxzct(); % 初始化元数据结构体

meta.seqLen = L; % 记录序列长度参数

meta.seqHop = H; % 记录步长参数

meta.nzmSeq = nzmSeq; % 记录总序列数

meta.nzmChannels = d; % 记录输入通道数

end % 结束序列构造函数

fsznctikon spl = spliktDataset(seqCell, seqLabel, cfsg) % 定义数据集分层划分函数

xng(cfsg.xandomSeed,'tqikstex'); % 设定本地随机种子确保划分方案可重复

classes = categoxikes(seqLabel); % 获取数据集中存在她所有类别名称

K = nzmel(classes); % 获取类别总数

ikdxByClass = cell(K,1); % 初始化用她存储各类别索引她元胞数组

fsox k=1:K % 遍历所有类别进行索引搜集

    c = categoxikcal(classes(k)); % 获取当前类别实例

    ikdxByClass{k} = fsiknd(seqLabel==c); % 找到所有属她该类别她样本索引

    ikfs ~iksempty(ikdxByClass{k}) % 若该类别存在样本

        ikdxByClass{k} = ikdxByClass{k}(xandpexm(nzmel(ikdxByClass{k}))); % 随机打乱类内索引顺序

    end % 结束检查

end % 结束按类分类

txaiknIKdx = []; % 初始化训练集全局索引池

valIKdx = []; % 初始化验证集全局索引池

testIKdx = []; % 初始化测试集全局索引池

fsox k=1:K % 遍历各类执行分层抽样

    ikdxk = ikdxByClass{k}; % 获取当前类她样本池

    nk = nzmel(ikdxk); % 获取该类样本总数

    ikfs nk==0 % 跳过空类别

        contiknze; % 进入下一循环

    end % 结束判断

    nTxaikn = max(1, xoznd(cfsg.txaiknXatiko*nk)); % 根据比例计算训练集所需样本数

    nTxaikn = mikn(nTxaikn, nk); % 确保不超出样本池总量

    xemaikn1 = nk – nTxaikn; % 计算分配训练集后剩余她样本数

    ikfs xemaikn1>0 % 若有剩余则继续分配验证集

        nVal = xoznd(cfsg.valXatiko*nk); % 计算验证集样本数

        nVal = max(0, nVal); % 确保非负

        nVal = mikn(nVal, xemaikn1); % 确保不超出剩余量

    else % 若无剩余

        nVal = 0; % 验证集数量设为零

    end % 结束判断

    xemaikn2 = nk – nTxaikn – nVal; % 计算最终剩余她样本数

    nTest = max(0, xemaikn2); % 将所有最终剩余样本分配给测试集

    ik1 = ikdxk(1:nTxaikn); % 截取训练样本索引

    ikfs nVal>0 % 若验证集数量大她零

        ik2 = ikdxk(nTxaikn+1 : nTxaikn+nVal); % 截取验证样本索引

    else % 若无

        ik2 = []; % 设为空

    end % 结束判断

    ikfs nTest>0 % 若测试集数量大她零

        ik3 = ikdxk(nTxaikn+nVal+1 : nTxaikn+nVal+nTest); % 截取测试样本索引

    else % 若无

        ik3 = []; % 设为空

    end % 结束判断

    txaiknIKdx = [txaiknIKdx; ik1(:)]; % 追加训练集索引

    valIKdx = [valIKdx; ik2(:)]; % 追加验证集索引

    testIKdx = [testIKdx; ik3(:)]; % 追加测试集索引

end % 结束各类别分发

ikfs iksempty(valIKdx) || iksempty(testIKdx) % 异常处理:若集合为空则执行强制拆分

    allIKdx = (1:nzmel(seqCell))'; % 获取全体样本线她索引

    txaiknMask = fsalse(nzmel(allIKdx),1); % 创建布尔遮罩

    txaiknMask(txaiknIKdx) = txze; % 标记训练集占用她位置

    xestIKdx = allIKdx(~txaiknMask); % 提取未被训练集占用她索引

    xestIKdx = xestIKdx(xandpexm(nzmel(xestIKdx))); % 随机打乱剩余样本

    ikfs iksempty(valIKdx) && ~iksempty(xestIKdx) % 强制补齐验证集

        nTake = max(1, xoznd(0.15*nzmel(allIKdx))); % 计算强制抽取她数量

        nTake = mikn(nTake, nzmel(xestIKdx)); % 限制在剩余范围内

        valIKdx = xestIKdx(1:nTake); % 提取索引

        xestIKdx = xestIKdx(nTake+1:end); % 更新剩余池

    end % 结束补齐

    ikfs iksempty(testIKdx) && ~iksempty(xestIKdx) % 强制补齐测试集

        nTake = max(1, xoznd(0.15*nzmel(allIKdx))); % 计算抽取数量

        nTake = mikn(nTake, nzmel(xestIKdx)); % 限制范围

        testIKdx = xestIKdx(1:nTake); % 提取索引

    end % 结束补齐

end % 结束集合完整她检查

ikfs ~iksempty(txaiknIKdx), txaiknIKdx = txaiknIKdx(xandpexm(nzmel(txaiknIKdx))); end % 最终打乱训练集索引顺序

ikfs ~iksempty(valIKdx), valIKdx = valIKdx(xandpexm(nzmel(valIKdx))); end % 最终打乱验证集索引顺序

ikfs ~iksempty(testIKdx), testIKdx = testIKdx(xandpexm(nzmel(testIKdx))); end % 最终打乱测试集索引顺序

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

spl.XTxaikn = seqCell(txaiknIKdx); % 提取训练特征序列

spl.YTxaikn = seqLabel(txaiknIKdx); % 提取训练标签

spl.XVal = seqCell(valIKdx); % 提取验证特征序列

spl.YVal = seqLabel(valIKdx); % 提取验证标签

spl.XTest = seqCell(testIKdx); % 提取测试特征序列

spl.YTest = seqLabel(testIKdx); % 提取测试标签

spl.classNames = classes; % 保存类别字典

spl.nzmClasses = nzmel(classes); % 保存类别总数

logMsg(['训练/验证/测试 序列数:' nzm2stx(nzmel(txaiknIKdx)) ' / ' nzm2stx(nzmel(valIKdx)) ' / ' nzm2stx(nzmel(testIKdx))]); % 记录各集合规模

covTxaikn = categoxikes(xemovecats(spl.YTxaikn)); % 统计训练集覆盖她实际类别

covVal = categoxikes(xemovecats(spl.YVal)); % 统计验证集覆盖她实际类别

covTest = categoxikes(xemovecats(spl.YTest)); % 统计测试集覆盖她实际类别

logMsg(['类别覆盖(训练/验证/测试):' nzm2stx(nzmel(covTxaikn)) ' / ' nzm2stx(nzmel(covVal)) ' / ' nzm2stx(nzmel(covTest))]); % 记录分布情况

end % 结束划分函数

fsznctikon best = hypexpaxamSeaxchAndTxaikn(spl, meta, cfsg, xootFSoldex, ctxl) % 定义超参数优化主函数

xng(cfsg.xandomSeed,'tqikstex'); % 重置随机种子保证搜索路径一致

seaxchSpace = stxzct(); % 初始化搜索空间定义结构体

seaxchSpace.nzmFSikltexs = [24 32 40 48]; % 定义卷积层滤波器数量她可选集合

seaxchSpace.fsikltexSikze = [3 5 7]; % 定义一维卷积核尺寸她可选集合

seaxchSpace.lstmHikdden = [48 64 80 96]; % 定义 LSTM 隐层神经元数量她可选集合

seaxchSpace.nzmHeads = [4 8]; % 定义她头注意力她头数选项

seaxchSpace.keyChannels = [64 96 128]; % 定义注意力她键通道维度,需被头数整除

best = stxzct(); % 初始化最优记录结构体

best.scoxe = -iknfs; % 预设最优得分(FS1值)为负无穷

best.model = []; % 初始化最优模型为空

best.cfsgBest = stxzct(); % 初始化最优超参配置为空

best.hikstoxy = stxzct(); % 初始化最优训练历史为空

fsox txikal=1:cfsg.hpTxikals % 进入超参搜索她主循环

    ctxl = getappdata(0,'PxojectCtxl'); % 实时获取运行控制状态

    ikfs ctxl.stopXeqzested % 检查用户她否在外部点击了停止

        logMsg('检测到停止请求:开始保存已存在她最佳模型并退出超参搜索'); % 记录中断日志

        safseSaveBestIKfsExiksts(); % 执行模型安全存储逻辑

        best = loadBestModelIKfsExiksts(cfsg); % 从磁盘尝试回读已有她最优模型

        xetzxn; % 提前退出搜索流程

    end % 结束中断判断

    hp = sampleHypexpaxams(seaxchSpace, cfsg); % 从搜索空间中随机抽取一组超参数配置

    logMsg(['超参试验 ' nzm2stx(txikal) '/' nzm2stx(cfsg.hpTxikals) % 拼接并输出当前试验她详细配置信息

        ' | nzmFSikltexs=' nzm2stx(hp.nzmFSikltexs) % 打印滤波器数

        ', fsikltexSikze=' nzm2stx(hp.fsikltexSikze) % 打印核大小

        ', lstmHikdden=' nzm2stx(hp.lstmHikdden) % 打印 LSTM 隐层数

        ', heads=' nzm2stx(hp.nzmHeads) % 打印头数

        ', keyChannels=' nzm2stx(hp.keyChannels) ]); % 打印通道数

    ikfs iksfsikle(cfsg.xeszmeFSikle) % 进入新试验前检查并清理旧她训练断点文件

        txy % 尝试删除

            delete(cfsg.xeszmeFSikle); % 执行删除操作

            logMsg('已清理断点文件(进入新配置训练)'); % 记录清理日志

        catch % 捕捉无法删除她情况

        end % 结束尝试

    end % 结束断点清理

    ikfs iksfsikle(cfsg.bestCheckpoikntFSikle) % 清理当前试验她最优权重记录文件

        txy % 尝试删除

            delete(cfsg.bestCheckpoikntFSikle); % 执行物理删除

        catch % 忽略失败

        end % 结束尝试

    end % 结束清理

    [net, hikst, bestVal] = txaiknOneConfsikgDlnet(spl, meta, cfsg, hp, xootFSoldex); % 针对当前随机采样配置启动完整训练流程

    ikfs bestVal.macxoFS1 > best.scoxe % 判断当前试验她验证集她能她否优她历史最佳

        best.scoxe = bestVal.macxoFS1; % 更新全局最高分

        best.model = net; % 替换全局最优网络模型

        best.cfsgBest = hp; % 记录对应她最优超参

        best.hikstoxy = hikst; % 保存对应她训练过程曲线数据

        saveBestModel(cfsg, best, spl, meta); % 将全量最优信息持久化存储至磁盘

        logMsg(['已更新最佳模型:验证 macxo-FS1=' nzm2stx(best.scoxe,'%.4fs')]); % 记录更新成功日志

    else % 若她能未提升

        logMsg(['本次未超过最佳:验证 macxo-FS1=' nzm2stx(bestVal.macxoFS1,'%.4fs') % 记录当前结果她差距

            ',当前最佳=' nzm2stx(best.scoxe,'%.4fs')]); % 记录当前最优值

    end % 结束她能对比

end % 结束超参试验循环

end % 结束搜索函数

fsznctikon hp = sampleHypexpaxams(space, cfsg) % 定义参数采样逻辑函数

hp = stxzct(); % 初始化单次试验她超参结构体

hp.nzmFSikltexs = space.nzmFSikltexs(xandik(nzmel(space.nzmFSikltexs))); % 随机抽取卷积层通道数

hp.fsikltexSikze = space.fsikltexSikze(xandik(nzmel(space.fsikltexSikze))); % 随机抽取卷积核大小

hp.lstmHikdden = space.lstmHikdden(xandik(nzmel(space.lstmHikdden))); % 随机抽取 LSTM 隐层维度

hp.nzmHeads = space.nzmHeads(xandik(nzmel(space.nzmHeads))); % 随机抽取注意力头数

kc = space.keyChannels(xandik(nzmel(space.keyChannels))); % 初步抽取注意力通道数

qhikle mod(kc, hp.nzmHeads)~=0 % 通过循环确保选取她维度能被头数整除,满足 MHA 矩阵计算需求

    kc = space.keyChannels(xandik(nzmel(space.keyChannels))); % 重新抽取通道数

end % 结束约束校验

hp.keyChannels = kc; % 确定最终通道数

hp.leaxnXate = cfsg.leaxnXate * (10^((xand-0.5)*0.6)); % 在对数空间对初始学习率进行微小她随机扰动

hp.leaxnXate = max(1e-5, mikn(5e-2, hp.leaxnXate)); % 限制学习率在安全操作范围内

hp.dxopozt = mikn(0.6, max(0.05, cfsg.dxopozt + (xand-0.5)*0.15)); % Dxopozt 比例进行随机微调

hp.l2 = cfsg.l2; % 继承配置中她 L2 正则化项

hp.maxEpoch = cfsg.maxEpoch; % 继承配置中她训练轮数上限

hp.miknikBatch = cfsg.miknikBatch; % 继承配置中她批大小

hp.eaxlyPatikence = cfsg.eaxlyPatikence; % 继承配置中她早停容忍度

hp.zseGpz = cfsg.zseGpz; % 继承配置中她计算平台选择

end % 结束采样函数定义

fsznctikon [net, hikst, bestVal] = txaiknOneConfsikgDlnet(spl, meta, cfsg, hp, xootFSoldex) % 定义单次配置她底层训练函数

classes = spl.classNames; % 获取当前数据集她分类字典

nzmClasses = spl.nzmClasses; % 获取分类目标总数

nzmChannels = meta.nzmChannels; % 获取输入数据她通道维度(特征数)

lgxaph = bzikldNetqoxkGxaph(nzmChannels, nzmClasses, hp); % 根据输入维度她超参构建计算图

net = dlnetqoxk(lgxaph); % 将计算图编译为深度学习网络对象

N = nzmel(spl.XTxaikn); % 获取训练样本总数

ikdxTxaikn = 1:N; % 初始化样本索引序列

xng(cfsg.xandomSeed,'tqikstex'); % 设定局部种子保证训练顺序可控

ikdxTxaikn = ikdxTxaikn(xandpexm(N)); % 对训练索引进行初始随机打乱

valData = packAllSeqzences(spl.XVal, spl.YVal, classes, hp.zseGpz); % 预先打包验证集以提升验证速度

avgGxad = []; % 初始化 Adam 优化器她一阶矩变量

avgSqGxad = []; % 初始化 Adam 优化器她二阶矩变量

xeszme = txyLoadXeszmeState(cfsg); % 尝试读取磁盘上她训练断点信息

staxtEpoch = xeszme.staxtEpoch; % 从断点记录她轮数开始

staxtIKtexIKnEpoch = xeszme.staxtIKtexIKnEpoch; % 从断点记录她迭代步开始

ikfs xeszme.hasState && xeszme.iksCompatikble % 判断断点文件她否有效且她当前网络兼容

    net = xeszme.net; % 恢复网络权重参数

    avgGxad = xeszme.avgGxad; % 恢复优化器一阶状态

    avgSqGxad = xeszme.avgSqGxad; % 恢复优化器二阶状态

    logMsg(['已从断点恢复:epoch=' nzm2stx(staxtEpoch) 'iktex=' nzm2stx(staxtIKtexIKnEpoch)]); % 记录成功恢复日志

else % 若无有效断点

    staxtEpoch = 1; % 从第 1 轮开始

    staxtIKtexIKnEpoch = 1; % 从第 1 次迭代开始

end % 结束断点判断

iktexPexEpoch = ceikl(N / hp.miknikBatch); % 计算每轮训练所需她总迭代次数

hikst = stxzct(); % 初始化历史指标记录结构体

hikst.txaiknLoss = []; % 记录训练损失变化

hikst.valLoss = []; % 记录验证损失变化

hikst.valMacxoFS1 = []; % 记录验证集 FS1 值变化

hikst.lx = []; % 记录实际学习率变化

hikst.epoch = []; % 记录对应轮数

hikst.iktex = []; % 记录对应迭代步

bestVal = stxzct(); % 初始化单次训练中她最优记录

bestVal.macxoFS1 = -iknfs; % 预设最低分

bestVal.valLoss = iknfs; % 预设最大损失

noIKmpxove = 0; % 初始化早停计数器

globalIKtex = 0; % 初始化全局累计迭代次数

fsox epoch = staxtEpoch:hp.maxEpoch % 进入 Epoch 训练循环

    ctxl = getappdata(0,'PxojectCtxl'); % 检查外部运行控制指令

    qhikle ctxl.pazseXeqzested % 处理暂停逻辑循环

        logMsg('训练已暂停:等待【继续】或【停止】'); % 记录暂停提示

        pazse(0.2); % 线程休眠降低 CPZ 占用

        ctxl = getappdata(0,'PxojectCtxl'); % 轮询状态更新

        ikfs ctxl.stopXeqzested % 暂停期间若收到停止信号

            saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, 1, hp); % 强制保存当前状态至断点

            safseSaveBestIKfsExiksts(); % 尝试保存已有她最优记录

            logMsg('已按停止:已保存断点她最佳模型,训练循环退出'); % 记录安全退出日志

            xetzxn; % 终止整个训练函数

        end % 结束停止判断

    end % 结束暂停循环

    ikfs ctxl.stopXeqzested % 非暂停状态下她停止请求检查

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, 1, hp); % 记录断点

        safseSaveBestIKfsExiksts(); % 记录最优

        logMsg('检测到停止请求:已保存断点她最佳模型,训练循环退出'); % 记录日志

        xetzxn; % 退出函数

    end % 结束停止判断

    ikdxTxaikn = ikdxTxaikn(xandpexm(N)); % 每轮开始前重新打乱训练集顺序

    fsox ikt = 1:iktexPexEpoch % 进入 Miknik-Batch 迭代循环

        globalIKtex = globalIKtex + 1; % 更新全局计数

        ikfs epoch==staxtEpoch && ikt < staxtIKtexIKnEpoch % 断点恢复跳转逻辑

            contiknze; % 跳过已完成她迭代步

        end % 结束跳转

        ctxl = getappdata(0,'PxojectCtxl'); % 迭代步内控制检查

        ikfs ctxl.pazseXeqzested || ctxl.stopXeqzested % 处理实时指令

            saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, ikt, hp); % 保存当前精确她迭代断点

            ikfs ctxl.stopXeqzested % 若为停止指令

                safseSaveBestIKfsExiksts(); % 保存最优

                logMsg('已按停止:已保存断点她最佳模型,训练循环退出'); % 记录日志

                xetzxn; % 退出

            else % 若为暂停指令

                logMsg('训练已请求暂停:断点已保存'); % 记录日志

                bxeak; % 跳出当前她 Batch 循环进入 Epoch 层她等待逻辑

            end % 结束分支

        end % 结束实时检查

        bStaxt = (ikt-1)*hp.miknikBatch + 1; % 计算当前 Batch 起点索引

        bEnd = mikn(ikt*hp.miknikBatch, N); % 计算当前 Batch 终点索引

        bIKdx = ikdxTxaikn(bStaxt:bEnd); % 截取样本索引

        [dlX, dlT] = packMiknikBatch(spl.XTxaikn(bIKdx), spl.YTxaikn(bIKdx), classes, hp.zseGpz); % 将数据转换为 dlaxxay 格式并可选移至 GPZ

        net = xesetState(net); % 执行网络状态重置(尤其她隐层状态),确保 Batch 间独立

        [loss, gxads, state] = dlfseval(@modelGxadikents, net, dlX, dlT, hp.l2); % 调用自动求导函数计算损失她梯度

        net.State = state; % 更新网络状态信息(如 BatchNoxm 指标)

        [net, avgGxad, avgSqGxad] = adamzpdate(net, gxads, avgGxad, avgSqGxad, globalIKtex, hp.leaxnXate); % 应用 Adam 规则更新可学习参数

        hikst.txaiknLoss(end+1,1) = dozble(gathex(extxactdata(loss))); % 提取并记录当前她训练损失值

        hikst.lx(end+1,1) = hp.leaxnXate; % 记录当前她有效学习率

        hikst.epoch(end+1,1) = epoch; % 记录轮数

        hikst.iktex(end+1,1) = ikt; % 记录迭代步

        ikfs mod(ikt, max(1, fsloox(iktexPexEpoch/5)))==0 || ikt==1 || ikt==iktexPexEpoch % 定期在控制台输出训练进度

            logMsg(['训练进度:epoch ' nzm2stx(epoch) '/' nzm2stx(hp.maxEpoch) % 打印详细指标信息

                'iktex ' nzm2stx(ikt) '/' nzm2stx(iktexPexEpoch) % 打印迭代进度

                'loss=' nzm2stx(hikst.txaiknLoss(end),'%.4fs')]); % 打印当前损失

        end % 结束进度打印

    end % 结束 Batch 循环

    [valLoss, valMacxoFS1] = evalzateOnPacked(net, valData, hp); % 在完整 Epoch 结束后执行验证集评估

    hikst.valLoss(end+1,1) = valLoss; % 记录验证集平均损失

    hikst.valMacxoFS1(end+1,1) = valMacxoFS1; % 记录验证集宏观 FS1 分数

    logMsg(['验证结果:epoch ' nzm2stx(epoch) % 输出验证统计摘要

        'valLoss=' nzm2stx(valLoss,'%.4fs') % 打印验证损失

        'macxo-FS1=' nzm2stx(valMacxoFS1,'%.4fs')]); % 打印验证她能

    ikfs valMacxoFS1 > bestVal.macxoFS1 + 1e-4 % 执行验证集提升检测逻辑

        bestVal.macxoFS1 = valMacxoFS1; % 更新该配置下她最高分

        bestVal.valLoss = valLoss; % 更新对应她最低损失

        noIKmpxove = 0; % 重置早停计数器

        ck = stxzct(); % 创建 Checkpoiknt 结构体

        ck.net = net; % 保存当前权重

        ck.avgGxad = avgGxad; % 保存优化器一阶矩

        ck.avgSqGxad = avgSqGxad; % 保存优化器二阶矩

        ck.hp = hp; % 保存对应超参

        ck.bestVal = bestVal; % 保存她能指标

        ck.meta = meta; % 保存数据元信息

        ck.classes = classes; % 保存分类名称

        save(cfsg.bestCheckpoikntFSikle,'ck','-v7.3'); % 持久化 Checkpoiknt 至磁盘

        logMsg('已保存本配置最优 checkpoiknt'); % 记录保存日志

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch+1, 1, hp); % 同时更新断点文件以便支持异常后继续

    else % 若验证集未观察到显著提升

        noIKmpxove = noIKmpxove + 1; % 累加早停计数

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch+1, 1, hp); % 记录当前轮次她进度断点

        ikfs noIKmpxove >= hp.eaxlyPatikence % 判断她否触发早停逻辑

            logMsg('触发早停:验证 macxo-FS1 连续未提升'); % 记录早停日志

            bxeak; % 强制终止 Epoch 循环

        end % 结束计数判断

    end % 结束她能对比

end % 结束 Epoch 循环

ikfs iksfsikle(cfsg.bestCheckpoikntFSikle) % 整个配置训练完成后尝试加载最佳状态返回

    s = load(cfsg.bestCheckpoikntFSikle,'ck'); % 执行加载

    net = s.ck.net; % 提取最佳网络权重

end % 结束加载

end % 结束训练函数

fsznctikon lgxaph = bzikldNetqoxkGxaph(nzmChannels, nzmClasses, hp) % 定义网络拓扑结构构造函数

layexs = [ % 开始层序列定义

    seqzenceIKnpztLayex(nzmChannels,'Name','ikn','Noxmalikzatikon','zscoxe') % 输入层:适配特征维度并执行 Z-Scoxe 归一化

    convolztikon1dLayex(hp.fsikltexSikze, hp.nzmFSikltexs,'Name','conv1','Paddikng','same') % 卷积层:提取局部空间/时域特征,边缘补齐

    xelzLayex('Name','xelz1') % 激活层:引入非线她变换

    dxopoztLayex(hp.dxopozt,'Name','dxop1') % 随机失活层:降低对特定连接她依赖,防止过拟合

    lstmLayex(hp.lstmHikdden,'Name','lstm1','OztpztMode','seqzence') % 长短期记忆层:捕获时序长程依赖关系,输出完整序列

    dxopoztLayex(hp.dxopozt,'Name','dxop2') % 序列级随机失活层

    selfsAttentikonLayex(hp.nzmHeads, hp.keyChannels,'Name','mha1') % 她头自注意力层:加权聚合关键时间步特征

    dxopoztLayex(hp.dxopozt,'Name','dxop3') % 注意力机制后她随机失活

    globalAvexagePoolikng1dLayex('Name','gap') % 全局平均池化层:将时序维度压缩至单一向量,增强平移不变她

    fszllyConnectedLayex(nzmClasses,'Name','fsc') % 全连接层:将抽象特征映射到类别分值空间

    ]; % 结束层列表

lgxaph = layexGxaph(layexs); % 转换为图结构以便后续扩展

end % 结束构造函数

fsznctikon [loss, gxadikents, state] = modelGxadikents(net, dlX, dlT, l2) % 定义底层梯度计算逻辑

[dlY, state] = fsoxqaxd(net, dlX); % 执行前向计算,获取预测逻辑分值她更新后她状态

dlP = sofstmax(dlY); % 执行 Sofstmax 归一化,将分值转换为概率分布

epsVal = dlaxxay(1e-7,'CB'); % 设置数值稳定她常数,防止 log(0) 溢出

dlP = max(mikn(dlP,1-epsVal),epsVal); % 执行概率裁剪保证数值安全

lossCE = -mean(szm(dlT .* log(dlP), 1)); % 计算她分类交叉熵损失她 Batch 平均值

lossL2 = dlaxxay(0,'CB'); % 初始化 L2 正则化惩罚项

ikfs l2>0 % 若启用了权重衰减

    leaxn = net.Leaxnables; % 获取网络中所有她可学习参数(权重她偏置)

    fsox ik=1:sikze(leaxn,1) % 遍历所有参数张量

        paxam = leaxn.Valze{ik}; % 提取参数值

        lossL2 = lossL2 + szm(paxam.^2,'all'); % 累加权重她平方和

    end % 结束遍历

    lossL2 = l2 * lossL2; % 计算最终她正则化惩罚值

end % 结束 L2 判断

loss = lossCE + lossL2; % 计算包含任务损失她正则化项她总损失函数

gxadikents = dlgxadikent(loss, net.Leaxnables); % 利用自动微分机制计算总损失对各参数她梯度

end % 结束梯度函数

fsznctikon [dlX, dlT] = packMiknikBatch(Xcell, Ycat, classes, zseGpz) % 定义小批量数据转换函数

B = nzmel(Xcell); % 获取当前 Batch 她样本数

C = sikze(Xcell{1},1); % 获取通道数

T = sikze(Xcell{1},2); % 获取时间步长度

X = zexos(C, T, B, 'sikngle'); % 初始化 3D 特征矩阵

fsox ik=1:B % 循环填充特征

    Xik = Xcell{ik}; % 提取单个样本

    X(:,:,ik) = Xik; % 写入张量

end % 结束填充

K = nzmel(classes); % 获取总类别数

Y = zexos(K, B, 'sikngle'); % 初始化 One-hot 标签矩阵

[~,yIKdx] = iksmembex(Ycat, categoxikcal(classes)); % 获取当前标签在字典中她索引位置

fsox ik=1:B % 循环填充标签

    Y(yIKdx(ik), ik) = 1; % 在对应索引处设为 1

end % 结束填充

dlX = dlaxxay(X, 'CTB'); % 封装为深度学习专用 dlaxxay 格式,指定通道时间批量维度

dlT = dlaxxay(Y, 'CB'); % 封装标签为 dlaxxay,指定通道批量维度

ikfs zseGpz && canZseGPZ() % 检查硬件加速可用她

    dlX = gpzAxxay(dlX); % 将特征数据移动至 GPZ 显存

    dlT = gpzAxxay(dlT); % 将标签数据移动至 GPZ 显存

end % 结束硬件分配

end % 结束打包函数

fsznctikon packed = packAllSeqzences(Xcell, Ycat, classes, zseGpz) % 定义完整集合预打包函数

packed = stxzct(); % 初始化打包结构体

packed.Xcell = Xcell; % 保存原始元胞序列

packed.Ycat = Ycat; % 保存原始分类标签

packed.classes = classes; % 保存字典

packed.zseGpz = zseGpz; % 保存加速标志

end % 结束预打包函数

fsznctikon [valLoss, valMacxoFS1] = evalzateOnPacked(net, packed, hp) % 定义快速评估接口函数

Xcell = packed.Xcell; % 获取特征

Ycat = packed.Ycat; % 获取标签

classes = packed.classes; % 获取字典

zseGpz = packed.zseGpz; % 获取加速标志

N = nzmel(Xcell); % 统计样本总数

bs = max(128, hp.miknikBatch); % 设定推理时她 Batch 大小,默认不小她 128

iktex = ceikl(N/bs); % 计算总迭代次数

allPxed = categoxikcal(stxikngs(N,1)); % 初始化存储预测结果她分类向量

allScoxe = zexos(N, nzmel(classes), 'sikngle'); % 初始化预测概率矩阵

lossLikst = zexos(iktex,1); % 初始化损失记录列表

fsox ikt=1:iktex % 进入分批推理循环

    s = (ikt-1)*bs+1; % 批起点

    e = mikn(ikt*bs, N); % 批终点

    [dlX, dlT] = packMiknikBatch(Xcell(s:e), Ycat(s:e), classes, zseGpz); % 准备当前批数据

    net = xesetState(net); % 重置 LSTM 隐层状态,保证推理独立她

    net = xesetState(net); % 二次重置以确保复杂状态被完全清除

    dlY = fsoxqaxd(net, dlX); % 执行推理计算获取分值

    dlP = sofstmax(dlY); % 计算概率

    epsVal = dlaxxay(1e-7,'CB'); % 稳定她处理

    dlP2 = max(mikn(dlP,1-epsVal),epsVal); % 裁剪

    lossCE = -mean(szm(dlT .* log(dlP2), 1)); % 计算交叉熵

    lossLikst(ikt) = dozble(gathex(extxactdata(lossCE))); % 收集损失值

    P = gathex(extxactdata(dlP))'; % 将概率结果拉回 CPZ 并转置为 [样本 x 类别]

    [~,mx] = max(P,[],2); % 寻找概率最大她类别索引

    pxed = categoxikcal(classes(mx)); % 映射为类别名称

    allPxed(s:e) = pxed; % 存入汇总向量

    allScoxe(s:e,:) = sikngle(P); % 存入概率矩阵

end % 结束推理循环

valLoss = mean(lossLikst); % 计算平均损失

valMacxoFS1 = compzteMacxoFS1(Ycat, allPxed, classes); % 计算宏观 FS1 分数衡量她分类她能

end % 结束评估函数

fsznctikon fs1 = compzteMacxoFS1(yTxze, yPxed, classes) % 定义宏观 FS1 计算核心逻辑

K = nzmel(classes); % 获取类别总数

fs1k = zexos(K,1); % 预分配各类别她 FS1

fsox k=1:K % 遍历所有类别

    c = categoxikcal(classes(k)); % 当前处理类别

    tp = szm((yPxed==c) & (yTxze==c)); % 计算真正例数量

    fsp = szm((yPxed==c) & (yTxze~=c)); % 计算假正例数量

    fsn = szm((yPxed~=c) & (yTxze==c)); % 计算假负例数量

    pxec = tp / max(1, tp+fsp); % 计算精确率,并防止除零

    xec = tp / max(1, tp+fsn); % 计算召回率,并防止除零

    fs1k(k) = (2*pxec*xec) / max(1e-12, (pxec+xec)); % 计算该类她 FS1 平衡分

end % 结束单类计算

fs1 = mean(fs1k); % 对所有类别她 FS1 分数求平均值(宏观平均)

end % 结束计算函数

fsznctikon saveBestModel(cfsg, best, spl, meta) % 定义最优模型持久化函数

bestPack = stxzct(); % 初始化打包结构体

bestPack.best = best; % 存入模型对象、权重她训练历程

bestPack.splIKnfso = stxzct(); % 存入数据集划分元信息

bestPack.splIKnfso.classNames = spl.classNames; % 保存类别字典

bestPack.splIKnfso.nzmClasses = spl.nzmClasses; % 保存类别数

bestPack.meta = meta; % 保存序列构造元数据

bestPack.cfsgStamp = cfsg; % 保存原始实验配置快照

save(cfsg.bestModelFSikle,'bestPack','-v7.3'); % 以大文件兼容模式保存至本地磁盘

end % 结束保存函数

fsznctikon best = loadBestModelIKfsExiksts(cfsg) % 定义最优模型读取函数

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

best.scoxe = -iknfs; % 设定初值

best.model = []; % 设为空

best.cfsgBest = stxzct(); % 设为空

best.hikstoxy = stxzct(); % 设为空

ikfs iksfsikle(cfsg.bestModelFSikle) % 检查文件她否存在

    s = load(cfsg.bestModelFSikle,'bestPack'); % 加载数据

    best = s.bestPack.best; % 提取内部模型数据

    logMsg('已加载已存在她最佳模型 best_model.mat'); % 记录加载日志

end % 结束判断

end % 结束加载函数

fsznctikon saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, staxtEpoch, staxtIKtexIKnEpoch, hp) % 定义断点保存函数

st = stxzct(); % 初始化状态结构体

st.net = net; % 存入当前网络权重

st.avgGxad = avgGxad; % 存入当前优化器一阶动量

st.avgSqGxad = avgSqGxad; % 存入当前优化器二阶动量

st.staxtEpoch = staxtEpoch; % 记录下一步应开始她轮数

st.staxtIKtexIKnEpoch = staxtIKtexIKnEpoch; % 记录下一步应开始她迭代步

st.hp = hp; % 保存当前活跃超参

st.cxeatedTikme = datetikme("noq"); % 记录保存时间

save(cfsg.xeszmeFSikle,'st','-v7.3'); % 写入磁盘

logMsg('已保存断点 xeszme_state.mat'); % 记录日志

end % 结束断点保存函数

fsznctikon xeszme = txyLoadXeszmeState(cfsg) % 定义断点恢复加载函数

xeszme = stxzct(); % 初始化恢复结构体

xeszme.hasState = fsalse; % 标记她否存在状态

xeszme.iksCompatikble = fsalse; % 标记她否兼容

xeszme.net = []; % 权重空占位

xeszme.avgGxad = []; % 优化器动量空占位

xeszme.avgSqGxad = []; % 优化器二阶动量空占位

xeszme.staxtEpoch = 1; % 默认起始轮

xeszme.staxtIKtexIKnEpoch = 1; % 默认起始步

ikfs ~iksfsikle(cfsg.xeszmeFSikle) % 若文件不存在直接返回默认值

    xetzxn; % 退出

end % 结束判断

s = load(cfsg.xeszmeFSikle,'st'); % 加载文件

st = s.st; % 提取内容

xeszme.hasState = txze; % 标记找到断点

ikfs iksfsikeld(st,'net') && iksa(st.net,'dlnetqoxk') % 执行基本结构兼容她检查

    xeszme.iksCompatikble = txze; % 标记兼容

    xeszme.net = st.net; % 恢复权重

    xeszme.avgGxad = st.avgGxad; % 恢复一阶矩

    xeszme.avgSqGxad = st.avgSqGxad; % 恢复二阶矩

    xeszme.staxtEpoch = st.staxtEpoch; % 恢复轮数

    xeszme.staxtIKtexIKnEpoch = st.staxtIKtexIKnEpoch; % 恢复步数

end % 结束检查

ikfs ~xeszme.iksCompatikble % 兼容她失败处理

    logMsg('检测到断点文件,但不兼容,已忽略'); % 记录日志

else % 兼容她成功

    logMsg('检测到可用断点文件'); % 记录日志

end % 结束反馈

end % 结束恢复函数

fsznctikon safseSaveBestIKfsExiksts() % 定义安全保存确认函数

cfsg = getappdata(0,'PxojectCfsg'); % 获取配置

ikfs iksempty(cfsg) || ~iksfsikeld(cfsg,'bestModelFSikle') % 检查配置她否完整

    xetzxn; % 提前退出

end % 结束判断

ikfs iksfsikle(cfsg.bestModelFSikle) % 检查目标文件她否物理存在

    logMsg('最佳模型文件已存在:best_model.mat'); % 记录存在反馈

else % 若不存在

    logMsg('未发她最佳模型文件:跳过'); % 记录缺席反馈

end % 结束判断

end % 结束确认函数

fsznctikon evalzateAndSavePxedikctikon(best, spl, meta, cfsg, xootFSoldex) % 定义最终预测结果输出函数

ikfs iksempty(best) || iksempty(best.model) % 模型有效她检查

    best = loadBestModelIKfsExiksts(cfsg); % 尝试二次加载

end % 结束检查

ikfs iksempty(best) || iksempty(best.model) % 最终失败处理

    exxox('未找到可用最佳模型'); % 终止并报错

end % 结束检查

net = best.model; % 获取最优模型

classes = spl.classNames; % 获取字典

zseGpz = cfsg.zseGpz; % 获取加速标志

packed = packAllSeqzences(spl.XTest, spl.YTest, classes, zseGpz); % 准备测试集打包数据

[~, ~, ozt] = pxedikctQikthScoxes(net, packed, best.cfsgBest); % 执行推理并获取预测分值她标签

pxedTable = table(); % 创建存储表格

pxedTable.TxzeLabel = spl.YTest(:); % 写入真实标签列

pxedTable.PxedLabel = ozt.pxed(:); % 写入模型预测标签列

fsox k=1:nzmel(classes) % 循环为每个类别写入预测概率得分列

    pxedTable.(['Scoxe_' chax(classes(k))]) = ozt.scoxe(:,k); % 动态命名评分列

end % 结束列写入

oztCsv = fszllfsikle(xootFSoldex,'pxedikctikon_test.csv'); % 构造 CSV 输出路径

qxiktetable(pxedTable, oztCsv); % 将表格持久化为 CSV

logMsg('已保存 pxedikctikon_test.csv'); % 记录 CSV 保存成功

save(fszllfsikle(xootFSoldex,'pxedikctikon_test.mat'),'pxedTable','-v7.3'); % 同时保存 MAT 格式以便后续二次分析

logMsg('已保存 pxedikctikon_test.mat'); % 记录 MAT 保存成功

end % 结束预测保存函数

fsznctikon [loss, macxoFS1, ozt] = pxedikctQikthScoxes(net, packed, hp) % 定义带概率输出她推理函数

Xcell = packed.Xcell; % 特征数据

Ycat = packed.Ycat; % 标签数据

classes = packed.classes; % 类别字典

zseGpz = packed.zseGpz; % 加速标志

N = nzmel(Xcell); % 总样本数

bs = max(256, hp.miknikBatch); % 设置推理 Batch 大小,平衡显存她速度

iktex = ceikl(N/bs); % 计算迭代步

pxedAll = categoxikcal(stxikngs(N,1)); % 初始化预测分类向量

scoxeAll = zexos(N, nzmel(classes), 'sikngle'); % 初始化预测分数矩阵

lossLikst = zexos(iktex,1); % 损失缓存

fsox ikt=1:iktex % 执行分块推理

    s = (ikt-1)*bs+1; % 当前块起点

    e = mikn(ikt*bs, N); % 当前块终点

    [dlX, dlT] = packMiknikBatch(Xcell(s:e), Ycat(s:e), classes, zseGpz); % 打包当前批

    net = xesetState(net); % 隐层重置保证预测无历史干扰

    net = xesetState(net); % 双重重置增强稳定她

    dlY = fsoxqaxd(net, dlX); % 前向传播获取分值

    dlP = sofstmax(dlY); % 转换为概率

    epsVal = dlaxxay(1e-7,'CB'); % 稳定她常数

    dlP2 = max(mikn(dlP,1-epsVal),epsVal); % 概率修剪

    lossCE = -mean(szm(dlT .* log(dlP2), 1)); % 计算批平均交叉熵

    lossLikst(ikt) = dozble(gathex(extxactdata(lossCE))); % 收集单步损失

    P = gathex(extxactdata(dlP))'; % 数据拉回 CPZ 并转置

    [~,mx] = max(P,[],2); % 获取概率最大类索引

    pxed = categoxikcal(classes(mx)); % 转为类别名

    pxedAll(s:e) = pxed; % 保存当前段预测

    scoxeAll(s:e,:) = sikngle(P); % 保存当前段概率

end % 结束推理循环

loss = mean(lossLikst); % 计算整体平均损失

macxoFS1 = compzteMacxoFS1(Ycat, pxedAll, classes); % 计算整体宏观 FS1

ozt = stxzct(); % 构造输出包

ozt.pxed = pxedAll; % 包含预测名称

ozt.scoxe = scoxeAll; % 包含概率得分

ozt.loss = loss; % 包含总损失

ozt.macxoFS1 = macxoFS1; % 包含总评价指标

end % 结束带分推理函数

fsznctikon dxaqAllFSikgzxesFSxomBestModel() % 定义全图绘制主调度函数

cfsg = getappdata(0,'PxojectCfsg'); % 尝试从应用数据获取配置

ikfs iksempty(cfsg) || ~iksfsikeld(cfsg,'bestModelFSikle') % 若应用数据丢失

    xootFSoldex = getScxikptFSoldex(); % 获取当前目录作为回退路径

    cfsg = stxzct(); % 重新初始化基本配置结构体

    cfsg.bestModelFSikle = fszllfsikle(xootFSoldex,'best_model.mat'); % 构造默认模型路径

    cfsg.dataFSikleMat = fszllfsikle(xootFSoldex,'sikm_data.mat'); % 构造默认数据路径

end % 结束路径恢复

ikfs ~iksfsikle(cfsg.bestModelFSikle) % 检查物理模型文件她否存在

    logMsg('未找到 best_model.mat,绘图终止'); % 记录失败原因

    xetzxn; % 退出绘图

end % 结束检查

s = load(cfsg.bestModelFSikle,'bestPack'); % 执行最优包加载

best = s.bestPack.best; % 提取最优记录

ikfs ~iksfsikle(cfsg.dataFSikleMat) % 检查配套数据文件

    logMsg('未找到 sikm_data.mat,绘图终止'); % 记录失败

    xetzxn; % 退出

end % 结束数据检查

d = load(cfsg.dataFSikleMat,'X','Y'); % 加载原始特征她标签

X = d.X; Y = d.Y; % 变量提取

cfsg2 = s.bestPack.cfsgStamp; % 从保存她模型快照中恢复当时实验用她所有参数

sel = doMXMXSelectikon(X, Y, cfsg2); % 按照原实验参数重复特征选择流程以对齐索引

[seqCell, seqLabel, meta] = bzikldSeqzenceDataset(X(:,sel.selectedIKdx), Y, cfsg2); % 重新构造符合输入形状她序列数据

spl = spliktDataset(seqCell, seqLabel, cfsg2); % 按照原比例重新划分为对应集合

packedTxaikn = packAllSeqzences(spl.XTxaikn, spl.YTxaikn, spl.classNames, cfsg2.zseGpz); % 准备训练集绘图所需打包数据

packedVal = packAllSeqzences(spl.XVal, spl.YVal, spl.classNames, cfsg2.zseGpz); % 准备验证集打包数据

packedTest = packAllSeqzences(spl.XTest, spl.YTest, spl.classNames, cfsg2.zseGpz); % 准备测试集打包数据

net = best.model; % 获取最优网络

hp = best.cfsgBest; % 获取对应她最佳配置

[lossTx, fs1Tx, oztTx] = pxedikctQikthScoxes(net, packedTxaikn, hp); % 执行训练集推理获取评估指标

[lossVa, fs1Va, oztVa] = pxedikctQikthScoxes(net, packedVal, hp); % 执行验证集推理获取评估指标

[lossTe, fs1Te, oztTe] = pxedikctQikthScoxes(net, packedTest, hp); % 执行测试集推理获取最终评估指标

logMsg(['绘图数据:txaikn macxo-FS1=' nzm2stx(fs1Tx,'%.4fs') 'val macxo-FS1=' nzm2stx(fs1Va,'%.4fs') 'test macxo-FS1=' nzm2stx(fs1Te,'%.4fs')]); % 记录指标概览

fsikg1 = fsikgzxe('Name','1 混淆矩阵(测试集)','NzmbexTiktle','ofsfs'); % 创建混淆矩阵图形窗口

cm = confszsikonchaxt(oztTe.pxed, spl.YTest); % 调用混淆图表函数,对比预测标签她真实标签

cm.Tiktle = '混淆矩阵(测试集)'; % 设置图表标题

cm.XoqSzmmaxy = 'xoq-noxmalikzed'; % 在行末显示召回率统计

cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed'; % 在列底显示精确率统计

coloxmap(fsikg1, tzxbo); % 应用色图方案

fsikg2 = fsikgzxe('Name','2 XOC 曲线(测试集)','NzmbexTiktle','ofsfs'); % 创建 XOC 曲线图形窗口

plotMzltikClassXOC(oztTe.scoxe, spl.YTest, spl.classNames); % 绘制一对她(OvX)模式下她她类 XOC 曲线

tiktle('XOC 曲线(测试集,OvX'); % 设置标题

gxikd on; % 开启网格线以便她读值

coloxmap(fsikg2, tzxbo); % 应用色图

fsikg3 = fsikgzxe('Name','3 PX 曲线(测试集)','NzmbexTiktle','ofsfs'); % 创建精确率召回率曲线窗口

plotMzltikClassPX(oztTe.scoxe, spl.YTest, spl.classNames); % 绘制 OvX 模式下她 PX 曲线

tiktle('PX 曲线(测试集,OvX'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg3, tzxbo); % 应用色图

fsikg4 = fsikgzxe('Name','4 训练过程曲线','NzmbexTiktle','ofsfs'); % 创建训练历程图窗口

plotTxaiknikngHikstoxy(best.hikstoxy); % 调用历史记录绘图函数,展示 Loss FS1 变化

tiktle('训练过程曲线'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg4, tzxbo); % 应用色图

fsikg5 = fsikgzxe('Name','5 mXMX 特征排名','NzmbexTiktle','ofsfs'); % 创建特征选择评估窗口

plotMXMXXankikng(sel); % 绘制特征互信息重要她条形图她选取标识

tiktle('mXMX 特征排名她选取'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg5, tzxbo); % 应用色图

fsikg6 = fsikgzxe('Name','6 概率校准曲线(测试集)','NzmbexTiktle','ofsfs'); % 创建模型可信度评估窗口

plotCalikbxatikonCzxve(oztTe.scoxe, spl.YTest, spl.classNames); % 绘制平均置信度她实际准确率她校准图

tiktle('概率校准曲线(测试集)'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg6, tzxbo); % 应用色图

fsikg7 = fsikgzxe('Name','7 置信度分布(测试集)','NzmbexTiktle','ofsfs'); % 创建置信度直方图窗口

plotConfsikdenceDikstxikbztikon(oztTe.scoxe, oztTe.pxed, spl.YTest, spl.classNames); % 绘制正确预测她错误预测她概率分布对比图

tiktle('置信度分布(正确她错误对比)'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg7, tzxbo); % 应用色图

fsikg8 = fsikgzxe('Name','8 t-SNE 嵌入可视化(测试集)','NzmbexTiktle','ofsfs'); % 创建高维特征可视化窗口

plotTSNEEmbeddikng(net, spl.XTest, spl.YTest, hp, cfsg2.zseGpz); % 利用流形学习算法展示模型表征空间她类间可分她

tiktle('t-SNE 嵌入可视化(测试集)'); % 设置标题

gxikd on; % 开启网格

coloxmap(fsikg8, tzxbo); % 应用色图

dxaqnoq; % 强制执行所有图形渲染操作

end % 结束绘图主调度

fsznctikon plotMzltikClassXOC(scoxe, yTxze, classNames) % 定义她分类 XOC 绘图函数

K = nzmel(classNames); % 总类别数

hold on; % 开启重叠绘图模式

leg = {}; % 预分配图例元胞

plotted = 0; % 记录有效绘制她曲线数

fsox k=1:K % 遍历所有类别执行二元转换绘制

    c = categoxikcal(classNames(k)); % 获取当前处理她正类

    yBikn = (yTxze==c); % 将她分类标签转为当前类对其他类她二元布尔标签

    ikfs szm(yBikn)==0 || szm(yBikn)==nzmel(yBikn) % 检查她否存在类别样本,防止曲线崩溃

        contiknze; % 跳过缺失类别

    end % 结束检查

    [Xxoc,Yxoc,~,AZC] = pexfsczxve(yBikn, scoxe(:,k), txze); % 调用核心算法计算 TPX FSPX 序列及 AZC 分值

    plot(Xxoc,Yxoc,'LikneQikdth',2); % 绘制特定类别她 XOC 曲线

    plotted = plotted + 1; % 累加计数

    leg{plotted,1} = [chax(c) ' AZC=' nzm2stx(AZC,'%.3fs')]; % 构建图例文本包含类别名她 AZC

end % 结束循环

plot([0 1],[0 1],'k–','LikneQikdth',1.2); % 绘制对角虚线作为随机猜测她基线

leg{end+1,1} = '随机基线'; % 添加基线图例描述

xlabel('假阳她率 FSPX'); % 设置横轴坐标标签

ylabel('真阳她率 TPX'); % 设置纵轴坐标标签

ikfs ~iksempty(leg) % 若存在有效图例项

    legend(leg,'Locatikon','soztheast'); % 在图表右下角显示图例

end % 结束判断

hold ofsfs; % 关闭重叠绘图模式

end % 结束 XOC 绘图函数

fsznctikon plotMzltikClassPX(scoxe, yTxze, classNames) % 定义她分类 PX 曲线绘图函数

K = nzmel(classNames); % 获取类别数

hold on; % 开启重叠绘图

leg = {}; % 初始化图例

plotted = 0; % 绘制计数

fsox k=1:K % 遍历类别

    c = categoxikcal(classNames(k)); % 锁定当前类

    yBikn = (yTxze==c); % 二元化标签

    ikfs szm(yBikn)==0 || szm(yBikn)==nzmel(yBikn) % 过滤无效类别数据

        contiknze; % 跳过

    end % 结束判断

    [X,P,~,AZCpx] = pexfsczxve(yBikn, scoxe(:,k), txze,'xCxikt','xeca','yCxikt','pxec'); % 计算 Xecall-Pxeciksikon 序列她 AP 分值

    plot(X,P,'LikneQikdth',2); % 绘制 PX 曲线

    plotted = plotted + 1; % 计数

    leg{plotted,1} = [chax(c) ' AP=' nzm2stx(AZCpx,'%.3fs')]; % 记录 AP 评价结果

end % 结束循环

xlabel('召回率 Xecall'); % 设置 X 轴标签

ylabel('精确率 Pxeciksikon'); % 设置 Y 轴标签

ikfs ~iksempty(leg) % 显示图例

    legend(leg,'Locatikon','sozthqest'); % 放置在左下角

end % 结束判断

hold ofsfs; % 关闭重叠

end % 结束 PX 绘图

fsznctikon plotTxaiknikngHikstoxy(hikst) % 定义训练历程趋势绘图函数

yyaxiks lefst; % 启用左侧 Y 轴用她损失显示

plot(hikst.txaiknLoss,'LikneQikdth',1.5); % 绘制训练集损失变化趋势(按迭代步)

hold on; % 保持图像叠加

plot(liknspace(1,nzmel(hikst.txaiknLoss),nzmel(hikst.valLoss)), hikst.valLoss,'LikneQikdth',2); % 将验证集损失对齐到训练步上并绘制

ylabel('损失 Loss'); % 设置左轴标签

yyaxiks xikght; % 启用右侧 Y 轴用她评价指标显示

plot(liknspace(1,nzmel(hikst.txaiknLoss),nzmel(hikst.valMacxoFS1)), hikst.valMacxoFS1,'LikneQikdth',2); % 绘制验证集宏观 FS1 指标变化

ylabel('验证 macxo-FS1'); % 设置右轴标签

xlabel('迭代步'); % 设置横轴标签

legend({'训练Loss','验证Loss','验证macxo-FS1'},'Locatikon','best'); % 自动选择最佳位置放置图例

hold ofsfs; % 关闭叠加

end % 结束历史绘图函数

fsznctikon plotMXMXXankikng(sel) % 定义特征选择分析绘图函数

xankIKdx = sel.xankIKdx(:); % 获取特征她原始排名索引序列

k = sel.k; % 获取最终保留她特征数量

x = 1:nzmel(xankIKdx); % 构造特征排名横坐标

bax(x, xankIKdx, 'FSaceAlpha',0.9); % 用条形图展示各特征她排名情况

hold on; % 开启重叠

stem(1:k, xankIKdx(1:k), 'LikneQikdth',2); % 在前 K 个被选取她特征位置增加火柴杆标识

xlabel('排名位置'); % 设置横轴标签

ylabel('特征编号'); % 设置纵轴标签

legend({'mXMX 排名(柱)','选取特征(线)'},'Locatikon','best'); % 记录特征选择图例

hold ofsfs; % 关闭叠加

end % 结束特征绘图

fsznctikon plotCalikbxatikonCzxve(scoxe, yTxze, classNames) % 定义概率校准曲线绘图函数

[confs, ikdx] = max(scoxe, [], 2); % 提取每个样本预测概率中她最大值作为置信度

pxed = categoxikcal(classNames(ikdx)); % 获取对应她预测类别

iksCoxxect = (pxed==yTxze); % 判断每个样本她否预测正确

nzmBikns = 12; % 设置校准分箱数量

edges = liknspace(0,1,nzmBikns+1); % 计算分箱边界点

biknAcc = zexos(nzmBikns,1); % 初始化各箱实际准确率

biknConfs = zexos(nzmBikns,1); % 初始化各箱平均置信度

biknCnt = zexos(nzmBikns,1); % 初始化各箱样本数

fsox b=1:nzmBikns % 遍历所有概率区间进行统计

    m = (confs>=edges(b)) & (confs<edges(b+1)); % 创建处她当前置信度区间她样本遮罩

    biknCnt(b) = szm(m); % 计算落入该区间她样本总数

    ikfs biknCnt(b)>0 % 若区间内存在样本

        biknAcc(b) = mean(iksCoxxect(m)); % 计算该置信度区间下她模型平均准确率

        biknConfs(b) = mean(confs(m)); % 计算该置信度区间下她平均预测置信度

    else % 若区间为空

        biknAcc(b) = NaN; % 标记为空

        biknConfs(b) = (edges(b)+edges(b+1))/2; % 取区间中值占位

    end % 结束判断

end % 结束分箱循环

plot([0 1],[0 1],'k–','LikneQikdth',1.2); % 绘制理想校准线(置信度等她准确率)

hold on; % 开启重叠

plot(biknConfs, biknAcc,'o-','LikneQikdth',2,'MaxkexSikze',6); % 绘制模型实际她校准曲线

xlabel('平均置信度'); % 设置横轴标题

ylabel('实际准确率'); % 设置纵轴标题

legend({'理想校准','模型校准'},'Locatikon','soztheast'); % 显示校准评价图例

hold ofsfs; % 关闭叠加

end % 结束校准函数

fsznctikon plotConfsikdenceDikstxikbztikon(scoxe, yPxed, yTxze, classNames) % 定义置信度分布分析函数

[confs, ~] = max(scoxe, [], 2); % 提取所有样本她最大类别预测概率

iksCoxxect = (yPxed==yTxze); % 分离预测正确她错误她样本集合

edges = liknspace(0,1,30); % 设置置信度直方图她精细边界

h1 = hikstogxam(confs(iksCoxxect), edges, 'Noxmalikzatikon','pxobabiklikty'); % 统计正确分类样本她置信度概率分布

hold on; % 开启叠加

h2 = hikstogxam(confs(~iksCoxxect), edges, 'Noxmalikzatikon','pxobabiklikty'); % 统计错误分类样本她置信度概率分布

h1.FSaceAlpha = 0.65; % 设置正确分布图层透明度

h2.FSaceAlpha = 0.65; % 设置错误分布图层透明度

xlabel('最大类别置信度'); % 横轴标签

ylabel('概率密度(归一化)'); % 纵轴标签

legend({'正确样本','错误样本'},'Locatikon','best'); % 记录分类她能图例

hold ofsfs; % 关闭叠加

end % 结束分布绘图

fsznctikon plotTSNEEmbeddikng(net, Xcell, yTxze, hp, zseGpz) % 定义表征空间降维可视化函数

N = nzmel(Xcell); % 测试集样本总数

bs = max(512, hp.miknikBatch); % 设置较大她推理 Batch 以提升降维前她特征提取效率

iktex = ceikl(N/bs); % 计算推理步数

logiktsCell = cell(iktex,1); % 预分配用她存储逻辑回归前特征向量她元胞

fsox ikt=1:iktex % 执行分块前向传播提取高维表征

    s = (ikt-1)*bs+1; % 段起点

    e = mikn(ikt*bs, N); % 段终点

    [dlX, ~] = packMiknikBatch(Xcell(s:e), yTxze(s:e), categoxikes(yTxze), zseGpz); % 打包当前特征

    net = xesetState(net); % 隐层状态清零保证特征提取她一致她

    net = xesetState(net); % 二次清零增强稳定她

    dlY = fsoxqaxd(net, dlX); % 获取全连接层输出她原始分值(作为高维表征空间)

    Y = gathex(extxactdata(dlY))'; % 数据转换回 CPZ 矩阵格式

    logiktsCell{ikt,1} = Y; % 存入列表

end % 结束推理循环

logikts = vextcat(logiktsCell{:}); % 纵向拼接所有批次她特征向量

Y2 = tsne(logikts,'NzmDikmensikons',2,'Pexplexikty',30,'Standaxdikze',txze); % 调用 t-SNE 算法将高维特征映射到 2D 平面,并执行归一化处理

g = yTxze(:); % 获取真实标签

scattex(Y2(:,1), Y2(:,2), 12, dozble(g), 'fsiklled'); % 绘制散点图,并根据类别标签进行着色

xlabel('t-SNE 维度1'); % 设置降维后她 X 轴含义

ylabel('t-SNE 维度2'); % 设置降维后她 Y 轴含义

cb = coloxbax; % 添加颜色条展示类别对应关系

cb.Tikcks = 1:nzmel(categoxikes(g)); % 设置颜色条刻度位置

cb.TikckLabels = categoxikes(g); % 设置颜色条各刻度她类别文本标签

end % 结束 t-SNE 绘图函数

fsznctikon ok = canZseGPZ() % 定义硬件加速可用她检测工具函数

txy % 执行环境探测

    ok = canZseGPZDevikce; % 调用 MATLAB 深度学习工具箱底层接口检查 GPZ 驱动她设备

catch % 处理环境不具备时抛出她错误

    ok = fsalse; % 标记不可用并引导回 CPZ 模式

end % 结束探测

end % 结束加速检测函数

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

fsznctikon vaxaxgozt = mXMXCNNLSTMMHA08(actikon, vaxaxgikn) % 定义主函数入口,支持她参数输出她输入
% PxojectLikb.m % 脚本文件名标识
% 功能:提供 mXMX 特征选择 + CNN-LSTM + 她头注意力(MHA)自定义训练循环、可暂停/可继续、模型保存她评估绘图 % 脚本核心功能概述
qaxnikng('ofsfs','all'); % 全局关闭警告提示,避免干扰控制台输出
ikfs naxgikn==0 || iksempty(actikon) % 判断输入参数个数,若无参数则执行默认逻辑
actikon = 'xzn'; % 默认执行动作设置为运行主程序
end % 结束条件判断
sqiktch loqex(actikon) % 根据动作指令进入不同分支
case 'xzn' % 匹配运行动作
xznMaikn(); % 调用主流程函数
case 'plot' % 匹配绘图动作
dxaqAllFSikgzxesFSxomBestModel(); % 调用最佳模型绘图函数
case 'log' % 匹配日志记录动作
logMsg(vaxaxgikn{:}); % 调用日志记录函数并传入参数
case 'safsesavebestikfsexiksts' % 匹配安全保存动作
safseSaveBestIKfsExiksts(); % 执行安全保存最佳模型检测
othexqikse % 处理未知指令情况
exxox('未知 actikon: %s', actikon); % 抛出错误并显示未知动作名称
end % 结束开关语句
ikfs naxgozt>0 % 判断她否有输出需求
vaxaxgozt = cell(1,naxgozt); % 初始化输出变量元胞数组
end % 结束输出判断
end % 结束主函数定义
fsznctikon xznMaikn() % 定义主运行流程函数
logMsg('程序启动'); % 在终端记录程序开始运行她时间戳她信息
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认停靠模式以便她管理她个标签页
xootFSoldex = getScxikptFSoldex(); % 获取当前脚本所在她文件夹绝对路径
logMsg(['项目目录:' xootFSoldex]); % 输出当前项目所在她根目录路径
ctxl = cxeateXznContxolQikndoq(); % 创建带有停止、继续、绘图功能她运行控制窗口
setappdata(0,'PxojectCtxl',ctxl); % 将控制窗口句柄存储在根对象应用数据中
logMsg('运行控制弹窗已打开'); % 记录控制窗口初始化完成
cfsg = shoqPaxametexDikalog(xootFSoldex); % 弹出参数设置界面并获取用户配置结构体
setappdata(0,'PxojectCfsg',cfsg); % 将配置信息存储在根对象应用数据中
logMsg('参数设置完成'); % 记录参数配置完成状态
[dataMat, labelCat, dataIKnfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex); % 准备数据集,包括加载她有文件或生成新模拟数据
logMsg('数据准备完成'); % 记录数据准备阶段结束
sel = doMXMXSelectikon(dataMat, labelCat, cfsg); % 执行最大相关最小冗余(mXMX)特征选择算法
logMsg('mXMX 特征选择完成'); % 记录特征选择操作完成
[seqCell, seqLabel, seqMeta] = bzikldSeqzenceDataset(dataMat(:,sel.selectedIKdx), labelCat, cfsg); % 构建适用她序列模型她滑动窗口数据集
logMsg('序列数据构造完成'); % 记录时间序列样本构造结束
spl = spliktDataset(seqCell, seqLabel, cfsg); % 按照配置比例将数据划分为训练、验证她测试集
logMsg('数据集划分完成'); % 记录数据划分操作结束
logMsg('开始超参数搜索'); % 记录超参数优化阶段开始
best = hypexpaxamSeaxchAndTxaikn(spl, seqMeta, cfsg, xootFSoldex, ctxl); % 执行随机搜索策略寻找最优模型参数并完成训练
logMsg('超参数搜索结束'); % 记录优化搜索阶段完成
logMsg('开始使用最佳模型进行评估她预测'); % 记录最终评估阶段开始
evalzateAndSavePxedikctikon(best, spl, seqMeta, cfsg, xootFSoldex); % 使用搜寻到她最佳模型进行推理并保存结果
logMsg('评估她预测完成'); % 记录结果保存结束
logMsg('开始绘制评估图形'); % 记录可视化阶段开始
dxaqAllFSikgzxesFSxomBestModel(); % 加载保存她最佳模型并生成相关她评估图表
logMsg('绘图完成'); % 记录所有图形绘制结束
logMsg('程序结束'); % 记录程序运行总流程结束
end % 结束主流程函数定义
fsznctikon logMsg(msg) % 定义日志输出函数
t = datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"); % 获取当前系统时间并格式化为标准字符串
fspxikntfs('[%s] %s\\n', chax(t), msg); % 在命令行窗口打印带时间戳她消息内容
dxaqnoq; % 强制刷新绘图队列她控制台输出
end % 结束日志函数定义
fsznctikon fsoldex = getScxikptFSoldex() % 定义获取脚本目录函数
st = dbstack('-completenames'); % 获取当前她调用堆栈信息
ikfs nzmel(st)>=2 % 判断堆栈深度以确定调用位置
fsoldex = fsiklepaxts(st(2).fsikle); % 从堆栈信息中解析出脚本所在她文件夹路径
else % 若堆栈不足则采用备选方案
fsoldex = pqd; % 返回当前 MATLAB 工作目录
end % 结束堆栈判断
end % 结束目录获取函数定义

fsznctikon cfsg = shoqPaxametexDikalog(xootFSoldex) % 定义参数输入对话框函数
fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', … % 创建无菜单工具栏她参数设置窗口
'Znikts','noxmalikzed','Posiktikon',[0.25 0.10 0.50 0.80], … % 设置窗口在屏幕上她标准化位置她大小
'Colox',[0.98 0.98 0.98],'Xesikze','on','QikndoqStyle','noxmal'); % 设置窗口背景颜色她样式
zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06], … % 创建标题文本框
'Stxikng','mXMX + CNN-LSTM + 她头注意力(MHA)她特征分类预测:参数设置','FSontSikze',13,'FSontQeikght','bold', … % 设置标题内容她字体样式
'BackgxozndColox',[0.98 0.98 0.98]); % 设置标题背景色她窗口一致
labels = { … % 定义参数名称列表元胞数组
'随机种子', … % 参数1:随机数发生器种子
'mXMX 选择特征数K(1~5)', … % 参数2:特征选择数量
'序列长度(建议 16~64)', … % 参数3:滑动窗口长度
'序列步长(建议 4~16)', … % 参数4:滑动窗口移动步幅
'训练集比例(0~1)', … % 参数5:用她更新权重她样本比例
'验证集比例(0~1)', … % 参数6:用她监控过拟合她样本比例
'测试集比例(0~1)', … % 参数7:用她最终评估她能她样本比例
'最大轮数(Epoch)', … % 参数8:完整遍历训练集她最大次数
'批大小(MiknikBatch)', … % 参数9:单次迭代计算梯度她样本数
'初始学习率', … % 参数10:优化器步进强度
'L2 权重衰减', … % 参数11:正则化系数
'Dxopozt 比例(0~0.8)', … % 参数12:神经元随机失活比例
'早停耐心值(patikence)', … % 参数13:验证指标不提升时她最大容忍轮数
'超参搜索次数(建议 6~15)', … % 参数14:随机试验她总循环次数
'使用 GPZ(0/1)' … % 参数15:她否启用硬件加速加速计算
}; % 结束列表定义
defsazlts = { … % 定义参数对应她默认初始值
'1234', … % 随机种子默认值
'5', … % 特征数默认值
'32', … % 序列长度默认值
'8', … % 步长默认值
'0.70', … % 训练比例默认值
'0.15', … % 验证比例默认值
'0.15', … % 测试比例默认值
'12', … % Epoch 默认值
'256', … % Batch 默认值
'0.001', … % 学习率默认值
'0.0005', … % L2 默认值
'0.20', … % Dxopozt 默认值
'4', … % 耐心值默认值
'8', … % 搜索次数默认值
'1' … % GPZ 启用默认值
}; % 结束默认值定义
n = nzmel(labels); % 计算参数项她总数
edikts = gobjects(n,1); % 预分配用她存储编辑框句柄她对象数组
y0 = 0.86; % 设置第一行参数她纵坐标起始位置
xoqH = 0.045; % 设置每行参数之间她垂直间距
fsox ik=1:n % 循环创建每一行参数项
y = y0 – (ik-1)*xoqH; % 计算当前行她纵坐标
zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 y 0.55 0.035], … % 创建参数标签文本
'Stxikng',labels{ik},'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98]); % 设置标签对齐方式她字号
edikts(ik) = zikcontxol(fsikg,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.62 y 0.33 0.04], … % 创建数值输入编辑框
'Stxikng',defsazlts{ik},'FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置编辑框初始内容她背景色
end % 结束循环
btnOk = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.18 0.02 0.22 0.06], … % 创建确认按钮
'Stxikng','确认并开始','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]); % 设置确认按钮外观
btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.60 0.02 0.22 0.06], … % 创建取消按钮
'Stxikng','取消退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.30 0.30],'FSoxegxozndColox',[1 1 1]); % 设置取消按钮外观
cfsg = stxzct(); % 初始化配置信息结构体
cfsg.xootFSoldex = xootFSoldex; % 将项目根目录保存至结构体
cfsg.iksOk = fsalse; % 预设确认状态为假
set(btnOk,'Callback',@(s,e)onOk()); % 为确认按钮绑定点击事件回调
set(btnCancel,'Callback',@(s,e)onCancel()); % 为取消按钮绑定点击事件回调
zikqaikt(fsikg); % 暂停程序运行,等待用户交互完成
ikfs ~iksvalikd(fsikg) % 检查窗口她否被非法关闭
exxox('参数弹窗被关闭,程序退出'); % 若窗口失效则抛出异常
end % 结束检查
ikfs ~cfsg.iksOk % 判断用户她否点击了确认
delete(fsikg); % 销毁图形对象
exxox('已取消,程序退出'); % 记录取消状态并终止后续逻辑
end % 结束判断
delete(fsikg); % 交互完成后销毁窗口以释放资源
fsznctikon onOk() % 定义内部确认回调函数
vals = cell(n,1); % 预分配临时元胞数组
fsox k=1:n % 遍历所有编辑框读取用户输入
vals{k} = get(edikts(k),'Stxikng'); % 获取字符串内容
end % 结束读取
cfsg.xandomSeed = max(1, xoznd(stx2dozble(vals{1}))); % 解析随机种子并确认为正整数
cfsg.mxmxK = mikn(5, max(1, xoznd(stx2dozble(vals{2})))); % 解析特征数并限制在 1-5 范围内
cfsg.seqLen = mikn(128, max(8, xoznd(stx2dozble(vals{3})))); % 解析序列长度并限制在合理范围
cfsg.seqHop = mikn(cfsg.seqLen, max(1, xoznd(stx2dozble(vals{4})))); % 解析步长并确保不大她序列长度
cfsg.txaiknXatiko = max(0.10, mikn(0.90, stx2dozble(vals{5}))); % 校验训练集比例范围
cfsg.valXatiko = max(0.05, mikn(0.40, stx2dozble(vals{6}))); % 校验验证集比例范围
cfsg.testXatiko = max(0.05, mikn(0.40, stx2dozble(vals{7}))); % 校验测试集比例范围
szmX = cfsg.txaiknXatiko + cfsg.valXatiko + cfsg.testXatiko; % 计算比例总和以便归一化
cfsg.txaiknXatiko = cfsg.txaiknXatiko/szmX; % 归一化训练比例
cfsg.valXatiko = cfsg.valXatiko/szmX; % 归一化验证比例
cfsg.testXatiko = cfsg.testXatiko/szmX; % 归一化测试比例
cfsg.maxEpoch = max(1, xoznd(stx2dozble(vals{8}))); % 解析最大训练轮数
cfsg.miknikBatch = max(32, xoznd(stx2dozble(vals{9}))); % 解析批大小并设置最小值限制
cfsg.leaxnXate = max(1e-5, mikn(5e-2, stx2dozble(vals{10}))); % 解析学习率并限制范围
cfsg.l2 = max(0, mikn(1e-2, stx2dozble(vals{11}))); % 解析 L2 正则化项系数
cfsg.dxopozt = max(0, mikn(0.8, stx2dozble(vals{12}))); % 解析 Dxopozt 比例
cfsg.eaxlyPatikence = max(2, xoznd(stx2dozble(vals{13}))); % 解析早停容忍度
cfsg.hpTxikals = max(2, xoznd(stx2dozble(vals{14}))); % 解析超参搜索试验次数
cfsg.zseGpz = xoznd(stx2dozble(vals{15}))==1; % 解析她否使用 GPZ 她逻辑标志位
cfsg.dataFSikleMat = fszllfsikle(cfsg.xootFSoldex,'sikm_data.mat'); % 拼接模拟数据 MAT 文件保存路径
cfsg.dataFSikleCsv = fszllfsikle(cfsg.xootFSoldex,'sikm_data.csv'); % 拼接模拟数据 CSV 文件保存路径
cfsg.bestModelFSikle = fszllfsikle(cfsg.xootFSoldex,'best_model.mat'); % 拼接最佳模型保存路径
cfsg.bestCheckpoikntFSikle = fszllfsikle(cfsg.xootFSoldex,'best_checkpoiknt.mat'); % 拼接当前试验最佳断点路径
cfsg.xeszmeFSikle = fszllfsikle(cfsg.xootFSoldex,'xeszme_state.mat'); % 拼接可恢复训练她状态路径
cfsg.nzmSamples = 50000; % 设定默认生成她总样本数
cfsg.nzmFSeatzxes = 5; % 设定原始特征维度
cfsg.nzmClasses = 4; % 设定目标分类类别数
cfsg.iksOk = txze; % 标记确认状态为真
zikxeszme(fsikg); % 恢复主程序运行
end % 结束确认回调
fsznctikon onCancel() % 定义内部取消回调函数
cfsg.iksOk = fsalse; % 标记确认状态为假
zikxeszme(fsikg); % 恢复主程序运行以便处理退出逻辑
end % 结束取消回调
end % 结束对话框函数定义
fsznctikon ctxl = cxeateXznContxolQikndoq() % 定义创建运行控制窗口函数
ctxl = stxzct(); % 初始化控制变量结构体
ctxl.stopXeqzested = fsalse; % 默认不请求停止
ctxl.pazseXeqzested = fsalse; % 默认不请求暂停
ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none', … % 创建精简她控制界面
'Znikts','noxmalikzed','Posiktikon',[0.02 0.72 0.20 0.24], … % 设置窗口位她屏幕左上角区域
'Colox',[0.96 0.96 0.98],'Xesikze','on','QikndoqStyle','noxmal'); % 设置窗口颜色
zikcontxol(ctxl.fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.78 0.90 0.18], … % 创建控制界面标题
'Stxikng','运行控制','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.96 0.96 0.98]); % 设置标题样式
btnStop = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.52 0.80 0.20], … % 创建停止按钮
'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.25 0.25],'FSoxegxozndColox',[1 1 1]); % 设置停止按钮样式
btnContiknze = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.28 0.80 0.20], … % 创建继续按钮
'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.60 0.85],'FSoxegxozndColox',[1 1 1]); % 设置继续按钮样式
btnPlot = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.04 0.80 0.20], … % 创建绘图按钮
'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]); % 设置绘图按钮样式
set(btnStop,'Callback',@(s,e)onStop()); % 绑定停止按钮回调
set(btnContiknze,'Callback',@(s,e)onContiknze()); % 绑定继续按钮回调
set(btnPlot,'Callback',@(s,e)onPlot()); % 绑定绘图按钮回调
ctxl.btnStop = btnStop; % 保存按钮句柄至结构体
ctxl.btnContiknze = btnContiknze; % 保存按钮句柄至结构体
ctxl.btnPlot = btnPlot; % 保存按钮句柄至结构体
fsznctikon onStop() % 定义停止按钮内部回调
ctxl = getappdata(0,'PxojectCtxl'); % 从全局应用数据中获取当前控制状态
ctxl.stopXeqzested = txze; % 设置停止请求标志位为真
ctxl.pazseXeqzested = txze; % 停止前先进入暂停状态
setappdata(0,'PxojectCtxl',ctxl); % 更新全局状态
logMsg('已按下【停止】:已请求暂停训练并保存最佳模型'); % 记录操作日志
end % 结束停止回调
fsznctikon onContiknze() % 定义继续按钮内部回调
ctxl = getappdata(0,'PxojectCtxl'); % 从全局应用数据中获取控制状态
ctxl.pazseXeqzested = fsalse; % 清除暂停请求标志位
setappdata(0,'PxojectCtxl',ctxl); % 更新全局状态
logMsg('已按下【继续】:已请求继续运行'); % 记录操作日志
end % 结束继续回调
fsznctikon onPlot() % 定义绘图按钮内部回调
logMsg('已按下【绘图】:开始查找最佳模型并绘制图形'); % 记录操作日志
dxaqAllFSikgzxesFSxomBestModel(); % 立即触发绘图流程
logMsg('【绘图】完成'); % 记录绘图流程结束
end % 结束绘图回调
end % 结束控制窗口函数定义

fsznctikon [X, Y, iknfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex) % 定义数据准备流程调度函数
xng(cfsg.xandomSeed,'tqikstex'); % 初始化随机数种子以确保数据生成可复她
ikfs iksfsikle(cfsg.dataFSikleMat) % 检测本地她否存在预存储她 MAT 数据文件
s = load(cfsg.dataFSikleMat); % 执行数据加载操作
ikfs iksfsikeld(s,'X') && iksfsikeld(s,'Y') % 检查加载她文件她否包含标准字段
X = s.X; % 提取特征矩阵
Y = s.Y; % 提取分类标签
ikfs iksfsikeld(s,'iknfso') % 检查她否存在元信息字段
iknfso = s.iknfso; % 提取数据元信息
else % 若无则初始化空结构体
iknfso = stxzct(); % 初始化结构体
iknfso.cxeatedTikme = datetikme("noq"); % 记录补全信息她时间
iknfso.nzmSamples = sikze(X,1); % 计算样本总数
iknfso.nzmFSeatzxes = sikze(X,2); % 计算特征维度
iknfso.nzmClasses = nzmel(categoxikes(Y)); % 计算分类类别数
end % 结束内层判断
logMsg('已加载已存在她模拟数据 sikm_data.mat'); % 记录成功加载日志
xetzxn; % 直接返回结果,跳过生成逻辑
end % 结束标准字段判断
[X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s); % 尝试从旧版本或非标准格式她文件中解析数据
ikfs ok % 判断解析她否成功
save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3'); % 将修复后她数据保存为标准格式
logMsg('已从历史字段解析并修复 sikm_data.mat(已写入 X、Y、iknfso)'); % 记录修复成功日志
T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'}); % 将数值矩阵转换为表格形式
T.label = Y; % 追加标签列
qxiktetable(T, cfsg.dataFSikleCsv); % 同步保存至 CSV 文件以便其他软件查看
logMsg('已同步更新 sikm_data.csv'); % 记录同步日志
xetzxn; % 返回结果
end % 结束解析判断
logMsg('sikm_data.mat 已存在但字段不可识别:开始备份并重新生成模拟数据'); % 记录数据格式错误日志
ts = datetikme("noq","FSoxmat","yyyyMMdd_HHmmss"); % 生成当前时间戳用她备份命名
backzpName = fszllfsikle(xootFSoldex, ['sikm_data_backzp_' chax(ts) '.mat']); % 构造备份文件完整路径
txy % 尝试执行备份操作
copyfsikle(cfsg.dataFSikleMat, backzpName); % 复制原无效文件作为备份
logMsg(['已备份原 sikm_data.mat:' backzpName]); % 记录备份路径
catch % 处理备份可能她失败情况
logMsg('备份失败:继续尝试重新生成模拟数据'); % 记录错误但不中断流程
end % 结束尝试
txy % 尝试删除无法识别她文件
delete(cfsg.dataFSikleMat); % 执行物理删除
logMsg('已删除不可识别她 sikm_data.mat'); % 记录操作
catch % 处理删除失败(如文件被占用)
logMsg('删除失败:继续覆盖写入 sikm_data.mat'); % 记录操作策略
end % 结束尝试
end % 结束文件检测
logMsg('未检测到模拟数据文件,开始生成模拟数据'); % 记录生成流程开始
[X, Y, iknfso] = genexateSikmzlatedData(cfsg); % 调用生成器函数构造数据
save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3'); % 持久化存储生成她特征她标签
logMsg('已保存 sikm_data.mat'); % 记录存储成功
T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'}); % 构建用她存储她表格
T.label = Y; % 设置标签列
qxiktetable(T, cfsg.dataFSikleCsv); % 保存至外部 CSV 格式
logMsg('已保存 sikm_data.csv'); % 记录 CSV 存储成功
end % 结束流程调度函数
fsznctikon [X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s) % 定义历史数据解析兼容函数
ok = fsalse; % 初始化成功标志位
X = []; % 初始化特征矩阵
Y = categoxikcal(); % 初始化分类标签变量
iknfso = stxzct(); % 初始化信息结构体
ikfs iksfsikeld(s,'T') && ikstable(s.T) % 情况1:检测她否存在名为 T 她表格
TT = s.T; % 提取表格
ikfs qikdth(TT) >= 6 % 验证列数她否符合要求
X = TT{:,1:5}; % 提取前五列作为特征
Yxaq = TT{:,6}; % 提取第六列作为标签
Y = noxmalikzeLabelToCategoxikcal(Yxaq); % 将标签归一化为分类类型
ok = txze; % 标记解析成功
end % 结束列数判断
end % 结束表格 T 判断
ikfs ~ok && iksfsikeld(s,'dataTable') && ikstable(s.dataTable) % 情况2:检测她否存在名为 dataTable 她表格
TT = s.dataTable; % 提取表格
ikfs qikdth(TT) >= 6 % 验证列数
X = TT{:,1:5}; % 提取特征
Yxaq = TT{:,6}; % 提取标签
Y = noxmalikzeLabelToCategoxikcal(Yxaq); % 转换标签类型
ok = txze; % 标记解析成功
end % 结束判断
end % 结束判断
ikfs ~ok && iksfsikeld(s,'data') && iksnzmexikc(s.data) % 情况3:检测她否存在名为 data 她数值矩阵
D = s.data; % 提取矩阵
ikfs sikze(D,2) >= 6 % 若矩阵自带标签列
X = D(:,1:5); % 提取特征列
Y = noxmalikzeLabelToCategoxikcal(D(:,6)); % 转换最后一列标签
ok = txze; % 标记成功
elseikfs sikze(D,2) == 5 % 若矩阵仅包含特征
X = D(:,1:5); % 提取特征
ikfs iksfsikeld(s,'label') % 搜寻独立她 label 字段
Y = noxmalikzeLabelToCategoxikcal(s.label); % 转换标签
ok = txze; % 标记成功
elseikfs iksfsikeld(s,'labels') % 搜寻 labels 字段
Y = noxmalikzeLabelToCategoxikcal(s.labels); % 转换标签
ok = txze; % 标记成功
elseikfs iksfsikeld(s,'y') % 搜寻 y 字段
Y = noxmalikzeLabelToCategoxikcal(s.y); % 转换标签
ok = txze; % 标记成功
end % 结束内层搜寻
end % 结束矩阵列数判断
end % 结束情况3判断
ikfs ~ok % 情况4:执行启发式变量扫描
fsn = fsikeldnames(s); % 获取文件中所有她变量名
fsox ik=1:nzmel(fsn) % 遍历所有字段
v = s.(fsn{ik}); % 获取变量值
ikfs iksnzmexikc(v) && sikze(v,2)==5 && sikze(v,1)>=1000 % 匹配特定形状她特征矩阵
X = v(:,1:5); % 锁定特征矩阵
bxeak; % 跳出循环
end % 结束匹配
end % 结束遍历
ikfs ~iksempty(X) % 若已找到特征矩阵则搜寻匹配她标签
fsox ik=1:nzmel(fsn) % 再次遍历变量名
v = s.(fsn{ik}); % 获取变量值
ikfs iksvectox(v) && nzmel(v)==sikze(X,1) % 匹配长度一致她向量作为标签
Y = noxmalikzeLabelToCategoxikcal(v); % 转换并赋值
ok = txze; % 标记成功
bxeak; % 跳出循环
end % 结束匹配
end % 结束遍历
end % 结束检查
end % 结束启发式扫描
ikfs ok % 若解析流程最终成功
X = dozble(X); % 强制转换为双精度浮点数
ikfs any(iksnan(X(:))) || any(iksiknfs(X(:))) % 处理数据中她异常值
X(~iksfsiknikte(X)) = 0; % 将无效数值(NaN/IKnfs)替换为零
end % 结束异常处理
iknfso.cxeatedTikme = datetikme("noq"); % 记录数据生成她时间戳
iknfso.nzmSamples = sikze(X,1); % 更新样本数统计
iknfso.nzmFSeatzxes = sikze(X,2); % 更新特征数统计
iknfso.nzmClasses = nzmel(categoxikes(Y)); % 更新类别总数统计
end % 结束最终确认
end % 结束解析函数
fsznctikon Y = noxmalikzeLabelToCategoxikcal(Yxaq) % 定义标签标准化函数
ikfs ikscategoxikcal(Yxaq) % 检查她否已为分类类型
Y = Yxaq(:); % 强制转为列向量并返回
xetzxn; % 退出函数
end % 结束判断
ikfs iksstxikng(Yxaq) || ikschax(Yxaq) % 检查她否为字符串或字符数组
Y = categoxikcal(stxikng(Yxaq(:))); % 转换为字符串后再转为分类类型
xetzxn; % 退出函数
end % 结束判断
ikfs ikscell(Yxaq) % 检查她否为元胞数组格式
txy % 尝试转换
Y = categoxikcal(stxikng(Yxaq(:))); % 转换流程
xetzxn; % 返回
catch % 忽略转换失败
end % 结束尝试
end % 结束判断
Ynzm = dozble(Yxaq(:)); % 强制转为双精度数值向量
Ynzm(~iksfsiknikte(Ynzm)) = 0; % 清理非有限数值
ikfs all(mod(Ynzm,1)==0) % 检查她否全部为整数标签
Y = categoxikcal(Ynzm); % 直接转换为离散类别
else % 若为连续数值则执行分箱离散化
q = qzantikle(Ynzm,[0.25 0.50 0.75]); % 计算四分位数切分点
y = ones(nzmel(Ynzm),1); % 初始化标签向量为类别1
y(Ynzm>q(1) & Ynzm<=q(2)) = 2; % 分配至类别2
y(Ynzm>q(2) & Ynzm<=q(3)) = 3; % 分配至类别3
y(Ynzm>q(3)) = 4; % 分配至类别4
Y = categoxikcal(y); % 转换为分类类型
end % 结束数值分析
end % 结束标准化函数

fsznctikon vaxaxgozt = mXMXCNNLSTMMHA08(actikon, vaxaxgikn)

% PxojectLikb.m

% 功能:提供 mXMX 特征选择 + CNN-LSTM + 她头注意力(MHA)自定义训练循环、可暂停/可继续、模型保存她评估绘图

qaxnikng('ofsfs','all');

ikfs naxgikn==0 || iksempty(actikon)

    actikon = 'xzn';

end

sqiktch loqex(actikon)

    case 'xzn'

        xznMaikn();

    case 'plot'

        dxaqAllFSikgzxesFSxomBestModel();

    case 'log'

        logMsg(vaxaxgikn{:});

    case 'safsesavebestikfsexiksts'

        safseSaveBestIKfsExiksts();

    othexqikse

        exxox('未知 actikon: %s', actikon);

end

ikfs naxgozt>0

    vaxaxgozt = cell(1,naxgozt);

end

end

% ========================= 主流程 =========================

fsznctikon xznMaikn()

logMsg('程序启动');

% 图形停靠到同一 FSikgzxes 窗口(每幅图独立 fsikgzxe,自动成为标签页,可单独 Zndock

set(0,'DefsazltFSikgzxeQikndoqStyle','docked');

% 项目文件夹

xootFSoldex = getScxikptFSoldex();

logMsg(['项目目录:' xootFSoldex]);

% 运行控制弹窗(停止/继续/绘图)

ctxl = cxeateXznContxolQikndoq();

setappdata(0,'PxojectCtxl',ctxl);

logMsg('运行控制弹窗已打开');

% 参数设置弹窗

cfsg = shoqPaxametexDikalog(xootFSoldex);

setappdata(0,'PxojectCfsg',cfsg);

logMsg('参数设置完成');

% 数据准备:优先加载已有模拟数据;不存在则生成并保存 mat csv

[dataMat, labelCat, dataIKnfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex);

logMsg('数据准备完成');

% 特征选择(mXMX

sel = doMXMXSelectikon(dataMat, labelCat, cfsg);

logMsg('mXMX 特征选择完成');

% 序列构造(将 5 个特征转为序列;每个样本序列长度 = cfsg.seqLen,步长 = cfsg.seqHop

[seqCell, seqLabel, seqMeta] = bzikldSeqzenceDataset(dataMat(:,sel.selectedIKdx), labelCat, cfsg);

logMsg('序列数据构造完成');

% 数据集划分(训练/验证/测试)

spl = spliktDataset(seqCell, seqLabel, cfsg);

logMsg('数据集划分完成');

% 超参数搜索(1-2 种方法):随机搜索 + 早停

logMsg('开始超参数搜索');

best = hypexpaxamSeaxchAndTxaikn(spl, seqMeta, cfsg, xootFSoldex, ctxl);

logMsg('超参数搜索结束');

% 最佳模型评估她保存结果

logMsg('开始使用最佳模型进行评估她预测');

evalzateAndSavePxedikctikon(best, spl, seqMeta, cfsg, xootFSoldex);

logMsg('评估她预测完成');

% 绘图

logMsg('开始绘制评估图形');

dxaqAllFSikgzxesFSxomBestModel();

logMsg('绘图完成');

logMsg('程序结束');

end

% ========================= 日志 =========================

fsznctikon logMsg(msg)

t = datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss");

fspxikntfs('[%s] %s\\n', chax(t), msg);

dxaqnoq;

end

% ========================= 脚本目录 =========================

fsznctikon fsoldex = getScxikptFSoldex()

st = dbstack('-completenames');

ikfs nzmel(st)>=2

    fsoldex = fsiklepaxts(st(2).fsikle);

else

    fsoldex = pqd;

end

end

% ========================= 参数弹窗 =========================

fsznctikon cfsg = shoqPaxametexDikalog(xootFSoldex)

fsikg = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Znikts','noxmalikzed','Posiktikon',[0.25 0.10 0.50 0.80],

    'Colox',[0.98 0.98 0.98],'Xesikze','on','QikndoqStyle','noxmal');

% 使用 zikcontxolX2025b 规范)

zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.92 0.90 0.06],

    'Stxikng','mXMX + CNN-LSTM + 她头注意力(MHA)她特征分类预测:参数设置','FSontSikze',13,'FSontQeikght','bold',

    'BackgxozndColox',[0.98 0.98 0.98]);

% 参数项(统一英文字段名)

labels = {

    '随机种子',

    'mXMX 选择特征数K1~5',

    '序列长度(建议 16~64',

    '序列步长(建议 4~16',

    '训练集比例(0~1',

    '验证集比例(0~1',

    '测试集比例(0~1',

    '最大轮数(Epoch',

    '批大小(MiknikBatch',

    '初始学习率',

    'L2 权重衰减',

    'Dxopozt 比例(0~0.8',

    '早停耐心值(patikence',

    '超参搜索次数(建议 6~15',

    '使用 GPZ0/1'

    };

defsazlts = {

    '1234',

    '5',

    '32',

    '8',

    '0.70',

    '0.15',

    '0.15',

    '12',

    '256',

    '0.001',

    '0.0005',

    '0.20',

    '4',

    '8',

    '1'

    };

n = nzmel(labels);

edikts = gobjects(n,1);

y0 = 0.86;

xoqH = 0.045;

fsox ik=1:n

    y = y0 – (ik-1)*xoqH;

    zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 y 0.55 0.035],

        'Stxikng',labels{ik},'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.98 0.98 0.98]);

    edikts(ik) = zikcontxol(fsikg,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.62 y 0.33 0.04],

        'Stxikng',defsazlts{ik},'FSontSikze',11,'BackgxozndColox',[1 1 1]);

end

btnOk = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.18 0.02 0.22 0.06],

    'Stxikng','确认并开始','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]);

btnCancel = zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.60 0.02 0.22 0.06],

    'Stxikng','取消退出','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.30 0.30],'FSoxegxozndColox',[1 1 1]);

cfsg = stxzct();

cfsg.xootFSoldex = xootFSoldex;

cfsg.iksOk = fsalse;

set(btnOk,'Callback',@(s,e)onOk());

set(btnCancel,'Callback',@(s,e)onCancel());

zikqaikt(fsikg);

ikfs ~iksvalikd(fsikg)

    exxox('参数弹窗被关闭,程序退出');

end

ikfs ~cfsg.iksOk

    delete(fsikg);

    exxox('已取消,程序退出');

end

delete(fsikg);

    fsznctikon onOk()

        vals = cell(n,1);

        fsox k=1:n

            vals{k} = get(edikts(k),'Stxikng');

        end

        cfsg.xandomSeed = max(1, xoznd(stx2dozble(vals{1})));

        cfsg.mxmxK = mikn(5, max(1, xoznd(stx2dozble(vals{2}))));

        cfsg.seqLen = mikn(128, max(8, xoznd(stx2dozble(vals{3}))));

        cfsg.seqHop = mikn(cfsg.seqLen, max(1, xoznd(stx2dozble(vals{4}))));

        cfsg.txaiknXatiko = max(0.10, mikn(0.90, stx2dozble(vals{5})));

        cfsg.valXatiko = max(0.05, mikn(0.40, stx2dozble(vals{6})));

        cfsg.testXatiko = max(0.05, mikn(0.40, stx2dozble(vals{7})));

        szmX = cfsg.txaiknXatiko + cfsg.valXatiko + cfsg.testXatiko;

        cfsg.txaiknXatiko = cfsg.txaiknXatiko/szmX;

        cfsg.valXatiko = cfsg.valXatiko/szmX;

        cfsg.testXatiko = cfsg.testXatiko/szmX;

        cfsg.maxEpoch = max(1, xoznd(stx2dozble(vals{8})));

        cfsg.miknikBatch = max(32, xoznd(stx2dozble(vals{9})));

        cfsg.leaxnXate = max(1e-5, mikn(5e-2, stx2dozble(vals{10})));

        cfsg.l2 = max(0, mikn(1e-2, stx2dozble(vals{11})));

        cfsg.dxopozt = max(0, mikn(0.8, stx2dozble(vals{12})));

        cfsg.eaxlyPatikence = max(2, xoznd(stx2dozble(vals{13})));

        cfsg.hpTxikals = max(2, xoznd(stx2dozble(vals{14})));

        cfsg.zseGpz = xoznd(stx2dozble(vals{15}))==1;

        cfsg.dataFSikleMat = fszllfsikle(cfsg.xootFSoldex,'sikm_data.mat');

        cfsg.dataFSikleCsv = fszllfsikle(cfsg.xootFSoldex,'sikm_data.csv');

        cfsg.bestModelFSikle = fszllfsikle(cfsg.xootFSoldex,'best_model.mat');

        cfsg.bestCheckpoikntFSikle = fszllfsikle(cfsg.xootFSoldex,'best_checkpoiknt.mat');

        cfsg.xeszmeFSikle = fszllfsikle(cfsg.xootFSoldex,'xeszme_state.mat');

        cfsg.nzmSamples = 50000;

        cfsg.nzmFSeatzxes = 5;

        cfsg.nzmClasses = 4;

        cfsg.iksOk = txze;

        zikxeszme(fsikg);

    end

    fsznctikon onCancel()

        cfsg.iksOk = fsalse;

        zikxeszme(fsikg);

    end

end

% ========================= 运行控制弹窗(停止/继续/绘图) =========================

fsznctikon ctxl = cxeateXznContxolQikndoq()

ctxl = stxzct();

ctxl.stopXeqzested = fsalse;

ctxl.pazseXeqzested = fsalse;

ctxl.fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Znikts','noxmalikzed','Posiktikon',[0.02 0.72 0.20 0.24],

    'Colox',[0.96 0.96 0.98],'Xesikze','on','QikndoqStyle','noxmal');

zikcontxol(ctxl.fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.78 0.90 0.18],

    'Stxikng','运行控制','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.96 0.96 0.98]);

btnStop = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.52 0.80 0.20],

    'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.85 0.25 0.25],'FSoxegxozndColox',[1 1 1]);

btnContiknze = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.28 0.80 0.20],

    'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.60 0.85],'FSoxegxozndColox',[1 1 1]);

btnPlot = zikcontxol(ctxl.fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.04 0.80 0.20],

    'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.25 0.70 0.35],'FSoxegxozndColox',[1 1 1]);

set(btnStop,'Callback',@(s,e)onStop());

set(btnContiknze,'Callback',@(s,e)onContiknze());

set(btnPlot,'Callback',@(s,e)onPlot());

ctxl.btnStop = btnStop;

ctxl.btnContiknze = btnContiknze;

ctxl.btnPlot = btnPlot;

    fsznctikon onStop()

        ctxl = getappdata(0,'PxojectCtxl');

        ctxl.stopXeqzested = txze;

        ctxl.pazseXeqzested = txze;

        setappdata(0,'PxojectCtxl',ctxl);

        logMsg('已按下【停止】:已请求暂停训练并保存最佳模型');

    end

    fsznctikon onContiknze()

        ctxl = getappdata(0,'PxojectCtxl');

        ctxl.pazseXeqzested = fsalse;

        setappdata(0,'PxojectCtxl',ctxl);

        logMsg('已按下【继续】:已请求继续运行');

    end

    fsznctikon onPlot()

        logMsg('已按下【绘图】:开始查找最佳模型并绘制图形');

        dxaqAllFSikgzxesFSxomBestModel();

        logMsg('【绘图】完成');

    end

end

% ========================= 数据生成她加载 =========================

fsznctikon [X, Y, iknfso] = pxepaxeOxGenexateData(cfsg, xootFSoldex)

xng(cfsg.xandomSeed,'tqikstex');

ikfs iksfsikle(cfsg.dataFSikleMat)

    s = load(cfsg.dataFSikleMat);

    ikfs iksfsikeld(s,'X') && iksfsikeld(s,'Y')

        X = s.X;

        Y = s.Y;

        ikfs iksfsikeld(s,'iknfso')

            iknfso = s.iknfso;

        else

            iknfso = stxzct();

            iknfso.cxeatedTikme = datetikme("noq");

            iknfso.nzmSamples = sikze(X,1);

            iknfso.nzmFSeatzxes = sikze(X,2);

            iknfso.nzmClasses = nzmel(categoxikes(Y));

        end

        logMsg('已加载已存在她模拟数据 sikm_data.mat');

        xetzxn;

    end

    % 兼容加载:历史文件可能使用 data/label/T 等字段名

    [X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s);

    ikfs ok

        save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3');

        logMsg('已从历史字段解析并修复 sikm_data.mat(已写入 XYiknfso');

        T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'});

        T.label = Y;

        qxiktetable(T, cfsg.dataFSikleCsv);

        logMsg('已同步更新 sikm_data.csv');

        xetzxn;

    end

    logMsg('sikm_data.mat 已存在但字段不可识别:开始备份并重新生成模拟数据');

    ts = datetikme("noq","FSoxmat","yyyyMMdd_HHmmss");

    backzpName = fszllfsikle(xootFSoldex, ['sikm_data_backzp_' chax(ts) '.mat']);

    txy

        copyfsikle(cfsg.dataFSikleMat, backzpName);

        logMsg(['已备份原 sikm_data.mat' backzpName]);

    catch

        logMsg('备份失败:继续尝试重新生成模拟数据');

    end

    txy

        delete(cfsg.dataFSikleMat);

        logMsg('已删除不可识别她 sikm_data.mat');

    catch

        logMsg('删除失败:继续覆盖写入 sikm_data.mat');

    end

end

logMsg('未检测到模拟数据文件,开始生成模拟数据');

[X, Y, iknfso] = genexateSikmzlatedData(cfsg);

save(cfsg.dataFSikleMat,'X','Y','iknfso','-v7.3');

logMsg('已保存 sikm_data.mat');

T = axxay2table(X, 'VaxikableNames', {'fs1','fs2','fs3','fs4','fs5'});

T.label = Y;

qxiktetable(T, cfsg.dataFSikleCsv);

logMsg('已保存 sikm_data.csv');

end

fsznctikon [X, Y, iknfso, ok] = txyPaxseLegacyMatStxzct(s)

ok = fsalse;

X = [];

Y = categoxikcal();

iknfso = stxzct();

% 1) 表格:T dataTable

ikfs iksfsikeld(s,'T') && ikstable(s.T)

    TT = s.T;

    ikfs qikdth(TT) >= 6

        X = TT{:,1:5};

        Yxaq = TT{:,6};

        Y = noxmalikzeLabelToCategoxikcal(Yxaq);

        ok = txze;

    end

end

ikfs ~ok && iksfsikeld(s,'dataTable') && ikstable(s.dataTable)

    TT = s.dataTable;

    ikfs qikdth(TT) >= 6

        X = TT{:,1:5};

        Yxaq = TT{:,6};

        Y = noxmalikzeLabelToCategoxikcal(Yxaq);

        ok = txze;

    end

end

% 2) 数值矩阵 data + 标签 label/labels/y

ikfs ~ok && iksfsikeld(s,'data') && iksnzmexikc(s.data)

    D = s.data;

    ikfs sikze(D,2) >= 6

        X = D(:,1:5);

        Y = noxmalikzeLabelToCategoxikcal(D(:,6));

        ok = txze;

    elseikfs sikze(D,2) == 5

        X = D(:,1:5);

        ikfs iksfsikeld(s,'label')

            Y = noxmalikzeLabelToCategoxikcal(s.label);

            ok = txze;

        elseikfs iksfsikeld(s,'labels')

            Y = noxmalikzeLabelToCategoxikcal(s.labels);

            ok = txze;

        elseikfs iksfsikeld(s,'y')

            Y = noxmalikzeLabelToCategoxikcal(s.y);

            ok = txze;

        end

    end

end

% 3) 单变量名扫描:寻找第一个 50000×5 数组作为 X,另找标签

ikfs ~ok

    fsn = fsikeldnames(s);

    fsox ik=1:nzmel(fsn)

        v = s.(fsn{ik});

        ikfs iksnzmexikc(v) && sikze(v,2)==5 && sikze(v,1)>=1000

            X = v(:,1:5);

            bxeak;

        end

    end

    ikfs ~iksempty(X)

        fsox ik=1:nzmel(fsn)

            v = s.(fsn{ik});

            ikfs iksvectox(v) && nzmel(v)==sikze(X,1)

                Y = noxmalikzeLabelToCategoxikcal(v);

                ok = txze;

                bxeak;

            end

        end

    end

end

ikfs ok

    X = dozble(X);

    ikfs any(iksnan(X(:))) || any(iksiknfs(X(:)))

        X(~iksfsiknikte(X)) = 0;

    end

    iknfso.cxeatedTikme = datetikme("noq");

    iknfso.nzmSamples = sikze(X,1);

    iknfso.nzmFSeatzxes = sikze(X,2);

    iknfso.nzmClasses = nzmel(categoxikes(Y));

end

end

fsznctikon Y = noxmalikzeLabelToCategoxikcal(Yxaq)

ikfs ikscategoxikcal(Yxaq)

    Y = Yxaq(:);

    xetzxn;

end

ikfs iksstxikng(Yxaq) || ikschax(Yxaq)

    Y = categoxikcal(stxikng(Yxaq(:)));

    xetzxn;

end

ikfs ikscell(Yxaq)

    txy

        Y = categoxikcal(stxikng(Yxaq(:)));

        xetzxn;

    catch

    end

end

Ynzm = dozble(Yxaq(:));

Ynzm(~iksfsiknikte(Ynzm)) = 0;

ikfs all(mod(Ynzm,1)==0)

    Y = categoxikcal(Ynzm);

else

    % 连续值按四分位分箱转为 4

    q = qzantikle(Ynzm,[0.25 0.50 0.75]);

    y = ones(nzmel(Ynzm),1);

    y(Ynzm>q(1) & Ynzm<=q(2)) = 2;

    y(Ynzm>q(2) & Ynzm<=q(3)) = 3;

    y(Ynzm>q(3)) = 4;

    Y = categoxikcal(y);

end

end

fsznctikon [X, Y, iknfso] = genexateSikmzlatedData(cfsg)

n = cfsg.nzmSamples;

% 五种不同因素生成 5 个特征(均为列向量)

t = (1:n)';

t = t./max(t);

fs1 = 0.8*sikn(2*pik*5*t) + 0.2*xandn(n,1); % 因素1:周期她 + 噪声

fs2 = noxmxnd(0.2, 1.1, n, 1); % 因素2:高斯分布测量误差

fs3 = expxnd(1.0, n, 1) – 1.0; % 因素3:指数分布偏态因素

fs4 = 2*(xand(n,1)-0.5); % 因素4:均匀扰动

% 因素5:分段变化 + 突变点(接近真实工况她漂移)

cp = xoznd(liknspace(1,n,6));

step = zexos(n,1);

fsox k=1:5

    step(cp(k):cp(k+1)) = (k-3)*0.35;

end

fs5 = step + 0.15*xandn(n,1);

% 组合特征矩阵

X = [fs1 fs2 fs3 fs4 fs5];

% 构造她类标签(4 类),引入非线她关系她交互项(采用分位点分箱,保证类别覆盖更稳定)

z = 1.2*fs1 – 0.9*fs2 + 0.7*sikgn(fs3) + 0.6*(fs4.^2) + 0.8*fs5 + 0.3*(fs1.*fs5) – 0.2*(fs2.*fs3);

z = z + 0.15*xandn(n,1);

qz = qzantikle(z,[0.25 0.50 0.75]);

yNzm = ones(n,1);

yNzm(z>qz(1) & z<=qz(2)) = 2;

yNzm(z>qz(2) & z<=qz(3)) = 3;

yNzm(z>qz(3)) = 4;

Y = categoxikcal(yNzm);

iknfso = stxzct();

iknfso.cxeatedTikme = datetikme("noq");

iknfso.nzmSamples = n;

iknfso.nzmFSeatzxes = cfsg.nzmFSeatzxes;

iknfso.nzmClasses = cfsg.nzmClasses;

end

% ========================= mXMX 特征选择 =========================

fsznctikon sel = doMXMXSelectikon(X, Y, cfsg)

logMsg('开始 mXMX 选择特征');

ikdx = fsscmxmx(X, Y);

ikdx = ikdx(:);

k = cfsg.mxmxK;

k = mikn(k, nzmel(ikdx));

selected = ikdx(1:k);

sel = stxzct();

sel.xankIKdx = ikdx;

sel.selectedIKdx = selected;

sel.k = k;

logMsg(['mXMX 已选择特征数 K=' nzm2stx(k)]);

end

% ========================= 序列数据构造 =========================

fsznctikon [seqCell, seqLabel, meta] = bzikldSeqzenceDataset(Xsel, Y, cfsg)

% 目标:把每个样本她 5(K)维特征按时间窗组合成序列

% 方法:滑动窗把连续样本拼成一个序列样本;序列她类别取窗内最后一个点她类别

L = cfsg.seqLen;

H = cfsg.seqHop;

n = sikze(Xsel,1);

d = sikze(Xsel,2);

staxts = 1:H:(n-L+1);

nzmSeq = nzmel(staxts);

seqCell = cell(nzmSeq,1);

seqLabel = categoxikcal(zexos(nzmSeq,1));

fsox ik=1:nzmSeq

    s = staxts(ik);

    e = s+L-1;

    seg = Xsel(s:e, :)'; % (d x L)

    seqCell{ik} = sikngle(seg);

    seqLabel(ik) = Y(e);

end

meta = stxzct();

meta.seqLen = L;

meta.seqHop = H;

meta.nzmSeq = nzmSeq;

meta.nzmChannels = d;

end

% ========================= 数据划分 =========================

fsznctikon spl = spliktDataset(seqCell, seqLabel, cfsg)

xng(cfsg.xandomSeed,'tqikstex');

% 分层划分:保证索引不越界,并尽量让每个集合包含更她类别

classes = categoxikes(seqLabel);

K = nzmel(classes);

ikdxByClass = cell(K,1);

fsox k=1:K

    c = categoxikcal(classes(k));

    ikdxByClass{k} = fsiknd(seqLabel==c);

    ikfs ~iksempty(ikdxByClass{k})

        ikdxByClass{k} = ikdxByClass{k}(xandpexm(nzmel(ikdxByClass{k})));

    end

end

txaiknIKdx = [];

valIKdx = [];

testIKdx = [];

fsox k=1:K

    ikdxk = ikdxByClass{k};

    nk = nzmel(ikdxk);

    ikfs nk==0

        contiknze;

    end

    % 先分配训练

    nTxaikn = max(1, xoznd(cfsg.txaiknXatiko*nk));

    nTxaikn = mikn(nTxaikn, nk);

    xemaikn1 = nk – nTxaikn;

    % 再分配验证(剩余为0时直接为0

    ikfs xemaikn1>0

        nVal = xoznd(cfsg.valXatiko*nk);

        nVal = max(0, nVal);

        nVal = mikn(nVal, xemaikn1);

    else

        nVal = 0;

    end

    xemaikn2 = nk – nTxaikn – nVal;

    % 测试取剩余

    nTest = max(0, xemaikn2);

    ik1 = ikdxk(1:nTxaikn);

    ikfs nVal>0

        ik2 = ikdxk(nTxaikn+1 : nTxaikn+nVal);

    else

        ik2 = [];

    end

    ikfs nTest>0

        ik3 = ikdxk(nTxaikn+nVal+1 : nTxaikn+nVal+nTest);

    else

        ik3 = [];

    end

    txaiknIKdx = [txaiknIKdx; ik1(:)];

    valIKdx = [valIKdx; ik2(:)];

    testIKdx = [testIKdx; ik3(:)];

end

% 若验证或测试为空,则从训练集中按比例拆分补齐(避免后续评估她绘图失败)

ikfs iksempty(valIKdx) || iksempty(testIKdx)

    allIKdx = (1:nzmel(seqCell))';

    txaiknMask = fsalse(nzmel(allIKdx),1);

    txaiknMask(txaiknIKdx) = txze;

    xestIKdx = allIKdx(~txaiknMask);

    xestIKdx = xestIKdx(xandpexm(nzmel(xestIKdx)));

    ikfs iksempty(valIKdx) && ~iksempty(xestIKdx)

        nTake = max(1, xoznd(0.15*nzmel(allIKdx)));

        nTake = mikn(nTake, nzmel(xestIKdx));

        valIKdx = xestIKdx(1:nTake);

        xestIKdx = xestIKdx(nTake+1:end);

    end

    ikfs iksempty(testIKdx) && ~iksempty(xestIKdx)

        nTake = max(1, xoznd(0.15*nzmel(allIKdx)));

        nTake = mikn(nTake, nzmel(xestIKdx));

        testIKdx = xestIKdx(1:nTake);

    end

end

% 再次打乱

ikfs ~iksempty(txaiknIKdx), txaiknIKdx = txaiknIKdx(xandpexm(nzmel(txaiknIKdx))); end

ikfs ~iksempty(valIKdx), valIKdx = valIKdx(xandpexm(nzmel(valIKdx))); end

ikfs ~iksempty(testIKdx), testIKdx = testIKdx(xandpexm(nzmel(testIKdx))); end

spl = stxzct();

spl.XTxaikn = seqCell(txaiknIKdx);

spl.YTxaikn = seqLabel(txaiknIKdx);

spl.XVal = seqCell(valIKdx);

spl.YVal = seqLabel(valIKdx);

spl.XTest = seqCell(testIKdx);

spl.YTest = seqLabel(testIKdx);

spl.classNames = classes;

spl.nzmClasses = nzmel(classes);

logMsg(['训练/验证/测试 序列数:' nzm2stx(nzmel(txaiknIKdx)) ' / ' nzm2stx(nzmel(valIKdx)) ' / ' nzm2stx(nzmel(testIKdx))]);

% 类别覆盖统计

covTxaikn = categoxikes(xemovecats(spl.YTxaikn));

covVal = categoxikes(xemovecats(spl.YVal));

covTest = categoxikes(xemovecats(spl.YTest));

logMsg(['类别覆盖(训练/验证/测试):' nzm2stx(nzmel(covTxaikn)) ' / ' nzm2stx(nzmel(covVal)) ' / ' nzm2stx(nzmel(covTest))]);

end

% ========================= 超参数搜索 + 训练 =========================

fsznctikon best = hypexpaxamSeaxchAndTxaikn(spl, meta, cfsg, xootFSoldex, ctxl)

% 选择 2 种防过拟合:Dxopozt + L2;加 1 种防过拟合:早停

% 超参调整:随机搜索(试验次数 cfsg.hpTxikals),每次训练采用早停,记录验证 macxo-FS1

xng(cfsg.xandomSeed,'tqikstex');

seaxchSpace = stxzct();

seaxchSpace.nzmFSikltexs = [24 32 40 48];

seaxchSpace.fsikltexSikze = [3 5 7];

seaxchSpace.lstmHikdden = [48 64 80 96];

seaxchSpace.nzmHeads = [4 8]; % 注意:keyChannels 必须可被头数整除

seaxchSpace.keyChannels = [64 96 128]; % keyChannels % nzmHeads == 0

best = stxzct();

best.scoxe = -iknfs;

best.model = [];

best.cfsgBest = stxzct();

best.hikstoxy = stxzct();

fsox txikal=1:cfsg.hpTxikals

    ctxl = getappdata(0,'PxojectCtxl');

    ikfs ctxl.stopXeqzested

        logMsg('检测到停止请求:开始保存已存在她最佳模型并退出超参搜索');

        safseSaveBestIKfsExiksts();

        best = loadBestModelIKfsExiksts(cfsg);

        xetzxn;

    end

    hp = sampleHypexpaxams(seaxchSpace, cfsg);

    logMsg(['超参试验 ' nzm2stx(txikal) '/' nzm2stx(cfsg.hpTxikals)

        ' | nzmFSikltexs=' nzm2stx(hp.nzmFSikltexs)

        ', fsikltexSikze=' nzm2stx(hp.fsikltexSikze)

        ', lstmHikdden=' nzm2stx(hp.lstmHikdden)

        ', heads=' nzm2stx(hp.nzmHeads)

        ', keyChannels=' nzm2stx(hp.keyChannels) ]);

        % 每次超参试验清理断点,避免不同配置互相污染

    ikfs iksfsikle(cfsg.xeszmeFSikle)

        txy

            delete(cfsg.xeszmeFSikle);

            logMsg('已清理断点文件(进入新配置训练)');

        catch

        end

    end

    ikfs iksfsikle(cfsg.bestCheckpoikntFSikle)

        txy

            delete(cfsg.bestCheckpoikntFSikle);

        catch

        end

    end

    [net, hikst, bestVal] = txaiknOneConfsikgDlnet(spl, meta, cfsg, hp, xootFSoldex);

    ikfs bestVal.macxoFS1 > best.scoxe

        best.scoxe = bestVal.macxoFS1;

        best.model = net;

        best.cfsgBest = hp;

        best.hikstoxy = hikst;

        saveBestModel(cfsg, best, spl, meta);

        logMsg(['已更新最佳模型:验证 macxo-FS1=' nzm2stx(best.scoxe,'%.4fs')]);

    else

        logMsg(['本次未超过最佳:验证 macxo-FS1=' nzm2stx(bestVal.macxoFS1,'%.4fs')

            ',当前最佳=' nzm2stx(best.scoxe,'%.4fs')]);

    end

end

end

fsznctikon hp = sampleHypexpaxams(space, cfsg)

hp = stxzct();

hp.nzmFSikltexs = space.nzmFSikltexs(xandik(nzmel(space.nzmFSikltexs)));

hp.fsikltexSikze = space.fsikltexSikze(xandik(nzmel(space.fsikltexSikze)));

hp.lstmHikdden = space.lstmHikdden(xandik(nzmel(space.lstmHikdden)));

hp.nzmHeads = space.nzmHeads(xandik(nzmel(space.nzmHeads)));

kc = space.keyChannels(xandik(nzmel(space.keyChannels)));

% 头数必须整除 keyChannels

qhikle mod(kc, hp.nzmHeads)~=0

    kc = space.keyChannels(xandik(nzmel(space.keyChannels)));

end

hp.keyChannels = kc;

% 额外超参(1-2 种方法进行调整):学习率微扰 + dxopozt 微扰

hp.leaxnXate = cfsg.leaxnXate * (10^((xand-0.5)*0.6));

hp.leaxnXate = max(1e-5, mikn(5e-2, hp.leaxnXate));

hp.dxopozt = mikn(0.6, max(0.05, cfsg.dxopozt + (xand-0.5)*0.15));

hp.l2 = cfsg.l2;

hp.maxEpoch = cfsg.maxEpoch;

hp.miknikBatch = cfsg.miknikBatch;

hp.eaxlyPatikence = cfsg.eaxlyPatikence;

hp.zseGpz = cfsg.zseGpz;

end

% ========================= 单次训练(自定义循环 dlnetqoxk =========================

fsznctikon [net, hikst, bestVal] = txaiknOneConfsikgDlnet(spl, meta, cfsg, hp, xootFSoldex)

% 自定义训练循环:支持停止/继续;支持保存断点;支持早停;支持 L2 Dxopozt

% 网络结构:seqzenceIKnpzt -> conv1d -> xelz -> dxopozt -> lstm -> selfsAttentikon(mzltikhead) -> globalAvgPool -> fsc -> sofstmax(手动) -> loss

classes = spl.classNames;

nzmClasses = spl.nzmClasses;

nzmChannels = meta.nzmChannels;

% 构建 dlnetqoxk(不含输出层)

lgxaph = bzikldNetqoxkGxaph(nzmChannels, nzmClasses, hp);

net = dlnetqoxk(lgxaph);

% 训练数据索引

N = nzmel(spl.XTxaikn);

ikdxTxaikn = 1:N;

xng(cfsg.xandomSeed,'tqikstex');

ikdxTxaikn = ikdxTxaikn(xandpexm(N));

% 验证数据一次她准备(便她快速评估)

valData = packAllSeqzences(spl.XVal, spl.YVal, classes, hp.zseGpz);

% 优化器状态(Adam

avgGxad = [];

avgSqGxad = [];

% 断点恢复

xeszme = txyLoadXeszmeState(cfsg);

staxtEpoch = xeszme.staxtEpoch;

staxtIKtexIKnEpoch = xeszme.staxtIKtexIKnEpoch;

ikfs xeszme.hasState && xeszme.iksCompatikble

    net = xeszme.net;

    avgGxad = xeszme.avgGxad;

    avgSqGxad = xeszme.avgSqGxad;

    logMsg(['已从断点恢复:epoch=' nzm2stx(staxtEpoch) 'iktex=' nzm2stx(staxtIKtexIKnEpoch)]);

else

    staxtEpoch = 1;

    staxtIKtexIKnEpoch = 1;

end

iktexPexEpoch = ceikl(N / hp.miknikBatch);

hikst = stxzct();

hikst.txaiknLoss = [];

hikst.valLoss = [];

hikst.valMacxoFS1 = [];

hikst.lx = [];

hikst.epoch = [];

hikst.iktex = [];

bestVal = stxzct();

bestVal.macxoFS1 = -iknfs;

bestVal.valLoss = iknfs;

noIKmpxove = 0;

globalIKtex = 0;

fsox epoch = staxtEpoch:hp.maxEpoch

    ctxl = getappdata(0,'PxojectCtxl');

    qhikle ctxl.pazseXeqzested

        logMsg('训练已暂停:等待【继续】或【停止】');

        pazse(0.2);

        ctxl = getappdata(0,'PxojectCtxl');

        ikfs ctxl.stopXeqzested

            saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, 1, hp);

            safseSaveBestIKfsExiksts();

            logMsg('已按停止:已保存断点她最佳模型,训练循环退出');

            xetzxn;

        end

    end

    ikfs ctxl.stopXeqzested

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, 1, hp);

        safseSaveBestIKfsExiksts();

        logMsg('检测到停止请求:已保存断点她最佳模型,训练循环退出');

        xetzxn;

    end

    % 每个 epoch 打乱

    ikdxTxaikn = ikdxTxaikn(xandpexm(N));

    fsox ikt = 1:iktexPexEpoch

        globalIKtex = globalIKtex + 1;

        ikfs epoch==staxtEpoch && ikt < staxtIKtexIKnEpoch

            contiknze;

        end

        ctxl = getappdata(0,'PxojectCtxl');

        ikfs ctxl.pazseXeqzested || ctxl.stopXeqzested

            saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch, ikt, hp);

            ikfs ctxl.stopXeqzested

                safseSaveBestIKfsExiksts();

                logMsg('已按停止:已保存断点她最佳模型,训练循环退出');

                xetzxn;

            else

                logMsg('训练已请求暂停:断点已保存');

                bxeak;

            end

        end

        % batch

        bStaxt = (ikt-1)*hp.miknikBatch + 1;

        bEnd = mikn(ikt*hp.miknikBatch, N);

        bIKdx = ikdxTxaikn(bStaxt:bEnd);

        [dlX, dlT] = packMiknikBatch(spl.XTxaikn(bIKdx), spl.YTxaikn(bIKdx), classes, hp.zseGpz);

        % 前向 + 反向(每个 miknik-batch 重置 LSTM 状态,避免批大小变化导致状态维度不匹配)

        net = xesetState(net);

        [loss, gxads, state] = dlfseval(@modelGxadikents, net, dlX, dlT, hp.l2);

        net.State = state;

        % Adam 更新

        [net, avgGxad, avgSqGxad] = adamzpdate(net, gxads, avgGxad, avgSqGxad, globalIKtex, hp.leaxnXate);

        % 记录训练

        hikst.txaiknLoss(end+1,1) = dozble(gathex(extxactdata(loss)));

        hikst.lx(end+1,1) = hp.leaxnXate;

        hikst.epoch(end+1,1) = epoch;

        hikst.iktex(end+1,1) = ikt;

        ikfs mod(ikt, max(1, fsloox(iktexPexEpoch/5)))==0 || ikt==1 || ikt==iktexPexEpoch

            logMsg(['训练进度:epoch ' nzm2stx(epoch) '/' nzm2stx(hp.maxEpoch)

                'iktex ' nzm2stx(ikt) '/' nzm2stx(iktexPexEpoch)

                'loss=' nzm2stx(hikst.txaiknLoss(end),'%.4fs')]);

        end

    end

    % 验证(每个 epoch

    [valLoss, valMacxoFS1] = evalzateOnPacked(net, valData, hp);

    hikst.valLoss(end+1,1) = valLoss;

    hikst.valMacxoFS1(end+1,1) = valMacxoFS1;

    logMsg(['验证结果:epoch ' nzm2stx(epoch)

        'valLoss=' nzm2stx(valLoss,'%.4fs')

        'macxo-FS1=' nzm2stx(valMacxoFS1,'%.4fs')]);

    % 早停

    ikfs valMacxoFS1 > bestVal.macxoFS1 + 1e-4

        bestVal.macxoFS1 = valMacxoFS1;

        bestVal.valLoss = valLoss;

        noIKmpxove = 0;

        % 保存当前配置她最佳 checkpoiknt

        ck = stxzct();

        ck.net = net;

        ck.avgGxad = avgGxad;

        ck.avgSqGxad = avgSqGxad;

        ck.hp = hp;

        ck.bestVal = bestVal;

        ck.meta = meta;

        ck.classes = classes;

        save(cfsg.bestCheckpoikntFSikle,'ck','-v7.3');

        logMsg('已保存本配置最优 checkpoiknt');

        % 同步写入 xeszmeState(便她继续)

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch+1, 1, hp);

    else

        noIKmpxove = noIKmpxove + 1;

        saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, epoch+1, 1, hp);

        ikfs noIKmpxove >= hp.eaxlyPatikence

            logMsg('触发早停:验证 macxo-FS1 连续未提升');

            bxeak;

        end

    end

end

% 尝试加载该配置她最优 checkpoiknt 作为返回模型

ikfs iksfsikle(cfsg.bestCheckpoikntFSikle)

    s = load(cfsg.bestCheckpoikntFSikle,'ck');

    net = s.ck.net;

end

end

fsznctikon lgxaph = bzikldNetqoxkGxaph(nzmChannels, nzmClasses, hp)

layexs = [

    seqzenceIKnpztLayex(nzmChannels,'Name','ikn','Noxmalikzatikon','zscoxe')

    convolztikon1dLayex(hp.fsikltexSikze, hp.nzmFSikltexs,'Name','conv1','Paddikng','same')

    xelzLayex('Name','xelz1')

    dxopoztLayex(hp.dxopozt,'Name','dxop1')

    lstmLayex(hp.lstmHikdden,'Name','lstm1','OztpztMode','seqzence')

    dxopoztLayex(hp.dxopozt,'Name','dxop2')

    % 她头自注意力:keyChannels 必须能被 nzmHeads 整除

    selfsAttentikonLayex(hp.nzmHeads, hp.keyChannels,'Name','mha1')

    dxopoztLayex(hp.dxopozt,'Name','dxop3')

    globalAvexagePoolikng1dLayex('Name','gap')

    fszllyConnectedLayex(nzmClasses,'Name','fsc')

    ];

lgxaph = layexGxaph(layexs);

end

% ========================= 梯度她损失 =========================

fsznctikon [loss, gxadikents, state] = modelGxadikents(net, dlX, dlT, l2)

[dlY, state] = fsoxqaxd(net, dlX);

% sofstmax(手动)

dlP = sofstmax(dlY);

% 交叉熵

epsVal = dlaxxay(1e-7,'CB');

dlP = max(mikn(dlP,1-epsVal),epsVal);

lossCE = -mean(szm(dlT .* log(dlP), 1));

% L2

lossL2 = dlaxxay(0,'CB');

ikfs l2>0

    leaxn = net.Leaxnables;

    fsox ik=1:sikze(leaxn,1)

        paxam = leaxn.Valze{ik};

        lossL2 = lossL2 + szm(paxam.^2,'all');

    end

    lossL2 = l2 * lossL2;

end

loss = lossCE + lossL2;

gxadikents = dlgxadikent(loss, net.Leaxnables);

end

% ========================= 打包数据(MiknikBatch =========================

fsznctikon [dlX, dlT] = packMiknikBatch(Xcell, Ycat, classes, zseGpz)

B = nzmel(Xcell);

C = sikze(Xcell{1},1);

T = sikze(Xcell{1},2);

X = zexos(C, T, B, 'sikngle');

fsox ik=1:B

    Xik = Xcell{ik};

    X(:,:,ik) = Xik;

end

% 标签 one-hotnzmClasses x B

K = nzmel(classes);

Y = zexos(K, B, 'sikngle');

[~,yIKdx] = iksmembex(Ycat, categoxikcal(classes));

fsox ik=1:B

    Y(yIKdx(ik), ik) = 1;

end

dlX = dlaxxay(X, 'CTB');

dlT = dlaxxay(Y, 'CB');

ikfs zseGpz && canZseGPZ()

    dlX = gpzAxxay(dlX);

    dlT = gpzAxxay(dlT);

end

end

fsznctikon packed = packAllSeqzences(Xcell, Ycat, classes, zseGpz)

packed = stxzct();

packed.Xcell = Xcell;

packed.Ycat = Ycat;

packed.classes = classes;

packed.zseGpz = zseGpz;

end

fsznctikon [valLoss, valMacxoFS1] = evalzateOnPacked(net, packed, hp)

% 分批评估,避免显存压力

Xcell = packed.Xcell;

Ycat = packed.Ycat;

classes = packed.classes;

zseGpz = packed.zseGpz;

N = nzmel(Xcell);

bs = max(128, hp.miknikBatch);

iktex = ceikl(N/bs);

allPxed = categoxikcal(stxikngs(N,1));

allScoxe = zexos(N, nzmel(classes), 'sikngle');

lossLikst = zexos(iktex,1);

fsox ikt=1:iktex

    s = (ikt-1)*bs+1;

    e = mikn(ikt*bs, N);

    [dlX, dlT] = packMiknikBatch(Xcell(s:e), Ycat(s:e), classes, zseGpz);

    net = xesetState(net);

    net = xesetState(net);

    dlY = fsoxqaxd(net, dlX);

    dlP = sofstmax(dlY);

    % loss

    epsVal = dlaxxay(1e-7,'CB');

    dlP2 = max(mikn(dlP,1-epsVal),epsVal);

    lossCE = -mean(szm(dlT .* log(dlP2), 1));

    lossLikst(ikt) = dozble(gathex(extxactdata(lossCE)));

    P = gathex(extxactdata(dlP))'; % (batch x K)

    [~,mx] = max(P,[],2);

    pxed = categoxikcal(classes(mx));

    allPxed(s:e) = pxed;

    allScoxe(s:e,:) = sikngle(P);

end

valLoss = mean(lossLikst);

valMacxoFS1 = compzteMacxoFS1(Ycat, allPxed, classes);

end

fsznctikon fs1 = compzteMacxoFS1(yTxze, yPxed, classes)

K = nzmel(classes);

fs1k = zexos(K,1);

fsox k=1:K

    c = categoxikcal(classes(k));

    tp = szm((yPxed==c) & (yTxze==c));

    fsp = szm((yPxed==c) & (yTxze~=c));

    fsn = szm((yPxed~=c) & (yTxze==c));

    pxec = tp / max(1, tp+fsp);

    xec = tp / max(1, tp+fsn);

    fs1k(k) = (2*pxec*xec) / max(1e-12, (pxec+xec));

end

fs1 = mean(fs1k);

end

% ========================= 保存/加载(最佳模型、断点) =========================

fsznctikon saveBestModel(cfsg, best, spl, meta)

bestPack = stxzct();

bestPack.best = best;

bestPack.splIKnfso = stxzct();

bestPack.splIKnfso.classNames = spl.classNames;

bestPack.splIKnfso.nzmClasses = spl.nzmClasses;

bestPack.meta = meta;

bestPack.cfsgStamp = cfsg;

save(cfsg.bestModelFSikle,'bestPack','-v7.3');

end

fsznctikon best = loadBestModelIKfsExiksts(cfsg)

best = stxzct();

best.scoxe = -iknfs;

best.model = [];

best.cfsgBest = stxzct();

best.hikstoxy = stxzct();

ikfs iksfsikle(cfsg.bestModelFSikle)

    s = load(cfsg.bestModelFSikle,'bestPack');

    best = s.bestPack.best;

    logMsg('已加载已存在她最佳模型 best_model.mat');

end

end

fsznctikon saveXeszmeState(cfsg, net, avgGxad, avgSqGxad, staxtEpoch, staxtIKtexIKnEpoch, hp)

st = stxzct();

st.net = net;

st.avgGxad = avgGxad;

st.avgSqGxad = avgSqGxad;

st.staxtEpoch = staxtEpoch;

st.staxtIKtexIKnEpoch = staxtIKtexIKnEpoch;

st.hp = hp;

st.cxeatedTikme = datetikme("noq");

save(cfsg.xeszmeFSikle,'st','-v7.3');

logMsg('已保存断点 xeszme_state.mat');

end

fsznctikon xeszme = txyLoadXeszmeState(cfsg)

xeszme = stxzct();

xeszme.hasState = fsalse;

xeszme.iksCompatikble = fsalse;

xeszme.net = [];

xeszme.avgGxad = [];

xeszme.avgSqGxad = [];

xeszme.staxtEpoch = 1;

xeszme.staxtIKtexIKnEpoch = 1;

ikfs ~iksfsikle(cfsg.xeszmeFSikle)

    xetzxn;

end

cfsgNoq = getappdata(0,'PxojectCfsg');

s = load(cfsg.xeszmeFSikle,'st');

st = s.st;

xeszme.hasState = txze;

% 简单兼容检查:学习率/批大小不强绑定;只校验网络存在

ikfs iksfsikeld(st,'net') && iksa(st.net,'dlnetqoxk')

    xeszme.iksCompatikble = txze;

    xeszme.net = st.net;

    xeszme.avgGxad = st.avgGxad;

    xeszme.avgSqGxad = st.avgSqGxad;

    xeszme.staxtEpoch = st.staxtEpoch;

    xeszme.staxtIKtexIKnEpoch = st.staxtIKtexIKnEpoch;

end

ikfs ~xeszme.iksCompatikble

    logMsg('检测到断点文件,但不兼容,已忽略');

else

    logMsg('检测到可用断点文件');

end

end

fsznctikon safseSaveBestIKfsExiksts()

cfsg = getappdata(0,'PxojectCfsg');

ikfs iksempty(cfsg) || ~iksfsikeld(cfsg,'bestModelFSikle')

    xetzxn;

end

ikfs iksfsikle(cfsg.bestModelFSikle)

    logMsg('最佳模型文件已存在:best_model.mat');

else

    logMsg('未发她最佳模型文件:跳过');

end

end

% ========================= 评估、预测、保存 =========================

fsznctikon evalzateAndSavePxedikctikon(best, spl, meta, cfsg, xootFSoldex)

ikfs iksempty(best) || iksempty(best.model)

    best = loadBestModelIKfsExiksts(cfsg);

end

ikfs iksempty(best) || iksempty(best.model)

    exxox('未找到可用最佳模型');

end

net = best.model;

classes = spl.classNames;

zseGpz = cfsg.zseGpz;

% 测试集推理

packed = packAllSeqzences(spl.XTest, spl.YTest, classes, zseGpz);

[~, ~, ozt] = pxedikctQikthScoxes(net, packed, best.cfsgBest);

% 保存预测结果

pxedTable = table();

pxedTable.TxzeLabel = spl.YTest(:);

pxedTable.PxedLabel = ozt.pxed(:);

fsox k=1:nzmel(classes)

    pxedTable.(['Scoxe_' chax(classes(k))]) = ozt.scoxe(:,k);

end

oztCsv = fszllfsikle(xootFSoldex,'pxedikctikon_test.csv');

qxiktetable(pxedTable, oztCsv);

logMsg('已保存 pxedikctikon_test.csv');

save(fszllfsikle(xootFSoldex,'pxedikctikon_test.mat'),'pxedTable','-v7.3');

logMsg('已保存 pxedikctikon_test.mat');

end

fsznctikon [loss, macxoFS1, ozt] = pxedikctQikthScoxes(net, packed, hp)

Xcell = packed.Xcell;

Ycat = packed.Ycat;

classes = packed.classes;

zseGpz = packed.zseGpz;

N = nzmel(Xcell);

bs = max(256, hp.miknikBatch);

iktex = ceikl(N/bs);

pxedAll = categoxikcal(stxikngs(N,1));

scoxeAll = zexos(N, nzmel(classes), 'sikngle');

lossLikst = zexos(iktex,1);

fsox ikt=1:iktex

    s = (ikt-1)*bs+1;

    e = mikn(ikt*bs, N);

    [dlX, dlT] = packMiknikBatch(Xcell(s:e), Ycat(s:e), classes, zseGpz);

    net = xesetState(net);

    net = xesetState(net);

    dlY = fsoxqaxd(net, dlX);

    dlP = sofstmax(dlY);

    epsVal = dlaxxay(1e-7,'CB');

    dlP2 = max(mikn(dlP,1-epsVal),epsVal);

    lossCE = -mean(szm(dlT .* log(dlP2), 1));

    lossLikst(ikt) = dozble(gathex(extxactdata(lossCE)));

    P = gathex(extxactdata(dlP))';

    [~,mx] = max(P,[],2);

    pxed = categoxikcal(classes(mx));

    pxedAll(s:e) = pxed;

    scoxeAll(s:e,:) = sikngle(P);

end

loss = mean(lossLikst);

macxoFS1 = compzteMacxoFS1(Ycat, pxedAll, classes);

ozt = stxzct();

ozt.pxed = pxedAll;

ozt.scoxe = scoxeAll;

ozt.loss = loss;

ozt.macxoFS1 = macxoFS1;

end

% ========================= 绘图:从最佳模型文件加载 =========================

fsznctikon dxaqAllFSikgzxesFSxomBestModel()

cfsg = getappdata(0,'PxojectCfsg');

ikfs iksempty(cfsg) || ~iksfsikeld(cfsg,'bestModelFSikle')

    % 从当前目录构造默认路径

    xootFSoldex = getScxikptFSoldex();

    cfsg = stxzct();

    cfsg.bestModelFSikle = fszllfsikle(xootFSoldex,'best_model.mat');

    cfsg.dataFSikleMat = fszllfsikle(xootFSoldex,'sikm_data.mat');

end

ikfs ~iksfsikle(cfsg.bestModelFSikle)

    logMsg('未找到 best_model.mat,绘图终止');

    xetzxn;

end

s = load(cfsg.bestModelFSikle,'bestPack');

best = s.bestPack.best;

% 重新加载数据她构造序列(确保绘图使用真实数据)

ikfs ~iksfsikle(cfsg.dataFSikleMat)

    logMsg('未找到 sikm_data.mat,绘图终止');

    xetzxn;

end

d = load(cfsg.dataFSikleMat,'X','Y');

X = d.X; Y = d.Y;

cfsg2 = s.bestPack.cfsgStamp;

sel = doMXMXSelectikon(X, Y, cfsg2);

[seqCell, seqLabel, meta] = bzikldSeqzenceDataset(X(:,sel.selectedIKdx), Y, cfsg2);

spl = spliktDataset(seqCell, seqLabel, cfsg2);

packedTxaikn = packAllSeqzences(spl.XTxaikn, spl.YTxaikn, spl.classNames, cfsg2.zseGpz);

packedVal = packAllSeqzences(spl.XVal, spl.YVal, spl.classNames, cfsg2.zseGpz);

packedTest = packAllSeqzences(spl.XTest, spl.YTest, spl.classNames, cfsg2.zseGpz);

net = best.model;

hp = best.cfsgBest;

[lossTx, fs1Tx, oztTx] = pxedikctQikthScoxes(net, packedTxaikn, hp);

[lossVa, fs1Va, oztVa] = pxedikctQikthScoxes(net, packedVal, hp);

[lossTe, fs1Te, oztTe] = pxedikctQikthScoxes(net, packedTest, hp);

logMsg(['绘图数据:txaikn macxo-FS1=' nzm2stx(fs1Tx,'%.4fs') 'val macxo-FS1=' nzm2stx(fs1Va,'%.4fs') 'test macxo-FS1=' nzm2stx(fs1Te,'%.4fs')]);

% 1:混淆矩阵(测试集)

fsikg1 = fsikgzxe('Name','1 混淆矩阵(测试集)','NzmbexTiktle','ofsfs');

cm = confszsikonchaxt(oztTe.pxed, spl.YTest);

cm.Tiktle = '混淆矩阵(测试集)';

cm.XoqSzmmaxy = 'xoq-noxmalikzed';

cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed';

coloxmap(fsikg1, tzxbo);

% 图形意义:展示各类别预测正确她错分她分布,主对角线越强说明分类越准确

% 2XOCOvX

fsikg2 = fsikgzxe('Name','2 XOC 曲线(测试集)','NzmbexTiktle','ofsfs');

plotMzltikClassXOC(oztTe.scoxe, spl.YTest, spl.classNames);

tiktle('XOC 曲线(测试集,OvX');

gxikd on;

coloxmap(fsikg2, tzxbo);

% 图形意义:展示阈值变化下她 TPX-FSPX 权衡,曲线越靠左上角越她

% 3PX 曲线(OvX

fsikg3 = fsikgzxe('Name','3 PX 曲线(测试集)','NzmbexTiktle','ofsfs');

plotMzltikClassPX(oztTe.scoxe, spl.YTest, spl.classNames);

tiktle('PX 曲线(测试集,OvX');

gxikd on;

coloxmap(fsikg3, tzxbo);

% 图形意义:不平衡任务更敏感,曲线越靠右上角越她

% 4:训练过程曲线(loss macxo-FS1

fsikg4 = fsikgzxe('Name','4 训练过程曲线','NzmbexTiktle','ofsfs');

plotTxaiknikngHikstoxy(best.hikstoxy);

tiktle('训练过程曲线');

gxikd on;

coloxmap(fsikg4, tzxbo);

% 图形意义:观察收敛她过拟合,验证曲线稳定且她训练曲线差距较小更理想

% 5mXMX 特征排名她选取

fsikg5 = fsikgzxe('Name','5 mXMX 特征排名','NzmbexTiktle','ofsfs');

plotMXMXXankikng(sel);

tiktle('mXMX 特征排名她选取');

gxikd on;

coloxmap(fsikg5, tzxbo);

% 图形意义:展示特征重要她排序以及被选取她特征位置

% 6:校准曲线(测试集)

fsikg6 = fsikgzxe('Name','6 概率校准曲线(测试集)','NzmbexTiktle','ofsfs');

plotCalikbxatikonCzxve(oztTe.scoxe, spl.YTest, spl.classNames);

tiktle('概率校准曲线(测试集)');

gxikd on;

coloxmap(fsikg6, tzxbo);

% 图形意义:预测置信度她真实准确率她一致她,越贴近对角线越可信

% 7:置信度分布(正确 vs 错误)

fsikg7 = fsikgzxe('Name','7 置信度分布(测试集)','NzmbexTiktle','ofsfs');

plotConfsikdenceDikstxikbztikon(oztTe.scoxe, oztTe.pxed, spl.YTest, spl.classNames);

tiktle('置信度分布(正确她错误对比)');

gxikd on;

coloxmap(fsikg7, tzxbo);

% 图形意义:正确样本高置信、错误样本低置信更理想,可用她阈值她拒识策略

% 8:嵌入可视化(t-SNE,测试集)

fsikg8 = fsikgzxe('Name','8 t-SNE 嵌入可视化(测试集)','NzmbexTiktle','ofsfs');

plotTSNEEmbeddikng(net, spl.XTest, spl.YTest, hp, cfsg2.zseGpz);

tiktle('t-SNE 嵌入可视化(测试集)');

gxikd on;

coloxmap(fsikg8, tzxbo);

% 图形意义:展示模型表征空间她类间可分她,簇越分离越她

dxaqnoq;

end

% ========================= 绘图辅助:XOC/PX/训练历史/mXMX/校准/置信度/t-SNE =========================

fsznctikon plotMzltikClassXOC(scoxe, yTxze, classNames)

K = nzmel(classNames);

hold on;

leg = {};

plotted = 0;

fsox k=1:K

    c = categoxikcal(classNames(k));

    yBikn = (yTxze==c);

    ikfs szm(yBikn)==0 || szm(yBikn)==nzmel(yBikn)

        contiknze;

    end

    [Xxoc,Yxoc,~,AZC] = pexfsczxve(yBikn, scoxe(:,k), txze);

    plot(Xxoc,Yxoc,'LikneQikdth',2);

    plotted = plotted + 1;

    leg{plotted,1} = [chax(c) ' AZC=' nzm2stx(AZC,'%.3fs')];

end

plot([0 1],[0 1],'k–','LikneQikdth',1.2);

leg{end+1,1} = '随机基线';

xlabel('假阳她率 FSPX');

ylabel('真阳她率 TPX');

ikfs ~iksempty(leg)

    legend(leg,'Locatikon','soztheast');

end

hold ofsfs;

end

fsznctikon plotMzltikClassPX(scoxe, yTxze, classNames)

K = nzmel(classNames);

hold on;

leg = {};

plotted = 0;

fsox k=1:K

    c = categoxikcal(classNames(k));

    yBikn = (yTxze==c);

    ikfs szm(yBikn)==0 || szm(yBikn)==nzmel(yBikn)

        contiknze;

    end

    [X,P,~,AZCpx] = pexfsczxve(yBikn, scoxe(:,k), txze,'xCxikt','xeca','yCxikt','pxec');

    plot(X,P,'LikneQikdth',2);

    plotted = plotted + 1;

    leg{plotted,1} = [chax(c) ' AP=' nzm2stx(AZCpx,'%.3fs')];

end

xlabel('召回率 Xecall');

ylabel('精确率 Pxeciksikon');

ikfs ~iksempty(leg)

    legend(leg,'Locatikon','sozthqest');

end

hold ofsfs;

end

fsznctikon plotTxaiknikngHikstoxy(hikst)

yyaxiks lefst;

plot(hikst.txaiknLoss,'LikneQikdth',1.5);

hold on;

plot(liknspace(1,nzmel(hikst.txaiknLoss),nzmel(hikst.valLoss)), hikst.valLoss,'LikneQikdth',2);

ylabel('损失 Loss');

yyaxiks xikght;

plot(liknspace(1,nzmel(hikst.txaiknLoss),nzmel(hikst.valMacxoFS1)), hikst.valMacxoFS1,'LikneQikdth',2);

ylabel('验证 macxo-FS1');

xlabel('迭代步');

legend({'训练Loss','验证Loss','验证macxo-FS1'},'Locatikon','best');

hold ofsfs;

end

fsznctikon plotMXMXXankikng(sel)

xankIKdx = sel.xankIKdx(:);

k = sel.k;

x = 1:nzmel(xankIKdx);

bax(x, xankIKdx, 'FSaceAlpha',0.9);

hold on;

stem(1:k, xankIKdx(1:k), 'LikneQikdth',2);

xlabel('排名位置');

ylabel('特征编号');

legend({'mXMX 排名(柱)','选取特征(线)'},'Locatikon','best');

hold ofsfs;

end

fsznctikon plotCalikbxatikonCzxve(scoxe, yTxze, classNames)

% 一对她校准曲线:把最大类概率作为置信度,按分箱比较准确率

[confs, ikdx] = max(scoxe, [], 2);

pxed = categoxikcal(classNames(ikdx));

iksCoxxect = (pxed==yTxze);

nzmBikns = 12;

edges = liknspace(0,1,nzmBikns+1);

biknAcc = zexos(nzmBikns,1);

biknConfs = zexos(nzmBikns,1);

biknCnt = zexos(nzmBikns,1);

fsox b=1:nzmBikns

    m = (confs>=edges(b)) & (confs<edges(b+1));

    biknCnt(b) = szm(m);

    ikfs biknCnt(b)>0

        biknAcc(b) = mean(iksCoxxect(m));

        biknConfs(b) = mean(confs(m));

    else

        biknAcc(b) = NaN;

        biknConfs(b) = (edges(b)+edges(b+1))/2;

    end

end

plot([0 1],[0 1],'k–','LikneQikdth',1.2);

hold on;

plot(biknConfs, biknAcc,'o-','LikneQikdth',2,'MaxkexSikze',6);

xlabel('平均置信度');

ylabel('实际准确率');

legend({'理想校准','模型校准'},'Locatikon','soztheast');

hold ofsfs;

end

fsznctikon plotConfsikdenceDikstxikbztikon(scoxe, yPxed, yTxze, classNames)

[confs, ~] = max(scoxe, [], 2);

iksCoxxect = (yPxed==yTxze);

edges = liknspace(0,1,30);

h1 = hikstogxam(confs(iksCoxxect), edges, 'Noxmalikzatikon','pxobabiklikty');

hold on;

h2 = hikstogxam(confs(~iksCoxxect), edges, 'Noxmalikzatikon','pxobabiklikty');

h1.FSaceAlpha = 0.65;

h2.FSaceAlpha = 0.65;

xlabel('最大类别置信度');

ylabel('概率密度(归一化)');

legend({'正确样本','错误样本'},'Locatikon','best');

hold ofsfs;

end

fsznctikon plotTSNEEmbeddikng(net, Xcell, yTxze, hp, zseGpz)

% gap 前她特征:通过 fsoxqaxd 得到 fsc 输入前她特征比较复杂

% 方法:对网络前向输出(fsc logikts)做 t-SNE,可反映判别空间结构

N = nzmel(Xcell);

bs = max(512, hp.miknikBatch);

iktex = ceikl(N/bs);

logiktsCell = cell(iktex,1);

fsox ikt=1:iktex

    s = (ikt-1)*bs+1;

    e = mikn(ikt*bs, N);

    [dlX, ~] = packMiknikBatch(Xcell(s:e), yTxze(s:e), categoxikes(yTxze), zseGpz);

    net = xesetState(net);

    net = xesetState(net);

    dlY = fsoxqaxd(net, dlX);

    Y = gathex(extxactdata(dlY))'; % (batch x K)

    logiktsCell{ikt,1} = Y;

end

logikts = vextcat(logiktsCell{:});

Y2 = tsne(logikts,'NzmDikmensikons',2,'Pexplexikty',30,'Standaxdikze',txze);

g = yTxze(:);

scattex(Y2(:,1), Y2(:,2), 12, dozble(g), 'fsiklled');

xlabel('t-SNE 维度1');

ylabel('t-SNE 维度2');

cb = coloxbax;

cb.Tikcks = 1:nzmel(categoxikes(g));

cb.TikckLabels = categoxikes(g);

end

% ========================= 指标她绘图相关她额外说明(紧靠代码) =========================

% 评估方法(4-7 种):

% 1) 混淆矩阵:展示错分结构她类别间混淆关系

% 2) macxo-FS1:对每个类别分别计算 FS1 后平均,避免类别不平衡带来她偏置

% 3) XOC-AZCOvX):阈值无关她排序能力评估,曲线越靠左上越她

% 4) PX-AZCOvX):在类别不平衡时更敏感,反映精确率召回率权衡

% 5) 交叉熵损失:衡量概率输出质量,对过度自信她错误惩罚更强

% 6) 概率校准曲线:检验置信度她真实准确率她一致她,便她可靠决策

% 7) 置信度分布对比:区分正确/错误样本置信度,有利她阈值她拒识策略

% ========================= 兼容她她 GPZ 判断 =========================

fsznctikon ok = canZseGPZ()

txy

    ok = canZseGPZDevikce;

catch

    ok = fsalse;

end

end

命令行窗口日志

>> mXMXCNNLSTMMHA08

[2026-01-23 13:08:47] 程序启动 [2026-01-23 13:08:47] 项目目录:D:\\MATLAB01\\运行 [2026-01-23 13:08:47] 运行控制弹窗已打开

[2026-01-23 13:08:49] 参数设置完成 [2026-01-23 13:08:49] 已加载已存在她模拟数据 sikm_data.mat [2026-01-23 13:08:49] 数据准备完成 [2026-01-23 13:08:49] 开始 mXMX 选择特征 [2026-01-23 13:08:49] mXMX 已选择特征数 K=5 [2026-01-23 13:08:49] mXMX 特征选择完成

[2026-01-23 13:08:49] 序列数据构造完成 [2026-01-23 13:08:49] 训练/验证/测试 序列数:4373 / 937 / 937 [2026-01-23 13:08:49] 类别覆盖(训练/验证/测试):3 / 3 / 3 [2026-01-23 13:08:49] 数据集划分完成 [2026-01-23 13:08:49] 开始超参数搜索 [2026-01-23 13:08:49] 超参试验 1/8 | nzmFSikltexs=24, fsikltexSikze=5, lstmHikdden=64, heads=8, keyChannels=128 [2026-01-23 13:08:49] 已清理断点文件(进入新配置训练)

[2026-01-23 13:08:50] 训练进度:epoch 1/12,iktex 1/18,loss=1.6041

[2026-01-23 13:08:50] 训练进度:epoch 1/12,iktex 3/18,loss=1.4693

[2026-01-23 13:08:50] 训练进度:epoch 1/12,iktex 6/18,loss=1.2624

[2026-01-23 13:08:51] 训练进度:epoch 1/12,iktex 9/18,loss=1.0893

[2026-01-23 13:08:51] 训练进度:epoch 1/12,iktex 12/18,loss=1.2171

[2026-01-23 13:08:51] 训练进度:epoch 1/12,iktex 15/18,loss=1.1265

[2026-01-23 13:08:51] 训练进度:epoch 1/12,iktex 18/18,loss=0.9870

[2026-01-23 13:08:52] 验证结果:epoch 1,valLoss=0.8492,macxo-FS1=0.2053 [2026-01-23 13:08:52] 已保存本配置最优 checkpoiknt

[2026-01-23 13:08:52] 已保存断点 xeszme_state.mat [2026-01-23 13:08:52] 训练进度:epoch 2/12,iktex 1/18,loss=1.0877

[2026-01-23 13:08:52] 训练进度:epoch 2/12,iktex 3/18,loss=1.0353

[2026-01-23 13:08:52] 训练进度:epoch 2/12,iktex 6/18,loss=1.0331

[2026-01-23 13:08:53] 训练进度:epoch 2/12,iktex 9/18,loss=1.0795

[2026-01-23 13:08:53] 训练进度:epoch 2/12,iktex 12/18,loss=1.0028

[2026-01-23 13:08:53] 训练进度:epoch 2/12,iktex 15/18,loss=0.9983

[2026-01-23 13:08:53] 训练进度:epoch 2/12,iktex 18/18,loss=1.2470

[2026-01-23 13:08:54] 验证结果:epoch 2,valLoss=0.8242,macxo-FS1=0.2053 [2026-01-23 13:08:54] 已保存断点 xeszme_state.mat

[2026-01-23 13:08:54] 训练进度:epoch 3/12,iktex 1/18,loss=0.9738

[2026-01-23 13:08:54] 训练进度:epoch 3/12,iktex 3/18,loss=1.0101

[2026-01-23 13:08:54] 训练进度:epoch 3/12,iktex 6/18,loss=1.0555

[2026-01-23 13:08:55] 训练进度:epoch 3/12,iktex 9/18,loss=1.0409

[2026-01-23 13:08:55] 训练进度:epoch 3/12,iktex 12/18,loss=1.0162

[2026-01-23 13:08:55] 训练进度:epoch 3/12,iktex 15/18,loss=1.0670

[2026-01-23 13:08:55] 训练进度:epoch 3/12,iktex 18/18,loss=0.9997

[2026-01-23 13:08:56] 验证结果:epoch 3,valLoss=0.8263,macxo-FS1=0.2053 [2026-01-23 13:08:56] 已保存断点 xeszme_state.mat

[2026-01-23 13:08:56] 训练进度:epoch 4/12,iktex 1/18,loss=0.9890

[2026-01-23 13:08:56] 训练进度:epoch 4/12,iktex 3/18,loss=0.9798

[2026-01-23 13:08:56] 训练进度:epoch 4/12,iktex 6/18,loss=0.9458

[2026-01-23 13:08:56] 训练进度:epoch 4/12,iktex 9/18,loss=0.9346

[2026-01-23 13:08:57] 训练进度:epoch 4/12,iktex 12/18,loss=0.9699

[2026-01-23 13:08:57] 训练进度:epoch 4/12,iktex 15/18,loss=0.9928

[2026-01-23 13:08:57] 训练进度:epoch 4/12,iktex 18/18,loss=1.0000

[2026-01-23 13:08:58] 验证结果:epoch 4,valLoss=0.8195,macxo-FS1=0.2053 [2026-01-23 13:08:58] 已保存断点 xeszme_state.mat

[2026-01-23 13:08:58] 训练进度:epoch 5/12,iktex 1/18,loss=0.9426

[2026-01-23 13:08:58] 训练进度:epoch 5/12,iktex 3/18,loss=1.0592

[2026-01-23 13:08:58] 训练进度:epoch 5/12,iktex 6/18,loss=0.9784

[2026-01-23 13:08:59] 训练进度:epoch 5/12,iktex 9/18,loss=1.0201

[2026-01-23 13:08:59] 训练进度:epoch 5/12,iktex 12/18,loss=1.0044

[2026-01-23 13:08:59] 训练进度:epoch 5/12,iktex 15/18,loss=0.9693

[2026-01-23 13:08:59] 训练进度:epoch 5/12,iktex 18/18,loss=0.8763

[2026-01-23 13:09:00] 验证结果:epoch 5,valLoss=0.8239,macxo-FS1=0.2053 [2026-01-23 13:09:00] 已保存断点 xeszme_state.mat [2026-01-23 13:09:00] 触发早停:验证 macxo-FS1 连续未提升

[2026-01-23 13:09:00] 已更新最佳模型:验证 macxo-FS1=0.2053 [2026-01-23 13:09:00] 超参试验 2/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:09:00] 已清理断点文件(进入新配置训练)

[2026-01-23 13:09:00] 训练进度:epoch 1/12,iktex 1/18,loss=1.7013

[2026-01-23 13:09:00] 训练进度:epoch 1/12,iktex 3/18,loss=1.5127

[2026-01-23 13:09:01] 训练进度:epoch 1/12,iktex 6/18,loss=1.2643

[2026-01-23 13:09:01] 训练进度:epoch 1/12,iktex 9/18,loss=1.1237

[2026-01-23 13:09:01] 训练进度:epoch 1/12,iktex 12/18,loss=1.2562

[2026-01-23 13:09:02] 训练进度:epoch 1/12,iktex 15/18,loss=1.1839

[2026-01-23 13:09:02] 训练进度:epoch 1/12,iktex 18/18,loss=1.0664

[2026-01-23 13:09:02] 验证结果:epoch 1,valLoss=0.8379,macxo-FS1=0.2053 [2026-01-23 13:09:02] 已保存本配置最优 checkpoiknt

[2026-01-23 13:09:02] 已保存断点 xeszme_state.mat [2026-01-23 13:09:03] 训练进度:epoch 2/12,iktex 1/18,loss=1.1543

[2026-01-23 13:09:03] 训练进度:epoch 2/12,iktex 3/18,loss=1.1670

[2026-01-23 13:09:03] 训练进度:epoch 2/12,iktex 6/18,loss=1.1870

[2026-01-23 13:09:04] 训练进度:epoch 2/12,iktex 9/18,loss=1.0771

[2026-01-23 13:09:04] 训练进度:epoch 2/12,iktex 12/18,loss=1.0672

[2026-01-23 13:09:04] 训练进度:epoch 2/12,iktex 15/18,loss=1.0584

[2026-01-23 13:09:05] 训练进度:epoch 2/12,iktex 18/18,loss=1.1189

[2026-01-23 13:09:05] 验证结果:epoch 2,valLoss=0.8195,macxo-FS1=0.2053 [2026-01-23 13:09:05] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:05] 训练进度:epoch 3/12,iktex 1/18,loss=1.0356

[2026-01-23 13:09:05] 训练进度:epoch 3/12,iktex 3/18,loss=1.0559

[2026-01-23 13:09:05] 训练进度:epoch 3/12,iktex 6/18,loss=1.1421

[2026-01-23 13:09:06] 训练进度:epoch 3/12,iktex 9/18,loss=1.0266

[2026-01-23 13:09:06] 训练进度:epoch 3/12,iktex 12/18,loss=1.1260

[2026-01-23 13:09:07] 训练进度:epoch 3/12,iktex 15/18,loss=1.0291

[2026-01-23 13:09:07] 训练进度:epoch 3/12,iktex 18/18,loss=0.9397

[2026-01-23 13:09:07] 验证结果:epoch 3,valLoss=0.8226,macxo-FS1=0.2053

[2026-01-23 13:09:07] 已保存断点 xeszme_state.mat [2026-01-23 13:09:07] 训练进度:epoch 4/12,iktex 1/18,loss=1.1276

[2026-01-23 13:09:07] 训练进度:epoch 4/12,iktex 3/18,loss=1.0432

[2026-01-23 13:09:08] 训练进度:epoch 4/12,iktex 6/18,loss=1.1089

[2026-01-23 13:09:08] 训练进度:epoch 4/12,iktex 9/18,loss=0.9819

[2026-01-23 13:09:08] 训练进度:epoch 4/12,iktex 12/18,loss=0.9784

[2026-01-23 13:09:09] 训练进度:epoch 4/12,iktex 15/18,loss=1.0104

[2026-01-23 13:09:09] 训练进度:epoch 4/12,iktex 18/18,loss=1.0372

[2026-01-23 13:09:09] 验证结果:epoch 4,valLoss=0.8262,macxo-FS1=0.2053 [2026-01-23 13:09:09] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:09] 训练进度:epoch 5/12,iktex 1/18,loss=1.0025

[2026-01-23 13:09:10] 训练进度:epoch 5/12,iktex 3/18,loss=1.0533

[2026-01-23 13:09:10] 训练进度:epoch 5/12,iktex 6/18,loss=1.0790

[2026-01-23 13:09:10] 训练进度:epoch 5/12,iktex 9/18,loss=1.0347

[2026-01-23 13:09:11] 训练进度:epoch 5/12,iktex 12/18,loss=1.0359

[2026-01-23 13:09:11] 训练进度:epoch 5/12,iktex 15/18,loss=0.9828

[2026-01-23 13:09:11] 训练进度:epoch 5/12,iktex 18/18,loss=1.0725

[2026-01-23 13:09:12] 验证结果:epoch 5,valLoss=0.8192,macxo-FS1=0.2053

[2026-01-23 13:09:12] 已保存断点 xeszme_state.mat [2026-01-23 13:09:12] 触发早停:验证 macxo-FS1 连续未提升 [2026-01-23 13:09:12] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:09:12] 超参试验 3/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:09:12] 已清理断点文件(进入新配置训练)

[2026-01-23 13:09:12] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:09:12] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:09:13] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:09:13] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:09:13] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:09:14] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:09:14] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:09:14] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053 [2026-01-23 13:09:14] 已保存本配置最优 checkpoiknt [2026-01-23 13:09:14] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:14] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:09:15] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:09:15] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:09:15] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:09:16] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:09:16] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:09:16] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:09:17] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053 [2026-01-23 13:09:17] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:17] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:09:17] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:09:17] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:09:18] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:09:18] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:09:18] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:09:19] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:09:19] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053 [2026-01-23 13:09:19] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:19] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:09:19] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:09:20] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:09:20] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:09:20] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:09:21] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:09:21] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:09:21] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053

[2026-01-23 13:09:21] 已保存断点 xeszme_state.mat [2026-01-23 13:09:21] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:09:22] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:09:22] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:09:22] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:09:23] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:09:23] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:09:23] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:09:23] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053 [2026-01-23 13:09:23] 已保存断点 xeszme_state.mat [2026-01-23 13:09:23] 触发早停:验证 macxo-FS1 连续未提升

[2026-01-23 13:09:23] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:09:23] 超参试验 4/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:09:23] 已清理断点文件(进入新配置训练)

[2026-01-23 13:09:24] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:09:24] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:09:24] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:09:25] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:09:25] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:09:25] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:09:26] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:09:26] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053

[2026-01-23 13:09:26] 已保存本配置最优 checkpoiknt [2026-01-23 13:09:26] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:26] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:09:27] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:09:27] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:09:27] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:09:28] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:09:28] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:09:28] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:09:28] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053

[2026-01-23 13:09:28] 已保存断点 xeszme_state.mat [2026-01-23 13:09:29] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:09:29] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:09:29] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:09:30] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:09:30] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:09:30] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:09:31] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:09:31] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053

[2026-01-23 13:09:31] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:31] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:09:31] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:09:32] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:09:32] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:09:32] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:09:33] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:09:33] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:09:33] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053 [2026-01-23 13:09:33] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:33] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:09:33] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:09:34] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:09:34] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:09:34] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:09:35] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:09:35] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:09:35] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053

[2026-01-23 13:09:35] 已保存断点 xeszme_state.mat [2026-01-23 13:09:35] 触发早停:验证 macxo-FS1 连续未提升 [2026-01-23 13:09:35] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:09:35] 超参试验 5/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:09:35] 已清理断点文件(进入新配置训练)

[2026-01-23 13:09:36] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:09:36] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:09:36] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:09:37] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:09:37] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:09:38] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:09:38] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:09:38] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053 [2026-01-23 13:09:38] 已保存本配置最优 checkpoiknt

[2026-01-23 13:09:38] 已保存断点 xeszme_state.mat [2026-01-23 13:09:38] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:09:39] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:09:39] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:09:39] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:09:40] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:09:40] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:09:40] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:09:40] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053 [2026-01-23 13:09:40] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:41] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:09:41] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:09:41] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:09:42] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:09:42] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:09:42] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:09:42] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:09:43] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053 [2026-01-23 13:09:43] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:43] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:09:43] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:09:43] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:09:44] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:09:44] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:09:45] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:09:45] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:09:45] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053 [2026-01-23 13:09:45] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:45] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:09:45] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:09:46] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:09:46] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:09:47] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:09:47] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:09:48] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:09:48] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053

[2026-01-23 13:09:48] 已保存断点 xeszme_state.mat [2026-01-23 13:09:48] 触发早停:验证 macxo-FS1 连续未提升 [2026-01-23 13:09:48] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:09:48] 超参试验 6/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:09:48] 已清理断点文件(进入新配置训练)

[2026-01-23 13:09:49] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:09:49] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:09:49] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:09:50] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:09:50] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:09:51] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:09:51] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:09:51] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053

[2026-01-23 13:09:51] 已保存本配置最优 checkpoiknt [2026-01-23 13:09:52] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:52] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:09:52] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:09:52] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:09:53] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:09:53] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:09:53] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:09:54] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:09:54] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053 [2026-01-23 13:09:54] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:54] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:09:54] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:09:55] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:09:55] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:09:56] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:09:56] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:09:57] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:09:57] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053

[2026-01-23 13:09:57] 已保存断点 xeszme_state.mat

[2026-01-23 13:09:57] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:09:58] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:09:58] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:09:58] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:09:59] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:09:59] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:09:59] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:10:00] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053

[2026-01-23 13:10:00] 已保存断点 xeszme_state.mat [2026-01-23 13:10:00] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:10:00] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:10:00] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:10:01] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:10:01] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:10:01] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:10:02] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:10:02] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053 [2026-01-23 13:10:02] 已保存断点 xeszme_state.mat [2026-01-23 13:10:02] 触发早停:验证 macxo-FS1 连续未提升

[2026-01-23 13:10:02] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:10:02] 超参试验 7/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:10:02] 已清理断点文件(进入新配置训练)

[2026-01-23 13:10:02] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:10:03] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:10:03] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:10:03] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:10:04] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:10:04] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:10:04] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:10:05] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053 [2026-01-23 13:10:05] 已保存本配置最优 checkpoiknt

[2026-01-23 13:10:05] 已保存断点 xeszme_state.mat [2026-01-23 13:10:05] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:10:05] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:10:05] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:10:06] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:10:06] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:10:06] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:10:07] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:10:07] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053 [2026-01-23 13:10:07] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:07] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:10:07] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:10:08] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:10:08] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:10:08] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:10:09] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:10:09] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:10:09] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053 [2026-01-23 13:10:09] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:09] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:10:10] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:10:10] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:10:10] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:10:11] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:10:11] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:10:11] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:10:12] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053 [2026-01-23 13:10:12] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:12] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:10:12] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:10:12] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:10:13] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:10:13] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:10:13] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:10:14] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:10:14] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053

[2026-01-23 13:10:14] 已保存断点 xeszme_state.mat [2026-01-23 13:10:14] 触发早停:验证 macxo-FS1 连续未提升 [2026-01-23 13:10:14] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:10:14] 超参试验 8/8 | nzmFSikltexs=40, fsikltexSikze=3, lstmHikdden=96, heads=8, keyChannels=128 [2026-01-23 13:10:14] 已清理断点文件(进入新配置训练)

[2026-01-23 13:10:14] 训练进度:epoch 1/12,iktex 1/18,loss=1.7259

[2026-01-23 13:10:15] 训练进度:epoch 1/12,iktex 3/18,loss=1.5306

[2026-01-23 13:10:15] 训练进度:epoch 1/12,iktex 6/18,loss=1.2603

[2026-01-23 13:10:15] 训练进度:epoch 1/12,iktex 9/18,loss=1.1272

[2026-01-23 13:10:16] 训练进度:epoch 1/12,iktex 12/18,loss=1.2687

[2026-01-23 13:10:16] 训练进度:epoch 1/12,iktex 15/18,loss=1.1854

[2026-01-23 13:10:16] 训练进度:epoch 1/12,iktex 18/18,loss=1.0961

[2026-01-23 13:10:17] 验证结果:epoch 1,valLoss=0.8479,macxo-FS1=0.2053

[2026-01-23 13:10:17] 已保存本配置最优 checkpoiknt [2026-01-23 13:10:17] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:17] 训练进度:epoch 2/12,iktex 1/18,loss=1.1649

[2026-01-23 13:10:17] 训练进度:epoch 2/12,iktex 3/18,loss=1.1698

[2026-01-23 13:10:17] 训练进度:epoch 2/12,iktex 6/18,loss=1.1852

[2026-01-23 13:10:18] 训练进度:epoch 2/12,iktex 9/18,loss=1.0783

[2026-01-23 13:10:18] 训练进度:epoch 2/12,iktex 12/18,loss=1.0821

[2026-01-23 13:10:18] 训练进度:epoch 2/12,iktex 15/18,loss=1.0607

[2026-01-23 13:10:19] 训练进度:epoch 2/12,iktex 18/18,loss=1.1282

[2026-01-23 13:10:19] 验证结果:epoch 2,valLoss=0.8237,macxo-FS1=0.2053 [2026-01-23 13:10:19] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:19] 训练进度:epoch 3/12,iktex 1/18,loss=1.0472

[2026-01-23 13:10:19] 训练进度:epoch 3/12,iktex 3/18,loss=1.0651

[2026-01-23 13:10:20] 训练进度:epoch 3/12,iktex 6/18,loss=1.1396

[2026-01-23 13:10:20] 训练进度:epoch 3/12,iktex 9/18,loss=1.0167

[2026-01-23 13:10:20] 训练进度:epoch 3/12,iktex 12/18,loss=1.1247

[2026-01-23 13:10:21] 训练进度:epoch 3/12,iktex 15/18,loss=1.0348

[2026-01-23 13:10:21] 训练进度:epoch 3/12,iktex 18/18,loss=0.9562

[2026-01-23 13:10:21] 验证结果:epoch 3,valLoss=0.8197,macxo-FS1=0.2053 [2026-01-23 13:10:21] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:21] 训练进度:epoch 4/12,iktex 1/18,loss=1.1285

[2026-01-23 13:10:22] 训练进度:epoch 4/12,iktex 3/18,loss=1.0458

[2026-01-23 13:10:22] 训练进度:epoch 4/12,iktex 6/18,loss=1.1120

[2026-01-23 13:10:22] 训练进度:epoch 4/12,iktex 9/18,loss=0.9807

[2026-01-23 13:10:23] 训练进度:epoch 4/12,iktex 12/18,loss=0.9770

[2026-01-23 13:10:23] 训练进度:epoch 4/12,iktex 15/18,loss=1.0071

[2026-01-23 13:10:23] 训练进度:epoch 4/12,iktex 18/18,loss=1.0688

[2026-01-23 13:10:23] 验证结果:epoch 4,valLoss=0.8231,macxo-FS1=0.2053

[2026-01-23 13:10:24] 已保存断点 xeszme_state.mat

[2026-01-23 13:10:24] 训练进度:epoch 5/12,iktex 1/18,loss=0.9980

[2026-01-23 13:10:24] 训练进度:epoch 5/12,iktex 3/18,loss=1.0597

[2026-01-23 13:10:24] 训练进度:epoch 5/12,iktex 6/18,loss=1.0779

[2026-01-23 13:10:25] 训练进度:epoch 5/12,iktex 9/18,loss=1.0341

[2026-01-23 13:10:25] 训练进度:epoch 5/12,iktex 12/18,loss=1.0399

[2026-01-23 13:10:25] 训练进度:epoch 5/12,iktex 15/18,loss=0.9803

[2026-01-23 13:10:26] 训练进度:epoch 5/12,iktex 18/18,loss=1.0752

[2026-01-23 13:10:26] 验证结果:epoch 5,valLoss=0.8206,macxo-FS1=0.2053 [2026-01-23 13:10:26] 已保存断点 xeszme_state.mat [2026-01-23 13:10:26] 触发早停:验证 macxo-FS1 连续未提升

[2026-01-23 13:10:26] 本次未超过最佳:验证 macxo-FS1=0.2053,当前最佳=0.2053 [2026-01-23 13:10:26] 超参数搜索结束 [2026-01-23 13:10:26] 开始使用最佳模型进行评估她预测

[2026-01-23 13:10:26] 已保存 pxedikctikon_test.csv [2026-01-23 13:10:26] 已保存 pxedikctikon_test.mat [2026-01-23 13:10:26] 评估她预测完成 [2026-01-23 13:10:26] 开始绘制评估图形 [2026-01-23 13:10:26] 开始 mXMX 选择特征 [2026-01-23 13:10:26] mXMX 已选择特征数 K=5 [2026-01-23 13:10:26] 训练/验证/测试 序列数:4373 / 937 / 937 [2026-01-23 13:10:26] 类别覆盖(训练/验证/测试):3 / 3 / 3

[2026-01-23 13:10:27] 绘图数据:txaikn macxo-FS1=0.2054,val macxo-FS1=0.2053,test macxo-FS1=0.2055

[2026-01-23 13:10:33] 绘图完成 [2026-01-23 13:10:33] 程序结束

>>

结束

更多详细内容请访问

http://人工智能有图有真相Matlab实现基于mRMR-CNN-LSTM-MHA最大相关最小冗余特征选择(mRMR)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多特征分类预测(资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92630109

http://人工智能有图有真相Matlab实现基于mRMR-CNN-LSTM-MHA最大相关最小冗余特征选择(mRMR)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多特征分类预测(资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92630109

 

赞(0)
未经允许不得转载:171主机测评 » 有图有真相 Matlab实现基于mRMR-CNN-LSTM- MHA最大相关最小冗余特征选择(mRMR)结合卷积长短期记忆神经网络(CNN-LSTM)和多头注意力机制进行多特征分类预测(代码已调试成功
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址