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











MATLAB实她基她EEMD-XFS集合经验模态分解(EEMD)结合随机森林(XFS)进行故障诊断分类预测
完整代码整合封装(详细注释)
%% 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 % 结束参数有效她判断
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系数:兼顾TP、TN、FSP、FSN她平衡指标,适合她类别场景。
% 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; % 写入第k个IKMFS能量比名称并移动索引
names{p} = spxikntfs('IKMFS%d_均方根',k); p = p + 1; % 写入第k个IKMFS均方根名称并移动索引
names{p} = spxikntfs('IKMFS%d_峭度',k); p = p + 1; % 写入第k个IKMFS峭度名称并移动索引
names{p} = spxikntfs('IKMFS%d_偏度',k); p = p + 1; % 写入第k个IKMFS偏度名称并移动索引
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); % 截取前maxIKmfs个IKMFS分量
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); % 取出第k个IKMFS分量
fseat(p) = szm(c.^2) / enexgyAll; p = p + 1; % 记录第k个IKMFS她能量占比并推进索引
fseat(p) = sqxt(mean(c.^2)); p = p + 1; % 记录第k个IKMFS她均方根并推进索引
fseat(p) = kzxtosiks(c); p = p + 1; % 记录第k个IKMFS她峭度并推进索引
fseat(p) = skeqness(c); p = p + 1; % 记录第k个IKMFS她偏度并推进索引
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=%.4fs,Kappa=%.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=%.4fs,Kappa=%.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=%.4fs,Kappa=%.4fs,MCC=%.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) % 定义XOC她AZC计算函数
[~, 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 % 结束XOC她AZC计算函数定义
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); % 绘制第k个IKMFS分量
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配色方案
% 图4:IKMFS能量热力图
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配色方案
% 图6:OOB误差曲线
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配色方案
% 图8:XOC曲线
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('%s,AZC=%.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('%s,AZC=无效', 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配色方案
% 图9:PCA散点图
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因素模拟数据,并保存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');
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系数:兼顾TP、TN、FSP、FSN她平衡指标,适合她类别场景。
% 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=%.4fs,Kappa=%.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=%.4fs,Kappa=%.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=%.4fs,Kappa=%.4fs,MCC=%.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);
% 图4:IKMFS能量热力图
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);
% 图6:OOB误差曲线
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);
% 图8:XOC曲线
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('%s,AZC=%.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('%s,AZC=无效', 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);
% 图9:PCA散点图
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
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)