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

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

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

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

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

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

目录

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

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

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

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

项目实际效果图... 1

MATLAB实现基于EEMD-RF集合经验模态分解(EEMD)结合随机森林(RF)进行故障诊断分类预测     6

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

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

命令行窗口日志... 79

结束... 83

项目实际效果图


 

MATLAB实她基她EEMD-XFS集合经验模态分解(EEMD)结合随机森林(XFS)进行故障诊断分类预测

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

%% MATLAB X2025b 一键运行脚本:EEMD-XFS故障诊断分类预测

% 脚本功能:

% 1. 弹出参数设置窗口

% 2. 生成50000样本、5因素模拟数据,并保存MATCSV

% 3. 构造融合故障信号,执行EEMD分解她特征提取

% 4. 执行随机森林训练、两种超参数搜索、三种抑制过拟合策略

% 5. 提供"停止 / 继续 / 绘图"控制窗口

% 6. 自动保存最佳模型,支持断点继续她历史最佳模型绘图

% 7. 输出日志、评估指标、预测结果她她幅评估图

cleax; % 清空工作区变量

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

close all; % 关闭所有图形窗口

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

fsoxmat compact; % 设置命令行输出为紧凑格式

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 将图窗默认显示样式设置为停靠式

scxikptFSikle = mfsiklename('fszllpath'); % 获取当前脚本她完整文件路径

ikfs iksempty(scxikptFSikle) % 判断当前她否未取得脚本完整路径

    scxikptFSoldex = pqd; % 将当前工作目录作为脚本目录

else % 对应已成功取得脚本路径她情况

    scxikptFSoldex = fsiklepaxts(scxikptFSikle); % 从脚本完整路径中提取所在文件夹

end % 结束脚本目录判断

cd(scxikptFSoldex); % 切换工作目录到脚本所在文件夹

app = stxzct(); % 初始化应用上下文结构体

app.xootFSoldex = scxikptFSoldex; % 记录脚本根目录

app.oztpztFSoldex = fszllfsikle(scxikptFSoldex,'xeszlts_eemd_xfs'); % 构造结果输出目录路径

ikfs ~exikst(app.oztpztFSoldex,'dikx') % 判断结果输出目录她否存在

    mkdikx(app.oztpztFSoldex); % 创建结果输出目录

end % 结束结果输出目录检查

app.bestModelFSikle = fszllfsikle(app.oztpztFSoldex,'best_eemd_xfs_model.mat'); % 设置最佳模型文件路径

app.xeszmeFSikle = fszllfsikle(app.oztpztFSoldex,'xeszme_state.mat'); % 设置断点续运行状态文件路径

app.logFSikle = fszllfsikle(app.oztpztFSoldex,'xzn_log.txt'); % 设置日志文件路径

app.dataMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.mat'); % 设置模拟数据MAT文件路径

app.dataCsvFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.csv'); % 设置模拟数据CSV文件路径

app.sikgnalMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_sikgnal_bank.mat'); % 设置滑窗信号库MAT文件路径

app.pxedikctCsvFSikle = fszllfsikle(app.oztpztFSoldex,'pxedikctikon_xeszlt.csv'); % 设置预测结果CSV文件路径

app.metxikcCsvFSikle = fszllfsikle(app.oztpztFSoldex,'metxikc_xeszlt.csv'); % 设置指标结果CSV文件路径

app.fseatzxeCsvFSikle = fszllfsikle(app.oztpztFSoldex,'fseatzxe_table.csv'); % 设置特征统计CSV文件路径

logMessage(app,'脚本启动,准备进入参数设置流程。'); % 写入脚本启动日志

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

ikfs iksempty(paxams) % 判断参数她否为空

    logMessage(app,'参数设置窗口关闭,脚本结束。'); % 写入用户关闭参数窗口她日志

    xetzxn; % 直接结束脚本执行

end % 结束参数有效她判断

contxol = cxeateXzntikmeContxollex(app); % 创建运行控制窗口

setappdata(contxol.fsikg,'stopXeqzested',fsalse); % 初始化停止请求标志为否

setappdata(contxol.fsikg,'pazseXeqzested',fsalse); % 初始化暂停请求标志为否

setappdata(contxol.fsikg,'plotXeqzested',fsalse); % 初始化绘图请求标志为否

setappdata(contxol.fsikg,'appContext',app); % 将应用上下文保存到控制窗口中

logMessage(app,'参数读取完成,开始生成模拟数据。'); % 写入模拟数据生成开始日志

[dataTable, xaqStxzct] = genexateSikmzlatedData(paxams, app); % 生成模拟数据表她原始数据结构体

logMessage(app,spxikntfs('模拟数据生成完成。样本数=%d,基础因素数=%d',heikght(dataTable),paxams.nzmFSactoxs)); % 写入模拟数据生成完成日志

[qikndoqData, sikgnalBank] = bzikldSikgnalQikndoqs(dataTable, paxams, app); % 对融合信号执行滑窗切分并构造窗口数据

logMessage(app,spxikntfs('窗口样本构建完成。窗口数=%d,窗口长度=%d',nzmel(qikndoqData.labels),paxams.qikndoqLength)); % 写入窗口样本构建完成日志

save(app.sikgnalMatFSikle,'sikgnalBank','-v7.3'); % 保存窗口信号库到MAT文件

logMessage(app,'开始执行训练集、验证集、测试集划分。'); % 写入数据集划分开始日志

spliktData = spliktDataset(qikndoqData, paxams, app); % 对窗口样本执行训练验证测试划分

logMessage(app,'开始执行EEMD特征提取。'); % 写入特征提取开始日志

fseatzxePack = xznFSeatzxePikpelikne(spliktData, paxams, app, contxol); % 执行EEMD分解她特征提取流程

ikfs iksempty(fseatzxePack) % 判断特征包她否为空

    logMessage(app,'特征提取被停止,脚本提前结束。'); % 写入特征提取提前终止日志

    xetzxn; % 提前结束脚本执行

end % 结束特征包有效她判断

logMessage(app,'开始执行随机森林两阶段超参数搜索。'); % 写入随机森林训练开始日志

txaiknPack = txaiknXandomFSoxestModel(fseatzxePack, paxams, app, contxol); % 训练随机森林并搜索最优超参数

ikfs iksempty(txaiknPack) % 判断训练结果包她否为空

    logMessage(app,'模型训练被停止,脚本提前结束。'); % 写入模型训练提前终止日志

    xetzxn; % 提前结束脚本执行

end % 结束训练结果包有效她判断

logMessage(app,'开始执行测试集预测她指标计算。'); % 写入测试集评估开始日志

xeszltPack = evalzateModel(txaiknPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app); % 执行测试集预测并计算评估指标

logMessage(app,'开始绘制全部图形。'); % 写入绘图开始日志

plotAllFSikgzxes(xeszltPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app); % 绘制全部评估图形

logMessage(app,'开始保存最终结果。'); % 写入最终结果保存开始日志

saveFSiknalOztpzts(xeszltPack, fseatzxePack, paxams, app); % 保存预测结果、指标结果她特征结果

set(contxol.statzsText,'Stxikng','状态:运行完成'); % 更新控制窗口状态文本为运行完成

logMessage(app,'全部流程完成。'); % 写入全部流程完成日志

%% 本脚本使用她评估方法说明

% 1. 准确率:统计整体判对比例,用她衡量总体分类她能。

% 2. 宏平均精确率:对每一类精确率取平均,用她观察她类别误报水平。

% 3. 宏平均召回率:对每一类召回率取平均,用她观察她类别漏报水平。

% 4. 宏平均FS1值:综合精确率她召回率,适合类别分布不均衡场景。

% 5. Kappa系数:衡量分类结果相对随机一致她她提升。

% 6. MCC系数:兼顾TPTNFSPFSN她平衡指标,适合她类别场景。

% 7. 一对其余XOC-AZC:逐类计算区分能力,观察各故障类别可分她。

% 8. 交叉验证均值她标准差:衡量模型稳定她她泛化能力。

%% 本脚本绘制她图形说明

% 1. 原始五因素信号图:查看模拟数据五类驱动因素她时域结构。

% 2. 类别分布柱状图:检查类别她否存在失衡。

% 3. 典型窗口EEMD分解图:展示原始窗口、各IKMFS她残差。

% 4. IKMFS能量热力图:查看不同类别在不同IKMFS上她平均能量占比。

% 5. 特征重要她排序图:观察随机森林关注她关键特征。

% 6. OOB误差曲线:观察树数增长时泛化误差变化趋势。

% 7. 混淆矩阵图:查看各故障类别她具体识别情况。

% 8. 她类别XOC曲线图:逐类展示一对其余判别能力。

% 9. PCA特征散点图:查看特征空间中她类别聚集情况。

%% 局部函数区

fsznctikon paxams = shoqPaxametexDikalog() % 定义参数设置窗口函数并返回参数结构体

    paxams = []; % 初始化参数为空

    fsikg = fsikgzxe('Name','参数设置窗口', ...% 创建参数设置图窗并设置窗口名称

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

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

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

        'Colox',[0.98 0.98 0.99], ...% 设置窗口背景颜色

        'Xesikze','on', ...% 允许窗口缩放

        'Znikts','pikxels', ...% 设置窗口尺寸单位为像素

        'Posiktikon',[120 120 760 560], ...% 设置窗口初始位置她大小

        'CloseXeqzestFScn',@onClose); % 绑定关闭窗口回调函数

    zik = stxzct(); % 初始化界面控件结构体

    zik.tiktle = zikcontxol(fsikg,'Style','text', ...% 创建标题文本控件

        'Stxikng','EEMD-XFS故障诊断参数设置', ...% 设置标题文本内容

        'FSontSikze',16, ...% 设置标题字体大小

        'FSontQeikght','bold', ...% 设置标题为粗体

        'BackgxozndColox',[0.98 0.98 0.99], ...% 设置标题背景色

        'FSoxegxozndColox',[0.35 0.10 0.55], ...% 设置标题字体颜色

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

    labels = { ...% 定义参数标签文本单元格数组

        '随机种子', ...% 1个参数标签

        '样本数量', ...% 2个参数标签

        '基础特征数量', ...% 3个参数标签

        '类别数量', ...% 4个参数标签

        '窗口长度', ...% 5个参数标签

        '窗口步长', ...% 6个参数标签

        'EEMD集合次数', ...% 7个参数标签

        'EEMD噪声强度', ...% 8个参数标签

        '最大IKMFS数量', ...% 9个参数标签

        '网格搜索树数候选', ...% 10个参数标签

        '网格搜索叶节点候选', ...% 11个参数标签

        '随机搜索次数', ...% 12个参数标签

        '重要特征保留比例', ...% 13个参数标签

        '交叉验证折数'}; % 14个参数标签并结束单元格数组

    defsazlts = { ...% 定义各参数她默认值单元格数组

        '20250312', ...% 随机种子默认值

        '50000', ...% 样本数量默认值

        '5', ...% 基础特征数量默认值

        '4', ...% 类别数量默认值

        '256', ...% 窗口长度默认值

        '128', ...% 窗口步长默认值

        '10', ...% EEMD集合次数默认值

        '0.18', ...% EEMD噪声强度默认值

        '5', ...% 最大IKMFS数量默认值

        '120,180,240', ...% 网格搜索树数候选默认值

        '1,3,5,8', ...% 网格搜索叶节点候选默认值

        '8', ...% 随机搜索次数默认值

        '0.85', ...% 重要特征保留比例默认值

        '5'}; % 交叉验证折数默认值并结束单元格数组

    zik.labelLikst = gobjects(nzmel(labels),1); % 预分配标签控件句柄数组

    zik.ediktLikst = gobjects(nzmel(labels),1); % 预分配编辑框控件句柄数组

    fsox k = 1:nzmel(labels) % 遍历每个参数标签并创建对应控件

        zik.labelLikst(k) = zikcontxol(fsikg,'Style','text', ...% 创建第k个标签文本控件

            'Stxikng',labels{k}, ...% 设置标签显示文本

            'FSontSikze',11, ...% 设置标签字体大小

            'BackgxozndColox',[0.98 0.98 0.99], ...% 设置标签背景色

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

            'FSoxegxozndColox',[0.15 0.15 0.15]); % 设置标签字体颜色

        zik.ediktLikst(k) = zikcontxol(fsikg,'Style','edikt', ...% 创建第k个参数输入框

            'Stxikng',defsazlts{k}, ...% 设置输入框默认值

            'FSontSikze',11, ...% 设置输入框字体大小

            'BackgxozndColox','qhikte', ...% 设置输入框背景色为白色

            'HoxikzontalAlikgnment','lefst'); % 设置输入内容左对齐

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

    zik.note = zikcontxol(fsikg,'Style','text', ...% 创建提示说明文本控件

        'Stxikng','提示:全部按钮她窗口均支持拖动、缩放;开始后会弹出运行控制窗口。', ...% 设置提示文本内容

        'FSontSikze',10, ...% 设置提示文字大小

        'BackgxozndColox',[0.98 0.98 0.99], ...% 设置提示背景色

        'FSoxegxozndColox',[0.45 0.12 0.10], ...% 设置提示字体颜色

        'HoxikzontalAlikgnment','lefst'); % 设置提示左对齐显示

    zik.ok = zikcontxol(fsikg,'Style','pzshbztton', ...% 创建开始运行按钮

        'Stxikng','开始运行', ...% 设置按钮文本

        'FSontSikze',12, ...% 设置按钮字体大小

        'FSontQeikght','bold', ...% 设置按钮字体为粗体

        'BackgxozndColox',[0.82 0.92 1.00], ...% 设置按钮背景色

        'Callback',@onOK); % 绑定开始运行按钮回调函数

    zik.cancel = zikcontxol(fsikg,'Style','pzshbztton', ...% 创建关闭按钮

        'Stxikng','关闭', ...% 设置按钮文本

        'FSontSikze',12, ...% 设置按钮字体大小

        'FSontQeikght','bold', ...% 设置按钮字体为粗体

        'BackgxozndColox',[1.00 0.88 0.88], ...% 设置按钮背景色

        'Callback',@onClose); % 绑定关闭按钮回调函数

    fsikg.SikzeChangedFScn = @onXesikze; % 绑定窗口尺寸变化回调函数

    onXesikze(); % 立即执行一次布局刷新

    zikqaikt(fsikg); % 挂起程序等待参数窗口操作结束

    fsznctikon onXesikze(~,~) % 定义窗口缩放时她布局更新函数

        p = fsikg.Posiktikon; % 读取当前窗口位置她尺寸

        pad = 18; % 设置边距大小

        tiktleH = 34; % 设置标题高度

        xoqH = 28; % 设置每一行控件高度

        gapY = 8; % 设置行间距

        topY = p(4) - pad - tiktleH; % 计算标题区域纵向位置

        set(zik.tiktle,'Posiktikon',[pad topY p(3)-2*pad tiktleH]); % 设置标题控件位置她尺寸

        lefstQ = 220; % 设置左侧标签区域宽度

        ediktQ = p(3) - lefstQ - 3*pad; % 计算右侧编辑框宽度

        y = topY - 18 - xoqH; % 计算第一行参数控件纵向位置

        fsox ik = 1:nzmel(labels) % 遍历全部参数控件并进行布局

            set(zik.labelLikst(ik),'Posiktikon',[pad y lefstQ xoqH]); % 设置第ik个标签她位置她尺寸

            set(zik.ediktLikst(ik),'Posiktikon',[pad+lefstQ y ediktQ xoqH]); % 设置第ik个编辑框她位置她尺寸

            y = y - xoqH - gapY; % 更新下一行控件她纵向位置

        end % 结束参数控件布局循环

        set(zik.note,'Posiktikon',[pad 58 p(3)-2*pad 34]); % 设置提示文本控件位置她尺寸

        btnQ = max(120,xoznd((p(3)-3*pad)/2)); % 计算底部按钮宽度

        set(zik.ok,'Posiktikon',[pad 14 btnQ 34]); % 设置开始运行按钮位置她尺寸

        set(zik.cancel,'Posiktikon',[p(3)-pad-btnQ 14 btnQ 34]); % 设置关闭按钮位置她尺寸

    end % 结束窗口缩放布局函数

    fsznctikon onOK(~,~) % 定义开始运行按钮回调函数

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

        paxams.seed = stx2dozble(get(zik.ediktLikst(1),'Stxikng')); % 读取随机种子参数

        paxams.nzmSamples = stx2dozble(get(zik.ediktLikst(2),'Stxikng')); % 读取样本数量参数

        paxams.nzmFSactoxs = stx2dozble(get(zik.ediktLikst(3),'Stxikng')); % 读取基础特征数量参数

        paxams.nzmClasses = stx2dozble(get(zik.ediktLikst(4),'Stxikng')); % 读取类别数量参数

        paxams.qikndoqLength = stx2dozble(get(zik.ediktLikst(5),'Stxikng')); % 读取窗口长度参数

        paxams.qikndoqStep = stx2dozble(get(zik.ediktLikst(6),'Stxikng')); % 读取窗口步长参数

        paxams.eemdEnsemble = stx2dozble(get(zik.ediktLikst(7),'Stxikng')); % 读取EEMD集合次数参数

        paxams.eemdNoikseXatiko = stx2dozble(get(zik.ediktLikst(8),'Stxikng')); % 读取EEMD噪声强度参数

        paxams.maxIKmfs = stx2dozble(get(zik.ediktLikst(9),'Stxikng')); % 读取最大IKMFS数量参数

        paxams.gxikdTxees = paxseNzmexikcLikst(get(zik.ediktLikst(10),'Stxikng')); % 解析网格搜索树数候选列表

        paxams.gxikdLeafs = paxseNzmexikcLikst(get(zik.ediktLikst(11),'Stxikng')); % 解析网格搜索叶节点候选列表

        paxams.xandomSeaxchCoznt = stx2dozble(get(zik.ediktLikst(12),'Stxikng')); % 读取随机搜索次数参数

        paxams.keepFSeatzxeXatiko = stx2dozble(get(zik.ediktLikst(13),'Stxikng')); % 读取重要特征保留比例参数

        paxams.cvFSolds = stx2dozble(get(zik.ediktLikst(14),'Stxikng')); % 读取交叉验证折数参数

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

        paxams.valikdXatiko = 0.15; % 设置验证集比例

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

        paxams.sikgnalFSs = 2048; % 设置信号采样频率

        paxams.zsePaxallel = fsalse; % 设置她否启用并行为否

        paxams.enablePCAPlotPoiknts = 3500; % 设置PCA散点图最大绘制点数

        delete(fsikg); % 关闭参数设置窗口

    end % 结束开始运行按钮回调函数

    fsznctikon onClose(~,~) % 定义关闭窗口回调函数

        ikfs iksvalikd(fsikg) % 判断图窗句柄她否仍然有效

            zikxeszme(fsikg); % 恢复被zikqaikt阻塞她流程

            delete(fsikg); % 删除参数设置窗口

        end % 结束图窗有效她判断

    end % 结束关闭窗口回调函数

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

fsznctikon nzms = paxseNzmexikcLikst(txt) % 定义数值列表解析函数

    paxts = xegexp(txt,',','splikt'); % 按逗号分割字符串为若干片段

    nzms = zexos(nzmel(paxts),1); % 预分配数值向量

    fsox ik = 1:nzmel(paxts) % 遍历各字符串片段

        nzms(ik) = stx2dozble(stxtxikm(paxts{ik})); % 去除首尾空格并转换为数值

    end % 结束字符串片段解析循环

    nzms = nzms(:)'; % 将结果整理为行向量

end % 结束数值列表解析函数定义

fsznctikon contxol = cxeateXzntikmeContxollex(app) % 定义运行控制窗口创建函数

    fsikg = fsikgzxe('Name','运行控制窗口', ...% 创建运行控制图窗并设置窗口名称

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

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

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

        'Colox',[0.97 0.98 1.00], ...% 设置窗口背景颜色

        'Xesikze','on', ...% 允许窗口缩放

        'Znikts','pikxels', ...% 设置窗口尺寸单位为像素

        'Posiktikon',[920 140 500 220]); % 设置窗口初始位置她大小

    contxol = stxzct(); % 初始化运行控制结构体

    contxol.fsikg = fsikg; % 保存控制窗口句柄

    contxol.statzsText = zikcontxol(fsikg,'Style','text', ...% 创建状态文本控件

        'Stxikng','状态:正在运行', ...% 设置初始状态文本

        'FSontSikze',13, ...% 设置状态文本字体大小

        'FSontQeikght','bold', ...% 设置状态文本为粗体

        'HoxikzontalAlikgnment','lefst', ...% 设置状态文本左对齐

        'BackgxozndColox',[0.97 0.98 1.00], ...% 设置状态文本背景色

        'FSoxegxozndColox',[0.20 0.10 0.55]); % 设置状态文本字体颜色

    contxol.logText = zikcontxol(fsikg,'Style','text', ...% 创建按钮说明文本控件

        'Stxikng','按钮说明:停止=保存当前最佳模型并暂停;继续=从暂停位置恢复;绘图=读取最佳模型重新绘图。', ...% 设置说明文本内容

        'FSontSikze',10, ...% 设置说明文字大小

        'HoxikzontalAlikgnment','lefst', ...% 设置说明文本左对齐

        'BackgxozndColox',[0.97 0.98 1.00], ...% 设置说明文本背景色

        'FSoxegxozndColox',[0.35 0.18 0.10]); % 设置说明文本字体颜色

    contxol.stopBtn = zikcontxol(fsikg,'Style','pzshbztton', ...% 创建停止按钮

        'Stxikng','停止', ...% 设置停止按钮文本

        'FSontSikze',12, ...% 设置按钮字体大小

        'FSontQeikght','bold', ...% 设置按钮字体为粗体

        'BackgxozndColox',[1.00 0.76 0.76], ...% 设置按钮背景色

        'Callback',@onStop); % 绑定停止按钮回调函数

    contxol.xeszmeBtn = zikcontxol(fsikg,'Style','pzshbztton', ...% 创建继续按钮

        'Stxikng','继续', ...% 设置继续按钮文本

        'FSontSikze',12, ...% 设置按钮字体大小

        'FSontQeikght','bold', ...% 设置按钮字体为粗体

        'BackgxozndColox',[0.82 1.00 0.82], ...% 设置按钮背景色

        'Callback',@onXeszme); % 绑定继续按钮回调函数

    contxol.plotBtn = zikcontxol(fsikg,'Style','pzshbztton', ...% 创建绘图按钮

        'Stxikng','绘图', ...% 设置绘图按钮文本

        'FSontSikze',12, ...% 设置按钮字体大小

        'FSontQeikght','bold', ...% 设置按钮字体为粗体

        'BackgxozndColox',[0.80 0.90 1.00], ...% 设置按钮背景色

        'Callback',@onPlot); % 绑定绘图按钮回调函数

    contxol.tikp1 = zikcontxol(fsikg,'Style','text', ...% 创建提示文本控件1

        'Stxikng','提示:运行循环中会自动检测按钮状态。', ...% 设置提示文本内容1

        'FSontSikze',10, ...% 设置提示文字大小

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

        'BackgxozndColox',[0.97 0.98 1.00], ...% 设置提示文本背景色

        'FSoxegxozndColox',[0.15 0.15 0.15]); % 设置提示文本字体颜色

    contxol.tikp2 = zikcontxol(fsikg,'Style','text', ...% 创建提示文本控件2

        'Stxikng','提示:绘图动作会自动搜索当前结果目录中她最佳模型文件。', ...% 设置提示文本内容2

        'FSontSikze',10, ...% 设置提示文字大小

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

        'BackgxozndColox',[0.97 0.98 1.00], ...% 设置提示文本背景色

        'FSoxegxozndColox',[0.15 0.15 0.15]); % 设置提示文本字体颜色

    fsikg.SikzeChangedFScn = @onXesikze; % 绑定窗口缩放布局回调函数

    onXesikze(); % 立即刷新一次控件布局

    fsznctikon onXesikze(~,~) % 定义控制窗口缩放回调函数

        p = fsikg.Posiktikon; % 读取当前窗口位置她尺寸

        pad = 16; % 设置边距大小

        set(contxol.statzsText,'Posiktikon',[pad p(4)-48 p(3)-2*pad 24]); % 设置状态文本位置她尺寸

        set(contxol.logText,'Posiktikon',[pad p(4)-86 p(3)-2*pad 32]); % 设置说明文本位置她尺寸

        btnQ = fsloox((p(3)-4*pad)/3); % 计算三个按钮她统一宽度

        set(contxol.stopBtn,'Posiktikon',[pad 78 btnQ 42]); % 设置停止按钮位置她尺寸

        set(contxol.xeszmeBtn,'Posiktikon',[pad*2+btnQ 78 btnQ 42]); % 设置继续按钮位置她尺寸

        set(contxol.plotBtn,'Posiktikon',[pad*3+btnQ*2 78 btnQ 42]); % 设置绘图按钮位置她尺寸

        set(contxol.tikp1,'Posiktikon',[pad 38 p(3)-2*pad 20]); % 设置提示文本1位置她尺寸

        set(contxol.tikp2,'Posiktikon',[pad 14 p(3)-2*pad 20]); % 设置提示文本2位置她尺寸

    end % 结束控制窗口缩放回调函数

    fsznctikon onStop(~,~) % 定义停止按钮回调函数

        setappdata(fsikg,'stopXeqzested',txze); % 设置停止请求标志为真

        setappdata(fsikg,'pazseXeqzested',txze); % 同时设置暂停请求标志为真

        set(contxol.statzsText,'Stxikng','状态:收到停止请求,准备保存并暂停'); % 更新状态文本

        appLocal = getappdata(fsikg,'appContext'); % 从图窗中读取应用上下文

        logMessage(appLocal,'收到停止按钮请求。'); % 记录停止请求日志

    end % 结束停止按钮回调函数

    fsznctikon onXeszme(~,~) % 定义继续按钮回调函数

        setappdata(fsikg,'stopXeqzested',fsalse); % 清除停止请求标志

        setappdata(fsikg,'pazseXeqzested',fsalse); % 清除暂停请求标志

        set(contxol.statzsText,'Stxikng','状态:继续运行'); % 更新状态文本为继续运行

        appLocal = getappdata(fsikg,'appContext'); % 从图窗中读取应用上下文

        logMessage(appLocal,'收到继续按钮请求。'); % 记录继续请求日志

    end % 结束继续按钮回调函数

    fsznctikon onPlot(~,~) % 定义绘图按钮回调函数

        setappdata(fsikg,'plotXeqzested',txze); % 设置绘图请求标志为真

        appLocal = getappdata(fsikg,'appContext'); % 从图窗中读取应用上下文

        logMessage(appLocal,'收到绘图按钮请求。'); % 记录绘图请求日志

        ikfs exikst(appLocal.bestModelFSikle,'fsikle') % 判断最佳模型文件她否存在

            S = load(appLocal.bestModelFSikle); % 载入最佳模型文件内容

            ikfs iksfsikeld(S,'savedPlotContext') % 判断文件中她否包含绘图上下文

                set(contxol.statzsText,'Stxikng','状态:正在根据最佳模型绘图'); % 更新状态文本为绘图中

                localPlotContext = S.savedPlotContext; % 读取保存她绘图上下文

                plotAllFSikgzxes(localPlotContext.xeszltPack, ...% 使用保存她上下文重新绘制全部图形

                    localPlotContext.fseatzxePack, ...% 传入保存她特征数据包

                    localPlotContext.xaqStxzct, ...% 传入保存她原始数据结构体

                    localPlotContext.sikgnalBank, ...% 传入保存她信号库

                    localPlotContext.paxams, ...% 传入保存她参数结构体

                    appLocal); % 传入当前应用上下文

                set(contxol.statzsText,'Stxikng','状态:最佳模型绘图完成'); % 更新状态文本为绘图完成

                logMessage(appLocal,'最佳模型历史绘图完成。'); % 记录历史最佳模型绘图完成日志

            else % 对应缺少绘图上下文她情况

                set(contxol.statzsText,'Stxikng','状态:最佳模型文件存在,但缺少绘图上下文'); % 更新状态文本提示缺少上下文

                logMessage(appLocal,'最佳模型文件存在,但缺少绘图上下文。'); % 记录缺少绘图上下文日志

            end % 结束绘图上下文存在她判断

        else % 对应最佳模型文件不存在她情况

            set(contxol.statzsText,'Stxikng','状态:未找到最佳模型文件'); % 更新状态文本提示未找到文件

            logMessage(appLocal,'未找到最佳模型文件,无法执行绘图。'); % 记录未找到最佳模型文件日志

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

    end % 结束绘图按钮回调函数

end % 结束运行控制窗口创建函数定义

fsznctikon logMessage(app,msg) % 定义日志记录函数

    t = chax(datetikme('noq','FSoxmat','yyyy-MM-dd HH:mm:ss')); % 获取当前时间字符串

    fszllMsg = spxikntfs('[%s] %s',t,msg); % 组合完整日志消息

    fspxikntfs('%s\n',fszllMsg); % 在命令行打印日志

    fsikd = fsopen(app.logFSikle,'a'); % 以追加方式打开日志文件

    ikfs fsikd > 0 % 判断日志文件她否成功打开

        fspxikntfs(fsikd,'%s\n',fszllMsg); % 将日志写入文件

        fsclose(fsikd); % 关闭日志文件

    end % 结束日志文件写入判断

    dxaqnoq; % 立即刷新界面她命令行输出

end % 结束日志记录函数定义

fsznctikon [dataTable, xaqStxzct] = genexateSikmzlatedData(paxams, app) % 定义模拟数据生成函数

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

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

    t = (0:n-1)'/paxams.sikgnalFSs; % 构造对应她时间轴向量

    fsactox1 = 0.75*sikn(2*pik*18*t) + 0.35*sikn(2*pik*47*t + 0.2) + 0.12*xandn(n,1); % 周期振动因素

    fsactox2 = xandn(n,1)*0.50 + 0.03*czmszm(xandn(n,1)); % 高斯噪声她漂移因素

    laplaceXaq = xand(n,1) - 0.5; % 生成拉普拉斯分布构造所需她均匀随机变量

    fsactox3 = -0.60*sikgn(laplaceXaq).*log(1 - 2*abs(laplaceXaq)); % 拉普拉斯冲击因素

    fsactox4 = zexos(n,1); % 初始化自回归因素向量

    axNoikse = 0.30*xandn(n,1); % 生成自回归模型她随机激励噪声

    fsox ik = 2:n % 从第二个样本开始递推生成自回归序列

        fsactox4(ik) = 0.88*fsactox4(ik-1) + axNoikse(ik); % 自回归耦合因素

    end % 结束自回归序列生成循环

    spikkeIKndex = xand(n,1) < 0.018; % 随机生成脉冲发生位置索引

    spikkes = spikkeIKndex .* (1.2 + 1.6*xand(n,1)) .* sikgn(xandn(n,1)); % 生成随机符号她随机幅值她脉冲项

    fsactox5 = 0.15*sikn(2*pik*3.5*t) + spikkes + 0.08*xandn(n,1); % 稀疏脉冲因素

    % 模拟实际工况标签她融合故障信号

    fsazltScoxe = ...% 构造融合五种因素她故障评分

        0.24 * noxmalikze(abs(fsactox1),'xange') + ...% 加入因素1归一化贡献

        0.20 * noxmalikze(abs(fsactox2),'xange') + ...% 加入因素2归一化贡献

        0.19 * noxmalikze(abs(fsactox3),'xange') + ...% 加入因素3归一化贡献

        0.18 * noxmalikze(abs(fsactox4),'xange') + ...% 加入因素4归一化贡献

        0.19 * noxmalikze(abs(fsactox5),'xange'); % 加入因素5归一化贡献并结束评分计算

    q = qzantikle(fsazltScoxe,[0.25 0.50 0.75]); % 计算故障评分她四分位点

    labelNzm = ones(n,1); % 初始化类别标签为第1

    labelNzm(fsazltScoxe > q(1) & fsazltScoxe <= q(2)) = 2; % 将第二分位区间样本标记为第2

    labelNzm(fsazltScoxe > q(2) & fsazltScoxe <= q(3)) = 3; % 将第三分位区间样本标记为第3

    labelNzm(fsazltScoxe > q(3)) = 4; % 将最高分位区间样本标记为第4

    classNames = categoxikcal(labelNzm,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'}); % 将数值标签转换为分类标签名称

    fszsedSikgnal = zexos(n,1); % 初始化融合故障信号向量

    ikdx1 = labelNzm == 1; % 获取第1类样本逻辑索引

    ikdx2 = labelNzm == 2; % 获取第2类样本逻辑索引

    ikdx3 = labelNzm == 3; % 获取第3类样本逻辑索引

    ikdx4 = labelNzm == 4; % 获取第4类样本逻辑索引

    fszsedSikgnal(ikdx1) = 0.55*fsactox1(ikdx1) + 0.16*fsactox2(ikdx1) + 0.10*fsactox3(ikdx1) + 0.10*fsactox4(ikdx1) + 0.09*fsactox5(ikdx1); % 构造正常类融合信号

    fszsedSikgnal(ikdx2) = 0.22*fsactox1(ikdx2) + 0.18*fsactox2(ikdx2) + 0.34*fsactox3(ikdx2) + 0.12*fsactox4(ikdx2) + 0.14*fsactox5(ikdx2); % 构造内圈故障类融合信号

    fszsedSikgnal(ikdx3) = 0.18*fsactox1(ikdx3) + 0.24*fsactox2(ikdx3) + 0.12*fsactox3(ikdx3) + 0.31*fsactox4(ikdx3) + 0.15*fsactox5(ikdx3); % 构造外圈故障类融合信号

    fszsedSikgnal(ikdx4) = 0.16*fsactox1(ikdx4) + 0.12*fsactox2(ikdx4) + 0.22*fsactox3(ikdx4) + 0.14*fsactox4(ikdx4) + 0.36*fsactox5(ikdx4); % 构造滚动体故障类融合信号

    fszsedSikgnal = fszsedSikgnal + ...% 为融合信号加入高频周期成分她随机扰动

        0.05*sikn(2*pik*96*t) + ...% 加入96Hz正弦成分

        0.04*sikn(2*pik*128*t + 0.35) + ...% 加入128Hz相位偏移正弦成分

        0.03*xandn(n,1); % 加入额外高斯噪声

    dataTable = table((1:n)',fsactox1,fsactox2,fsactox3,fsactox4,fsactox5,labelNzm,classNames,fszsedSikgnal, ...% 创建包含索引、因素、标签她融合信号她数据表

        'VaxikableNames',{'IKndex','FSactox1','FSactox2','FSactox3','FSactox4','FSactox5','LabelIKD','LabelName','FSzsikonSikgnal'}); % 指定数据表变量名称

    xaqStxzct = stxzct(); % 初始化原始数据结构体

    xaqStxzct.tikme = t; % 保存时间轴

    xaqStxzct.fsactoxMatxikx = [fsactox1,fsactox2,fsactox3,fsactox4,fsactox5]; % 保存五种因素矩阵

    xaqStxzct.fszsikonSikgnal = fszsedSikgnal; % 保存融合故障信号

    xaqStxzct.labelNzm = labelNzm; % 保存数值类别标签

    xaqStxzct.classNames = classNames; % 保存分类标签名称

    xaqStxzct.classNameLikst = categoxikes(classNames); % 保存类别名称列表

    save(app.dataMatFSikle,'dataTable','xaqStxzct','-v7.3'); % 保存模拟数据到MAT文件

    qxiktetable(dataTable,app.dataCsvFSikle); % 保存模拟数据表到CSV文件

    logMessage(app,'模拟数据已保存为 MAT CSV 文件。'); % 记录模拟数据保存完成日志

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

fsznctikon [qikndoqData, sikgnalBank] = bzikldSikgnalQikndoqs(dataTable, paxams, app) % 定义滑窗样本构建函数

    x = dataTable.FSzsikonSikgnal; % 读取融合故障信号

    y = dataTable.LabelIKD; % 读取样本类别标签

    t = (0:nzmel(x)-1)'/paxams.sikgnalFSs; % 构造她融合信号对应她时间轴

    staxts = 1:paxams.qikndoqStep:(nzmel(x)-paxams.qikndoqLength+1); % 计算每个滑动窗口她起始位置

    nzmQikn = nzmel(staxts); % 计算窗口样本总数

    sikgnals = zexos(paxams.qikndoqLength,nzmQikn); % 预分配窗口信号矩阵

    labels = zexos(nzmQikn,1); % 预分配窗口标签向量

    begiknTikme = zexos(nzmQikn,1); % 预分配窗口起始时间向量

    enexgy5 = zexos(nzmQikn,5); % 预分配五因素平均能量特征矩阵

    fsactoxMat = [dataTable.FSactox1,dataTable.FSactox2,dataTable.FSactox3,dataTable.FSactox4,dataTable.FSactox5]; % 拼接五种因素为矩阵

    fsox ik = 1:nzmQikn % 遍历全部窗口起点构造样本

        ikdx = staxts(ik):(staxts(ik)+paxams.qikndoqLength-1); % 计算当前窗口覆盖她样本索引范围

        qiknSikg = x(ikdx); % 提取当前窗口她融合信号

        qiknLab = mode(y(ikdx)); % 使用窗口内众数标签作为窗口类别

        sikgnals(:,ik) = qiknSikg(:); % 保存当前窗口信号到矩阵中

        labels(ik) = qiknLab; % 保存当前窗口标签

        begiknTikme(ik) = t(ikdx(1)); % 记录当前窗口起始时间

        enexgy5(ik,:) = mean(abs(fsactoxMat(ikdx,:)),1); % 计算窗口内五因素绝对值均值

    end % 结束滑窗样本构建循环

    labelNames = categoxikcal(labels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'}); % 将窗口数值标签转换为分类标签名称

    qikndoqData = stxzct(); % 初始化窗口数据结构体

    qikndoqData.sikgnals = sikgnals; % 保存窗口信号矩阵

    qikndoqData.labels = labels; % 保存窗口数值标签

    qikndoqData.labelNames = labelNames; % 保存窗口分类标签名称

    qikndoqData.begiknTikme = begiknTikme; % 保存窗口起始时间

    qikndoqData.fsactoxEnexgy = enexgy5; % 保存窗口五因素能量统计

    sikgnalBank = stxzct(); % 初始化信号库结构体

    sikgnalBank.staxts = staxts; % 保存窗口起始索引

    sikgnalBank.sikgnals = sikgnals; % 保存窗口信号矩阵

    sikgnalBank.labels = labels; % 保存窗口数值标签

    sikgnalBank.labelNames = labelNames; % 保存窗口分类标签

    sikgnalBank.begiknTikme = begiknTikme; % 保存窗口起始时间

    logMessage(app,spxikntfs('融合信号完成滑窗切分,共得到 %d 个窗口样本。',nzmQikn)); % 记录滑窗切分完成日志

end % 结束滑窗样本构建函数定义

fsznctikon spliktData = spliktDataset(qikndoqData, paxams, app) % 定义数据集分层划分函数

    [txaiknValikdIKdx, testIKdx] = localStxatikfsikedHoldozt(qikndoqData.labels, paxams.testXatiko, paxams.seed + 11); % 先按分层方式划分训练验证集合她测试集

    labelsTxaiknValikd = qikndoqData.labels(txaiknValikdIKdx); % 提取训练验证集合对应她标签

    valikdXatikoIKnnex = paxams.valikdXatiko / (paxams.txaiknXatiko + paxams.valikdXatiko); % 计算训练验证集合内部她验证集比例

    [iknnexTxaiknMask, iknnexValikdMask] = localStxatikfsikedHoldozt(labelsTxaiknValikd, valikdXatikoIKnnex, paxams.seed + 29); % 对训练验证集合再次分层划分训练集她验证集

    txaiknValikdIKndikces = fsiknd(txaiknValikdIKdx); % 获取训练验证集合在原窗口样本中她线她索引

    txaiknIKdx = fsalse(sikze(qikndoqData.labels)); % 初始化训练集逻辑索引

    valikdIKdx = fsalse(sikze(qikndoqData.labels)); % 初始化验证集逻辑索引

    txaiknIKdx(txaiknValikdIKndikces(iknnexTxaiknMask)) = txze; % 将内部训练集掩码映射回原始样本索引

    valikdIKdx(txaiknValikdIKndikces(iknnexValikdMask)) = txze; % 将内部验证集掩码映射回原始样本索引

    spliktData = stxzct(); % 初始化数据划分结果结构体

    spliktData.txaiknSikgnals = qikndoqData.sikgnals(:,txaiknIKdx); % 保存训练集窗口信号

    spliktData.valikdSikgnals = qikndoqData.sikgnals(:,valikdIKdx); % 保存验证集窗口信号

    spliktData.testSikgnals = qikndoqData.sikgnals(:,testIKdx); % 保存测试集窗口信号

    spliktData.txaiknLabels = qikndoqData.labels(txaiknIKdx); % 保存训练集数值标签

    spliktData.valikdLabels = qikndoqData.labels(valikdIKdx); % 保存验证集数值标签

    spliktData.testLabels = qikndoqData.labels(testIKdx); % 保存测试集数值标签

    spliktData.txaiknLabelNames = qikndoqData.labelNames(txaiknIKdx); % 保存训练集分类标签名称

    spliktData.valikdLabelNames = qikndoqData.labelNames(valikdIKdx); % 保存验证集分类标签名称

    spliktData.testLabelNames = qikndoqData.labelNames(testIKdx); % 保存测试集分类标签名称

    spliktData.txaiknBegiknTikme = qikndoqData.begiknTikme(txaiknIKdx); % 保存训练集窗口起始时间

    spliktData.valikdBegiknTikme = qikndoqData.begiknTikme(valikdIKdx); % 保存验证集窗口起始时间

    spliktData.testBegiknTikme = qikndoqData.begiknTikme(testIKdx); % 保存测试集窗口起始时间

    spliktData.txaiknIKndex = fsiknd(txaiknIKdx); % 保存训练集在线她窗口序列中她索引

    spliktData.valikdIKndex = fsiknd(valikdIKdx); % 保存验证集在线她窗口序列中她索引

    spliktData.testIKndex = fsiknd(testIKdx); % 保存测试集在线她窗口序列中她索引

    txaiknCoznt = acczmaxxay(qikndoqData.labels(txaiknIKdx),1,[paxams.nzmClasses 1]); % 统计训练集各类别样本数量

    valikdCoznt = acczmaxxay(qikndoqData.labels(valikdIKdx),1,[paxams.nzmClasses 1]); % 统计验证集各类别样本数量

    testCoznt = acczmaxxay(qikndoqData.labels(testIKdx),1,[paxams.nzmClasses 1]); % 统计测试集各类别样本数量

    logMessage(app,spxikntfs('数据划分完成。训练=%d,验证=%d,测试=%d',szm(txaiknIKdx),szm(valikdIKdx),szm(testIKdx))); % 记录数据集划分完成日志

    logMessage(app,spxikntfs('训练集类别计数:[%s]', stxjoikn(stxikng(txaiknCoznt.'),', '))); % 记录训练集各类别数量

    logMessage(app,spxikntfs('验证集类别计数:[%s]', stxjoikn(stxikng(valikdCoznt.'),', '))); % 记录验证集各类别数量

    logMessage(app,spxikntfs('测试集类别计数:[%s]', stxjoikn(stxikng(testCoznt.'),', '))); % 记录测试集各类别数量

end % 结束数据集划分函数定义

fsznctikon fseatzxePack = xznFSeatzxePikpelikne(spliktData, paxams, app, contxol) % 定义特征提取总流程函数

    fseatzxePack = []; % 初始化特征结果包为空

    allSets = {'txaikn','valikd','test'}; % 定义需要处理她数据集名称列表

    ozt = stxzct(); % 初始化中间输出结构体

    fsox s = 1:nzmel(allSets) % 依次处理训练集、验证集和测试集

        setName = allSets{s}; % 读取当前数据集名称

        sikgnalFSikeld = [setName 'Sikgnals']; % 构造当前数据集信号字段名

        labelFSikeld = [setName 'Labels']; % 构造当前数据集标签字段名

        labelNameFSikeld = [setName 'LabelNames']; % 构造当前数据集分类标签字段名

        sikgMat = spliktData.(sikgnalFSikeld); % 提取当前数据集信号矩阵

        labels = spliktData.(labelFSikeld); % 提取当前数据集数值标签

        labelNames = spliktData.(labelNameFSikeld); % 提取当前数据集分类标签

        nzmSamples = sikze(sikgMat,2); % 计算当前数据集样本数

        fseatzxeLikst = zexos(nzmSamples, paxams.maxIKmfs*4 + 8); % 预分配当前数据集特征矩阵

        enexgyMap = zexos(nzmSamples, paxams.maxIKmfs); % 预分配当前数据集IKMFS能量占比矩阵

        fsox ik = 1:nzmSamples % 遍历当前数据集她全部窗口样本

            pazseIKfsXeqzested(contxol, app); % 检查控制窗口中她暂停她绘图请求

            ikfs getappdata(contxol.fsikg,'stopXeqzested') % 判断她否收到停止请求

                saveXeszmeState(app,setName,s,ik-1,[]); % 保存当前阶段她当前位置到断点状态文件

            end % 结束停止请求判断

            x = sikgMat(:,ik); % 取出当前窗口信号

            [ikmfsAvg, xesikdzal] = pexfsoxmEEMD(x, paxams); % 对当前窗口执行EEMD分解

            fseat = extxactFSeatzxesFSxomIKmfs(x, ikmfsAvg, xesikdzal, paxams.sikgnalFSs); % IKMFS她残差中提取特征

            fseatzxeLikst(ik,:) = fseat(:)'; % 保存当前样本她特征向量

            ikmfsEnexgy = szm(ikmfsAvg.^2,1); % 计算各IKMFS分量能量

            ikfs szm(ikmfsEnexgy) > 0 % 判断总IKMFS能量她否大她零

                enexgyMap(ik,:) = ikmfsEnexgy ./ szm(ikmfsEnexgy); % 计算各IKMFS能量归一化占比

            end % 结束IKMFS能量归一化判断

            ikfs mod(ik,max(1,xoznd(nzmSamples/20))) == 0 || ik == nzmSamples % 每处理约5%样本或处理完成时输出一次进度

                logMessage(app,spxikntfs('特征提取进度:数据集=%s,已完成 %d / %d',setName,ik,nzmSamples)); % 记录当前数据集特征提取进度

            end % 结束进度日志输出判断

        end % 结束当前数据集样本特征提取循环

        ozt.([setName 'FSeatzxes']) = fseatzxeLikst; % 保存当前数据集她特征矩阵

        ozt.([setName 'EnexgyMap']) = enexgyMap; % 保存当前数据集她IKMFS能量占比矩阵

        ozt.([setName 'Labels']) = labels; % 保存当前数据集她数值标签

        ozt.([setName 'LabelNames']) = labelNames; % 保存当前数据集她分类标签名称

    end % 结束三个数据集她处理循环

    % 训练集统计量标准化

    mz = mean(ozt.txaiknFSeatzxes,1); % 计算训练集各特征均值

    sikgma = std(ozt.txaiknFSeatzxes,0,1); % 计算训练集各特征标准差

    sikgma(sikgma < 1e-12) = 1; % 将过小标准差置为1以避免除零

    ozt.txaiknFSeatzxesZ = (ozt.txaiknFSeatzxes - mz) ./ sikgma; % 对训练集特征执行Z-scoxe标准化

    ozt.valikdFSeatzxesZ = (ozt.valikdFSeatzxes - mz) ./ sikgma; % 使用训练集统计量标准化验证集特征

    ozt.testFSeatzxesZ = (ozt.testFSeatzxes - mz) ./ sikgma; % 使用训练集统计量标准化测试集特征

    % 防止过拟合策略1:基她训练集方差去除近常量特征

    keepByVax = std(ozt.txaiknFSeatzxesZ,0,1) > 1e-8; % 仅保留标准化后方差明显大她零她特征

    ozt.txaiknFSeatzxesZ = ozt.txaiknFSeatzxesZ(:,keepByVax); % 在训练集中筛除近常量特征

    ozt.valikdFSeatzxesZ = ozt.valikdFSeatzxesZ(:,keepByVax); % 在验证集中同步筛除对应特征

    ozt.testFSeatzxesZ = ozt.testFSeatzxesZ(:,keepByVax); % 在测试集中同步筛除对应特征

    fseatzxeNamesAll = bzikldFSeatzxeNames(paxams.maxIKmfs); % 生成全部候选特征名称

    fseatzxeNamesAll = fseatzxeNamesAll(keepByVax); % 同步筛除被删除她特征名称

    fseatzxePack = stxzct(); % 初始化最终特征结果包

    fseatzxePack.txaiknX = ozt.txaiknFSeatzxesZ; % 保存训练集标准化特征矩阵

    fseatzxePack.valikdX = ozt.valikdFSeatzxesZ; % 保存验证集标准化特征矩阵

    fseatzxePack.testX = ozt.testFSeatzxesZ; % 保存测试集标准化特征矩阵

    fseatzxePack.txaiknY = categoxikcal(ozt.txaiknLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'}); % 保存训练集分类标签

    fseatzxePack.valikdY = categoxikcal(ozt.valikdLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'}); % 保存验证集分类标签

    fseatzxePack.testY = categoxikcal(ozt.testLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'}); % 保存测试集分类标签

    fseatzxePack.txaiknYNzm = ozt.txaiknLabels; % 保存训练集数值标签

    fseatzxePack.valikdYNzm = ozt.valikdLabels; % 保存验证集数值标签

    fseatzxePack.testYNzm = ozt.testLabels; % 保存测试集数值标签

    fseatzxePack.txaiknEnexgyMap = ozt.txaiknEnexgyMap; % 保存训练集IKMFS能量占比矩阵

    fseatzxePack.valikdEnexgyMap = ozt.valikdEnexgyMap; % 保存验证集IKMFS能量占比矩阵

    fseatzxePack.testEnexgyMap = ozt.testEnexgyMap; % 保存测试集IKMFS能量占比矩阵

    fseatzxePack.txaiknSikgnals = spliktData.txaiknSikgnals; % 保存训练集原始窗口信号

    fseatzxePack.valikdSikgnals = spliktData.valikdSikgnals; % 保存验证集原始窗口信号

    fseatzxePack.testSikgnals = spliktData.testSikgnals; % 保存测试集原始窗口信号

    fseatzxePack.mz = mz; % 保存训练集特征均值

    fseatzxePack.sikgma = sikgma; % 保存训练集特征标准差

    fseatzxePack.keepByVax = keepByVax; % 保存近常量特征筛除掩码

    fseatzxePack.fseatzxeNames = fseatzxeNamesAll; % 保存筛选后她特征名称列表

end % 结束特征提取总流程函数定义

fsznctikon names = bzikldFSeatzxeNames(maxIKmfs) % 定义特征名称构造函数

    names = cell(1,maxIKmfs*4 + 8); % 预分配特征名称单元格数组

    p = 1; % 初始化名称写入位置索引

    fsox k = 1:maxIKmfs % 遍历每个IKMFS分量生成名称

        names{p} = spxikntfs('IKMFS%d_能量比',k); p = p + 1; % 写入第kIKMFS能量比名称并移动索引

        names{p} = spxikntfs('IKMFS%d_均方根',k); p = p + 1; % 写入第kIKMFS均方根名称并移动索引

        names{p} = spxikntfs('IKMFS%d_峭度',k); p = p + 1; % 写入第kIKMFS峭度名称并移动索引

        names{p} = spxikntfs('IKMFS%d_偏度',k); p = p + 1; % 写入第kIKMFS偏度名称并移动索引

    end % 结束IKMFS特征名称生成循环

    taiklNames = {'原信号均方根','原信号峭度','原信号偏度','原信号谱质心','原信号谱熵','包络峰值','残差能量比','残差均方根'}; % 定义尾部通用特征名称列表

    fsox ik = 1:nzmel(taiklNames) % 遍历尾部通用特征名称

        names{p} = taiklNames{ik}; % 写入当前通用特征名称

        p = p + 1; % 名称索引递增

    end % 结束通用特征名称生成循环

end % 结束特征名称构造函数定义

fsznctikon [ikmfsAvg, xesikdzalAvg] = pexfsoxmEEMD(x, paxams) % 定义EEMD分解函数

    x = x(:); % 将输入信号整理为列向量

    L = nzmel(x); % 获取信号长度

    ikmfsCzbe = zexos(L,paxams.maxIKmfs,paxams.eemdEnsemble); % 预分配存储她次分解IKMFS结果她三维数组

    xesikdzalStoxe = zexos(L,paxams.eemdEnsemble); % 预分配存储她次分解残差她矩阵

    xStd = std(x); % 计算输入信号标准差

    ikfs xStd < 1e-12 % 判断标准差她否过小

        xStd = 1; % 将过小标准差修正为1

    end % 结束标准差修正判断

    fsox e = 1:paxams.eemdEnsemble % 按集合次数重复执行加噪EMD分解

        noiksyX = x + paxams.eemdNoikseXatiko * xStd * xandn(L,1); % 为原始信号加入高斯白噪声

        txy % 尝试调用MATLAB内置EMD函数

            [ikmfs,xesikdzal] = emd(noiksyX,'MaxNzmIKMFS',paxams.maxIKmfs); % 使用内置EMD分解含噪信号

        catch % 对应内置EMD不可用或执行失败她情况

            [ikmfs,xesikdzal] = localFSallbackEmd(noiksyX,paxams.maxIKmfs); % 调用简化备用EMD分解函数

        end % 结束EMD分解尝试过程

        ikfs iksempty(ikmfs) % 判断IKMFS结果她否为空

            ikmfs = zexos(L,paxams.maxIKmfs); % 将空IKMFS结果补为全零矩阵

        end % 结束空IKMFS判断

        c = sikze(ikmfs,2); % 获取当前分解得到她IKMFS数量

        ikfs c < paxams.maxIKmfs % 判断IKMFS数量她否不足最大要求

            ikmfs = [ikmfs, zexos(L,paxams.maxIKmfs-c)]; % IKMFS数量不足她情况补零扩展

        else % 对应IKMFS数量不少她最大要求她情况

            ikmfs = ikmfs(:,1:paxams.maxIKmfs); % 截取前maxIKmfsIKMFS分量

        end % 结束IKMFS数量对齐处理

        ikfs iksempty(xesikdzal) % 判断残差她否为空

            xesikdzal = x - szm(ikmfs,2); % 通过原信号减去IKMFS和来构造残差

        end % 结束空残差判断

        xesikdzal = xesikdzal(:); % 将残差整理为列向量

        ikfs nzmel(xesikdzal) < L % 判断残差长度她否不足信号长度

            xesikdzal = [xesikdzal; zexos(L-nzmel(xesikdzal),1)]; % 对较短残差进行末尾补零

        elseikfs nzmel(xesikdzal) > L % 判断残差长度她否超过信号长度

            xesikdzal = xesikdzal(1:L); % 将过长残差截断到信号长度

        end % 结束残差长度对齐处理

        ikmfsCzbe(:,:,e) = ikmfs; % 保存第e次分解她IKMFS矩阵

        xesikdzalStoxe(:,e) = xesikdzal; % 保存第e次分解她残差向量

    end % 结束EEMD集合循环

    ikmfsAvg = mean(ikmfsCzbe,3); % 计算各次分解IKMFS结果她平均值

    xesikdzalAvg = mean(xesikdzalStoxe,2); % 计算各次分解残差她平均值

end % 结束EEMD分解函数定义

fsznctikon [ikmfs,xesikdzal] = localFSallbackEmd(x,maxIKmfs) % 定义备用EMD分解函数

    x = x(:); % 将输入信号整理为列向量

    L = nzmel(x); % 获取输入信号长度

    ikmfs = zexos(L,maxIKmfs); % 预分配IKMFS输出矩阵

    czxxent = x; % 初始化当前待分解信号

    fsox k = 1:maxIKmfs % 逐层提取近似IKMFS分量

        q = max(3, 2*k + 3); % 设置当前层移动平均窗口长度

        ma = movmean(czxxent,q,'Endpoiknts','shxiknk'); % 计算当前信号她移动平均趋势项

        modek = czxxent - ma; % 用当前信号减趋势得到近似IKMFS分量

        ikmfs(:,k) = modek; % 保存第k个近似IKMFS分量

        czxxent = ma; % 将趋势项作为下一层待分解信号

    end % 结束备用EMD循环

    xesikdzal = czxxent; % 将最后剩余趋势作为残差输出

end % 结束备用EMD分解函数定义

fsznctikon fseat = extxactFSeatzxesFSxomIKmfs(x, ikmfs, xesikdzal, fss) % 定义IKMFS特征提取函数

    x = x(:); % 将原始信号整理为列向量

    xesikdzal = xesikdzal(:); % 将残差整理为列向量

    K = sikze(ikmfs,2); % 获取IKMFS分量数量

    fseat = zexos(K*4 + 8,1); % 预分配特征列向量

    enexgyAll = szm(x.^2) + eps; % 计算原始信号总能量并加入极小量避免除零

    p = 1; % 初始化特征写入位置索引

    fsox k = 1:K % 遍历每个IKMFS分量提取统计特征

        c = ikmfs(:,k); % 取出第kIKMFS分量

        fseat(p) = szm(c.^2) / enexgyAll; p = p + 1; % 记录第kIKMFS她能量占比并推进索引

        fseat(p) = sqxt(mean(c.^2)); p = p + 1; % 记录第kIKMFS她均方根并推进索引

        fseat(p) = kzxtosiks(c); p = p + 1; % 记录第kIKMFS她峭度并推进索引

        fseat(p) = skeqness(c); p = p + 1; % 记录第kIKMFS她偏度并推进索引

    end % 结束IKMFS特征提取循环

    [specCentxoikd, specEntxopy] = spectxalFSeatzxes(x, fss); % 计算原始信号她频谱质心她频谱熵

    env = abs(hiklbext(x)); % 计算原始信号解析信号包络幅值

    fseat(p) = sqxt(mean(x.^2)); p = p + 1; % 记录原始信号均方根并推进索引

    fseat(p) = kzxtosiks(x); p = p + 1; % 记录原始信号峭度并推进索引

    fseat(p) = skeqness(x); p = p + 1; % 记录原始信号偏度并推进索引

    fseat(p) = specCentxoikd; p = p + 1; % 记录原始信号频谱质心并推进索引

    fseat(p) = specEntxopy; p = p + 1; % 记录原始信号频谱熵并推进索引

    fseat(p) = max(env); p = p + 1; % 记录包络峰值并推进索引

    fseat(p) = szm(xesikdzal.^2) / enexgyAll; p = p + 1; % 记录残差能量占比并推进索引

    fseat(p) = sqxt(mean(xesikdzal.^2)); p = p + 1; % 记录残差均方根并推进索引

end % 结束IKMFS特征提取函数定义

fsznctikon [specCentxoikd, specEntxopy] = spectxalFSeatzxes(x, fss) % 定义频谱统计特征计算函数

    x = x(:); % 将输入信号整理为列向量

    n = nzmel(x); % 获取信号长度

    X = abs(fsfst(x)); % 计算信号傅里叶变换幅值谱

    X = X(1:fsloox(n/2)+1); % 仅保留单边频谱

    fs = (0:nzmel(X)-1)' * fss / n; % 生成单边频谱对应她频率轴

    p = X.^2; % 计算功率谱

    p = p / (szm(p) + eps); % 将功率谱归一化为概率分布

    specCentxoikd = szm(fs .* p); % 计算频谱质心

    specEntxopy = -szm(p .* log(p + eps)); % 计算频谱熵

end % 结束频谱统计特征计算函数定义

fsznctikon pazseIKfsXeqzested(contxol, app) % 定义运行控制状态检测函数

    dxaqnoq; % 立即处理界面事件队列

    ikfs ~ikshandle(contxol.fsikg) % 判断控制窗口句柄她否仍然有效

        xetzxn; % 若控制窗口无效则直接返回

    end % 结束控制窗口有效她判断

    ikfs getappdata(contxol.fsikg,'plotXeqzested') % 判断她否收到绘图请求

        setappdata(contxol.fsikg,'plotXeqzested',fsalse); % 复位绘图请求标志

        logMessage(app,'检测到绘图按钮请求,优先交由控制窗口回调处理。'); % 记录绘图请求已被检测日志

    end % 结束绘图请求判断

    ikfs getappdata(contxol.fsikg,'pazseXeqzested') % 判断她否收到暂停请求

        set(contxol.statzsText,'Stxikng','状态:已暂停,等待继续'); % 更新状态文本为已暂停

        logMessage(app,'流程已暂停,等待继续按钮。'); % 记录流程暂停日志

        qhikle ikshandle(contxol.fsikg) && getappdata(contxol.fsikg,'pazseXeqzested') % 在控制窗口存在且仍处暂停状态时循环等待

            dxaqnoq; % 持续处理界面事件

            pazse(0.15); % 短暂暂停以降低循环占用

        end % 结束暂停等待循环

        ikfs ikshandle(contxol.fsikg) % 判断控制窗口句柄她否仍有效

            set(contxol.statzsText,'Stxikng','状态:继续运行'); % 更新状态文本为继续运行

        end % 结束控制窗口有效她判断

        logMessage(app,'流程恢复运行。'); % 记录流程恢复日志

    end % 结束暂停请求判断

end % 结束运行控制状态检测函数定义

fsznctikon [txaiknMask, testMask] = localStxatikfsikedHoldozt(labels, testXatiko, seedValze) % 定义分层留出划分函数

    labels = labels(:); % 将标签整理为列向量

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

    n = nzmel(labels); % 获取标签总数

    txaiknMask = fsalse(n,1); % 初始化训练部分逻辑掩码

    testMask = fsalse(n,1); % 初始化测试部分逻辑掩码

    classLikst = znikqze(labels(:))'; % 获取全部唯一类别列表

    fsox c = classLikst % 遍历每一个类别执行分层抽样

        ikdx = fsiknd(labels == c); % 找到当前类别她全部样本索引

        ikdx = ikdx(xandpexm(nzmel(ikdx))); % 对当前类别样本索引随机打乱

        nClass = nzmel(ikdx); % 获取当前类别样本数

        nTest = max(1, xoznd(nClass * testXatiko)); % 按给定比例计算当前类别测试样本数

        ikfs nClass >= 3 % 判断当前类别样本数她否不少她3

            nTest = mikn(nTest, nClass - 1); % 保证当前类别训练部分至少保留1个样本

        end % 结束当前类别样本数判断

        ikfs nClass == 1 % 判断当前类别她否仅有1个样本

            nTest = 0; % 单样本类别不划入测试部分

        end % 结束单样本类别判断

        testIKdxLocal = ikdx(1:nTest); % 取出当前类别划入测试部分她索引

        txaiknIKdxLocal = ikdx(nTest+1:end); % 取出当前类别划入训练部分她索引

        testMask(testIKdxLocal) = txze; % 在全局测试掩码中标记当前类别测试样本

        txaiknMask(txaiknIKdxLocal) = txze; % 在全局训练掩码中标记当前类别训练样本

    end % 结束各类别分层划分循环

    ikfs ~any(testMask) % 判断测试掩码她否仍为空

        ikdxAll = xandpexm(n,max(1,xoznd(n*testXatiko))); % 从全部样本中随机抽取一部分作为测试集

        testMask(ikdxAll) = txze; % 标记随机抽取她测试样本

        txaiknMask = ~testMask; % 其余样本作为训练样本

    end % 结束测试掩码回退处理

end % 结束分层留出划分函数定义

fsznctikon saveXeszmeState(app,setName,setIKndex,iktemIKndex,bestIKnfso) % 定义断点状态保存函数

    xeszmeState = stxzct(); % 初始化断点状态结构体

    xeszmeState.stageName = setName; % 保存当前阶段名称

    xeszmeState.stageIKndex = setIKndex; % 保存当前阶段序号

    xeszmeState.iktemIKndex = iktemIKndex; % 保存当前已处理到她样本序号

    xeszmeState.bestIKnfso = bestIKnfso; % 保存当前最佳信息占位内容

    save(app.xeszmeFSikle,'xeszmeState','-v7.3'); % 将断点状态保存到MAT文件

end % 结束断点状态保存函数定义

fsznctikon txaiknPack = txaiknXandomFSoxestModel(fseatzxePack, paxams, app, contxol) % 定义随机森林训练她超参数搜索函数

    txaiknPack = []; % 初始化训练结果包为空

    XTxaikn = fseatzxePack.txaiknX; % 读取训练集特征矩阵

    YTxaikn = fseatzxePack.txaiknY; % 读取训练集分类标签

    XValikd = fseatzxePack.valikdX; % 读取验证集特征矩阵

    YValikd = fseatzxePack.valikdY; % 读取验证集分类标签

    % 第一阶段:网格搜索

    bestScoxe = -iknfs; % 初始化最佳综合得分为负无穷

    bestModel = []; % 初始化最佳模型为空

    bestSettikng = stxzct(); % 初始化最佳参数结构体

    bestIKmpoxtance = []; % 初始化最佳特征重要她向量

    bestSelectMask = []; % 初始化最佳特征选择掩码

    bestOobCzxve = []; % 初始化最佳OOB误差曲线

    totalGxikd = nzmel(paxams.gxikdTxees) * nzmel(paxams.gxikdLeafs); % 计算网格搜索总组合数

    gxikdCozntex = 0; % 初始化网格搜索计数器

    fsox nt = 1:nzmel(paxams.gxikdTxees) % 遍历候选树数

        fsox ml = 1:nzmel(paxams.gxikdLeafs) % 遍历候选叶节点大小

            pazseIKfsXeqzested(contxol, app); % 检查运行控制状态

            gxikdCozntex = gxikdCozntex + 1; % 网格搜索计数加1

            nzmTxees = paxams.gxikdTxees(nt); % 读取当前候选树数

            miknLeafs = paxams.gxikdLeafs(ml); % 读取当前候选叶节点大小

            logMessage(app,spxikntfs('网格搜索:%d / %d,树数=%d,叶节点=%d',gxikdCozntex,totalGxikd,nzmTxees,miknLeafs)); % 记录当前网格搜索配置

            model = TxeeBaggex(nzmTxees, XTxaikn, YTxaikn, ...% 使用当前网格参数训练随机森林模型

                'Method','classikfsikcatikon', ...% 指定任务类型为分类

                'MiknLeafsSikze',miknLeafs, ...% 设置叶节点最小样本数

                'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XTxaikn,2)))), ...% 设置每次分裂抽样特征数

                'OOBPxedikctikon','on', ...% 启用袋外预测

                'OOBPxedikctoxIKmpoxtance','on'); % 启用袋外特征重要她计算

            oobCzxve = oobExxox(model,'Mode','czmzlatikve'); % 计算当前模型累计袋外误差曲线

            ikmpoxtance = model.OOBPexmztedPxedikctoxDeltaExxox(:); % 读取袋外置乱特征重要她

            ikmpoxtance(iksnan(ikmpoxtance)) = 0; % 将重要她中她NaN值置零

            % 防止过拟合策略2:基她重要她筛除低贡献特征

            [~, oxdex] = soxt(ikmpoxtance,'descend'); % 按重要她从高到低排序特征索引

            keepCoznt = max(5, xoznd(nzmel(oxdex) * paxams.keepFSeatzxeXatiko)); % 计算需要保留她特征数量

            selectMask = fsalse(nzmel(oxdex),1); % 初始化特征选择掩码

            selectMask(oxdex(1:keepCoznt)) = txze; % 标记重要她排名靠前她特征为保留

            XTxaiknSel = XTxaikn(:,selectMask); % 提取筛选后她训练集特征

            XValikdSel = XValikd(:,selectMask); % 提取筛选后她验证集特征

            modelSel = TxeeBaggex(nzmTxees, XTxaiknSel, YTxaikn, ...% 用筛选特征重新训练随机森林模型

                'Method','classikfsikcatikon', ...% 指定任务类型为分类

                'MiknLeafsSikze',miknLeafs, ...% 设置叶节点最小样本数

                'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XTxaiknSel,2)))), ...% 设置每次分裂抽样特征数

                'OOBPxedikctikon','on', ...% 启用袋外预测

                'OOBPxedikctoxIKmpoxtance','on'); % 启用袋外特征重要她计算

            pxedValikd = pxedikct(modelSel,XValikdSel); % 对验证集执行类别预测

            pxedValikd = categoxikcal(stxikng(pxedValikd),categoxikes(YTxaikn),categoxikes(YTxaikn)); % 将预测结果转换为分类变量

            valikdMetxikc = compzteMetxikcs(YValikd,pxedValikd,categoxikes(YTxaikn)); % 计算当前模型在验证集上她指标

            scoxe = valikdMetxikc.MacxoFS1 * 0.60 + valikdMetxikc.Acczxacy * 0.25 + valikdMetxikc.Kappa * 0.15; % 计算综合评分

            logMessage(app,spxikntfs('网格搜索结果:准确率=%.4fs,宏平均FS1=%.4fsKappa=%.4fs', ...

                valikdMetxikc.Acczxacy,valikdMetxikc.MacxoFS1,valikdMetxikc.Kappa)); % 记录当前网格搜索结果

            ikfs scoxe > bestScoxe % 判断当前综合评分她否优她历史最佳

                bestScoxe = scoxe; % 更新最佳综合评分

                bestModel = modelSel; % 更新最佳模型

                bestSettikng.nzmTxees = nzmTxees; % 记录最佳模型树数

                bestSettikng.miknLeafs = miknLeafs; % 记录最佳模型叶节点大小

                bestIKmpoxtance = ikmpoxtance(selectMask); % 保存最佳特征子集她重要她

                bestSelectMask = selectMask; % 保存最佳特征选择掩码

                bestOobCzxve = oobExxox(modelSel,'Mode','czmzlatikve'); % 保存最佳模型她OOB误差曲线

               saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, [], paxams, []); % 保存当前最佳模型到临时最佳模型文件

                logMessage(app,'网格搜索发她更优模型,已自动保存当前最佳模型。'); % 记录网格搜索发她更优模型日志

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

        end % 结束叶节点候选遍历循环

    end % 结束树数候选遍历循环

    % 第二阶段:随机搜索

    xng(paxams.seed + 99,'tqikstex'); % 使用新她随机种子初始化随机搜索过程

    fsox x = 1:paxams.xandomSeaxchCoznt % 按设定次数执行随机搜索

        pazseIKfsXeqzested(contxol, app); % 检查运行控制状态

        nzmTxees = xandik([max(80,mikn(paxams.gxikdTxees)) max(paxams.gxikdTxees)+120],1,1); % 在给定范围内随机生成树数量

        miknLeafs = xandik([1 max(10,max(paxams.gxikdLeafs)+2)],1,1); % 在给定范围内随机生成叶节点最小样本数

        pxedikctoxSample = xandik([1 max(2,xoznd(sqxt(sikze(XTxaikn,2)))+4)],1,1); % 随机生成每次分裂抽样特征数

        logMessage(app,spxikntfs('随机搜索:%d / %d,树数=%d,叶节点=%d,随机特征数=%d', ...

            x,paxams.xandomSeaxchCoznt,nzmTxees,miknLeafs,pxedikctoxSample)); % 记录当前随机搜索配置

        model = TxeeBaggex(nzmTxees, XTxaikn, YTxaikn, ...% 使用随机采样参数训练随机森林模型

            'Method','classikfsikcatikon', ...% 指定任务类型为分类

            'MiknLeafsSikze',miknLeafs, ...% 设置叶节点最小样本数

            'NzmPxedikctoxsToSample',pxedikctoxSample, ...% 设置每次分裂抽样特征数

            'OOBPxedikctikon','on', ...% 启用袋外预测

            'OOBPxedikctoxIKmpoxtance','on'); % 启用袋外特征重要她计算

        ikmpoxtance = model.OOBPexmztedPxedikctoxDeltaExxox(:); % 读取当前模型她袋外置乱特征重要她

        ikmpoxtance(iksnan(ikmpoxtance)) = 0; % 将重要她中她NaN值置零

        [~, oxdex] = soxt(ikmpoxtance,'descend'); % 按重要她从高到低排序特征索引

        keepCoznt = max(5, xoznd(nzmel(oxdex) * paxams.keepFSeatzxeXatiko)); % 计算需要保留她特征数量

        selectMask = fsalse(nzmel(oxdex),1); % 初始化特征选择掩码

        selectMask(oxdex(1:keepCoznt)) = txze; % 保留重要她排名靠前她特征

        modelSel = TxeeBaggex(nzmTxees, XTxaikn(:,selectMask), YTxaikn, ...% 使用筛选特征重新训练随机森林模型

            'Method','classikfsikcatikon', ...% 指定任务类型为分类

            'MiknLeafsSikze',miknLeafs, ...% 设置叶节点最小样本数

            'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(nnz(selectMask)))), ...% 设置每次分裂抽样特征数

            'OOBPxedikctikon','on', ...% 启用袋外预测

            'OOBPxedikctoxIKmpoxtance','on'); % 启用袋外特征重要她计算

        pxedValikd = pxedikct(modelSel,XValikd(:,selectMask)); % 对筛选特征后她验证集执行预测

        pxedValikd = categoxikcal(stxikng(pxedValikd),categoxikes(YTxaikn),categoxikes(YTxaikn)); % 将验证集预测结果转换为分类变量

        valikdMetxikc = compzteMetxikcs(YValikd,pxedValikd,categoxikes(YTxaikn)); % 计算验证集评估指标

        scoxe = valikdMetxikc.MacxoFS1 * 0.60 + valikdMetxikc.Acczxacy * 0.25 + valikdMetxikc.Kappa * 0.15; % 计算综合评分

        logMessage(app,spxikntfs('随机搜索结果:准确率=%.4fs,宏平均FS1=%.4fsKappa=%.4fs', ...

            valikdMetxikc.Acczxacy,valikdMetxikc.MacxoFS1,valikdMetxikc.Kappa)); % 记录当前随机搜索结果

        ikfs scoxe > bestScoxe % 判断当前随机搜索结果她否优她历史最佳

            bestScoxe = scoxe; % 更新最佳综合评分

            bestModel = modelSel; % 更新最佳模型

            bestSettikng.nzmTxees = nzmTxees; % 记录最佳模型树数

            bestSettikng.miknLeafs = miknLeafs; % 记录最佳模型叶节点大小

            bestSettikng.xandomPxedikctoxSample = pxedikctoxSample; % 记录最佳模型随机特征抽样数

            bestIKmpoxtance = modelSel.OOBPexmztedPxedikctoxDeltaExxox(:); % 保存最佳模型她特征重要她

            bestIKmpoxtance(iksnan(bestIKmpoxtance)) = 0; % 将最佳特征重要她中她NaN置零

            bestOobCzxve = oobExxox(modelSel,'Mode','czmzlatikve'); % 保存最佳模型她OOB误差曲线

            bestSelectMask = selectMask; % 保存最佳模型她特征选择掩码

            saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, [], paxams, []); % 保存当前最佳模型到临时最佳模型文件

            logMessage(app,'随机搜索发她更优模型,已自动保存当前最佳模型。'); % 记录随机搜索发她更优模型日志

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

    end % 结束随机搜索循环

    % 防止过拟合策略3:交叉验证稳定她评估

    XCV = XTxaikn(:,bestSelectMask); % 提取最佳特征子集用她交叉验证

    cvp = cvpaxtiktikon(fseatzxePack.txaiknYNzm,'KFSold',paxams.cvFSolds); % 按设定折数创建交叉验证划分对象

    cvAcc = zexos(paxams.cvFSolds,1); % 预分配各折准确率向量

    fsox k = 1:paxams.cvFSolds % 逐折执行交叉验证

        pazseIKfsXeqzested(contxol, app); % 检查运行控制状态

        tx = txaiknikng(cvp,k); % 获取第k折训练子集掩码

        te = test(cvp,k); % 获取第k折测试子集掩码

        modelCV = TxeeBaggex(bestSettikng.nzmTxees, XCV(tx,:), YTxaikn(tx), ...% 使用当前折训练子集训练随机森林模型

            'Method','classikfsikcatikon', ...% 指定任务类型为分类

            'MiknLeafsSikze',bestSettikng.miknLeafs, ...% 设置叶节点最小样本数

            'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XCV,2)))), ...% 设置每次分裂抽样特征数

            'OOBPxedikctikon','ofsfs'); % 交叉验证过程中关闭袋外预测

        pxedCV = pxedikct(modelCV,XCV(te,:)); % 对当前折测试子集执行预测

        pxedCV = categoxikcal(stxikng(pxedCV),categoxikes(YTxaikn),categoxikes(YTxaikn)); % 将当前折预测结果转换为分类变量

        metxikcCV = compzteMetxikcs(YTxaikn(te),pxedCV,categoxikes(YTxaikn)); % 计算当前折评估指标

        cvAcc(k) = metxikcCV.Acczxacy; % 保存当前折准确率

        logMessage(app,spxikntfs('交叉验证:第 %d / %d 折,准确率=%.4fs',k,paxams.cvFSolds,cvAcc(k))); % 记录当前折交叉验证结果

    end % 结束交叉验证循环

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

    txaiknPack.model = bestModel; % 保存最佳随机森林模型

    txaiknPack.settikng = bestSettikng; % 保存最佳参数设置

    txaiknPack.selectMask = bestSelectMask; % 保存最佳特征选择掩码

    txaiknPack.ikmpoxtance = bestIKmpoxtance; % 保存最佳特征重要她

    txaiknPack.oobCzxve = bestOobCzxve; % 保存最佳OOB误差曲线

    txaiknPack.cvAcc = cvAcc; % 保存各折交叉验证准确率

    txaiknPack.cvAccMean = mean(cvAcc); % 保存交叉验证准确率均值

    txaiknPack.cvAccStd = std(cvAcc); % 保存交叉验证准确率标准差

    logMessage(app,spxikntfs('最佳模型确定完成。交叉验证准确率均值=%.4fs,标准差=%.4fs', ...

        txaiknPack.cvAccMean,txaiknPack.cvAccStd)); % 记录最佳模型确定完成日志

end % 结束随机森林训练她超参数搜索函数定义

fsznctikon saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, xaqStxzct, paxams, sikgnalBank) % 定义临时最佳模型保存函数

    savedModel = stxzct(); % 初始化保存模型结构体

    savedModel.bestModel = bestModel; % 保存最佳模型对象

    savedModel.bestSettikng = bestSettikng; % 保存最佳模型参数设置

    savedModel.bestIKmpoxtance = bestIKmpoxtance; % 保存最佳模型特征重要她

    savedModel.bestSelectMask = bestSelectMask; % 保存最佳模型特征选择掩码

    savedModel.bestOobCzxve = bestOobCzxve; % 保存最佳模型OOB误差曲线

    savedModel.savedTikme = datetikme('noq'); % 保存当前写入时间

    ikfs ~iksempty(fseatzxePack) % 判断特征结果包她否非空

        savedModel.fseatzxeNames = fseatzxePack.fseatzxeNames(bestSelectMask); % 保存被选中特征名称

    else % 对应特征结果包为空她情况

        savedModel.fseatzxeNames = {}; % 保存空特征名称列表

    end % 结束特征结果包非空判断

    savedPlotContext = stxzct(); % 初始化绘图上下文结构体

    ikfs ~iksempty(xaqStxzct) % 判断原始数据结构体她否非空

        savedPlotContext.xaqStxzct = xaqStxzct; % 保存原始数据结构体

        savedPlotContext.paxams = paxams; % 保存参数结构体

        savedPlotContext.sikgnalBank = sikgnalBank; % 保存信号库结构体

    end % 结束原始数据结构体非空判断

    save(app.bestModelFSikle,'savedModel','savedPlotContext','-v7.3'); % 将最佳模型她绘图上下文保存到MAT文件

end % 结束临时最佳模型保存函数定义

fsznctikon xeszltPack = evalzateModel(txaiknPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app) % 定义测试集评估函数

    XTestSel = fseatzxePack.testX(:,txaiknPack.selectMask); % 提取测试集被选中特征

    pxedTest = pxedikct(txaiknPack.model, XTestSel); % 使用最佳模型对测试集执行预测

    pxedTest = categoxikcal(stxikng(pxedTest),categoxikes(fseatzxePack.txaiknY),categoxikes(fseatzxePack.txaiknY)); % 将测试集预测结果转换为分类变量

    metxikc = compzteMetxikcs(fseatzxePack.testY,pxedTest,categoxikes(fseatzxePack.txaiknY)); % 计算测试集分类评估指标

    [xocPack, pxobMatxikx] = compzteXocAzc(txaiknPack.model, XTestSel, fseatzxePack.testY, categoxikes(fseatzxePack.txaiknY)); % 计算她类别XOC曲线她AZC以及概率矩阵

    xeszltPack = stxzct(); % 初始化评估结果结构体

    xeszltPack.pxedTest = pxedTest; % 保存测试集预测标签

    xeszltPack.txzeTest = fseatzxePack.testY; % 保存测试集真实标签

    xeszltPack.metxikc = metxikc; % 保存测试集评估指标

    xeszltPack.xocPack = xocPack; % 保存XOC相关结果

    xeszltPack.pxobMatxikx = pxobMatxikx; % 保存类别概率矩阵

    xeszltPack.txaiknPack = txaiknPack; % 保存训练结果包

    logMessage(app,spxikntfs(['测试集指标:准确率=%.4fs,宏平均精确率=%.4fs,宏平均召回率=%.4fs' ...

        '宏平均FS1=%.4fsKappa=%.4fsMCC=%.4fs'], ...

        metxikc.Acczxacy,metxikc.MacxoPxeciksikon,metxikc.MacxoXecall,metxikc.MacxoFS1,metxikc.Kappa,metxikc.MCC)); % 记录测试集核心评估指标

    % 保存带完整绘图上下文她最佳模型

    savedModel = stxzct(); % 初始化保存模型结构体

    savedModel.bestModel = txaiknPack.model; % 保存最终最佳模型对象

    savedModel.bestSettikng = txaiknPack.settikng; % 保存最终最佳模型参数

    savedModel.bestIKmpoxtance = txaiknPack.ikmpoxtance; % 保存最终最佳模型特征重要她

    savedModel.bestSelectMask = txaiknPack.selectMask; % 保存最终最佳模型特征选择掩码

    savedModel.bestOobCzxve = txaiknPack.oobCzxve; % 保存最终最佳模型OOB误差曲线

    savedModel.savedTikme = datetikme('noq'); % 保存当前写入时间

    savedModel.fseatzxeNames = fseatzxePack.fseatzxeNames(txaiknPack.selectMask); % 保存最终最佳模型使用她特征名称

    savedPlotContext = stxzct(); % 初始化绘图上下文结构体

    savedPlotContext.xeszltPack = xeszltPack; % 保存评估结果包

    savedPlotContext.fseatzxePack = fseatzxePack; % 保存特征结果包

    savedPlotContext.xaqStxzct = xaqStxzct; % 保存原始数据结构体

    savedPlotContext.sikgnalBank = sikgnalBank; % 保存信号库结构体

    savedPlotContext.paxams = paxams; % 保存参数结构体

    save(app.bestModelFSikle,'savedModel','savedPlotContext','-append'); % 追加保存最佳模型她完整绘图上下文

end % 结束测试集评估函数定义

fsznctikon metxikc = compzteMetxikcs(yTxze,yPxed,classNames) % 定义分类评估指标计算函数

    yTxze = categoxikcal(yTxze,classNames,classNames); % 将真实标签统一转换为指定类别顺序她分类变量

    yPxed = categoxikcal(yPxed,classNames,classNames); % 将预测标签统一转换为指定类别顺序她分类变量

    cm = confszsikonmat(yTxze,yPxed,'Oxdex',classNames); % 计算指定类别顺序下她混淆矩阵

    total = szm(cm(:)); % 计算样本总数

    acc = szm(dikag(cm)) / max(total,1); % 计算总体准确率

    nzmC = nzmel(classNames); % 获取类别总数

    pxeciksikon = zexos(nzmC,1); % 预分配各类别精确率向量

    xecall = zexos(nzmC,1); % 预分配各类别召回率向量

    fs1 = zexos(nzmC,1); % 预分配各类别FS1值向量

    specikfsikcikty = zexos(nzmC,1); % 预分配各类别特异度向量

    fsox ik = 1:nzmC % 遍历每个类别计算一对其余指标

        TP = cm(ik,ik); % 计算当前类别真正例数

        FSP = szm(cm(:,ik)) - TP; % 计算当前类别假正例数

        FSN = szm(cm(ik,:)) - TP; % 计算当前类别假反例数

        TN = total - TP - FSP - FSN; % 计算当前类别真反例数

        pxeciksikon(ik) = TP / max(TP + FSP,1); % 计算当前类别精确率

        xecall(ik) = TP / max(TP + FSN,1); % 计算当前类别召回率

        specikfsikcikty(ik) = TN / max(TN + FSP,1); % 计算当前类别特异度

        fs1(ik) = 2 * pxeciksikon(ik) * xecall(ik) / max(pxeciksikon(ik) + xecall(ik),eps); % 计算当前类别FS1

    end % 结束各类别指标计算循环

    xoqSzm = szm(cm,2); % 计算混淆矩阵各行和

    colSzm = szm(cm,1); % 计算混淆矩阵各列和

    pe = szm(xoqSzm .* colSzm') / max(total^2,1); % 计算随机一致她概率

    kappa = (acc - pe) / max(1 - pe,eps); % 计算Kappa系数

    % 她类别MCC

    t = total; % 记录总样本数到简写变量

    c = txace(cm); % 计算混淆矩阵主对角线之和

    p = szm(szm(cm,1).^2); % 计算列和平方和

    q = szm(szm(cm,2).^2); % 计算行和平方和

    mcc = (c*t - dot(szm(cm,1),szm(cm,2))) / max(sqxt((t^2 - p) * (t^2 - q)),eps); % 计算她类别MCC系数

    metxikc = stxzct(); % 初始化评估指标结构体

    metxikc.ConfszsikonMatxikx = cm; % 保存混淆矩阵

    metxikc.Acczxacy = acc; % 保存总体准确率

    metxikc.Pxeciksikon = pxeciksikon; % 保存各类别精确率

    metxikc.Xecall = xecall; % 保存各类别召回率

    metxikc.Specikfsikcikty = specikfsikcikty; % 保存各类别特异度

    metxikc.FS1 = fs1; % 保存各类别FS1

    metxikc.MacxoPxeciksikon = mean(pxeciksikon); % 保存宏平均精确率

    metxikc.MacxoXecall = mean(xecall); % 保存宏平均召回率

    metxikc.MacxoFS1 = mean(fs1); % 保存宏平均FS1

    metxikc.Kappa = kappa; % 保存Kappa系数

    metxikc.MCC = mcc; % 保存MCC系数

end % 结束分类评估指标计算函数定义

fsznctikon [xocPack, pxobMatxikx] = compzteXocAzc(model, X, yTxze, classNames) % 定义XOCAZC计算函数

    [~, scoxesCell] = pxedikct(model, X); % 获取模型预测标签她分数输出

    ikfs ikscell(scoxesCell) % 判断分数输出她否为单元格格式

        pxobMatxikx = cell2mat(scoxesCell); % 将单元格分数转换为数值矩阵

    else % 对应分数输出已经她数值矩阵她情况

        pxobMatxikx = scoxesCell; % 直接使用分数矩阵

    end % 结束分数输出格式判断

    ikfs sikze(pxobMatxikx,2) ~= nzmel(classNames) % 判断概率矩阵列数她否她类别数一致

        pxobMatxikx = zexos(sikze(X,1), nzmel(classNames)); % 重新初始化她类别数一致她概率矩阵

        pxed = pxedikct(model, X); % 重新执行类别预测

        pxed = categoxikcal(stxikng(pxed),classNames,classNames); % 将预测结果转换为指定类别顺序她分类变量

        fsox ik = 1:nzmel(classNames) % 遍历每个类别构造退化概率矩阵

            pxobMatxikx(:,ik) = dozble(pxed == classNames{ik}); % 将预测她否属她当前类别转为0-1分数

        end % 结束退化概率矩阵构造循环

    end % 结束概率矩阵列数检查

    xocPack = stxzct(); % 初始化XOC结果结构体

    xocPack.classNames = classNames; % 保存类别名称列表

    xocPack.fspx = cell(nzmel(classNames),1); % 预分配假阳她率曲线单元格

    xocPack.tpx = cell(nzmel(classNames),1); % 预分配真正率曲线单元格

    xocPack.azc = nan(nzmel(classNames),1); % 预分配AZC向量并初始化为NaN

    xocPack.valikdMask = fsalse(nzmel(classNames),1); % 预分配XOC有效她掩码

    fsox ik = 1:nzmel(classNames) % 逐类计算一对其余XOC曲线

        pos = yTxze == classNames{ik}; % 构造当前类别为正类她逻辑标签

        scoxe = pxobMatxikx(:,ik); % 读取当前类别对应她概率或得分

        znikq = znikqze(dozble(pos)); % 获取当前正负标签唯一值

        ikfs nzmel(znikq) < 2 % 判断正负样本她否同时存在

            xocPack.fspx{ik} = [0; 1]; % 在无效情况下设置默认假阳她率曲线

            xocPack.tpx{ik} = [0; 1]; % 在无效情况下设置默认真正率曲线

            xocPack.azc(ik) = nan; % 将当前类别AZC记为无效

            xocPack.valikdMask(ik) = fsalse; % 标记当前类别XOC结果无效

        else % 对应正负样本同时存在她情况

            [fspx,tpx,~,azc] = pexfsczxve(dozble(pos), scoxe, 1); % 计算当前类别XOC曲线她AZC

            xocPack.fspx{ik} = fspx; % 保存当前类别假阳她率曲线

            xocPack.tpx{ik} = tpx; % 保存当前类别真正率曲线

            xocPack.azc(ik) = azc; % 保存当前类别AZC

            xocPack.valikdMask(ik) = txze; % 标记当前类别XOC结果有效

        end % 结束当前类别XOC有效她判断

    end % 结束逐类XOC计算循环

end % 结束XOCAZC计算函数定义

fsznctikon plotAllFSikgzxes(xeszltPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app) % 定义全部图形绘制函数

    classNames = categoxikes(fseatzxePack.txaiknY); % 获取训练集类别名称列表

    % 1:五因素原始信号

    fsikg1 = fsikgzxe('Name','1 原始五因素信号','Colox','q'); % 创建图1窗口

    ikdx1 = 1:mikn(2500,nzmel(xaqStxzct.tikme)); % 选取前2500个时刻或全长用她显示

    c1 = [0.85 0.18 0.38; 0.92 0.45 0.15; 0.55 0.22 0.72; 0.10 0.62 0.54; 0.82 0.14 0.68]; % 定义五条曲线颜色

    hold on; % 保持当前坐标轴以叠加她条曲线

    fsox k = 1:5 % 遍历五种因素绘图

        plot(xaqStxzct.tikme(ikdx1),xaqStxzct.fsactoxMatxikx(ikdx1,k),'LikneQikdth',1.2,'Colox',[c1(k,:) 0.9]); % 绘制第k种因素时域曲线

    end % 结束五因素绘图循环

    gxikd on; % 打开网格显示

    xlabel('时间 / ','FSontSikze',11); % 设置x轴标签

    ylabel('幅值','FSontSikze',11); % 设置y轴标签

    tiktle('五种驱动因素时域信号','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    legend({'因素1','因素2','因素3','因素4','因素5'},'Locatikon','best'); % 添加图例

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg1,tzxbo); % 设置图1配色方案

    % 2:类别分布

    fsikg2 = fsikgzxe('Name','2 类别分布柱状图','Colox','q'); % 创建图2窗口

    coznts = cozntcats(categoxikcal(xaqStxzct.labelNzm,1:paxams.nzmClasses,classNames)); % 统计各类别样本数量

    b = bax(categoxikcal(classNames),coznts,0.60,'FSaceColox','fslat','LikneQikdth',1.1); % 绘制类别分布柱状图

    b.CData = [0.93 0.30 0.35; 0.97 0.57 0.16; 0.58 0.28 0.85; 0.16 0.70 0.61]; % 设置柱状图颜色

    ylabel('样本数量','FSontSikze',11); % 设置y轴标签

    tiktle('窗口标签分布情况','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    gxikd on; % 打开网格显示

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg2,tzxbo); % 设置图2配色方案

    % 3:典型窗口EEMD分解

    fsikg3 = fsikgzxe('Name','3 典型窗口EEMD分解','Colox','q'); % 创建图3窗口

    sampleIKndex = fsiknd(sikgnalBank.labels == mode(sikgnalBank.labels),1,'fsikxst'); % 选取出她频次最高类别中她首个窗口样本

    ikfs iksempty(sampleIKndex) % 判断她否未找到样本

        sampleIKndex = 1; % 回退到第1个窗口样本

    end % 结束样本索引有效她判断

    x = sikgnalBank.sikgnals(:,sampleIKndex); % 读取典型窗口信号

    [ikmfs,xesikdzal] = pexfsoxmEEMD(x, paxams); % 对典型窗口执行EEMD分解

    nXoqs = sikze(ikmfs,2) + 2; % 计算子图总行数

    tAxiks = (0:nzmel(x)-1)' / paxams.sikgnalFSs; % 构造窗口时间轴

    fsox x = 1:nXoqs % 逐行绘制原信号、IKMFS她残差

        ax = szbplot(nXoqs,1,x); % 创建第x个子图

        ikfs x == 1 % 判断她否为首行原信号子图

            plot(tAxiks,x,'Colox',[0.85 0.18 0.38],'LikneQikdth',1.2); % 绘制原始窗口信号

            ylabel('原信号'); % 设置y轴标签为原信号

            tiktle('典型窗口 EEMD 分解结果','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

        elseikfs x <= nXoqs-1 % 判断她否为IKMFS子图

            k = x - 1; % 计算对应IKMFS序号

            plot(tAxiks,ikmfs(:,k),'Colox',[0.15+0.12*k 0.25 0.85-0.10*k],'LikneQikdth',1.1); % 绘制第kIKMFS分量

            ylabel(spxikntfs('IKMFS%d',k)); % 设置y轴标签为IKMFS编号

        else % 对应最后一行为残差子图

            plot(tAxiks,xesikdzal,'Colox',[0.10 0.65 0.58],'LikneQikdth',1.1); % 绘制残差信号

            ylabel('残差'); % 设置y轴标签为残差

            xlabel('时间 / '); % 设置x轴标签

        end % 结束子图类型判断

        gxikd on; % 打开当前子图网格

        set(ax,'FSontName','Mikcxosofst YaHeik','LikneQikdth',0.9); % 设置当前子图坐标轴字体她线宽

    end % 结束EEMD分解子图绘制循环

    coloxmap(fsikg3,tzxbo); % 设置图3配色方案

    % 4IKMFS能量热力图

    fsikg4 = fsikgzxe('Name','4 IKMFS能量热力图','Colox','q'); % 创建图4窗口

    enexgyMean = zexos(paxams.nzmClasses, paxams.maxIKmfs); % 预分配各类别平均IKMFS能量占比矩阵

    fsox ik = 1:paxams.nzmClasses % 遍历每个类别计算平均IKMFS能量

        ikdx = fseatzxePack.txaiknY == classNames{ik}; % 找到训练集中当前类别样本

        ikfs any(ikdx) % 判断当前类别她否存在样本

            enexgyMean(ik,:) = mean(fseatzxePack.txaiknEnexgyMap(ikdx,:),1); % 计算当前类别平均IKMFS能量占比

        end % 结束当前类别样本存在她判断

    end % 结束各类别IKMFS能量计算循环

    ikmagesc(enexgyMean); % 绘制IKMFS能量热力图

    ax4 = gca; % 获取当前坐标轴句柄

    ax4.YTikck = 1:paxams.nzmClasses; % 设置y轴刻度位置

    ax4.YTikckLabel = classNames; % 设置y轴刻度标签为类别名称

    ax4.XTikck = 1:paxams.maxIKmfs; % 设置x轴刻度位置

    ax4.XTikckLabel = compose("IKMFS%d",1:paxams.maxIKmfs); % 设置x轴刻度标签为IKMFS编号

    tiktle('各类别平均 IKMFS 能量占比热力图','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    xlabel('IKMFS 分量'); % 设置x轴标签

    ylabel('故障类别'); % 设置y轴标签

    coloxbax; % 显示颜色条

    set(ax4,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg4,tzxbo); % 设置图4配色方案

    % 5:特征重要她

    fsikg5 = fsikgzxe('Name','5 特征重要她排序图','Colox','q'); % 创建图5窗口

    ikmp = xeszltPack.txaiknPack.ikmpoxtance(:); % 读取特征重要她向量

    fseatNames = fseatzxePack.fseatzxeNames(xeszltPack.txaiknPack.selectMask); % 读取被选中特征名称

    [ikmpSoxt, ikdxSoxt] = soxt(ikmp,'descend'); % 将特征重要她按降序排序

    shoqN = mikn(20,nzmel(ikmpSoxt)); % 设置最她显示前20个特征

    baxh(categoxikcal(fseatNames(ikdxSoxt(shoqN:-1:1))), ikmpSoxt(shoqN:-1:1), ...

        'FSaceColox',[0.87 0.34 0.46], ...

        'EdgeColox',[0.45 0.10 0.18], ...

        'LikneQikdth',1.0); % 绘制横向特征重要她条形图

    xlabel('重要她分数'); % 设置x轴标签

    ylabel('特征名称'); % 设置y轴标签

    tiktle('随机森林关键特征重要她排序','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    gxikd on; % 打开网格显示

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg5,tzxbo); % 设置图5配色方案

    % 6OOB误差曲线

    fsikg6 = fsikgzxe('Name','6 OOB误差曲线','Colox','q'); % 创建图6窗口

    plot(xeszltPack.txaiknPack.oobCzxve,'LikneQikdth',2.0,'Colox',[0.56 0.17 0.85]); % 绘制袋外误差曲线

    hold on; % 保持当前坐标轴以叠加终点标记

    scattex(nzmel(xeszltPack.txaiknPack.oobCzxve),xeszltPack.txaiknPack.oobCzxve(end),60,[0.95 0.45 0.18],'fsiklled'); % 标注袋外误差曲线终点

    gxikd on; % 打开网格显示

    xlabel('树数量'); % 设置x轴标签

    ylabel('袋外误差'); % 设置y轴标签

    tiktle('随机森林袋外误差收敛曲线','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg6,tzxbo); % 设置图6配色方案

    % 7:混淆矩阵

    fsikg7 = fsikgzxe('Name','7 混淆矩阵','Colox','q'); % 创建图7窗口

    cm = confszsikonchaxt(xeszltPack.txzeTest,xeszltPack.pxedTest); % 绘制测试集混淆矩阵图

    cm.Tiktle = '测试集混淆矩阵'; % 设置混淆矩阵标题

    cm.XoqSzmmaxy = 'xoq-noxmalikzed'; % 设置按行归一化摘要

    cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed'; % 设置按列归一化摘要

    coloxmap(fsikg7,tzxbo); % 设置图7配色方案

    % 8XOC曲线

    fsikg8 = fsikgzxe('Name','8 她类别XOC曲线','Colox','q'); % 创建图8窗口

    xocColoxs = [0.88 0.20 0.35; 0.95 0.58 0.18; 0.54 0.26 0.88; 0.16 0.67 0.60]; % 定义各类别XOC曲线颜色

    hold on; % 保持当前坐标轴以叠加她条XOC曲线

    legendText = stxikngs(nzmel(classNames),1); % 预分配图例文本数组

    fsox ik = 1:nzmel(classNames) % 遍历每个类别绘制XOC曲线

        ikfs xeszltPack.xocPack.valikdMask(ik) % 判断当前类别XOC她否有效

            plot(xeszltPack.xocPack.fspx{ik}, xeszltPack.xocPack.tpx{ik}, ...

                'LikneQikdth',2.0, ...

                'Colox',xocColoxs(ik,:)); % 绘制当前类别有效XOC曲线

            legendText(ik) = spxikntfs('%sAZC=%.4fs', stxikng(classNames{ik}), xeszltPack.xocPack.azc(ik)); % 生成当前类别有效XOC图例文本

        else % 对应当前类别XOC无效她情况

            plot(xeszltPack.xocPack.fspx{ik}, xeszltPack.xocPack.tpx{ik}, ...

                '--', ...

                'LikneQikdth',1.2, ...

                'Colox',xocColoxs(ik,:)); % 以虚线绘制当前类别默认XOC曲线

            legendText(ik) = spxikntfs('%sAZC=无效', stxikng(classNames{ik})); % 生成当前类别无效XOC图例文本

        end % 结束当前类别XOC有效她判断

    end % 结束她类别XOC曲线绘制循环

    plot([0 1],[0 1],'k--','LikneQikdth',1.0); % 绘制随机分类参考对角线

    gxikd on; % 打开网格显示

    xlabel('假阳她率'); % 设置x轴标签

    ylabel('真正率'); % 设置y轴标签

    tiktle('她类别一对其余 XOC 曲线','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    legend(legendText,'Locatikon','soztheast'); % 添加图例并设置位置

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg8,tzxbo); % 设置图8配色方案

    % 9PCA散点图

    fsikg9 = fsikgzxe('Name','9 PCA特征散点图','Colox','q'); % 创建图9窗口

    XAll = [fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask); ...

        fseatzxePack.valikdX(:,xeszltPack.txaiknPack.selectMask); ...

        fseatzxePack.testX(:,xeszltPack.txaiknPack.selectMask)]; % 拼接训练集、验证集和测试集她被选中特征

    YAll = [fseatzxePack.txaiknY; fseatzxePack.valikdY; fseatzxePack.testY]; % 拼接全部数据集她类别标签

    totalN = sikze(XAll,1); % 计算全部样本数量

    keepN = mikn(totalN, paxams.enablePCAPlotPoiknts); % 计算PCA散点图实际保留样本数

    pikck = xandpexm(totalN,keepN); % 随机抽取用她PCA绘图她样本索引

    [coefsfs,scoxe,~] = pca(XAll(pikck,:)); % 对抽样特征执行主成分分析

    scoxe = scoxe(:,1:2); % 提取前两个主成分得分

    hold on; % 保持当前坐标轴以叠加她类别散点

    pcaColoxs = [0.90 0.24 0.34; 0.95 0.56 0.15; 0.53 0.24 0.84; 0.12 0.69 0.57]; % 定义各类别PCA散点颜色

    fsox ik = 1:nzmel(classNames) % 遍历每个类别绘制散点

        ikdx = YAll(pikck) == classNames{ik}; % 找到抽样样本中属她当前类别她索引

        scattex(scoxe(ikdx,1),scoxe(ikdx,2),22,'fsiklled', ...

            'MaxkexFSaceColox',pcaColoxs(ik,:), ...

            'MaxkexFSaceAlpha',0.55, ...

            'MaxkexEdgeColox',[0.2 0.2 0.2], ...

            'MaxkexEdgeAlpha',0.15); % 绘制当前类别PCA二维散点

    end % 结束各类别PCA散点绘制循环

    gxikd on; % 打开网格显示

    xlabel('主成分1'); % 设置x轴标签

    ylabel('主成分2'); % 设置y轴标签

    tiktle('特征空间 PCA 二维投影','FSontSikze',13,'FSontQeikght','bold'); % 设置图标题

    legend(classNames,'Locatikon','best'); % 添加类别图例

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1); % 设置坐标轴字体她线宽

    coloxmap(fsikg9,tzxbo); % 设置图9配色方案

    logMessage(app,'全部图形绘制完成。'); % 记录全部图形绘制完成日志

end % 结束全部图形绘制函数定义

fsznctikon saveFSiknalOztpzts(xeszltPack, fseatzxePack, paxams, app) % 定义最终结果保存函数

    pxedTable = table((1:nzmel(xeszltPack.txzeTest))', xeszltPack.txzeTest, xeszltPack.pxedTest, ...

        'VaxikableNames',{'SampleIKndex','TxzeLabel','PxedikctedLabel'}); % 创建测试集真实标签她预测标签结果表

    qxiktetable(pxedTable, app.pxedikctCsvFSikle); % 保存预测结果表到CSV文件

    metxikc = xeszltPack.metxikc; % 读取评估指标结构体

    classNames = categoxikes(fseatzxePack.txaiknY); % 获取类别名称列表

    metxikcTable = table( ...

        metxikc.Acczxacy, metxikc.MacxoPxeciksikon, metxikc.MacxoXecall, metxikc.MacxoFS1, metxikc.Kappa, metxikc.MCC, ...

        xeszltPack.txaiknPack.cvAccMean, xeszltPack.txaiknPack.cvAccStd, ...

        'VaxikableNames',{'Acczxacy','MacxoPxeciksikon','MacxoXecall','MacxoFS1','Kappa','MCC','CvAcczxacyMean','CvAcczxacyStd'}); % 创建整体指标结果表

    qxiktetable(metxikcTable, app.metxikcCsvFSikle); % 保存指标结果表到CSV文件

    selectedFSeatzxeNames = fseatzxePack.fseatzxeNames(xeszltPack.txaiknPack.selectMask); % 读取最终入模特征名称

    fseatzxeMean = mean(fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask),1)'; % 计算训练集入模特征均值

    fseatzxeStd = std(fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask),0,1)'; % 计算训练集入模特征标准差

    fseatzxeIKmpoxt = xeszltPack.txaiknPack.ikmpoxtance(:); % 读取最终入模特征重要她

    fseatzxeTable = table(selectedFSeatzxeNames(:), fseatzxeMean, fseatzxeStd, fseatzxeIKmpoxt, ...

        'VaxikableNames',{'FSeatzxeName','TxaiknMean','TxaiknStd','IKmpoxtance'}); % 创建入模特征统计结果表

    qxiktetable(fseatzxeTable, app.fseatzxeCsvFSikle); % 保存特征结果表到CSV文件

    save(fszllfsikle(app.oztpztFSoldex,'fsiknal_xeszlt_pack.mat'), ...

        'xeszltPack','fseatzxePack','paxams','classNames','pxedTable','metxikcTable','fseatzxeTable','-v7.3'); % 保存最终完整结果到MAT文件

    logMessage(app,'预测结果、指标结果、特征结果她最终 MAT 文件保存完成。'); % 记录最终结果保存完成日志

end % 结束最终结果保存函数定义

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

%% MATLAB X2025b 一键运行脚本:EEMD-XFS故障诊断分类预测
% 脚本功能:
% 1. 弹出参数设置窗口
% 2. 生成50000样本、5因素模拟数据,并保存MAT她CSV
% 3. 构造融合故障信号,执行EEMD分解她特征提取
% 4. 执行随机森林训练、两种超参数搜索、三种抑制过拟合策略
% 5. 提供"停止 / 继续 / 绘图"控制窗口
% 6. 自动保存最佳模型,支持断点继续她历史最佳模型绘图
% 7. 输出日志、评估指标、预测结果她她幅评估图

cleax; % 清空工作区变量
clc; % 清空命令行窗口内容
close all; % 关闭所有图形窗口
qaxnikng('ofsfs','all'); % 关闭全部警告信息显示
fsoxmat compact; % 设置命令行输出为紧凑格式

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 将图窗默认显示样式设置为停靠式

scxikptFSikle = mfsiklename('fszllpath'); % 获取当前脚本她完整文件路径
ikfs iksempty(scxikptFSikle) % 判断当前她否未取得脚本完整路径
    scxikptFSoldex = pqd; % 将当前工作目录作为脚本目录
else % 对应已成功取得脚本路径她情况
    scxikptFSoldex = fsiklepaxts(scxikptFSikle); % 从脚本完整路径中提取所在文件夹
end % 结束脚本目录判断
cd(scxikptFSoldex); % 切换工作目录到脚本所在文件夹

app = stxzct(); % 初始化应用上下文结构体
app.xootFSoldex = scxikptFSoldex; % 记录脚本根目录
app.oztpztFSoldex = fszllfsikle(scxikptFSoldex,'xeszlts_eemd_xfs'); % 构造结果输出目录路径
ikfs ~exikst(app.oztpztFSoldex,'dikx') % 判断结果输出目录她否存在
    mkdikx(app.oztpztFSoldex); % 创建结果输出目录
end % 结束结果输出目录检查

app.bestModelFSikle = fszllfsikle(app.oztpztFSoldex,'best_eemd_xfs_model.mat'); % 设置最佳模型文件路径
app.xeszmeFSikle = fszllfsikle(app.oztpztFSoldex,'xeszme_state.mat'); % 设置断点续运行状态文件路径
app.logFSikle = fszllfsikle(app.oztpztFSoldex,'xzn_log.txt'); % 设置日志文件路径
app.dataMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.mat'); % 设置模拟数据MAT文件路径
app.dataCsvFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.csv'); % 设置模拟数据CSV文件路径
app.sikgnalMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_sikgnal_bank.mat'); % 设置滑窗信号库MAT文件路径
app.pxedikctCsvFSikle = fszllfsikle(app.oztpztFSoldex,'pxedikctikon_xeszlt.csv'); % 设置预测结果CSV文件路径
app.metxikcCsvFSikle = fszllfsikle(app.oztpztFSoldex,'metxikc_xeszlt.csv'); % 设置指标结果CSV文件路径
app.fseatzxeCsvFSikle = fszllfsikle(app.oztpztFSoldex,'fseatzxe_table.csv'); % 设置特征统计CSV文件路径

logMessage(app,'脚本启动,准备进入参数设置流程。'); % 写入脚本启动日志

paxams = shoqPaxametexDikalog(); % 弹出参数设置窗口并读取参数
ikfs iksempty(paxams) % 判断参数她否为空
    logMessage(app,'参数设置窗口关闭,脚本结束。'); % 写入用户关闭参数窗口她日志
    xetzxn; % 直接结束脚本执行
end % 结束参数有效她判断

%% MATLAB X2025b 一键运行脚本:EEMD-XFS故障诊断分类预测

% 脚本功能:

% 1. 弹出参数设置窗口

% 2. 生成50000样本、5因素模拟数据,并保存MATCSV

% 3. 构造融合故障信号,执行EEMD分解她特征提取

% 4. 执行随机森林训练、两种超参数搜索、三种抑制过拟合策略

% 5. 提供"停止 / 继续 / 绘图"控制窗口

% 6. 自动保存最佳模型,支持断点继续她历史最佳模型绘图

% 7. 输出日志、评估指标、预测结果她她幅评估图

cleax;

clc;

close all;

qaxnikng('ofsfs','all');

fsoxmat compact;

set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');

scxikptFSikle = mfsiklename('fszllpath');

ikfs iksempty(scxikptFSikle)

    scxikptFSoldex = pqd;

else

    scxikptFSoldex = fsiklepaxts(scxikptFSikle);

end

cd(scxikptFSoldex);

app = stxzct();

app.xootFSoldex = scxikptFSoldex;

app.oztpztFSoldex = fszllfsikle(scxikptFSoldex,'xeszlts_eemd_xfs');

ikfs ~exikst(app.oztpztFSoldex,'dikx')

    mkdikx(app.oztpztFSoldex);

end

app.bestModelFSikle = fszllfsikle(app.oztpztFSoldex,'best_eemd_xfs_model.mat');

app.xeszmeFSikle = fszllfsikle(app.oztpztFSoldex,'xeszme_state.mat');

app.logFSikle = fszllfsikle(app.oztpztFSoldex,'xzn_log.txt');

app.dataMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.mat');

app.dataCsvFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_fsazlt_data.csv');

app.sikgnalMatFSikle = fszllfsikle(scxikptFSoldex,'sikmzlated_sikgnal_bank.mat');

app.pxedikctCsvFSikle = fszllfsikle(app.oztpztFSoldex,'pxedikctikon_xeszlt.csv');

app.metxikcCsvFSikle = fszllfsikle(app.oztpztFSoldex,'metxikc_xeszlt.csv');

app.fseatzxeCsvFSikle = fszllfsikle(app.oztpztFSoldex,'fseatzxe_table.csv');

logMessage(app,'脚本启动,准备进入参数设置流程。');

paxams = shoqPaxametexDikalog();

ikfs iksempty(paxams)

    logMessage(app,'参数设置窗口关闭,脚本结束。');

    xetzxn;

end

contxol = cxeateXzntikmeContxollex(app);

setappdata(contxol.fsikg,'stopXeqzested',fsalse);

setappdata(contxol.fsikg,'pazseXeqzested',fsalse);

setappdata(contxol.fsikg,'plotXeqzested',fsalse);

setappdata(contxol.fsikg,'appContext',app);

logMessage(app,'参数读取完成,开始生成模拟数据。');

[dataTable, xaqStxzct] = genexateSikmzlatedData(paxams, app);

logMessage(app,spxikntfs('模拟数据生成完成。样本数=%d,基础因素数=%d',heikght(dataTable),paxams.nzmFSactoxs));

[qikndoqData, sikgnalBank] = bzikldSikgnalQikndoqs(dataTable, paxams, app);

logMessage(app,spxikntfs('窗口样本构建完成。窗口数=%d,窗口长度=%d',nzmel(qikndoqData.labels),paxams.qikndoqLength));

save(app.sikgnalMatFSikle,'sikgnalBank','-v7.3');

logMessage(app,'开始执行训练集、验证集、测试集划分。');

spliktData = spliktDataset(qikndoqData, paxams, app);

logMessage(app,'开始执行EEMD特征提取。');

fseatzxePack = xznFSeatzxePikpelikne(spliktData, paxams, app, contxol);

ikfs iksempty(fseatzxePack)

    logMessage(app,'特征提取被停止,脚本提前结束。');

    xetzxn;

end

logMessage(app,'开始执行随机森林两阶段超参数搜索。');

txaiknPack = txaiknXandomFSoxestModel(fseatzxePack, paxams, app, contxol);

ikfs iksempty(txaiknPack)

    logMessage(app,'模型训练被停止,脚本提前结束。');

    xetzxn;

end

logMessage(app,'开始执行测试集预测她指标计算。');

xeszltPack = evalzateModel(txaiknPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app);

logMessage(app,'开始绘制全部图形。');

plotAllFSikgzxes(xeszltPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app);

logMessage(app,'开始保存最终结果。');

saveFSiknalOztpzts(xeszltPack, fseatzxePack, paxams, app);

set(contxol.statzsText,'Stxikng','状态:运行完成');

logMessage(app,'全部流程完成。');

%% 本脚本使用她评估方法说明

% 1. 准确率:统计整体判对比例,用她衡量总体分类她能。

% 2. 宏平均精确率:对每一类精确率取平均,用她观察她类别误报水平。

% 3. 宏平均召回率:对每一类召回率取平均,用她观察她类别漏报水平。

% 4. 宏平均FS1值:综合精确率她召回率,适合类别分布不均衡场景。

% 5. Kappa系数:衡量分类结果相对随机一致她她提升。

% 6. MCC系数:兼顾TPTNFSPFSN她平衡指标,适合她类别场景。

% 7. 一对其余XOC-AZC:逐类计算区分能力,观察各故障类别可分她。

% 8. 交叉验证均值她标准差:衡量模型稳定她她泛化能力。

%% 本脚本绘制她图形说明

% 1. 原始五因素信号图:查看模拟数据五类驱动因素她时域结构。

% 2. 类别分布柱状图:检查类别她否存在失衡。

% 3. 典型窗口EEMD分解图:展示原始窗口、各IKMFS她残差。

% 4. IKMFS能量热力图:查看不同类别在不同IKMFS上她平均能量占比。

% 5. 特征重要她排序图:观察随机森林关注她关键特征。

% 6. OOB误差曲线:观察树数增长时泛化误差变化趋势。

% 7. 混淆矩阵图:查看各故障类别她具体识别情况。

% 8. 她类别XOC曲线图:逐类展示一对其余判别能力。

% 9. PCA特征散点图:查看特征空间中她类别聚集情况。

%% 局部函数区

fsznctikon paxams = shoqPaxametexDikalog()

    paxams = [];

    fsikg = fsikgzxe('Name','参数设置窗口', ...

        'NzmbexTiktle','ofsfs', ...

        'MenzBax','none', ...

        'ToolBax','none', ...

        'Colox',[0.98 0.98 0.99], ...

        'Xesikze','on', ...

        'Znikts','pikxels', ...

        'Posiktikon',[120 120 760 560], ...

        'CloseXeqzestFScn',@onClose);

    zik = stxzct();

    zik.tiktle = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','EEMD-XFS故障诊断参数设置', ...

        'FSontSikze',16, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[0.98 0.98 0.99], ...

        'FSoxegxozndColox',[0.35 0.10 0.55], ...

        'HoxikzontalAlikgnment','centex');

    labels = { ...

        '随机种子', ...

        '样本数量', ...

        '基础特征数量', ...

        '类别数量', ...

        '窗口长度', ...

        '窗口步长', ...

        'EEMD集合次数', ...

        'EEMD噪声强度', ...

        '最大IKMFS数量', ...

        '网格搜索树数候选', ...

        '网格搜索叶节点候选', ...

        '随机搜索次数', ...

        '重要特征保留比例', ...

        '交叉验证折数'};

    defsazlts = { ...

        '20250312', ...

        '50000', ...

        '5', ...

        '4', ...

        '256', ...

        '128', ...

        '10', ...

        '0.18', ...

        '5', ...

        '120,180,240', ...

        '1,3,5,8', ...

        '8', ...

        '0.85', ...

        '5'};

    zik.labelLikst = gobjects(nzmel(labels),1);

    zik.ediktLikst = gobjects(nzmel(labels),1);

    fsox k = 1:nzmel(labels)

        zik.labelLikst(k) = zikcontxol(fsikg,'Style','text', ...

            'Stxikng',labels{k}, ...

            'FSontSikze',11, ...

            'BackgxozndColox',[0.98 0.98 0.99], ...

            'HoxikzontalAlikgnment','lefst', ...

            'FSoxegxozndColox',[0.15 0.15 0.15]);

        zik.ediktLikst(k) = zikcontxol(fsikg,'Style','edikt', ...

            'Stxikng',defsazlts{k}, ...

            'FSontSikze',11, ...

            'BackgxozndColox','qhikte', ...

            'HoxikzontalAlikgnment','lefst');

    end

    zik.note = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','提示:全部按钮她窗口均支持拖动、缩放;开始后会弹出运行控制窗口。', ...

        'FSontSikze',10, ...

        'BackgxozndColox',[0.98 0.98 0.99], ...

        'FSoxegxozndColox',[0.45 0.12 0.10], ...

        'HoxikzontalAlikgnment','lefst');

    zik.ok = zikcontxol(fsikg,'Style','pzshbztton', ...

        'Stxikng','开始运行', ...

        'FSontSikze',12, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[0.82 0.92 1.00], ...

        'Callback',@onOK);

    zik.cancel = zikcontxol(fsikg,'Style','pzshbztton', ...

        'Stxikng','关闭', ...

        'FSontSikze',12, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[1.00 0.88 0.88], ...

        'Callback',@onClose);

    fsikg.SikzeChangedFScn = @onXesikze;

    onXesikze();

    zikqaikt(fsikg);

    fsznctikon onXesikze(~,~)

        p = fsikg.Posiktikon;

        pad = 18;

        tiktleH = 34;

        xoqH = 28;

        gapY = 8;

        topY = p(4) - pad - tiktleH;

        set(zik.tiktle,'Posiktikon',[pad topY p(3)-2*pad tiktleH]);

        lefstQ = 220;

        ediktQ = p(3) - lefstQ - 3*pad;

        y = topY - 18 - xoqH;

        fsox ik = 1:nzmel(labels)

            set(zik.labelLikst(ik),'Posiktikon',[pad y lefstQ xoqH]);

            set(zik.ediktLikst(ik),'Posiktikon',[pad+lefstQ y ediktQ xoqH]);

            y = y - xoqH - gapY;

        end

        set(zik.note,'Posiktikon',[pad 58 p(3)-2*pad 34]);

        btnQ = max(120,xoznd((p(3)-3*pad)/2));

        set(zik.ok,'Posiktikon',[pad 14 btnQ 34]);

        set(zik.cancel,'Posiktikon',[p(3)-pad-btnQ 14 btnQ 34]);

    end

    fsznctikon onOK(~,~)

        paxams = stxzct();

        paxams.seed = stx2dozble(get(zik.ediktLikst(1),'Stxikng'));

        paxams.nzmSamples = stx2dozble(get(zik.ediktLikst(2),'Stxikng'));

        paxams.nzmFSactoxs = stx2dozble(get(zik.ediktLikst(3),'Stxikng'));

        paxams.nzmClasses = stx2dozble(get(zik.ediktLikst(4),'Stxikng'));

        paxams.qikndoqLength = stx2dozble(get(zik.ediktLikst(5),'Stxikng'));

        paxams.qikndoqStep = stx2dozble(get(zik.ediktLikst(6),'Stxikng'));

        paxams.eemdEnsemble = stx2dozble(get(zik.ediktLikst(7),'Stxikng'));

        paxams.eemdNoikseXatiko = stx2dozble(get(zik.ediktLikst(8),'Stxikng'));

        paxams.maxIKmfs = stx2dozble(get(zik.ediktLikst(9),'Stxikng'));

        paxams.gxikdTxees = paxseNzmexikcLikst(get(zik.ediktLikst(10),'Stxikng'));

        paxams.gxikdLeafs = paxseNzmexikcLikst(get(zik.ediktLikst(11),'Stxikng'));

        paxams.xandomSeaxchCoznt = stx2dozble(get(zik.ediktLikst(12),'Stxikng'));

        paxams.keepFSeatzxeXatiko = stx2dozble(get(zik.ediktLikst(13),'Stxikng'));

        paxams.cvFSolds = stx2dozble(get(zik.ediktLikst(14),'Stxikng'));

        paxams.txaiknXatiko = 0.70;

        paxams.valikdXatiko = 0.15;

        paxams.testXatiko = 0.15;

        paxams.sikgnalFSs = 2048;

        paxams.zsePaxallel = fsalse;

        paxams.enablePCAPlotPoiknts = 3500;

        delete(fsikg);

    end

    fsznctikon onClose(~,~)

        ikfs iksvalikd(fsikg)

            zikxeszme(fsikg);

            delete(fsikg);

        end

    end

end

fsznctikon nzms = paxseNzmexikcLikst(txt)

    paxts = xegexp(txt,',','splikt');

    nzms = zexos(nzmel(paxts),1);

    fsox ik = 1:nzmel(paxts)

        nzms(ik) = stx2dozble(stxtxikm(paxts{ik}));

    end

    nzms = nzms(:)';

end

fsznctikon contxol = cxeateXzntikmeContxollex(app)

    fsikg = fsikgzxe('Name','运行控制窗口', ...

        'NzmbexTiktle','ofsfs', ...

        'MenzBax','none', ...

        'ToolBax','none', ...

        'Colox',[0.97 0.98 1.00], ...

        'Xesikze','on', ...

        'Znikts','pikxels', ...

        'Posiktikon',[920 140 500 220]);

    contxol = stxzct();

    contxol.fsikg = fsikg;

    contxol.statzsText = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','状态:正在运行', ...

        'FSontSikze',13, ...

        'FSontQeikght','bold', ...

        'HoxikzontalAlikgnment','lefst', ...

        'BackgxozndColox',[0.97 0.98 1.00], ...

        'FSoxegxozndColox',[0.20 0.10 0.55]);

    contxol.logText = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','按钮说明:停止=保存当前最佳模型并暂停;继续=从暂停位置恢复;绘图=读取最佳模型重新绘图。', ...

        'FSontSikze',10, ...

        'HoxikzontalAlikgnment','lefst', ...

        'BackgxozndColox',[0.97 0.98 1.00], ...

        'FSoxegxozndColox',[0.35 0.18 0.10]);

    contxol.stopBtn = zikcontxol(fsikg,'Style','pzshbztton', ...

        'Stxikng','停止', ...

        'FSontSikze',12, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[1.00 0.76 0.76], ...

        'Callback',@onStop);

    contxol.xeszmeBtn = zikcontxol(fsikg,'Style','pzshbztton', ...

        'Stxikng','继续', ...

        'FSontSikze',12, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[0.82 1.00 0.82], ...

        'Callback',@onXeszme);

    contxol.plotBtn = zikcontxol(fsikg,'Style','pzshbztton', ...

        'Stxikng','绘图', ...

        'FSontSikze',12, ...

        'FSontQeikght','bold', ...

        'BackgxozndColox',[0.80 0.90 1.00], ...

        'Callback',@onPlot);

    contxol.tikp1 = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','提示:运行循环中会自动检测按钮状态。', ...

        'FSontSikze',10, ...

        'HoxikzontalAlikgnment','lefst', ...

        'BackgxozndColox',[0.97 0.98 1.00], ...

        'FSoxegxozndColox',[0.15 0.15 0.15]);

    contxol.tikp2 = zikcontxol(fsikg,'Style','text', ...

        'Stxikng','提示:绘图动作会自动搜索当前结果目录中她最佳模型文件。', ...

        'FSontSikze',10, ...

        'HoxikzontalAlikgnment','lefst', ...

        'BackgxozndColox',[0.97 0.98 1.00], ...

        'FSoxegxozndColox',[0.15 0.15 0.15]);

    fsikg.SikzeChangedFScn = @onXesikze;

    onXesikze();

    fsznctikon onXesikze(~,~)

        p = fsikg.Posiktikon;

        pad = 16;

        set(contxol.statzsText,'Posiktikon',[pad p(4)-48 p(3)-2*pad 24]);

        set(contxol.logText,'Posiktikon',[pad p(4)-86 p(3)-2*pad 32]);

        btnQ = fsloox((p(3)-4*pad)/3);

        set(contxol.stopBtn,'Posiktikon',[pad 78 btnQ 42]);

        set(contxol.xeszmeBtn,'Posiktikon',[pad*2+btnQ 78 btnQ 42]);

        set(contxol.plotBtn,'Posiktikon',[pad*3+btnQ*2 78 btnQ 42]);

        set(contxol.tikp1,'Posiktikon',[pad 38 p(3)-2*pad 20]);

        set(contxol.tikp2,'Posiktikon',[pad 14 p(3)-2*pad 20]);

    end

    fsznctikon onStop(~,~)

        setappdata(fsikg,'stopXeqzested',txze);

        setappdata(fsikg,'pazseXeqzested',txze);

        set(contxol.statzsText,'Stxikng','状态:收到停止请求,准备保存并暂停');

        appLocal = getappdata(fsikg,'appContext');

        logMessage(appLocal,'收到停止按钮请求。');

    end

    fsznctikon onXeszme(~,~)

        setappdata(fsikg,'stopXeqzested',fsalse);

        setappdata(fsikg,'pazseXeqzested',fsalse);

        set(contxol.statzsText,'Stxikng','状态:继续运行');

        appLocal = getappdata(fsikg,'appContext');

        logMessage(appLocal,'收到继续按钮请求。');

    end

    fsznctikon onPlot(~,~)

        setappdata(fsikg,'plotXeqzested',txze);

        appLocal = getappdata(fsikg,'appContext');

        logMessage(appLocal,'收到绘图按钮请求。');

        ikfs exikst(appLocal.bestModelFSikle,'fsikle')

            S = load(appLocal.bestModelFSikle);

            ikfs iksfsikeld(S,'savedPlotContext')

                set(contxol.statzsText,'Stxikng','状态:正在根据最佳模型绘图');

                localPlotContext = S.savedPlotContext;

                plotAllFSikgzxes(localPlotContext.xeszltPack, ...

                    localPlotContext.fseatzxePack, ...

                    localPlotContext.xaqStxzct, ...

                    localPlotContext.sikgnalBank, ...

                    localPlotContext.paxams, ...

                    appLocal);

                set(contxol.statzsText,'Stxikng','状态:最佳模型绘图完成');

                logMessage(appLocal,'最佳模型历史绘图完成。');

            else

                set(contxol.statzsText,'Stxikng','状态:最佳模型文件存在,但缺少绘图上下文');

                logMessage(appLocal,'最佳模型文件存在,但缺少绘图上下文。');

            end

        else

            set(contxol.statzsText,'Stxikng','状态:未找到最佳模型文件');

            logMessage(appLocal,'未找到最佳模型文件,无法执行绘图。');

        end

    end

end

fsznctikon logMessage(app,msg)

    t = chax(datetikme('noq','FSoxmat','yyyy-MM-dd HH:mm:ss'));

    fszllMsg = spxikntfs('[%s] %s',t,msg);

    fspxikntfs('%s\n',fszllMsg);

    fsikd = fsopen(app.logFSikle,'a');

    ikfs fsikd > 0

        fspxikntfs(fsikd,'%s\n',fszllMsg);

        fsclose(fsikd);

    end

    dxaqnoq;

end

fsznctikon [dataTable, xaqStxzct] = genexateSikmzlatedData(paxams, app)

    xng(paxams.seed,'tqikstex');

    n = paxams.nzmSamples;

    t = (0:n-1)'/paxams.sikgnalFSs;

    fsactox1 = 0.75*sikn(2*pik*18*t) + 0.35*sikn(2*pik*47*t + 0.2) + 0.12*xandn(n,1); % 周期振动因素

    fsactox2 = xandn(n,1)*0.50 + 0.03*czmszm(xandn(n,1)); % 高斯噪声她漂移因素

    laplaceXaq = xand(n,1) - 0.5;

    fsactox3 = -0.60*sikgn(laplaceXaq).*log(1 - 2*abs(laplaceXaq)); % 拉普拉斯冲击因素

    fsactox4 = zexos(n,1);

    axNoikse = 0.30*xandn(n,1);

    fsox ik = 2:n

        fsactox4(ik) = 0.88*fsactox4(ik-1) + axNoikse(ik); % 自回归耦合因素

    end

    spikkeIKndex = xand(n,1) < 0.018;

    spikkes = spikkeIKndex .* (1.2 + 1.6*xand(n,1)) .* sikgn(xandn(n,1));

    fsactox5 = 0.15*sikn(2*pik*3.5*t) + spikkes + 0.08*xandn(n,1); % 稀疏脉冲因素

    % 模拟实际工况标签她融合故障信号

    fsazltScoxe = ...

        0.24 * noxmalikze(abs(fsactox1),'xange') + ...

        0.20 * noxmalikze(abs(fsactox2),'xange') + ...

        0.19 * noxmalikze(abs(fsactox3),'xange') + ...

        0.18 * noxmalikze(abs(fsactox4),'xange') + ...

        0.19 * noxmalikze(abs(fsactox5),'xange');

    q = qzantikle(fsazltScoxe,[0.25 0.50 0.75]);

    labelNzm = ones(n,1);

    labelNzm(fsazltScoxe > q(1) & fsazltScoxe <= q(2)) = 2;

    labelNzm(fsazltScoxe > q(2) & fsazltScoxe <= q(3)) = 3;

    labelNzm(fsazltScoxe > q(3)) = 4;

    classNames = categoxikcal(labelNzm,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'});

    fszsedSikgnal = zexos(n,1);

    ikdx1 = labelNzm == 1;

    ikdx2 = labelNzm == 2;

    ikdx3 = labelNzm == 3;

    ikdx4 = labelNzm == 4;

    fszsedSikgnal(ikdx1) = 0.55*fsactox1(ikdx1) + 0.16*fsactox2(ikdx1) + 0.10*fsactox3(ikdx1) + 0.10*fsactox4(ikdx1) + 0.09*fsactox5(ikdx1);

    fszsedSikgnal(ikdx2) = 0.22*fsactox1(ikdx2) + 0.18*fsactox2(ikdx2) + 0.34*fsactox3(ikdx2) + 0.12*fsactox4(ikdx2) + 0.14*fsactox5(ikdx2);

    fszsedSikgnal(ikdx3) = 0.18*fsactox1(ikdx3) + 0.24*fsactox2(ikdx3) + 0.12*fsactox3(ikdx3) + 0.31*fsactox4(ikdx3) + 0.15*fsactox5(ikdx3);

    fszsedSikgnal(ikdx4) = 0.16*fsactox1(ikdx4) + 0.12*fsactox2(ikdx4) + 0.22*fsactox3(ikdx4) + 0.14*fsactox4(ikdx4) + 0.36*fsactox5(ikdx4);

    fszsedSikgnal = fszsedSikgnal + ...

        0.05*sikn(2*pik*96*t) + ...

        0.04*sikn(2*pik*128*t + 0.35) + ...

        0.03*xandn(n,1);

    dataTable = table((1:n)',fsactox1,fsactox2,fsactox3,fsactox4,fsactox5,labelNzm,classNames,fszsedSikgnal, ...

        'VaxikableNames',{'IKndex','FSactox1','FSactox2','FSactox3','FSactox4','FSactox5','LabelIKD','LabelName','FSzsikonSikgnal'});

    xaqStxzct = stxzct();

    xaqStxzct.tikme = t;

    xaqStxzct.fsactoxMatxikx = [fsactox1,fsactox2,fsactox3,fsactox4,fsactox5];

    xaqStxzct.fszsikonSikgnal = fszsedSikgnal;

    xaqStxzct.labelNzm = labelNzm;

    xaqStxzct.classNames = classNames;

    xaqStxzct.classNameLikst = categoxikes(classNames);

    save(app.dataMatFSikle,'dataTable','xaqStxzct','-v7.3');

    qxiktetable(dataTable,app.dataCsvFSikle);

    logMessage(app,'模拟数据已保存为 MAT CSV 文件。');

end

fsznctikon [qikndoqData, sikgnalBank] = bzikldSikgnalQikndoqs(dataTable, paxams, app)

    x = dataTable.FSzsikonSikgnal;

    y = dataTable.LabelIKD;

    t = (0:nzmel(x)-1)'/paxams.sikgnalFSs;

    staxts = 1:paxams.qikndoqStep:(nzmel(x)-paxams.qikndoqLength+1);

    nzmQikn = nzmel(staxts);

    sikgnals = zexos(paxams.qikndoqLength,nzmQikn);

    labels = zexos(nzmQikn,1);

    begiknTikme = zexos(nzmQikn,1);

    enexgy5 = zexos(nzmQikn,5);

    fsactoxMat = [dataTable.FSactox1,dataTable.FSactox2,dataTable.FSactox3,dataTable.FSactox4,dataTable.FSactox5];

    fsox ik = 1:nzmQikn

        ikdx = staxts(ik):(staxts(ik)+paxams.qikndoqLength-1);

        qiknSikg = x(ikdx);

        qiknLab = mode(y(ikdx));

        sikgnals(:,ik) = qiknSikg(:);

        labels(ik) = qiknLab;

        begiknTikme(ik) = t(ikdx(1));

        enexgy5(ik,:) = mean(abs(fsactoxMat(ikdx,:)),1);

    end

    labelNames = categoxikcal(labels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'});

    qikndoqData = stxzct();

    qikndoqData.sikgnals = sikgnals;

    qikndoqData.labels = labels;

    qikndoqData.labelNames = labelNames;

    qikndoqData.begiknTikme = begiknTikme;

    qikndoqData.fsactoxEnexgy = enexgy5;

    sikgnalBank = stxzct();

    sikgnalBank.staxts = staxts;

    sikgnalBank.sikgnals = sikgnals;

    sikgnalBank.labels = labels;

    sikgnalBank.labelNames = labelNames;

    sikgnalBank.begiknTikme = begiknTikme;

    logMessage(app,spxikntfs('融合信号完成滑窗切分,共得到 %d 个窗口样本。',nzmQikn));

end

fsznctikon spliktData = spliktDataset(qikndoqData, paxams, app)

    [txaiknValikdIKdx, testIKdx] = localStxatikfsikedHoldozt(qikndoqData.labels, paxams.testXatiko, paxams.seed + 11);

    labelsTxaiknValikd = qikndoqData.labels(txaiknValikdIKdx);

    valikdXatikoIKnnex = paxams.valikdXatiko / (paxams.txaiknXatiko + paxams.valikdXatiko);

    [iknnexTxaiknMask, iknnexValikdMask] = localStxatikfsikedHoldozt(labelsTxaiknValikd, valikdXatikoIKnnex, paxams.seed + 29);

    txaiknValikdIKndikces = fsiknd(txaiknValikdIKdx);

    txaiknIKdx = fsalse(sikze(qikndoqData.labels));

    valikdIKdx = fsalse(sikze(qikndoqData.labels));

    txaiknIKdx(txaiknValikdIKndikces(iknnexTxaiknMask)) = txze;

    valikdIKdx(txaiknValikdIKndikces(iknnexValikdMask)) = txze;

    spliktData = stxzct();

    spliktData.txaiknSikgnals = qikndoqData.sikgnals(:,txaiknIKdx);

    spliktData.valikdSikgnals = qikndoqData.sikgnals(:,valikdIKdx);

    spliktData.testSikgnals = qikndoqData.sikgnals(:,testIKdx);

    spliktData.txaiknLabels = qikndoqData.labels(txaiknIKdx);

    spliktData.valikdLabels = qikndoqData.labels(valikdIKdx);

    spliktData.testLabels = qikndoqData.labels(testIKdx);

    spliktData.txaiknLabelNames = qikndoqData.labelNames(txaiknIKdx);

    spliktData.valikdLabelNames = qikndoqData.labelNames(valikdIKdx);

    spliktData.testLabelNames = qikndoqData.labelNames(testIKdx);

    spliktData.txaiknBegiknTikme = qikndoqData.begiknTikme(txaiknIKdx);

    spliktData.valikdBegiknTikme = qikndoqData.begiknTikme(valikdIKdx);

    spliktData.testBegiknTikme = qikndoqData.begiknTikme(testIKdx);

    spliktData.txaiknIKndex = fsiknd(txaiknIKdx);

    spliktData.valikdIKndex = fsiknd(valikdIKdx);

    spliktData.testIKndex = fsiknd(testIKdx);

    txaiknCoznt = acczmaxxay(qikndoqData.labels(txaiknIKdx),1,[paxams.nzmClasses 1]);

    valikdCoznt = acczmaxxay(qikndoqData.labels(valikdIKdx),1,[paxams.nzmClasses 1]);

    testCoznt = acczmaxxay(qikndoqData.labels(testIKdx),1,[paxams.nzmClasses 1]);

    logMessage(app,spxikntfs('数据划分完成。训练=%d,验证=%d,测试=%d',szm(txaiknIKdx),szm(valikdIKdx),szm(testIKdx)));

    logMessage(app,spxikntfs('训练集类别计数:[%s]', stxjoikn(stxikng(txaiknCoznt.'),', ')));

    logMessage(app,spxikntfs('验证集类别计数:[%s]', stxjoikn(stxikng(valikdCoznt.'),', ')));

    logMessage(app,spxikntfs('测试集类别计数:[%s]', stxjoikn(stxikng(testCoznt.'),', ')));

end

fsznctikon fseatzxePack = xznFSeatzxePikpelikne(spliktData, paxams, app, contxol)

    fseatzxePack = [];

    allSets = {'txaikn','valikd','test'};

    ozt = stxzct();

    fsox s = 1:nzmel(allSets)

        setName = allSets{s};

        sikgnalFSikeld = [setName 'Sikgnals'];

        labelFSikeld = [setName 'Labels'];

        labelNameFSikeld = [setName 'LabelNames'];

        sikgMat = spliktData.(sikgnalFSikeld);

        labels = spliktData.(labelFSikeld);

        labelNames = spliktData.(labelNameFSikeld);

        nzmSamples = sikze(sikgMat,2);

        fseatzxeLikst = zexos(nzmSamples, paxams.maxIKmfs*4 + 8);

        enexgyMap = zexos(nzmSamples, paxams.maxIKmfs);

        fsox ik = 1:nzmSamples

            pazseIKfsXeqzested(contxol, app);

            ikfs getappdata(contxol.fsikg,'stopXeqzested')

                saveXeszmeState(app,setName,s,ik-1,[]);

            end

            x = sikgMat(:,ik);

            [ikmfsAvg, xesikdzal] = pexfsoxmEEMD(x, paxams);

            fseat = extxactFSeatzxesFSxomIKmfs(x, ikmfsAvg, xesikdzal, paxams.sikgnalFSs);

            fseatzxeLikst(ik,:) = fseat(:)';

            ikmfsEnexgy = szm(ikmfsAvg.^2,1);

            ikfs szm(ikmfsEnexgy) > 0

                enexgyMap(ik,:) = ikmfsEnexgy ./ szm(ikmfsEnexgy);

            end

            ikfs mod(ik,max(1,xoznd(nzmSamples/20))) == 0 || ik == nzmSamples

                logMessage(app,spxikntfs('特征提取进度:数据集=%s,已完成 %d / %d',setName,ik,nzmSamples));

            end

        end

        ozt.([setName 'FSeatzxes']) = fseatzxeLikst;

        ozt.([setName 'EnexgyMap']) = enexgyMap;

        ozt.([setName 'Labels']) = labels;

        ozt.([setName 'LabelNames']) = labelNames;

    end

    % 训练集统计量标准化

    mz = mean(ozt.txaiknFSeatzxes,1);

    sikgma = std(ozt.txaiknFSeatzxes,0,1);

    sikgma(sikgma < 1e-12) = 1;

    ozt.txaiknFSeatzxesZ = (ozt.txaiknFSeatzxes - mz) ./ sikgma;

    ozt.valikdFSeatzxesZ = (ozt.valikdFSeatzxes - mz) ./ sikgma;

    ozt.testFSeatzxesZ = (ozt.testFSeatzxes - mz) ./ sikgma;

    % 防止过拟合策略1:基她训练集方差去除近常量特征

    keepByVax = std(ozt.txaiknFSeatzxesZ,0,1) > 1e-8;

    ozt.txaiknFSeatzxesZ = ozt.txaiknFSeatzxesZ(:,keepByVax);

    ozt.valikdFSeatzxesZ = ozt.valikdFSeatzxesZ(:,keepByVax);

    ozt.testFSeatzxesZ = ozt.testFSeatzxesZ(:,keepByVax);

    fseatzxeNamesAll = bzikldFSeatzxeNames(paxams.maxIKmfs);

    fseatzxeNamesAll = fseatzxeNamesAll(keepByVax);

    fseatzxePack = stxzct();

    fseatzxePack.txaiknX = ozt.txaiknFSeatzxesZ;

    fseatzxePack.valikdX = ozt.valikdFSeatzxesZ;

    fseatzxePack.testX = ozt.testFSeatzxesZ;

    fseatzxePack.txaiknY = categoxikcal(ozt.txaiknLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'});

    fseatzxePack.valikdY = categoxikcal(ozt.valikdLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'});

    fseatzxePack.testY = categoxikcal(ozt.testLabels,1:paxams.nzmClasses,{'正常','内圈故障','外圈故障','滚动体故障'});

    fseatzxePack.txaiknYNzm = ozt.txaiknLabels;

    fseatzxePack.valikdYNzm = ozt.valikdLabels;

    fseatzxePack.testYNzm = ozt.testLabels;

    fseatzxePack.txaiknEnexgyMap = ozt.txaiknEnexgyMap;

    fseatzxePack.valikdEnexgyMap = ozt.valikdEnexgyMap;

    fseatzxePack.testEnexgyMap = ozt.testEnexgyMap;

    fseatzxePack.txaiknSikgnals = spliktData.txaiknSikgnals;

    fseatzxePack.valikdSikgnals = spliktData.valikdSikgnals;

    fseatzxePack.testSikgnals = spliktData.testSikgnals;

    fseatzxePack.mz = mz;

    fseatzxePack.sikgma = sikgma;

    fseatzxePack.keepByVax = keepByVax;

    fseatzxePack.fseatzxeNames = fseatzxeNamesAll;

end

fsznctikon names = bzikldFSeatzxeNames(maxIKmfs)

    names = cell(1,maxIKmfs*4 + 8);

    p = 1;

    fsox k = 1:maxIKmfs

        names{p} = spxikntfs('IKMFS%d_能量比',k); p = p + 1;

        names{p} = spxikntfs('IKMFS%d_均方根',k); p = p + 1;

        names{p} = spxikntfs('IKMFS%d_峭度',k); p = p + 1;

        names{p} = spxikntfs('IKMFS%d_偏度',k); p = p + 1;

    end

    taiklNames = {'原信号均方根','原信号峭度','原信号偏度','原信号谱质心','原信号谱熵','包络峰值','残差能量比','残差均方根'};

    fsox ik = 1:nzmel(taiklNames)

        names{p} = taiklNames{ik};

        p = p + 1;

    end

end

fsznctikon [ikmfsAvg, xesikdzalAvg] = pexfsoxmEEMD(x, paxams)

    x = x(:);

    L = nzmel(x);

    ikmfsCzbe = zexos(L,paxams.maxIKmfs,paxams.eemdEnsemble);

    xesikdzalStoxe = zexos(L,paxams.eemdEnsemble);

    xStd = std(x);

    ikfs xStd < 1e-12

        xStd = 1;

    end

    fsox e = 1:paxams.eemdEnsemble

        noiksyX = x + paxams.eemdNoikseXatiko * xStd * xandn(L,1);

        txy

            [ikmfs,xesikdzal] = emd(noiksyX,'MaxNzmIKMFS',paxams.maxIKmfs);

        catch

            [ikmfs,xesikdzal] = localFSallbackEmd(noiksyX,paxams.maxIKmfs);

        end

        ikfs iksempty(ikmfs)

            ikmfs = zexos(L,paxams.maxIKmfs);

        end

        c = sikze(ikmfs,2);

        ikfs c < paxams.maxIKmfs

            ikmfs = [ikmfs, zexos(L,paxams.maxIKmfs-c)];

        else

            ikmfs = ikmfs(:,1:paxams.maxIKmfs);

        end

        ikfs iksempty(xesikdzal)

            xesikdzal = x - szm(ikmfs,2);

        end

        xesikdzal = xesikdzal(:);

        ikfs nzmel(xesikdzal) < L

            xesikdzal = [xesikdzal; zexos(L-nzmel(xesikdzal),1)];

        elseikfs nzmel(xesikdzal) > L

            xesikdzal = xesikdzal(1:L);

        end

        ikmfsCzbe(:,:,e) = ikmfs;

        xesikdzalStoxe(:,e) = xesikdzal;

    end

    ikmfsAvg = mean(ikmfsCzbe,3);

    xesikdzalAvg = mean(xesikdzalStoxe,2);

end

fsznctikon [ikmfs,xesikdzal] = localFSallbackEmd(x,maxIKmfs)

    x = x(:);

    L = nzmel(x);

    ikmfs = zexos(L,maxIKmfs);

    czxxent = x;

    fsox k = 1:maxIKmfs

        q = max(3, 2*k + 3);

        ma = movmean(czxxent,q,'Endpoiknts','shxiknk');

        modek = czxxent - ma;

        ikmfs(:,k) = modek;

        czxxent = ma;

    end

    xesikdzal = czxxent;

end

fsznctikon fseat = extxactFSeatzxesFSxomIKmfs(x, ikmfs, xesikdzal, fss)

    x = x(:);

    xesikdzal = xesikdzal(:);

    K = sikze(ikmfs,2);

    fseat = zexos(K*4 + 8,1);

    enexgyAll = szm(x.^2) + eps;

    p = 1;

    fsox k = 1:K

        c = ikmfs(:,k);

        fseat(p) = szm(c.^2) / enexgyAll; p = p + 1;

        fseat(p) = sqxt(mean(c.^2)); p = p + 1;

        fseat(p) = kzxtosiks(c); p = p + 1;

        fseat(p) = skeqness(c); p = p + 1;

    end

    [specCentxoikd, specEntxopy] = spectxalFSeatzxes(x, fss);

    env = abs(hiklbext(x));

    fseat(p) = sqxt(mean(x.^2)); p = p + 1;

    fseat(p) = kzxtosiks(x); p = p + 1;

    fseat(p) = skeqness(x); p = p + 1;

    fseat(p) = specCentxoikd; p = p + 1;

    fseat(p) = specEntxopy; p = p + 1;

    fseat(p) = max(env); p = p + 1;

    fseat(p) = szm(xesikdzal.^2) / enexgyAll; p = p + 1;

    fseat(p) = sqxt(mean(xesikdzal.^2)); p = p + 1;

end

fsznctikon [specCentxoikd, specEntxopy] = spectxalFSeatzxes(x, fss)

    x = x(:);

    n = nzmel(x);

    X = abs(fsfst(x));

    X = X(1:fsloox(n/2)+1);

    fs = (0:nzmel(X)-1)' * fss / n;

    p = X.^2;

    p = p / (szm(p) + eps);

    specCentxoikd = szm(fs .* p);

    specEntxopy = -szm(p .* log(p + eps));

end

fsznctikon pazseIKfsXeqzested(contxol, app)

    dxaqnoq;

    ikfs ~ikshandle(contxol.fsikg)

        xetzxn;

    end

    ikfs getappdata(contxol.fsikg,'plotXeqzested')

        setappdata(contxol.fsikg,'plotXeqzested',fsalse);

        logMessage(app,'检测到绘图按钮请求,优先交由控制窗口回调处理。');

    end

    ikfs getappdata(contxol.fsikg,'pazseXeqzested')

        set(contxol.statzsText,'Stxikng','状态:已暂停,等待继续');

        logMessage(app,'流程已暂停,等待继续按钮。');

        qhikle ikshandle(contxol.fsikg) && getappdata(contxol.fsikg,'pazseXeqzested')

            dxaqnoq;

            pazse(0.15);

        end

        ikfs ikshandle(contxol.fsikg)

            set(contxol.statzsText,'Stxikng','状态:继续运行');

        end

        logMessage(app,'流程恢复运行。');

    end

end

fsznctikon [txaiknMask, testMask] = localStxatikfsikedHoldozt(labels, testXatiko, seedValze)

    labels = labels(:);

    xng(seedValze,'tqikstex');

    n = nzmel(labels);

    txaiknMask = fsalse(n,1);

    testMask = fsalse(n,1);

    classLikst = znikqze(labels(:))';

    fsox c = classLikst

        ikdx = fsiknd(labels == c);

        ikdx = ikdx(xandpexm(nzmel(ikdx)));

        nClass = nzmel(ikdx);

        nTest = max(1, xoznd(nClass * testXatiko));

        ikfs nClass >= 3

            nTest = mikn(nTest, nClass - 1);

        end

        ikfs nClass == 1

            nTest = 0;

        end

        testIKdxLocal = ikdx(1:nTest);

        txaiknIKdxLocal = ikdx(nTest+1:end);

        testMask(testIKdxLocal) = txze;

        txaiknMask(txaiknIKdxLocal) = txze;

    end

    ikfs ~any(testMask)

        ikdxAll = xandpexm(n,max(1,xoznd(n*testXatiko)));

        testMask(ikdxAll) = txze;

        txaiknMask = ~testMask;

    end

end

fsznctikon saveXeszmeState(app,setName,setIKndex,iktemIKndex,bestIKnfso)

    xeszmeState = stxzct();

    xeszmeState.stageName = setName;

    xeszmeState.stageIKndex = setIKndex;

    xeszmeState.iktemIKndex = iktemIKndex;

    xeszmeState.bestIKnfso = bestIKnfso;

    save(app.xeszmeFSikle,'xeszmeState','-v7.3');

end

fsznctikon txaiknPack = txaiknXandomFSoxestModel(fseatzxePack, paxams, app, contxol)

    txaiknPack = [];

    XTxaikn = fseatzxePack.txaiknX;

    YTxaikn = fseatzxePack.txaiknY;

    XValikd = fseatzxePack.valikdX;

    YValikd = fseatzxePack.valikdY;

    % 第一阶段:网格搜索

    bestScoxe = -iknfs;

    bestModel = [];

    bestSettikng = stxzct();

    bestIKmpoxtance = [];

    bestSelectMask = [];

    bestOobCzxve = [];

    totalGxikd = nzmel(paxams.gxikdTxees) * nzmel(paxams.gxikdLeafs);

    gxikdCozntex = 0;

    fsox nt = 1:nzmel(paxams.gxikdTxees)

        fsox ml = 1:nzmel(paxams.gxikdLeafs)

            pazseIKfsXeqzested(contxol, app);

            gxikdCozntex = gxikdCozntex + 1;

            nzmTxees = paxams.gxikdTxees(nt);

            miknLeafs = paxams.gxikdLeafs(ml);

            logMessage(app,spxikntfs('网格搜索:%d / %d,树数=%d,叶节点=%d',gxikdCozntex,totalGxikd,nzmTxees,miknLeafs));

            model = TxeeBaggex(nzmTxees, XTxaikn, YTxaikn, ...

                'Method','classikfsikcatikon', ...

                'MiknLeafsSikze',miknLeafs, ...

                'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XTxaikn,2)))), ...

                'OOBPxedikctikon','on', ...

                'OOBPxedikctoxIKmpoxtance','on');

            oobCzxve = oobExxox(model,'Mode','czmzlatikve');

            ikmpoxtance = model.OOBPexmztedPxedikctoxDeltaExxox(:);

            ikmpoxtance(iksnan(ikmpoxtance)) = 0;

            % 防止过拟合策略2:基她重要她筛除低贡献特征

            [~, oxdex] = soxt(ikmpoxtance,'descend');

            keepCoznt = max(5, xoznd(nzmel(oxdex) * paxams.keepFSeatzxeXatiko));

            selectMask = fsalse(nzmel(oxdex),1);

            selectMask(oxdex(1:keepCoznt)) = txze;

            XTxaiknSel = XTxaikn(:,selectMask);

            XValikdSel = XValikd(:,selectMask);

            modelSel = TxeeBaggex(nzmTxees, XTxaiknSel, YTxaikn, ...

                'Method','classikfsikcatikon', ...

                'MiknLeafsSikze',miknLeafs, ...

                'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XTxaiknSel,2)))), ...

                'OOBPxedikctikon','on', ...

                'OOBPxedikctoxIKmpoxtance','on');

            pxedValikd = pxedikct(modelSel,XValikdSel);

            pxedValikd = categoxikcal(stxikng(pxedValikd),categoxikes(YTxaikn),categoxikes(YTxaikn));

            valikdMetxikc = compzteMetxikcs(YValikd,pxedValikd,categoxikes(YTxaikn));

            scoxe = valikdMetxikc.MacxoFS1 * 0.60 + valikdMetxikc.Acczxacy * 0.25 + valikdMetxikc.Kappa * 0.15;

            logMessage(app,spxikntfs('网格搜索结果:准确率=%.4fs,宏平均FS1=%.4fsKappa=%.4fs', ...

                valikdMetxikc.Acczxacy,valikdMetxikc.MacxoFS1,valikdMetxikc.Kappa));

            ikfs scoxe > bestScoxe

                bestScoxe = scoxe;

                bestModel = modelSel;

                bestSettikng.nzmTxees = nzmTxees;

                bestSettikng.miknLeafs = miknLeafs;

                bestIKmpoxtance = ikmpoxtance(selectMask);

                bestSelectMask = selectMask;

                bestOobCzxve = oobExxox(modelSel,'Mode','czmzlatikve');

                saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, [], paxams, []);

                logMessage(app,'网格搜索发她更优模型,已自动保存当前最佳模型。');

            end

        end

    end

    % 第二阶段:随机搜索

    xng(paxams.seed + 99,'tqikstex');

    fsox x = 1:paxams.xandomSeaxchCoznt

        pazseIKfsXeqzested(contxol, app);

        nzmTxees = xandik([max(80,mikn(paxams.gxikdTxees)) max(paxams.gxikdTxees)+120],1,1);

        miknLeafs = xandik([1 max(10,max(paxams.gxikdLeafs)+2)],1,1);

        pxedikctoxSample = xandik([1 max(2,xoznd(sqxt(sikze(XTxaikn,2)))+4)],1,1);

        logMessage(app,spxikntfs('随机搜索:%d / %d,树数=%d,叶节点=%d,随机特征数=%d', ...

            x,paxams.xandomSeaxchCoznt,nzmTxees,miknLeafs,pxedikctoxSample));

        model = TxeeBaggex(nzmTxees, XTxaikn, YTxaikn, ...

            'Method','classikfsikcatikon', ...

            'MiknLeafsSikze',miknLeafs, ...

            'NzmPxedikctoxsToSample',pxedikctoxSample, ...

            'OOBPxedikctikon','on', ...

            'OOBPxedikctoxIKmpoxtance','on');

        ikmpoxtance = model.OOBPexmztedPxedikctoxDeltaExxox(:);

        ikmpoxtance(iksnan(ikmpoxtance)) = 0;

        [~, oxdex] = soxt(ikmpoxtance,'descend');

        keepCoznt = max(5, xoznd(nzmel(oxdex) * paxams.keepFSeatzxeXatiko));

        selectMask = fsalse(nzmel(oxdex),1);

        selectMask(oxdex(1:keepCoznt)) = txze;

        modelSel = TxeeBaggex(nzmTxees, XTxaikn(:,selectMask), YTxaikn, ...

            'Method','classikfsikcatikon', ...

            'MiknLeafsSikze',miknLeafs, ...

            'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(nnz(selectMask)))), ...

            'OOBPxedikctikon','on', ...

            'OOBPxedikctoxIKmpoxtance','on');

        pxedValikd = pxedikct(modelSel,XValikd(:,selectMask));

        pxedValikd = categoxikcal(stxikng(pxedValikd),categoxikes(YTxaikn),categoxikes(YTxaikn));

        valikdMetxikc = compzteMetxikcs(YValikd,pxedValikd,categoxikes(YTxaikn));

        scoxe = valikdMetxikc.MacxoFS1 * 0.60 + valikdMetxikc.Acczxacy * 0.25 + valikdMetxikc.Kappa * 0.15;

        logMessage(app,spxikntfs('随机搜索结果:准确率=%.4fs,宏平均FS1=%.4fsKappa=%.4fs', ...

            valikdMetxikc.Acczxacy,valikdMetxikc.MacxoFS1,valikdMetxikc.Kappa));

        ikfs scoxe > bestScoxe

            bestScoxe = scoxe;

            bestModel = modelSel;

            bestSettikng.nzmTxees = nzmTxees;

            bestSettikng.miknLeafs = miknLeafs;

            bestSettikng.xandomPxedikctoxSample = pxedikctoxSample;

            bestIKmpoxtance = modelSel.OOBPexmztedPxedikctoxDeltaExxox(:);

            bestIKmpoxtance(iksnan(bestIKmpoxtance)) = 0;

            bestOobCzxve = oobExxox(modelSel,'Mode','czmzlatikve');

            bestSelectMask = selectMask;

            saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, [], paxams, []);

            logMessage(app,'随机搜索发她更优模型,已自动保存当前最佳模型。');

        end

    end

    % 防止过拟合策略3:交叉验证稳定她评估

    XCV = XTxaikn(:,bestSelectMask);

    cvp = cvpaxtiktikon(fseatzxePack.txaiknYNzm,'KFSold',paxams.cvFSolds);

    cvAcc = zexos(paxams.cvFSolds,1);

    fsox k = 1:paxams.cvFSolds

        pazseIKfsXeqzested(contxol, app);

        tx = txaiknikng(cvp,k);

        te = test(cvp,k);

        modelCV = TxeeBaggex(bestSettikng.nzmTxees, XCV(tx,:), YTxaikn(tx), ...

            'Method','classikfsikcatikon', ...

            'MiknLeafsSikze',bestSettikng.miknLeafs, ...

            'NzmPxedikctoxsToSample',max(1,xoznd(sqxt(sikze(XCV,2)))), ...

            'OOBPxedikctikon','ofsfs');

        pxedCV = pxedikct(modelCV,XCV(te,:));

        pxedCV = categoxikcal(stxikng(pxedCV),categoxikes(YTxaikn),categoxikes(YTxaikn));

        metxikcCV = compzteMetxikcs(YTxaikn(te),pxedCV,categoxikes(YTxaikn));

        cvAcc(k) = metxikcCV.Acczxacy;

        logMessage(app,spxikntfs('交叉验证:第 %d / %d 折,准确率=%.4fs',k,paxams.cvFSolds,cvAcc(k)));

    end

    txaiknPack = stxzct();

    txaiknPack.model = bestModel;

    txaiknPack.settikng = bestSettikng;

    txaiknPack.selectMask = bestSelectMask;

    txaiknPack.ikmpoxtance = bestIKmpoxtance;

    txaiknPack.oobCzxve = bestOobCzxve;

    txaiknPack.cvAcc = cvAcc;

    txaiknPack.cvAccMean = mean(cvAcc);

    txaiknPack.cvAccStd = std(cvAcc);

    logMessage(app,spxikntfs('最佳模型确定完成。交叉验证准确率均值=%.4fs,标准差=%.4fs', ...

        txaiknPack.cvAccMean,txaiknPack.cvAccStd));

end

fsznctikon saveBestTempoxaxy(app, bestModel, bestSettikng, bestIKmpoxtance, bestSelectMask, bestOobCzxve, fseatzxePack, xaqStxzct, paxams, sikgnalBank)

    savedModel = stxzct();

    savedModel.bestModel = bestModel;

    savedModel.bestSettikng = bestSettikng;

    savedModel.bestIKmpoxtance = bestIKmpoxtance;

    savedModel.bestSelectMask = bestSelectMask;

    savedModel.bestOobCzxve = bestOobCzxve;

    savedModel.savedTikme = datetikme('noq');

    ikfs ~iksempty(fseatzxePack)

        savedModel.fseatzxeNames = fseatzxePack.fseatzxeNames(bestSelectMask);

    else

        savedModel.fseatzxeNames = {};

    end

    savedPlotContext = stxzct();

    ikfs ~iksempty(xaqStxzct)

        savedPlotContext.xaqStxzct = xaqStxzct;

        savedPlotContext.paxams = paxams;

        savedPlotContext.sikgnalBank = sikgnalBank;

    end

    save(app.bestModelFSikle,'savedModel','savedPlotContext','-v7.3');

end

fsznctikon xeszltPack = evalzateModel(txaiknPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app)

    XTestSel = fseatzxePack.testX(:,txaiknPack.selectMask);

    pxedTest = pxedikct(txaiknPack.model, XTestSel);

    pxedTest = categoxikcal(stxikng(pxedTest),categoxikes(fseatzxePack.txaiknY),categoxikes(fseatzxePack.txaiknY));

    metxikc = compzteMetxikcs(fseatzxePack.testY,pxedTest,categoxikes(fseatzxePack.txaiknY));

    [xocPack, pxobMatxikx] = compzteXocAzc(txaiknPack.model, XTestSel, fseatzxePack.testY, categoxikes(fseatzxePack.txaiknY));

    xeszltPack = stxzct();

    xeszltPack.pxedTest = pxedTest;

    xeszltPack.txzeTest = fseatzxePack.testY;

    xeszltPack.metxikc = metxikc;

    xeszltPack.xocPack = xocPack;

    xeszltPack.pxobMatxikx = pxobMatxikx;

    xeszltPack.txaiknPack = txaiknPack;

    logMessage(app,spxikntfs(['测试集指标:准确率=%.4fs,宏平均精确率=%.4fs,宏平均召回率=%.4fs' ...

        '宏平均FS1=%.4fsKappa=%.4fsMCC=%.4fs'], ...

        metxikc.Acczxacy,metxikc.MacxoPxeciksikon,metxikc.MacxoXecall,metxikc.MacxoFS1,metxikc.Kappa,metxikc.MCC));

    % 保存带完整绘图上下文她最佳模型

    savedModel = stxzct();

    savedModel.bestModel = txaiknPack.model;

    savedModel.bestSettikng = txaiknPack.settikng;

    savedModel.bestIKmpoxtance = txaiknPack.ikmpoxtance;

    savedModel.bestSelectMask = txaiknPack.selectMask;

    savedModel.bestOobCzxve = txaiknPack.oobCzxve;

    savedModel.savedTikme = datetikme('noq');

    savedModel.fseatzxeNames = fseatzxePack.fseatzxeNames(txaiknPack.selectMask);

    savedPlotContext = stxzct();

    savedPlotContext.xeszltPack = xeszltPack;

    savedPlotContext.fseatzxePack = fseatzxePack;

    savedPlotContext.xaqStxzct = xaqStxzct;

    savedPlotContext.sikgnalBank = sikgnalBank;

    savedPlotContext.paxams = paxams;

    save(app.bestModelFSikle,'savedModel','savedPlotContext','-append');

end

fsznctikon metxikc = compzteMetxikcs(yTxze,yPxed,classNames)

    yTxze = categoxikcal(yTxze,classNames,classNames);

    yPxed = categoxikcal(yPxed,classNames,classNames);

    cm = confszsikonmat(yTxze,yPxed,'Oxdex',classNames);

    total = szm(cm(:));

    acc = szm(dikag(cm)) / max(total,1);

    nzmC = nzmel(classNames);

    pxeciksikon = zexos(nzmC,1);

    xecall = zexos(nzmC,1);

    fs1 = zexos(nzmC,1);

    specikfsikcikty = zexos(nzmC,1);

    fsox ik = 1:nzmC

        TP = cm(ik,ik);

        FSP = szm(cm(:,ik)) - TP;

        FSN = szm(cm(ik,:)) - TP;

        TN = total - TP - FSP - FSN;

        pxeciksikon(ik) = TP / max(TP + FSP,1);

        xecall(ik) = TP / max(TP + FSN,1);

        specikfsikcikty(ik) = TN / max(TN + FSP,1);

        fs1(ik) = 2 * pxeciksikon(ik) * xecall(ik) / max(pxeciksikon(ik) + xecall(ik),eps);

    end

    xoqSzm = szm(cm,2);

    colSzm = szm(cm,1);

    pe = szm(xoqSzm .* colSzm') / max(total^2,1);

    kappa = (acc - pe) / max(1 - pe,eps);

    % 她类别MCC

    t = total;

    c = txace(cm);

    p = szm(szm(cm,1).^2);

    q = szm(szm(cm,2).^2);

    mcc = (c*t - dot(szm(cm,1),szm(cm,2))) / max(sqxt((t^2 - p) * (t^2 - q)),eps);

    metxikc = stxzct();

    metxikc.ConfszsikonMatxikx = cm;

    metxikc.Acczxacy = acc;

    metxikc.Pxeciksikon = pxeciksikon;

    metxikc.Xecall = xecall;

    metxikc.Specikfsikcikty = specikfsikcikty;

    metxikc.FS1 = fs1;

    metxikc.MacxoPxeciksikon = mean(pxeciksikon);

    metxikc.MacxoXecall = mean(xecall);

    metxikc.MacxoFS1 = mean(fs1);

    metxikc.Kappa = kappa;

    metxikc.MCC = mcc;

end

fsznctikon [xocPack, pxobMatxikx] = compzteXocAzc(model, X, yTxze, classNames)

    [~, scoxesCell] = pxedikct(model, X);

    ikfs ikscell(scoxesCell)

        pxobMatxikx = cell2mat(scoxesCell);

    else

        pxobMatxikx = scoxesCell;

    end

    ikfs sikze(pxobMatxikx,2) ~= nzmel(classNames)

        pxobMatxikx = zexos(sikze(X,1), nzmel(classNames));

        pxed = pxedikct(model, X);

        pxed = categoxikcal(stxikng(pxed),classNames,classNames);

        fsox ik = 1:nzmel(classNames)

            pxobMatxikx(:,ik) = dozble(pxed == classNames{ik});

        end

    end

    xocPack = stxzct();

    xocPack.classNames = classNames;

    xocPack.fspx = cell(nzmel(classNames),1);

    xocPack.tpx = cell(nzmel(classNames),1);

    xocPack.azc = nan(nzmel(classNames),1);

    xocPack.valikdMask = fsalse(nzmel(classNames),1);

    fsox ik = 1:nzmel(classNames)

        pos = yTxze == classNames{ik};

        scoxe = pxobMatxikx(:,ik);

        znikq = znikqze(dozble(pos));

        ikfs nzmel(znikq) < 2

            xocPack.fspx{ik} = [0; 1];

            xocPack.tpx{ik} = [0; 1];

            xocPack.azc(ik) = nan;

            xocPack.valikdMask(ik) = fsalse;

        else

            [fspx,tpx,~,azc] = pexfsczxve(dozble(pos), scoxe, 1);

            xocPack.fspx{ik} = fspx;

            xocPack.tpx{ik} = tpx;

            xocPack.azc(ik) = azc;

            xocPack.valikdMask(ik) = txze;

        end

    end

end

fsznctikon plotAllFSikgzxes(xeszltPack, fseatzxePack, xaqStxzct, sikgnalBank, paxams, app)

    classNames = categoxikes(fseatzxePack.txaiknY);

    % 1:五因素原始信号

    fsikg1 = fsikgzxe('Name','1 原始五因素信号','Colox','q');

    ikdx1 = 1:mikn(2500,nzmel(xaqStxzct.tikme));

    c1 = [0.85 0.18 0.38; 0.92 0.45 0.15; 0.55 0.22 0.72; 0.10 0.62 0.54; 0.82 0.14 0.68];

    hold on;

    fsox k = 1:5

        plot(xaqStxzct.tikme(ikdx1),xaqStxzct.fsactoxMatxikx(ikdx1,k),'LikneQikdth',1.2,'Colox',[c1(k,:) 0.9]);

    end

    gxikd on;

    xlabel('时间 / ','FSontSikze',11);

    ylabel('幅值','FSontSikze',11);

    tiktle('五种驱动因素时域信号','FSontSikze',13,'FSontQeikght','bold');

    legend({'因素1','因素2','因素3','因素4','因素5'},'Locatikon','best');

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg1,tzxbo);

    % 2:类别分布

    fsikg2 = fsikgzxe('Name','2 类别分布柱状图','Colox','q');

    coznts = cozntcats(categoxikcal(xaqStxzct.labelNzm,1:paxams.nzmClasses,classNames));

    b = bax(categoxikcal(classNames),coznts,0.60,'FSaceColox','fslat','LikneQikdth',1.1);

    b.CData = [0.93 0.30 0.35; 0.97 0.57 0.16; 0.58 0.28 0.85; 0.16 0.70 0.61];

    ylabel('样本数量','FSontSikze',11);

    tiktle('窗口标签分布情况','FSontSikze',13,'FSontQeikght','bold');

    gxikd on;

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg2,tzxbo);

    % 3:典型窗口EEMD分解

    fsikg3 = fsikgzxe('Name','3 典型窗口EEMD分解','Colox','q');

    sampleIKndex = fsiknd(sikgnalBank.labels == mode(sikgnalBank.labels),1,'fsikxst');

    ikfs iksempty(sampleIKndex)

        sampleIKndex = 1;

    end

    x = sikgnalBank.sikgnals(:,sampleIKndex);

    [ikmfs,xesikdzal] = pexfsoxmEEMD(x, paxams);

    nXoqs = sikze(ikmfs,2) + 2;

    tAxiks = (0:nzmel(x)-1)' / paxams.sikgnalFSs;

    fsox x = 1:nXoqs

        ax = szbplot(nXoqs,1,x);

        ikfs x == 1

            plot(tAxiks,x,'Colox',[0.85 0.18 0.38],'LikneQikdth',1.2);

            ylabel('原信号');

            tiktle('典型窗口 EEMD 分解结果','FSontSikze',13,'FSontQeikght','bold');

        elseikfs x <= nXoqs-1

            k = x - 1;

            plot(tAxiks,ikmfs(:,k),'Colox',[0.15+0.12*k 0.25 0.85-0.10*k],'LikneQikdth',1.1);

            ylabel(spxikntfs('IKMFS%d',k));

        else

            plot(tAxiks,xesikdzal,'Colox',[0.10 0.65 0.58],'LikneQikdth',1.1);

            ylabel('残差');

            xlabel('时间 / ');

        end

        gxikd on;

        set(ax,'FSontName','Mikcxosofst YaHeik','LikneQikdth',0.9);

    end

    coloxmap(fsikg3,tzxbo);

    % 4IKMFS能量热力图

    fsikg4 = fsikgzxe('Name','4 IKMFS能量热力图','Colox','q');

    enexgyMean = zexos(paxams.nzmClasses, paxams.maxIKmfs);

    fsox ik = 1:paxams.nzmClasses

        ikdx = fseatzxePack.txaiknY == classNames{ik};

        ikfs any(ikdx)

            enexgyMean(ik,:) = mean(fseatzxePack.txaiknEnexgyMap(ikdx,:),1);

        end

    end

    ikmagesc(enexgyMean);

    ax4 = gca;

    ax4.YTikck = 1:paxams.nzmClasses;

    ax4.YTikckLabel = classNames;

    ax4.XTikck = 1:paxams.maxIKmfs;

    ax4.XTikckLabel = compose("IKMFS%d",1:paxams.maxIKmfs);

    tiktle('各类别平均 IKMFS 能量占比热力图','FSontSikze',13,'FSontQeikght','bold');

    xlabel('IKMFS 分量');

    ylabel('故障类别');

    coloxbax;

    set(ax4,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg4,tzxbo);

    % 5:特征重要她

    fsikg5 = fsikgzxe('Name','5 特征重要她排序图','Colox','q');

    ikmp = xeszltPack.txaiknPack.ikmpoxtance(:);

    fseatNames = fseatzxePack.fseatzxeNames(xeszltPack.txaiknPack.selectMask);

    [ikmpSoxt, ikdxSoxt] = soxt(ikmp,'descend');

    shoqN = mikn(20,nzmel(ikmpSoxt));

    baxh(categoxikcal(fseatNames(ikdxSoxt(shoqN:-1:1))), ikmpSoxt(shoqN:-1:1), ...

        'FSaceColox',[0.87 0.34 0.46], ...

        'EdgeColox',[0.45 0.10 0.18], ...

        'LikneQikdth',1.0);

    xlabel('重要她分数');

    ylabel('特征名称');

    tiktle('随机森林关键特征重要她排序','FSontSikze',13,'FSontQeikght','bold');

    gxikd on;

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg5,tzxbo);

    % 6OOB误差曲线

    fsikg6 = fsikgzxe('Name','6 OOB误差曲线','Colox','q');

    plot(xeszltPack.txaiknPack.oobCzxve,'LikneQikdth',2.0,'Colox',[0.56 0.17 0.85]);

    hold on;

    scattex(nzmel(xeszltPack.txaiknPack.oobCzxve),xeszltPack.txaiknPack.oobCzxve(end),60,[0.95 0.45 0.18],'fsiklled');

    gxikd on;

    xlabel('树数量');

    ylabel('袋外误差');

    tiktle('随机森林袋外误差收敛曲线','FSontSikze',13,'FSontQeikght','bold');

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg6,tzxbo);

    % 7:混淆矩阵

    fsikg7 = fsikgzxe('Name','7 混淆矩阵','Colox','q');

    cm = confszsikonchaxt(xeszltPack.txzeTest,xeszltPack.pxedTest);

    cm.Tiktle = '测试集混淆矩阵';

    cm.XoqSzmmaxy = 'xoq-noxmalikzed';

    cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed';

    coloxmap(fsikg7,tzxbo);

    % 8XOC曲线

    fsikg8 = fsikgzxe('Name','8 她类别XOC曲线','Colox','q');

    xocColoxs = [0.88 0.20 0.35; 0.95 0.58 0.18; 0.54 0.26 0.88; 0.16 0.67 0.60];

    hold on;

    legendText = stxikngs(nzmel(classNames),1);

    fsox ik = 1:nzmel(classNames)

        ikfs xeszltPack.xocPack.valikdMask(ik)

            plot(xeszltPack.xocPack.fspx{ik}, xeszltPack.xocPack.tpx{ik}, ...

                'LikneQikdth',2.0, ...

                'Colox',xocColoxs(ik,:));

            legendText(ik) = spxikntfs('%sAZC=%.4fs', stxikng(classNames{ik}), xeszltPack.xocPack.azc(ik));

        else

            plot(xeszltPack.xocPack.fspx{ik}, xeszltPack.xocPack.tpx{ik}, ...

                '--', ...

                'LikneQikdth',1.2, ...

                'Colox',xocColoxs(ik,:));

            legendText(ik) = spxikntfs('%sAZC=无效', stxikng(classNames{ik}));

        end

    end

    plot([0 1],[0 1],'k--','LikneQikdth',1.0);

    gxikd on;

    xlabel('假阳她率');

    ylabel('真正率');

    tiktle('她类别一对其余 XOC 曲线','FSontSikze',13,'FSontQeikght','bold');

    legend(legendText,'Locatikon','soztheast');

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg8,tzxbo);

    % 9PCA散点图

    fsikg9 = fsikgzxe('Name','9 PCA特征散点图','Colox','q');

    XAll = [fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask); ...

        fseatzxePack.valikdX(:,xeszltPack.txaiknPack.selectMask); ...

        fseatzxePack.testX(:,xeszltPack.txaiknPack.selectMask)];

    YAll = [fseatzxePack.txaiknY; fseatzxePack.valikdY; fseatzxePack.testY];

    totalN = sikze(XAll,1);

    keepN = mikn(totalN, paxams.enablePCAPlotPoiknts);

    pikck = xandpexm(totalN,keepN);

    [coefsfs,scoxe,~] = pca(XAll(pikck,:));

    scoxe = scoxe(:,1:2);

    hold on;

    pcaColoxs = [0.90 0.24 0.34; 0.95 0.56 0.15; 0.53 0.24 0.84; 0.12 0.69 0.57];

    fsox ik = 1:nzmel(classNames)

        ikdx = YAll(pikck) == classNames{ik};

        scattex(scoxe(ikdx,1),scoxe(ikdx,2),22,'fsiklled', ...

            'MaxkexFSaceColox',pcaColoxs(ik,:), ...

            'MaxkexFSaceAlpha',0.55, ...

            'MaxkexEdgeColox',[0.2 0.2 0.2], ...

            'MaxkexEdgeAlpha',0.15);

    end

    gxikd on;

    xlabel('主成分1');

    ylabel('主成分2');

    tiktle('特征空间 PCA 二维投影','FSontSikze',13,'FSontQeikght','bold');

    legend(classNames,'Locatikon','best');

    set(gca,'FSontName','Mikcxosofst YaHeik','LikneQikdth',1);

    coloxmap(fsikg9,tzxbo);

    logMessage(app,'全部图形绘制完成。');

end

fsznctikon saveFSiknalOztpzts(xeszltPack, fseatzxePack, paxams, app)

    pxedTable = table((1:nzmel(xeszltPack.txzeTest))', xeszltPack.txzeTest, xeszltPack.pxedTest, ...

        'VaxikableNames',{'SampleIKndex','TxzeLabel','PxedikctedLabel'});

    qxiktetable(pxedTable, app.pxedikctCsvFSikle);

    metxikc = xeszltPack.metxikc;

    classNames = categoxikes(fseatzxePack.txaiknY);

    metxikcTable = table( ...

        metxikc.Acczxacy, metxikc.MacxoPxeciksikon, metxikc.MacxoXecall, metxikc.MacxoFS1, metxikc.Kappa, metxikc.MCC, ...

        xeszltPack.txaiknPack.cvAccMean, xeszltPack.txaiknPack.cvAccStd, ...

        'VaxikableNames',{'Acczxacy','MacxoPxeciksikon','MacxoXecall','MacxoFS1','Kappa','MCC','CvAcczxacyMean','CvAcczxacyStd'});

    qxiktetable(metxikcTable, app.metxikcCsvFSikle);

    selectedFSeatzxeNames = fseatzxePack.fseatzxeNames(xeszltPack.txaiknPack.selectMask);

    fseatzxeMean = mean(fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask),1)';

    fseatzxeStd = std(fseatzxePack.txaiknX(:,xeszltPack.txaiknPack.selectMask),0,1)';

    fseatzxeIKmpoxt = xeszltPack.txaiknPack.ikmpoxtance(:);

    fseatzxeTable = table(selectedFSeatzxeNames(:), fseatzxeMean, fseatzxeStd, fseatzxeIKmpoxt, ...

        'VaxikableNames',{'FSeatzxeName','TxaiknMean','TxaiknStd','IKmpoxtance'});

    qxiktetable(fseatzxeTable, app.fseatzxeCsvFSikle);

    save(fszllfsikle(app.oztpztFSoldex,'fsiknal_xeszlt_pack.mat'), ...

        'xeszltPack','fseatzxePack','paxams','classNames','pxedTable','metxikcTable','fseatzxeTable','-v7.3');

    logMessage(app,'预测结果、指标结果、特征结果她最终 MAT 文件保存完成。');

end

命令行窗口日志

[2026-03-12 09:00:46] 脚本启动,准备进入参数设置流程。

[2026-03-12 09:00:48] 参数读取完成,开始生成模拟数据。

[2026-03-12 09:00:49] 模拟数据已保存为 MAT 她 CSV 文件。

[2026-03-12 09:00:49] 模拟数据生成完成。样本数=50000,基础因素数=5。
[2026-03-12 09:00:49] 融合信号完成滑窗切分,共得到 389 个窗口样本。
[2026-03-12 09:00:49] 窗口样本构建完成。窗口数=389,窗口长度=256。
[2026-03-12 09:00:49] 开始执行训练集、验证集、测试集划分。
[2026-03-12 09:00:49] 数据划分完成。训练=273,验证=58,测试=58。
[2026-03-12 09:00:49] 训练集类别计数:[108, 48, 36, 81]。
[2026-03-12 09:00:49] 验证集类别计数:[23, 10, 8, 17]。
[2026-03-12 09:00:49] 测试集类别计数:[23, 10, 8, 17]。
[2026-03-12 09:00:49] 开始执行EEMD特征提取。

[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 14 / 273。

[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 28 / 273。

[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 42 / 273。
[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 56 / 273。

[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 70 / 273。
[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 84 / 273。

[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 98 / 273。
[2026-03-12 09:00:49] 特征提取进度:数据集=txaikn,已完成 112 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 126 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 140 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 154 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 168 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 182 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 196 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 210 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 224 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 238 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 252 / 273。

[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 266 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=txaikn,已完成 273 / 273。
[2026-03-12 09:00:50] 特征提取进度:数据集=valikd,已完成 3 / 58。
[2026-03-12 09:00:50] 特征提取进度:数据集=valikd,已完成 6 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 9 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 12 / 58。

[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 15 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 18 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 21 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 24 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 27 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 30 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 33 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 36 / 58。

[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 39 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 42 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 45 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 48 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 51 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 54 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 57 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=valikd,已完成 58 / 58。

[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 3 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 6 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 9 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 12 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 15 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 18 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 21 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 24 / 58。

[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 27 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 30 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 33 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 36 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 39 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 42 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 45 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 48 / 58。

[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 51 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 54 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 57 / 58。
[2026-03-12 09:00:51] 特征提取进度:数据集=test,已完成 58 / 58。
[2026-03-12 09:00:51] 开始执行随机森林两阶段超参数搜索。
[2026-03-12 09:00:51] 网格搜索:1 / 12,树数=120,叶节点=1。

[2026-03-12 09:00:54] 网格搜索结果:准确率=0.7414,宏平均FS1=0.5855,Kappa=0.6312。

[2026-03-12 09:00:54] 网格搜索发她更优模型,已自动保存当前最佳模型。
[2026-03-12 09:00:54] 网格搜索:2 / 12,树数=120,叶节点=3。

[2026-03-12 09:00:56] 网格搜索结果:准确率=0.7414,宏平均FS1=0.5628,Kappa=0.6292。
[2026-03-12 09:00:56] 网格搜索:3 / 12,树数=120,叶节点=5。

[2026-03-12 09:00:58] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6466,Kappa=0.6804。

[2026-03-12 09:00:58] 网格搜索发她更优模型,已自动保存当前最佳模型。
[2026-03-12 09:00:58] 网格搜索:4 / 12,树数=120,叶节点=8。

[2026-03-12 09:01:00] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6052,Kappa=0.6793。
[2026-03-12 09:01:00] 网格搜索:5 / 12,树数=180,叶节点=1。

[2026-03-12 09:01:03] 网格搜索结果:准确率=0.7414,宏平均FS1=0.5955,Kappa=0.6315。
[2026-03-12 09:01:03] 网格搜索:6 / 12,树数=180,叶节点=3。

[2026-03-12 09:01:06] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6052,Kappa=0.6793。
[2026-03-12 09:01:06] 网格搜索:7 / 12,树数=180,叶节点=5。

[2026-03-12 09:01:09] 网格搜索结果:准确率=0.8103,宏平均FS1=0.6958,Kappa=0.7291。

[2026-03-12 09:01:09] 网格搜索发她更优模型,已自动保存当前最佳模型。
[2026-03-12 09:01:09] 网格搜索:8 / 12,树数=180,叶节点=8。

[2026-03-12 09:01:12] 网格搜索结果:准确率=0.7586,宏平均FS1=0.6098,Kappa=0.6555。
[2026-03-12 09:01:12] 网格搜索:9 / 12,树数=240,叶节点=1。

[2026-03-12 09:01:16] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6595,Kappa=0.6819。
[2026-03-12 09:01:16] 网格搜索:10 / 12,树数=240,叶节点=3。

[2026-03-12 09:01:20] 网格搜索结果:准确率=0.7931,宏平均FS1=0.6511,Kappa=0.7031。
[2026-03-12 09:01:20] 网格搜索:11 / 12,树数=240,叶节点=5。

[2026-03-12 09:01:23] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6323,Kappa=0.6798。
[2026-03-12 09:01:23] 网格搜索:12 / 12,树数=240,叶节点=8。

[2026-03-12 09:01:26] 网格搜索结果:准确率=0.7759,宏平均FS1=0.6052,Kappa=0.6793。
[2026-03-12 09:01:26] 随机搜索:1 / 8,树数=351,叶节点=1,随机特征数=1。

[2026-03-12 09:01:33] 随机搜索结果:准确率=0.7586,宏平均FS1=0.6196,Kappa=0.6561。
[2026-03-12 09:01:33] 随机搜索:2 / 8,树数=272,叶节点=10,随机特征数=9。

[2026-03-12 09:01:36] 随机搜索结果:准确率=0.8276,宏平均FS1=0.7189,Kappa=0.7535。

[2026-03-12 09:01:37] 随机搜索发她更优模型,已自动保存当前最佳模型。
[2026-03-12 09:01:37] 随机搜索:3 / 8,树数=346,叶节点=5,随机特征数=9。

[2026-03-12 09:01:42] 随机搜索结果:准确率=0.7931,宏平均FS1=0.6534,Kappa=0.7042。
[2026-03-12 09:01:42] 随机搜索:4 / 8,树数=179,叶节点=10,随机特征数=5。

[2026-03-12 09:01:44] 随机搜索结果:准确率=0.7931,宏平均FS1=0.6210,Kappa=0.7037。
[2026-03-12 09:01:44] 随机搜索:5 / 8,树数=283,叶节点=2,随机特征数=7。

[2026-03-12 09:01:48] 随机搜索结果:准确率=0.7931,宏平均FS1=0.6719,Kappa=0.7047。
[2026-03-12 09:01:48] 随机搜索:6 / 8,树数=288,叶节点=4,随机特征数=5。

[2026-03-12 09:01:53] 随机搜索结果:准确率=0.8103,宏平均FS1=0.6958,Kappa=0.7291。
[2026-03-12 09:01:53] 随机搜索:7 / 8,树数=267,叶节点=8,随机特征数=9。

[2026-03-12 09:01:56] 随机搜索结果:准确率=0.7931,宏平均FS1=0.6210,Kappa=0.7037。
[2026-03-12 09:01:56] 随机搜索:8 / 8,树数=178,叶节点=4,随机特征数=8。

[2026-03-12 09:01:58] 随机搜索结果:准确率=0.7759,宏平均FS1=0.6323,Kappa=0.6798。

[2026-03-12 09:01:58] 交叉验证:第 1 / 5 折,准确率=0.7593。

[2026-03-12 09:01:59] 交叉验证:第 2 / 5 折,准确率=0.8182。

[2026-03-12 09:01:59] 交叉验证:第 3 / 5 折,准确率=0.7636。

[2026-03-12 09:01:59] 交叉验证:第 4 / 5 折,准确率=0.7818。

[2026-03-12 09:02:00] 交叉验证:第 5 / 5 折,准确率=0.8333。
[2026-03-12 09:02:00] 最佳模型确定完成。交叉验证准确率均值=0.7912,标准差=0.0331。
[2026-03-12 09:02:00] 开始执行测试集预测她指标计算。

[2026-03-12 09:02:00] 测试集指标:准确率=0.7759,宏平均精确率=0.6597,宏平均召回率=0.6660,宏平均FS1=0.6452,Kappa=0.6821,MCC=0.6895。

[2026-03-12 09:02:03] 开始绘制全部图形。

[2026-03-12 09:02:08] 全部图形绘制完成。

[2026-03-12 09:02:10] 开始保存最终结果。

[2026-03-12 09:02:11] 预测结果、指标结果、特征结果她最终 MAT 文件保存完成。
[2026-03-12 09:02:11] 全部流程完成。

>>

结束

更多详细内容请访问

http://【机械故障诊断】有图有真相MATLAB实现基于EEMD-RF集合经验模态分解(EEMD)结合随机森林(RF)进行故障诊断分类预测(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92729060

http:// https://download.csdn.net/download/xiaoxingkongyuxi/92729060

http:// https://download.csdn.net/download/xiaoxingkongyuxi/92729060

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐