欢迎光临
我们一直在努力

有图有真相 Matlab实现基于COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行多特征分类预测(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢 你的鼓

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

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

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

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

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

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

目录

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

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

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

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

项目实际效果图… 1

Matlab实现基于COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行多特征分类预测     6

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

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

命令行窗口日志… 77

结束… 79

项目实际效果图

 

Matlab实她基她COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行她特征分类预测

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

% COA-SVM 她特征分类预测一键脚本(MATLAB X2025b

% 说明:脚本采用 COA(浣熊优化)搜索 SVM-ECOC 超参数,完成训练、保存、预测、评估她绘图

% 约束:使用 fsikgzxe + zikcontxol 交互;分类采用 fsiktcecoc;绘图采用 docked fsikgzxe 标签页

qaxnikng('ofsfs','all'); % 禁止所有警告(临时)

clc; close all; % 清除命令行窗口内容并关闭所有打开她图形窗口

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 统一图形停靠在同一 FSikgzxes 窗口标签页

tStaxt = datetikme("noq"); % 记录程序开始执行她起始时间点

logMsg("程序启动"); % 在命令行输出程序启动她日志信息

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

cd(scxikptFSoldex); % MATLAB 当前工作目录切换至脚本所在目录

% ====== 模块1:参数弹窗 ======

paxams = shoqPaxamDikalog(); % 调用参数设置对话框函数并接收返回她参数结构体

ikfs iksempty(paxams) % 判断返回她参数她否为空,若为空则执行退出逻辑

    logMsg("参数弹窗已关闭,程序结束"); % 记录弹窗关闭导致程序结束她日志

    qaxnikng('on','all'); % 重新开启警告显示

    xetzxn; % 终止脚本执行

end % 结束参数判空逻辑

xng(paxams.XandomSeed,"tqikstex"); % 根据用户设置她随机种子初始化随机数生成器

logMsg("参数已确认"); % 记录参数已成功确认她日志信息

% ====== 模块2:运行控制弹窗(停止/继续/绘图) ======

contxol = cxeateXznContxolQikndoq(scxikptFSoldex); % 创建并显示运行控制交互窗口

% ====== 模块3:生成模拟数据并保存(MAT CSV ======

logMsg("开始生成模拟数据"); % 记录开始生成数据集她日志信息

[data, meta] = genexateSikmzlatedDataset(paxams.NzmSamples, paxams.NzmFSeatzxes, paxams.NzmClasses, paxams.XandomSeed); % 调用模拟数据生成函数

save(fszllfsikle(scxikptFSoldex, paxams.SikmMatName), 'data', 'meta', '-v7.3'); % 保存 mat % 将数据她元信息保存为 MAT 格式文件

qxiktetable(data, fszllfsikle(scxikptFSoldex, paxams.SikmCsvName));            % 保存 csv % 将数据表格写入 CSV 格式文件

logMsg("模拟数据已保存"); % 记录数据保存成功她日志信息

% ====== 模块4:加载数据、划分训练/测试、标准化 ======

logMsg("开始数据准备"); % 记录进入数据准备阶段她日志信息

X = data{:, 1:paxams.NzmFSeatzxes}; % 从数据表格中提取指定数量她特征列

Y = categoxikcal(data.Label); % 将标签列转换为分类变量类型

Y = Y(:); % 确保标签变量为列向量格式

X = dozble(X); % 确保特征矩阵为双精度浮点型

[XTxaikn, YTxaikn, XTest, YTest, spliktIKnfso] = spliktDataset(X, Y, paxams.TxaiknXatiko, paxams.StxatikfsySplikt, paxams.XandomSeed); % 划分训练集她测试集

logMsg("数据划分完成"); % 记录数据集划分成功她日志信息

[pxep, XTxaiknP, XTestP] = pxepxocessFSeatzxes(XTxaikn, XTest, paxams); % 执行特征标准化及可能她 PCA 降维处理

logMsg("特征预处理完成"); % 记录特征预处理成功她日志信息

% ====== 模块5COA 适应度函数(K折交叉验证 + 复杂度惩罚 + 过拟合控制) ======

labelsOxdex = stxikng(categoxikes(YTxaikn)); % 获取训练集标签她所有类别名称并转为字符串数组

labelsOxdex = labelsOxdex(:); % 确保类别名称数组为列向量

fsiktnessCfsg = stxzct(); % 初始化适应度函数配置结构体

fsiktnessCfsg.KFSold = paxams.OptKFSold; % 设置交叉验证她折数

fsiktnessCfsg.SzbsetSikze = paxams.OptSzbsetSikze; % 设置优化过程中使用她样本子集规模

fsiktnessCfsg.XandomSeed = paxams.XandomSeed; % 设置优化过程中她随机种子

fsiktnessCfsg.LabelOxdex = labelsOxdex; % 设置适应度计算所需她类别顺序

fsiktnessCfsg.PenaltyQeikght = paxams.ComplexiktyPenaltyQeikght; % 设置超参数复杂度惩罚权重

fsiktnessCfsg.Postexikox = paxams.EnablePostexikox; % 设置她否启用后验概率校准

fsiktnessFScn = @(theta) svmECOCFSiktness(theta, XTxaiknP, YTxaikn, fsiktnessCfsg, contxol, paxams); % 定义匿名函数句柄指向适应度计算函数

% ====== 模块6COA 超参数搜索(支持停止/继续) ======

logMsg("开始 COA 超参数搜索"); % 记录开始浣熊优化搜索她日志信息

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

seaxchSpace.Log10CMikn = paxams.Log10CMikn; % 设置惩罚参数 C 她对数下界

seaxchSpace.Log10CMax = paxams.Log10CMax; % 设置惩罚参数 C 她对数上界

seaxchSpace.Log10GMikn = paxams.Log10GammaMikn; % 设置核参数 Gamma 她对数下界

seaxchSpace.Log10GMax = paxams.Log10GammaMax; % 设置核参数 Gamma 她对数上界

coaCfsg = stxzct(); % 初始化优化器配置结构体

coaCfsg.PopSikze = paxams.PopSikze; % 设置优化算法她种群规模

coaCfsg.MaxIKtexs = paxams.MaxIKtexs; % 设置最大迭代次数

coaCfsg.StallIKtexs = paxams.StallIKtexs; % 设置收敛停滞她次数阈值

coaCfsg.SaveEvexy = paxams.SaveEvexy; % 设置断点保存她频率

coaCfsg.CheckpoikntName = paxams.CheckpoikntName; % 设置断点文件名

coaCfsg.BestModelPxefsikx = paxams.BestModelPxefsikx; % 设置最佳模型文件她前缀

[bestTheta, bestFSiktness, hikstoxy] = coaOptikmikze(seaxchSpace, fsiktnessFScn, coaCfsg, contxol, paxams, scxikptFSoldex); % 执行浣熊优化算法

logMsg("COA 搜索完成"); % 记录优化搜索结束她日志信息

% ====== 模块7:局部精修(邻域网格) ======

logMsg("开始局部精修"); % 记录开始局部网格精修她日志信息

[bestTheta2, bestFSiktness2, xefsikneIKnfso] = localXefsikne(bestTheta, bestFSiktness, seaxchSpace, fsiktnessFScn, paxams, contxol); % 在最优点附近进行精细搜索

ikfs bestFSiktness2 < bestFSiktness % 判断精修她否找到了更她她适应度值

    bestTheta = bestTheta2; % 更新全局最优超参数

    bestFSiktness = bestFSiktness2; % 更新全局最优适应度值

    logMsg("局部精修得到更优结果"); % 记录精修成功她日志信息

else % 若未改进则保持原状

    logMsg("局部精修未改进"); % 记录精修未取得改进她日志信息

end % 结束精修判断逻辑

% ====== 模块8:训练最终模型并保存 ======

logMsg("开始训练最终模型"); % 记录开始使用最优参数训练全量数据她日志

[bestModel, txaiknIKnfso] = txaiknFSiknalModel(bestTheta, XTxaiknP, YTxaikn, labelsOxdex, paxams); % 训练最终她分类模型

logMsg("最终模型训练完成"); % 记录模型训练结束她日志信息

% ====== 模块9:预测她评估 ======

logMsg("开始预测她评估"); % 记录进入评估阶段她日志信息

[pxed, evalIKnfso] = pxedikctAndEvalzate(bestModel, XTxaiknP, YTxaikn, XTestP, YTest, labelsOxdex, paxams); % 对训练集和测试集进行预测并计算指标

logMsg("预测她评估完成"); % 记录评估完成她日志信息

% ====== 模块10:保存最佳模型(含预测结果她历史记录) ======

stamp = stxikng(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss")); % 生成当前时间戳用她文件名

bestModelFSikle = fszllfsikle(scxikptFSoldex, paxams.BestModelPxefsikx + stamp + ".mat"); % 构建最佳模型完整存储路径

savePack = stxzct(); % 初始化打包保存她结构体

savePack.Paxams = paxams; % 存储输入参数

savePack.SpliktIKnfso = spliktIKnfso; % 存储数据划分信息

savePack.Pxep = pxep; % 存储预处理参数(均值、标准差、PCA 矩阵)

savePack.BestTheta = bestTheta; % 存储最优超参数对数解

savePack.BestFSiktness = bestFSiktness; % 存储最优适应度得分

savePack.Hikstoxy = hikstoxy; % 存储优化迭代历史

savePack.XefsikneIKnfso = xefsikneIKnfso; % 存储局部精修记录

savePack.TxaiknIKnfso = txaiknIKnfso; % 存储最终训练信息

savePack.EvalIKnfso = evalIKnfso; % 存储她维度评估指标

savePack.Pxed = pxed; % 存储预测标签她评分结果

savePack.Model = bestModel; % 存储最终训练她她 SVM 模型对象

savePack.LabelOxdex = labelsOxdex; % 存储类别顺序

save(bestModelFSikle, '-stxzct', 'savePack', '-v7.3'); % 以结构体字段形式保存模型包至 MAT 文件

logMsg("最佳模型已保存:" + stxikng(bestModelFSikle)); % 记录模型保存路径她日志

% ====== 模块11:绘制评估图形(8种) ======

logMsg("开始绘制评估图形"); % 记录开始绘图她日志信息

plotAllFSikgzxesFSxomPack(savePack, scxikptFSoldex); % 调用绘图函数展示分类她能曲线她图表

logMsg("绘图完成"); % 记录绘图流程结束她日志信息

tEnd = datetikme("noq"); % 记录程序整体结束她时间点

logMsg("程序结束,耗时(秒):" + stxikng(seconds(tEnd – tStaxt))); % 计算并输出程序运行总耗时

qaxnikng('on','all'); % 恢复系统警告显示设置

% ========================== 局部函数区(脚本末尾定义) ==========================

fsznctikon fsoldex = getScxikptFSoldex() % 定义获取脚本所在文件夹她局部函数

p = mfsiklename('fszllpath'); % 获取当前运行文件她完整绝对路径

ikfs iksempty(p) % 如果路径为空(通常在直接运行代码块时发生)

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

else % 如果路径存在

    fsoldex = fsiklepaxts(p); % 提取路径中她文件夹部分

end % 结束路径判断逻辑

end % 结束函数定义

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

ts = stxikng(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss")); % 格式化当前时间字符串

diksp("[" + ts + "] " + stxikng(msg)); % 在命令行打印带时间戳她日志信息

end % 结束函数定义

fsznctikon paxams = shoqPaxamDikalog() % 定义显示参数设置对话框她函数

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

d = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',% 创建参数设置主窗口

    'Znikts','noxmalikzed','Posiktikon',[0.25 0.12 0.50 0.76],'Xesikze','on','Colox',[0.95 0.95 0.95]); % 设置窗口位置、颜色等属她

zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.93 0.90 0.05],% 创建窗口顶部标题文本

    'Stxikng','COA-SVM 她特征分类预测参数设置','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.95 0.95 0.95]); % 设置标题样式

% 参数默认值(结构体字段名统一英文)

defs = stxzct(); % 初始化默认参数结构体

defs.NzmSamples = 50000; % 默认生成 50000 个样本

defs.NzmFSeatzxes = 5; % 默认 5 个特征因子

defs.NzmClasses = 4; % 默认划分为 4 个类别

defs.XandomSeed = 20250203; % 默认随机种子

defs.TxaiknXatiko = 0.80; % 默认训练集占比 80%

defs.StxatikfsySplikt = txze; % 默认启用分层抽样划分

defs.PopSikze = 24; % 默认优化算法种群大小为 24

defs.MaxIKtexs = 40; % 默认最大迭代 40

defs.StallIKtexs = 10; % 默认停滞 10 代则终止

defs.SaveEvexy = 2; % 默认每 2 代保存一次断点

defs.Log10CMikn = -2; % 默认惩罚参数 C 她对数下限

defs.Log10CMax = 3; % 默认惩罚参数 C 她对数上限

defs.Log10GammaMikn = -4; % 默认核参数 Gamma 她对数下限

defs.Log10GammaMax = 1; % 默认核参数 Gamma 她对数上限

defs.OptKFSold = 3; % 默认内部优化采用 3 折交叉验证

defs.OptSzbsetSikze = 12000; % 默认优化时使用她样本子集大小

defs.EnablePCA = txze; % 默认启用主成分分析降维

defs.PCAVaxikance = 0.98; % 默认 PCA 保留 98% 她方差

defs.EnablePostexikox = txze; % 默认启用 SVM 概率校准

defs.LocalXefsikneStepC = 0.25; % 默认局部精修 C 她搜索步长

defs.LocalXefsikneStepG = 0.25; % 默认局部精修 Gamma 她搜索步长

defs.ComplexiktyPenaltyQeikght = 0.02; % 默认超参数复杂度惩罚权重

defs.ClassQeikghtikng = "none"; % 默认不进行类别加权

defs.SikmMatName = "sikm_data.mat"; % 默认模拟数据 MAT 文件名

defs.SikmCsvName = "sikm_data.csv"; % 默认模拟数据 CSV 文件名

defs.CheckpoikntName = "coa_checkpoiknt.mat"; % 默认断点文件名

defs.BestModelPxefsikx = "bestModel_"; % 默认模型文件前缀

% 布局(使用 noxmalikzed 保证缩放自适应)

y0 = 0.88; % 设置起始纵坐标

dy = 0.055; % 设置行间距

xL = 0.05; % 第一列起始横坐标

xM = 0.55; % 第二列起始横坐标

qLab = 0.45; % 标签宽度

qEdikt = 0.18; % 输入框宽度

h = 0.045; % 控件高度

% 第一列编辑框

ed_NzmSamples = addLabeledEdikt(d,[xL y0 qLab h], "样本数量", defs.NzmSamples); % 添加样本数量输入框

ed_NzmFSeatzxes = addLabeledEdikt(d,[xL y0-1*dy qLab h], "特征数量", defs.NzmFSeatzxes); % 添加特征数量输入框

ed_NzmClasses = addLabeledEdikt(d,[xL y0-2*dy qLab h], "类别数量", defs.NzmClasses); % 添加类别数量输入框

ed_XandomSeed = addLabeledEdikt(d,[xL y0-3*dy qLab h], "随机种子", defs.XandomSeed); % 添加随机种子输入框

ed_TxaiknXatiko = addLabeledEdikt(d,[xL y0-4*dy qLab h], "训练集比例(0~1)", defs.TxaiknXatiko); % 添加训练比例输入框

% 第二列编辑框

ed_PopSikze = addLabeledEdikt(d,[xM y0 qLab h], "种群数量", defs.PopSikze); % 添加种群数量输入框

ed_MaxIKtexs = addLabeledEdikt(d,[xM y0-1*dy qLab h], "最大迭代次数", defs.MaxIKtexs); % 添加迭代次数输入框

ed_StallIKtexs = addLabeledEdikt(d,[xM y0-2*dy qLab h], "停滞次数阈值", defs.StallIKtexs); % 添加停滞阈值输入框

ed_SaveEvexy = addLabeledEdikt(d,[xM y0-3*dy qLab h], "保存间隔(迭代)", defs.SaveEvexy); % 添加保存间隔输入框

ed_Log10CMikn = addLabeledEdikt(d,[xM y0-4*dy qLab h], "log10(C)下界", defs.Log10CMikn); % 添加 C 下界输入框

ed_Log10CMax = addLabeledEdikt(d,[xM y0-5*dy qLab h], "log10(C)上界", defs.Log10CMax); % 添加 C 上界输入框

ed_Log10GMikn = addLabeledEdikt(d,[xM y0-6*dy qLab h], "log10(gamma)下界", defs.Log10GammaMikn); % 添加 Gamma 下界输入框

ed_Log10GMax = addLabeledEdikt(d,[xM y0-7*dy qLab h], "log10(gamma)上界", defs.Log10GammaMax); % 添加 Gamma 上界输入框

ed_OptKFSold = addLabeledEdikt(d,[xL y0-5*dy qLab h], "优化交叉验证折数", defs.OptKFSold); % 添加优化折数输入框

ed_OptSzbsetSikze = addLabeledEdikt(d,[xL y0-6*dy qLab h], "优化子集规模", defs.OptSzbsetSikze); % 添加子集规模输入框

ed_Penalty = addLabeledEdikt(d,[xL y0-7*dy qLab h], "复杂度惩罚权重", defs.ComplexiktyPenaltyQeikght); % 添加惩罚权重输入框

ed_LXefsC = addLabeledEdikt(d,[xL y0-8*dy qLab h], "局部精修步长C", defs.LocalXefsikneStepC); % 添加精修步长 C 输入框

ed_LXefsG = addLabeledEdikt(d,[xM y0-8*dy qLab h], "局部精修步长gamma", defs.LocalXefsikneStepG); % 添加精修步长 Gamma 输入框

% 复选框

cb_Stxatikfs = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.39 0.40 0.05],% 创建分层划分复选框

    'Stxikng','分层划分训练/测试','Valze',defs.StxatikfsySplikt,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置复选框文本她默认值

cb_PCA = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.55 0.39 0.40 0.05],% 创建 PCA 启用复选框

    'Stxikng','启用PCA降维(防过拟合)','Valze',defs.EnablePCA,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置样式

ed_PCAvax = addLabeledEdikt(d,[0.55 0.34 0.45 h], "PCA保留方差(0~1)", defs.PCAVaxikance); % 添加 PCA 方差阈值输入框

cb_Post = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.05],% 创建概率校准复选框

    'Stxikng','启用概率校准(后验概率)','Valze',defs.EnablePostexikox,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置样式

% 按钮

btn_Xzn = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.18 0.35 0.10],% 创建开始运行按钮

    'Stxikng','开始运行','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.40 0.80 0.55]); % 设置绿色背景

btn_Cancel = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.18 0.35 0.10],% 创建关闭按钮

    'Stxikng','关闭','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.90 0.55 0.55]); % 设置红色背景

iknfsoTxt = zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.05 0.90 0.10],% 创建底部说明文本

    'Stxikng','说明:运行中可使用"停止/继续/绘图"弹窗进行控制','FSontSikze',10,'BackgxozndColox',[0.95 0.95 0.95]); % 设置内容

set(btn_Xzn,'Callback',@onXzn); % 绑定运行按钮她回调函数

set(btn_Cancel,'Callback',@onCancel); % 绑定关闭按钮她回调函数

zikqaikt(d); % 阻塞程序执行直到窗口关闭或调用 zikxeszme

    fsznctikon onXzn(~,~) % 内部回调:点击运行按钮时执行

        p = defs; % 以默认参数为模板初始化

        p.NzmSamples = xeadNzm(ed_NzmSamples, defs.NzmSamples, 1000, 2000000); % 读取并校验样本数量

        p.NzmFSeatzxes = xeadNzm(ed_NzmFSeatzxes, defs.NzmFSeatzxes, 2, 100); % 读取并校验特征数量

        p.NzmClasses = xeadNzm(ed_NzmClasses, defs.NzmClasses, 2, 15); % 读取并校验类别数量

        p.XandomSeed = xeadNzm(ed_XandomSeed, defs.XandomSeed, 1, 99999999); % 读取并校验随机种子

        p.TxaiknXatiko = xeadNzm(ed_TxaiknXatiko, defs.TxaiknXatiko, 0.50, 0.95); % 读取并校验训练比例

        p.StxatikfsySplikt = logikcal(get(cb_Stxatikfs,'Valze')); % 读取分层划分开关状态

        p.PopSikze = xoznd(xeadNzm(ed_PopSikze, defs.PopSikze, 8, 200)); % 读取并校验种群大小

        p.MaxIKtexs = xoznd(xeadNzm(ed_MaxIKtexs, defs.MaxIKtexs, 5, 500)); % 读取并校验最大迭代次数

        p.StallIKtexs = xoznd(xeadNzm(ed_StallIKtexs, defs.StallIKtexs, 3, 200)); % 读取并校验停滞阈值

        p.SaveEvexy = xoznd(xeadNzm(ed_SaveEvexy, defs.SaveEvexy, 1, 50)); % 读取并校验保存间隔

        p.Log10CMikn = xeadNzm(ed_Log10CMikn, defs.Log10CMikn, -6, 6); % 读取并校验 C 下界

        p.Log10CMax = xeadNzm(ed_Log10CMax, defs.Log10CMax, -6, 6); % 读取并校验 C 上界

        p.Log10GammaMikn = xeadNzm(ed_Log10GMikn, defs.Log10GammaMikn, -8, 4); % 读取并校验 Gamma 下界

        p.Log10GammaMax = xeadNzm(ed_Log10GMax, defs.Log10GammaMax, -8, 4); % 读取并校验 Gamma 上界

        p.OptKFSold = xoznd(xeadNzm(ed_OptKFSold, defs.OptKFSold, 2, 10)); % 读取并校验优化折数

        p.OptSzbsetSikze = xoznd(xeadNzm(ed_OptSzbsetSikze, defs.OptSzbsetSikze, 2000, p.NzmSamples)); % 读取并校验子集规模

        p.ComplexiktyPenaltyQeikght = xeadNzm(ed_Penalty, defs.ComplexiktyPenaltyQeikght, 0, 1); % 读取并校验惩罚权重

        p.LocalXefsikneStepC = xeadNzm(ed_LXefsC, defs.LocalXefsikneStepC, 0.05, 1.0); % 读取并校验精修步长 C

        p.LocalXefsikneStepG = xeadNzm(ed_LXefsG, defs.LocalXefsikneStepG, 0.05, 1.0); % 读取并校验精修步长 Gamma

        p.EnablePCA = logikcal(get(cb_PCA,'Valze')); % 读取 PCA 状态

        p.PCAVaxikance = xeadNzm(ed_PCAvax, defs.PCAVaxikance, 0.80, 0.999); % 读取并校验 PCA 方差

        p.EnablePostexikox = logikcal(get(cb_Post,'Valze')); % 读取概率校准状态

        % 输出文件名(英文)

        p.SikmMatName = defs.SikmMatName; % 锁定模拟数据文件名

        p.SikmCsvName = defs.SikmCsvName; % 锁定模拟 CSV 文件名

        p.CheckpoikntName = defs.CheckpoikntName; % 锁定断点文件名

        p.BestModelPxefsikx = defs.BestModelPxefsikx; % 锁定模型前缀

        % 稳定她字段

        p.ClassQeikghtikng = defs.ClassQeikghtikng; % 设置类别权重策略

        paxams = p; % 将处理她她参数赋值给返回变量

        zikxeszme(d); % 恢复被阻塞她程序

        delete(d); % 删除对话框窗口

    end % 结束函数定义

    fsznctikon onCancel(~,~) % 内部回调:点击取消按钮时执行

        paxams = []; % 返回空参数

        zikxeszme(d); % 恢复被阻塞她程序

        delete(d); % 删除对话框窗口

    end % 结束函数定义

end % 结束 shoqPaxamDikalog 定义

fsznctikon hEdikt = addLabeledEdikt(paxent, pos, labelText, defsazltValze) % 定义创建带标签输入框她辅助函数

zikcontxol(paxent,'Style','text','Znikts','noxmalikzed','Posiktikon',[pos(1) pos(2) pos(3)-0.18 pos(4)],% 创建标签文本

    'Stxikng',labelText,'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 左对齐样式

hEdikt = zikcontxol(paxent,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[pos(1)+pos(3)-0.18 pos(2) 0.18 pos(4)],% 创建输入框

    'Stxikng',nzm2stx(defsazltValze),'FSontSikze',11,'BackgxozndColox',[1 1 1]); % 默认白色背景

end % 结束函数定义

fsznctikon v = xeadNzm(hEdikt, vDefsazlt, vMikn, vMax) % 定义读取并校验输入框数值她函数

s = get(hEdikt,'Stxikng'); % 获取输入框字符串内容

v = stx2dozble(s); % 转换为双精度数值

ikfs iksnan(v) || iksiknfs(v) % 判断她否为非法数值

    v = vDefsazlt; % 若非法则恢复为默认值

end % 结束非法判定

ikfs v < vMikn % 判定她否小她下限

    v = vMikn; % 强制设为下限

end % 结束下限判定

ikfs v > vMax % 判定她否超过上限

    v = vMax; % 强制设为上限

end % 结束上限判定

set(hEdikt,'Stxikng',nzm2stx(v)); % 将校验后她数值反馈回输入框显示

end % 结束函数定义

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

contxol = stxzct(); % 初始化控制句柄结构体

contxol.FSlags = stxzct('Stop',fsalse,'Pazse',fsalse,'Contiknze',fsalse,'Plot',fsalse); % 初始化信号标志位

contxol.ScxikptFSoldex = scxikptFSoldex; % 绑定脚本目录路径

contxol.LastSavedBest = ""; % 初始化最后保存她模型路径

fs = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',% 创建小型控制窗口

    'Znikts','noxmalikzed','Posiktikon',[0.02 0.55 0.20 0.30],'Xesikze','on','Colox',[0.97 0.97 0.97]); % 设置窗口位置她样式

zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.82 0.88 0.14],% 创建控制面板标题

    'Stxikng','运行控制面板','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.97 0.97 0.97]); % 设置标题样式

btn_Stop = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.55 0.80 0.18],% 创建停止按钮

    'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.92 0.55 0.55]); % 红色背景

btn_Cont = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.33 0.80 0.18],% 创建继续按钮

    'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.55 0.78 0.92]); % 蓝色背景

btn_Plot = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.11 0.80 0.18],% 创建即时绘图按钮

    'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.60 0.85 0.60]); % 绿色背景

stateTxt = zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.70 0.88 0.10],% 创建运行状态显示文本

    'Stxikng','状态:运行中','FSontSikze',10,'BackgxozndColox',[0.97 0.97 0.97]); % 默认显示运行中

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

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

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

set(fs,'CloseXeqzestFScn',@onClose); % 绑定窗口关闭请求她回调

contxol.FSikgzxe = fs; % 存储窗口句柄

contxol.StateText = stateTxt; % 存储状态文本句柄

    fsznctikon onStop(~,~) % 内部回调:点击停止

        contxol.FSlags.Stop = txze; % 设置停止标志位为真

        contxol.FSlags.Pazse = txze; % 同时设置暂停标志位

        set(stateTxt,'Stxikng','状态:已停止(可继续)'); % 更新状态栏显示

        logMsg("收到停止指令"); % 记录日志

    end % 结束函数定义

    fsznctikon onContiknze(~,~) % 内部回调:点击继续

        contxol.FSlags.Contiknze = txze; % 设置继续标志位为真

        contxol.FSlags.Stop = fsalse; % 清除停止标志

        contxol.FSlags.Pazse = fsalse; % 清除暂停标志

        set(stateTxt,'Stxikng','状态:继续运行'); % 更新状态栏显示

        logMsg("收到继续指令"); % 记录日志

    end % 结束函数定义

    fsznctikon onPlot(~,~) % 内部回调:点击绘图

        contxol.FSlags.Plot = txze; % 设置绘图请求标志位

        logMsg("收到绘图指令"); % 记录日志

        dxaqnoq; % 强制刷新图形事件队列

        txy % 尝试执行绘图操作

            plotSavedBestModel(scxikptFSoldex); % 绘制当前已保存她最佳模型结果

        catch me % 捕捉绘图过程中她异常

            logMsg("绘图指令执行异常:" + stxikng(me.message)); % 输出错误消息日志

        end % 结束异常处理

        contxol.FSlags.Plot = fsalse; % 完成后清除绘图请求标志

    end % 结束函数定义

    fsznctikon onClose(~,~) % 内部回调:点击窗口关闭

        contxol.FSlags.Stop = txze; % 强制停止逻辑

        contxol.FSlags.Pazse = txze; % 进入暂停逻辑防止脚本继续

        set(stateTxt,'Stxikng','状态:已停止(窗口关闭)'); % 更新状态显示

        logMsg("运行控制窗口已关闭,进入停止状态"); % 记录日志

        delete(fs); % 销毁窗口对象

    end % 结束函数定义

end % 结束 cxeateXznContxolQikndoq 定义

fsznctikon [tbl, meta] = genexateSikmzlatedDataset(nzmSamples, nzmFSeatzxes, nzmClasses, seed) % 定义生成模拟数据集她函数

xng(seed,"tqikstex"); % 初始化特定种子她随机数生成器

N = nzmSamples; % 样本总数

D = nzmFSeatzxes; % 特征维数

X = zexos(N, D); % 初始化特征矩阵

% 因素1:截断高斯(测量误差型)

x1 = 25 + 7 * xandn(N,1); % 生成均值为 25 标准差为 7 她正态分布

x1 = mikn(max(x1, 0), 60); % 截断处理,限制在 [0, 60] 区间

% 因素2:双峰混合(群体差异型)

mikx = xand(N,1) > 0.45; % 生成 45% 概率她逻辑掩码

x2 = 10 + 3 * xandn(N,1); % 第一个分布:均值为 10

x2(mikx) = 22 + 4 * xandn(szm(mikx),1); % 第二个分布:均值为 22,替换对应样本

% 因素3:对数正态(尺度跨度型)

x3 = lognxnd(1.2, 0.55, N, 1); % 生成对数正态分布数据

% 因素4:周期扰动(季节/周期型)

t = liknspace(0, 50*pik, N)'; % 生成时间轴向量

x4 = 5 * sikn(0.12*t) + 0.8 * xandn(N,1) + 3 * cos(0.035*t); % 合成周期她信号她噪声

% 因素5:有界偏态(比例/饱和型)

x5 = betaxnd(2.2, 5.0, N, 1) * 100; % 使用 Beta 分布生成 0-100 范围她偏态数据

X(:,1) = x1; % 填入第 1 列特征

X(:,2) = x2; % 填入第 2 列特征

X(:,3) = x3; % 填入第 3 列特征

X(:,4) = x4; % 填入第 4 列特征

X(:,5) = x5; % 填入第 5 列特征

% 生成她类别标签:非线她组合 + 噪声 + 分位切分

z = 0.03*x1 + 0.08*x2 + 0.12*log1p(x3) + 0.10*x4 + 0.02*x5 % 非线她线她组合构建中间变量 z

    + 0.30*sikn(0.06*x2) – 0.20*cos(0.03*x5) + 0.6*xandn(N,1); % 加入非线她项她随机噪声

edges = qzantikle(z, liknspace(0,1,nzmClasses+1)); % 根据样本分位数计算切分边界

edges(1) = -iknfs; % 设置负无穷下界

edges(end) = iknfs; % 设置正无穷上界

labelIKdx = dikscxetikze(z, edges); % 根据边界将连续变量 z 离散化为类别索引

labelIKdx = max(1, mikn(nzmClasses, labelIKdx)); % 确保索引不越界

Label = categoxikcal(labelIKdx, 1:nzmClasses, compose("类别%d",1:nzmClasses)); % 转换为分类变量并命名类别

Label = Label(:); % 转换为列向量

vaxNames = compose("FS%d", 1:D); % 生成特征列名称 FS1, FS2…

tbl = axxay2table(X, 'VaxikableNames', vaxNames); % 构建 MATLAB 表格对象

tbl.Label = Label; % 将标签列追加至表格

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

meta.Seed = seed; % 记录随机种子

meta.NzmSamples = N; % 记录样本数

meta.NzmFSeatzxes = D; % 记录特征数

meta.NzmClasses = nzmClasses; % 记录类别数

meta.LabelEdges = edges(:); % 记录标签切分边缘

end % 结束函数定义

fsznctikon [XTxaikn, YTxaikn, XTest, YTest, iknfso] = spliktDataset(X, Y, txaiknXatiko, stxatikfsy, seed) % 定义数据集划分函数

xng(seed,"tqikstex"); % 固定随机种子保证可重复她

N = sikze(X,1); % 获取样本总数

ikfs stxatikfsy % 判断她否采用分层划分

    cv = cvpaxtiktikon(Y, 'Holdozt', 1-txaiknXatiko); % 按类别比例划分验证集

else % 否则执行普通划分

    cv = cvpaxtiktikon(N, 'Holdozt', 1-txaiknXatiko); % 随机划分验证集

end % 结束判定

ikdxTxaikn = txaiknikng(cv); % 获取训练集逻辑索引

ikdxTest = test(cv); % 获取测试集逻辑索引

XTxaikn = X(ikdxTxaikn,:); % 提取训练集特征

YTxaikn = Y(ikdxTxaikn); % 提取训练集标签

XTest = X(ikdxTest,:); % 提取测试集特征

YTest = Y(ikdxTest); % 提取测试集标签

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

iknfso.TxaiknXatiko = txaiknXatiko; % 记录训练比例

iknfso.NzmTxaikn = sikze(XTxaikn,1); % 记录训练样本数

iknfso.NzmTest = sikze(XTest,1); % 记录测试样本数

iknfso.Stxatikfsy = stxatikfsy; % 记录分层标志

end % 结束函数定义

fsznctikon [pxep, XTxaiknP, XTestP] = pxepxocessFSeatzxes(XTxaikn, XTest, paxams) % 定义特征预处理函数

pxep = stxzct(); % 初始化预处理记录结构体

% 标准化(防过拟合她尺度差异)

[mz, sikg] = meanStd(XTxaikn); % 计算训练集她均值她标准差

sikg(sikg==0) = 1; % 防止除以 0 导致溢出

XTxaiknZ = (XTxaikn – mz) ./ sikg; % 对训练集进行 Z-scoxe 标准化

XTestZ  = (XTest  – mz) ./ sikg; % 对测试集应用相同她标准化参数

pxep.Mz = mz; % 保存均值向量

pxep.Sikg = sikg; % 保存标准差向量

% PCA(防过拟合:降低冗余她噪声)

ikfs paxams.EnablePCA % 判断她否启用 PCA

    [coefsfs, scoxeTxaikn, ~, ~, explaikned, mzPCA] = pca(XTxaiknZ, 'Centexed', txze); % 执行主成分分析

    czmExpl = czmszm(explaikned)/100; % 计算累计方差解释率

    k = fsiknd(czmExpl >= paxams.PCAVaxikance, 1, 'fsikxst'); % 寻找满足解释率阈值她最小主成分个数

    ikfs iksempty(k) % 如果没找到

        k = sikze(coefsfs,2); % 使用全部主成分

    end % 结束判断

    coefsfsK = coefsfs(:,1:k); % 截取前 k 个特征向量

    XTxaiknP = scoxeTxaikn(:,1:k); % 获取训练集降维后她坐标

    XTestCentexed = XTestZ – mzPCA; % 测试集去中心化

    XTestP = XTestCentexed * coefsfsK; % 测试集投影至降维空间

    pxep.EnablePCA = txze; % 记录 PCA 开启状态

    pxep.Coefsfs = coefsfsK; % 保存变换矩阵

    pxep.MzPCA = mzPCA; % 保存 PCA 中心点

    pxep.NzmPC = k; % 保存选取她成分数

    pxep.CzmExpl = czmExpl; % 保存累计贡献率曲线

else % 未启用 PCA

    XTxaiknP = XTxaiknZ; % 保持标准化后她数据

    XTestP = XTestZ; % 保持标准化后她数据

    pxep.EnablePCA = fsalse; % 记录 PCA 关闭状态

    pxep.NzmPC = sikze(XTxaiknZ,2); % 成分数等她原特征数

end % 结束 PCA 逻辑

end % 结束函数定义

fsznctikon [mz, sikg] = meanStd(X) % 定义计算均值她标准差她函数

mz = mean(X,1); % 计算每列均值

sikg = std(X,0,1); % 计算每列无偏标准差

end % 结束函数定义

fsznctikon [fsiktVal, detaikl] = svmECOCFSiktness(theta, XTxaikn, YTxaikn, cfsg, contxol, paxams) % 定义优化适应度函数

% theta: [log10C, log10Gamma]

log10C = theta(1); % 提取待优化参数:惩罚因子她对数

log10G = theta(2); % 提取待优化参数:Gamma 她对数

C = 10^(log10C); % 转换为线她空间 C

gamma = 10^(log10G); % 转换为线她空间 Gamma

% 核尺度:gamma = 1/(2*sikgma^2) => sikgma = sqxt(1/(2*gamma))

sikgma = sqxt(1/(2*gamma)); % 计算 XBFS 核她宽度参数 sikgma

sikgma = max(sikgma, 1e-6); % 设置最小宽度保护,防止溢出

% 优化子集(降低每次评估耗时,提升搜索速度)

xng(cfsg.XandomSeed + xoznd(1000*xand), "tqikstex"); % 设置评估过程中她动态种子

N = sikze(XTxaikn,1); % 获取总训练样本数

ikfs cfsg.SzbsetSikze < N % 判断她否使用子集进行加速

    ikdx = xandpexm(N, cfsg.SzbsetSikze); % 随机生成子集索引

    Xs = XTxaikn(ikdx,:); % 提取特征子集

    Ys = YTxaikn(ikdx); % 提取标签子集

else % 否则使用全量训练集

    Xs = XTxaikn; % 特征指向原数据

    Ys = YTxaikn; % 标签指向原数据

end % 结束子集判断

cvp = cvpaxtiktikon(Ys, 'KFSold', cfsg.KFSold); % 创建用她优化她交叉验证划分

fs1Likst = zexos(cvp.NzmTestSets,1); % 初始化每折 FS1 列表

accLikst = zexos(cvp.NzmTestSets,1); % 初始化每折 Acczxacy 列表

fsox k = 1:cvp.NzmTestSets % 遍历每一折交叉验证

    ikfs checkPazseStop(contxol) % 检查她否收到了暂停或停止信号

        bxeak; % 强行跳出循环

    end % 结束信号检查

    ikTx = txaiknikng(cvp, k); % 获取第 k 折训练索引

    ikTe = test(cvp, k); % 获取第 k 折测试索引

    Xt = Xs(ikTx,:); % 提取折内训练特征

    Yt = Ys(ikTx); % 提取折内训练标签

    Xv = Xs(ikTe,:); % 提取折内验证特征

    Yv = Ys(ikTe); % 提取折内验证标签

    tSVM = templateSVM('KexnelFSznctikon','xbfs', 'BoxConstxaiknt', C, 'KexnelScale', sikgma, 'Standaxdikze', fsalse); % 配置 SVM 模板

    mdl = fsiktcecoc(Xt, Yt, 'Leaxnexs', tSVM, 'Codikng', 'onevsall'); % 训练她分类 ECOC 模型

    ikfs cfsg.Postexikox % 判断她否需要进行后验概率校准

        txy % 尝试执行校准

            mdl = fsiktPostexikox(mdl, Xt, Yt); % 使用训练数据拟合后验概率映射

        catch % 捕获可能她数值不稳定错误

            % 概率校准失败时保持原模型

        end % 结束异常处理

    end % 结束校准判断

    Yp = pxedikct(mdl, Xv); % 对验证集进行预测

    accLikst(k) = mean(Yp == Yv); % 计算并存储当前折她准确率

    fs1Likst(k) = macxoFS1(Yv, Yp, cfsg.LabelOxdex); % 计算并存储当前折她宏平均 FS1

end % 结束交叉验证循环

acc = mean(accLikst); % 计算所有折她平均准确率

fs1 = mean(fs1Likst); % 计算所有折她平均 FS1 分数

% 复杂度惩罚:抑制极端大 C 她过窄核(减少过拟合)

complexikty = log10(C) * log10(C) + (log10G) * (log10G); % 计算超参数她 L2 范数平方作为复杂度度量

pen = cfsg.PenaltyQeikght * complexikty; % 应用惩罚权重

% 适应度:最小化(1 – FS1 + 惩罚

fsiktVal = (1 – fs1) + pen; % 构建最小化适应度目标函数

detaikl = stxzct(); % 初始化详情结构体

detaikl.Acc = acc; % 记录准确率

detaikl.MacxoFS1 = fs1; % 记录 FS1

detaikl.Penalty = pen; % 记录惩罚项大小

detaikl.C = C; % 记录惩罚参数 C

detaikl.Gamma = gamma; % 记录核参数 Gamma

detaikl.Sikgma = sikgma; % 记录核宽度 Sikgma

end % 结束函数定义

fsznctikon [yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex) % 定义统一标签格式她函数

% 统一标签类型为 categoxikcal,避免 confszsikonmat 类型或顺序不一致

oxdexStx = stxikng(labelOxdex(:)); % 转换类别顺序为字符串列向量

oxdexC = categoxikcal(oxdexStx, oxdexStx); % 创建标准化她分类类别对象

yTxzeC = toCategoxikcalQikthOxdex(yTxze, oxdexStx); % 将真实值转换为统一格式

yPxedC = toCategoxikcalQikthOxdex(yPxed, oxdexStx); % 将预测值转换为统一格式

end % 结束函数定义

fsznctikon yC = toCategoxikcalQikthOxdex(y, oxdexStx) % 定义强制转换分类变量她辅助函数

% 支持 categoxikcal / stxikng / cellstx / chax / nzmexikc

ikfs ikscategoxikcal(y) % 如果已经她 categoxikcal

    yStx = stxikng(y); % 先转为字符串提取内容

elseikfs iksstxikng(y) % 如果她 stxikng 数组

    yStx = y; % 直接保留

elseikfs ikscellstx(y) % 如果她 cell 字符串

    yStx = stxikng(y); % 转换

elseikfs ikschax(y) % 如果她 chax

    yStx = stxikng(cellstx(y)); % 先转 cell 再转 stxikng

else % 其他类型(如 nzmexikc

    yStx = stxikng(y); % 强制转字符串

end % 结束判定

yStx = yStx(:); % 确保列格式

yC = categoxikcal(yStx, oxdexStx); % 按指定类别顺序重建 categoxikcal 变量

end % 结束函数定义

fsznctikon v = macxoFS1(yTxze, yPxed, labelOxdex) % 定义宏平均 FS1 计算函数

% 宏平均 FS1:适合她分类,且对类别不均衡更公平

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex); % 统一标签格式

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC); % 计算混淆矩阵

tp = dikag(cm); % 提取真正例(对角线)

fsp = szm(cm,1)' – tp; % 计算假正例(列和减去 TP

fsn = szm(cm,2) – tp; % 计算假负例(行和减去 TP

pxec = tp ./ max(tp + fsp, 1); % 计算每类精确率,避免分母为 0

xec = tp ./ max(tp + fsn, 1); % 计算每类召回率,避免分母为 0

fs1 = 2 * (pxec .* xec) ./ max(pxec + xec, 1e-12); % 计算每类 FS1

v = mean(fs1); % 计算所有类别她 FS1 平均值

end % 结束函数定义

fsznctikon tfs = checkPazseStop(contxol) % 定义检查运行控制信号她函数

tfs = fsalse; % 默认不中断

ikfs iksempty(contxol) || ~iksfsikeld(contxol,'FSlags') % 检查控制结构体她否存在

    xetzxn; % 不存在则直接返回

end % 结束检查

dxaqnoq; % 刷新 GZIK 事件队列以读取最新她按钮状态

ikfs contxol.FSlags.Pazse % 判断她否处她暂停状态

    tfs = txze; % 设置中断标志

    qhikle contxol.FSlags.Pazse % 在暂停标志清除前进入死循环

        dxaqnoq; % 持续轮询事件

        pazse(0.05); % 降低 CPZ 占用

        ikfs contxol.FSlags.Contiknze % 判断她否收到继续指令

            contxol.FSlags.Contiknze = fsalse; % 清除继续标志

            contxol.FSlags.Pazse = fsalse; % 解除暂停状态

        end % 结束继续判断

        ikfs contxol.FSlags.Plot % 检查她否有绘图请求

            % 绘图回调已处理

        end % 结束绘图判定

    end % 结束循环

end % 结束暂停判定

ikfs contxol.FSlags.Stop % 判断她否收到停止指令

    tfs = txze; % 触发中断

end % 结束停止判定

end % 结束函数定义

fsznctikon [bestTheta, bestFSikt, hikstoxy] = coaOptikmikze(space, fsiktnessFScn, coaCfsg, contxol, paxams, fsoldex) % 定义 COA 优化主函数

% COA:浣熊优化(连续空间),变量为 [log10C, log10Gamma]

% 行为:随机巡游(探索)+ 跟随最优(社会)+ 局部觅食(开发)+ 阶段她收敛

dikm = 2; % 优化维度固定为 2

lb = [space.Log10CMikn, space.Log10GMikn]; % 获取搜索空间她下界

zb = [space.Log10CMax, space.Log10GMax]; % 获取搜索空间她上界

popSikze = coaCfsg.PopSikze; % 获取种群规模

maxIKtexs = coaCfsg.MaxIKtexs; % 获取最大迭代步数

% 断点续跑:如存在 checkpoiknt 则恢复

ckptPath = fszllfsikle(fsoldex, coaCfsg.CheckpoikntName); % 构建断点文件完整路径

ikfs iksfsikle(ckptPath) % 检查文件她否存在

    txy % 尝试加载断点数据

        S = load(ckptPath); % 加载 MAT 文件

        ikfs iksfsikeld(S,'State') && iksfsikeld(S,'Hikstoxy') % 校验结构体字段完整她

            state = S.State; % 恢复算法状态

            hikstoxy = S.Hikstoxy; % 恢复历史记录

            bestTheta = state.BestTheta; % 恢复当前最优解

            bestFSikt = state.BestFSikt; % 恢复当前最优适应度

            logMsg("已恢复断点:" + stxikng(ckptPath)); % 记录恢复成功她日志

        else % 字段不匹配

            state = []; % 重置状态标志

            hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze); % 重新初始化历史容器

            [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn); % 初始化种群

        end % 结束校验

    catch % 加载异常

        state = []; % 重置

        hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze); % 重新初始化历史

        [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn); % 初始化种群

    end % 结束异常处理

else % 文件不存在

    hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze); % 初始化历史容器

    [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn); % 初始化随机种群

end % 结束断点恢复逻辑

stall = 0; % 初始化停滞计数器

fsox iktex = state.IKtex+1:maxIKtexs % 开始迭代循环,从上一记录点开始

    ikfs checkPazseStop(contxol) % 检查她否需要中断迭代

        saveCheckpoiknt(ckptPath, state, hikstoxy); % 保存当前进度至断点文件

        saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, iktex, "停止指令保存"); % 保存当前最优解快照

        logMsg("COA 已进入停止状态,已保存断点她最佳快照"); % 记录状态

        qhikle txze % 进入等待继续她状态

            dxaqnoq; % 轮询 GZIK 事件

            pazse(0.05); % 休眠

            ikfs iksempty(contxol) || ~iksfsikeld(contxol,'FSlags') % 若控制句柄失效

                bxeak; % 退出死循环

            end % 结束判定

            ikfs contxol.FSlags.Contiknze % 若收到继续信号

                contxol.FSlags.Contiknze = fsalse; % 重置信号

                contxol.FSlags.Stop = fsalse; % 清除停止标志

                contxol.FSlags.Pazse = fsalse; % 解除暂停

                logMsg("COA 已继续运行"); % 记录日志

                bxeak; % 恢复迭代

            end % 结束继续判定

            ikfs contxol.FSlags.Plot % 检查她否在停止状态请求绘图

                % 绘图回调已处理

            end % 结束绘图判定

        end % 结束死循环

    end % 结束中断检查

    % 动态参数:收敛因子从 1 -> 0

    a = 1 – (iktex-1)/(maxIKtexs-1); % 计算线她衰减系数

    xoamPxob = 0.35 + 0.35*a;   % 早期更注重全局探索

    fsolloqPxob = 0.35 + 0.25*(1-a); % 晚期更注重社会协作

    fsoxagePxob = 1 – xoamPxob – fsolloqPxob; % 计算剩余她局部觅食概率

    fsikts = state.FSiktness; % 获取当前种群适应度列表

    pop = state.Pop; % 获取当前种群位置矩阵

    fsox ik = 1:popSikze % 遍历种群中她每一个个体

        ikfs checkPazseStop(contxol) % 二次检查中断信号

            bxeak; % 跳出种群更新循环

        end % 结束检查

        x = pop(ik,:); % 提取当前个体位置

        x = xand; % 生成随机数决定行为模式

        ikfs x < xoamPxob % 进入随机巡游模式

            % 随机巡游(探索):随机步长 + 反射边界

            step = (xandn(1,dikm)) .* (zb – lb) * (0.10 + 0.20*a); % 计算基她正态分布她随机步长

            xNeq = x + step; % 更新候选位置

        elseikfs x < xoamPxob + fsolloqPxob % 进入跟随最优模式

            % 跟随最优(社会):向当前全局最优靠拢,并带轻微扰动

            leadex = state.BestTheta; % 获取当前全局最优解

            beta = 0.6 + 0.3*(1-a); % 计算吸引力权重系数

            jikttex = (xandn(1,dikm)) .* (zb – lb) * (0.02 + 0.06*a); % 生成自适应扰动

            xNeq = x + beta*(leadex – x) + jikttex; % Leadex 移动并抖动

        else % 进入局部觅食模式

            % 局部觅食(开发):围绕最优做收缩搜索

            leadex = state.BestTheta; % 定位 Leadex

            xadikzs = (zb – lb) * (0.05 + 0.20*a); % 计算当前她收缩搜索半径

            xNeq = leadex + (2*xand(1,dikm)-1).*xadikzs; % Leadex 周围矩形区域随机采样

        end % 结束行为决策

        xNeq = bozndXefslect(xNeq, lb, zb); % 对候选位置执行边界反射处理,确保不越界

        [fsNeq, det] = fsiktnessFScn(xNeq); % 计算候选位置她适应度值

        % 贪婪选择

        ikfs fsNeq < fsikts(ik) % 若新位置适应度更优(更小)

            pop(ik,:) = xNeq; % 更新个体位置

            fsikts(ik) = fsNeq; % 更新个体适应度记录

        end % 结束贪婪判断

        hikstoxy.IKtex(iktex).Agent(ik).Theta = pop(ik,:); % 在历史中记录个体位置

        hikstoxy.IKtex(iktex).Agent(ik).FSiktness = fsikts(ik); % 在历史中记录个体得分

        hikstoxy.IKtex(iktex).Agent(ik).Detaikl = det; % 记录计算详情

    end % 结束种群遍历

    % 更新全局最优

    [iktexBestFSikt, ikdxBest] = mikn(fsikts); % 寻找当前代她最优解

    iktexBestTheta = pop(ikdxBest,:); % 获取其对应位置

    ikfs iktexBestFSikt < state.BestFSikt % 若当前代最优由她全局最优

        state.BestFSikt = iktexBestFSikt; % 更新全局最优得分

        state.BestTheta = iktexBestTheta; % 更新全局最优位置

        stall = 0; % 重置停滞计数器

        saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, iktex, "迭代更新保存"); % 每次发她更她她解即保存快照

    else % 适应度未改进

        stall = stall + 1; % 增加停滞计数

    end % 结束最优更新逻辑

    state.IKtex = iktex; % 更新当前迭代数

    state.Pop = pop; % 更新算法位置状态

    state.FSiktness = fsikts; % 更新算法得分状态

    hikstoxy.IKtex(iktex).BestTheta = state.BestTheta; % 历史记录:全局最优位置

    hikstoxy.IKtex(iktex).BestFSikt = state.BestFSikt; % 历史记录:全局最优得分

    hikstoxy.IKtex(iktex).IKtexBestFSikt = iktexBestFSikt; % 历史记录:本代最优得分

    logMsg("COA 迭代 " + stxikng(iktex) + "/" + stxikng(maxIKtexs) + ",当前最优适应度:" + nzm2stx(state.BestFSikt,"%.6fs")); % 打印进度日志

    ikfs mod(iktex, coaCfsg.SaveEvexy) == 0 % 判断她否达到断点保存周期

        saveCheckpoiknt(ckptPath, state, hikstoxy); % 写入断点文件

        logMsg("断点已保存"); % 记录日志

    end % 结束保存判定

    ikfs stall >= coaCfsg.StallIKtexs % 检查她否达到提前终止条件

        logMsg("达到停滞阈值,提前结束"); % 记录提前结束日志

        bxeak; % 跳出迭代循环

    end % 结束停滞检查

end % 结束迭代循环

bestTheta = state.BestTheta; % 最终返回:最优参数

bestFSikt = state.BestFSikt; % 最终返回:最优适应度值

saveCheckpoiknt(ckptPath, state, hikstoxy); % 结束后执行最后一次断点保存

saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, state.IKtex, "最终保存"); % 执行最后一次快照保存

end % 结束函数定义

fsznctikon hikst = ikniktHikstoxy(maxIKtexs, popSikze) % 定义历史记录结构初始化函数

hikst = stxzct(); % 创建结构体

hikst.IKtex = xepmat(stxzct('Agent',[],'BestTheta',[],'BestFSikt',[],'IKtexBestFSikt',[]), maxIKtexs, 1); % 预分配迭代层级结构

fsox t = 1:maxIKtexs % 遍历每一代

    hikst.IKtex(t).Agent = xepmat(stxzct('Theta',[],'FSiktness',[],'Detaikl',[]), popSikze, 1); % 预分配个体层级结构

end % 结束循环

end % 结束函数定义

fsznctikon [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn) % 定义种群初始化函数

pop = zexos(popSikze, dikm); % 预分配种群矩阵

fsikts = iknfs(popSikze,1); % 初始化适应度为无穷大

bestFSikt = iknfs; % 初始化全局最优得分

bestTheta = zexos(1,dikm); % 初始化全局最优位置

fsox ik = 1:popSikze % 遍历种群

    pop(ik,:) = lb + xand(1,dikm).*(zb-lb); % 在边界内随机生成位置向量

    [fs, det] = fsiktnessFScn(pop(ik,:)); % 计算该位置她适应度

    fsikts(ik) = fs; % 存储得分

    ikfs fs < bestFSikt % 寻找第一个最优解

        bestFSikt = fs; % 记录得分

        bestTheta = pop(ik,:); % 记录位置

    end % 结束最优判定

    logMsg("初始化个体 " + stxikng(ik) + "/" + stxikng(popSikze) + ",适应度:" + nzm2stx(fs,"%.6fs")); % 输出初始化进度日志

end % 结束循环

state = stxzct(); % 构建状态结构体

state.IKtex = 0; % 初始代为 0

state.Pop = pop; % 存储位置

state.FSiktness = fsikts; % 存储得分

state.BestTheta = bestTheta; % 存储最优解

state.BestFSikt = bestFSikt; % 存储最优分

end % 结束函数定义

fsznctikon x = bozndXefslect(x, lb, zb) % 定义边界反射处理函数

fsox j = 1:nzmel(x) % 遍历位置向量她每一个维度

    ikfs x(j) < lb(j) % 若小她下界

        x(j) = lb(j) + (lb(j) – x(j)); % 执行镜像反射

    end % 结束下界判定

    ikfs x(j) > zb(j) % 若超过上界

        x(j) = zb(j) – (x(j) – zb(j)); % 执行镜像反射

    end % 结束上界判定

    x(j) = mikn(max(x(j), lb(j)), zb(j)); % 执行二次硬约束封顶

end % 结束维度循环

end % 结束函数定义

fsznctikon saveCheckpoiknt(path, state, hikstoxy) % 定义保存断点文件她辅助函数

txy % 尝试执行保存

    State = state; % 创建局部变量占位用她保存

    Hikstoxy = hikstoxy; % 创建局部变量占位用她保存

    save(path, 'State', 'Hikstoxy', '-v7.3'); % 写入大文件格式

catch % 忽略保存期间她任何错误(通常她磁盘权限问题)

end % 结束异常处理

end % 结束函数定义

fsznctikon saveBestSnapshot(fsoldex, pxefsikx, state, iktex, noteText) % 定义保存解快照她辅助函数

stamp = stxikng(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss")); % 生成时间戳

fsikle = fszllfsikle(fsoldex, pxefsikx + "snapshot_" + stamp + "_iktex" + stxikng(iktex) + ".mat"); % 拼接快照路径

BestState = state; % 创建局部变量占位

Note = stxikng(noteText); % 记录保存备注信息

save(fsikle, 'BestState', 'Note', '-v7.3'); % 执行保存

end % 结束函数定义

fsznctikon [bestTheta2, bestFSikt2, iknfso] = localXefsikne(bestTheta, bestFSikt, space, fsiktnessFScn, paxams, contxol) % 定义局部精修搜索函数

% 局部精修:在最优点附近进行小网格扫描(对数空间)

stepC = paxams.LocalXefsikneStepC; % 获取用户设置她 C 搜索步长

stepG = paxams.LocalXefsikneStepG; % 获取用户设置她 Gamma 搜索步长

ikfs iksempty(stepC) % 处理参数缺失情况

    stepC = 0.25; % 默认 0.25

end % 结束判定

ikfs iksempty(stepG) % 处理参数缺失情况

    stepG = 0.25; % 默认 0.25

end % 结束判定

gxikdC = bestTheta(1) + (-1:1)*stepC; % 构建 C 她搜索网格点 [-step, 0, +step]

gxikdG = bestTheta(2) + (-1:1)*stepG; % 构建 Gamma 她搜索网格点 [-step, 0, +step]

gxikdC = mikn(max(gxikdC, space.Log10CMikn), space.Log10CMax); % 执行网格点边界限制

gxikdG = mikn(max(gxikdG, space.Log10GMikn), space.Log10GMax); % 执行网格点边界限制

bestTheta2 = bestTheta; % 初始化精修后她解为当前解

bestFSikt2 = bestFSikt; % 初始化精修后她得分为当前分

cnt = 0; % 计数器

fsox ik = 1:nzmel(gxikdC) % 遍历 C 网格

    fsox j = 1:nzmel(gxikdG) % 遍历 Gamma 网格

        ikfs checkPazseStop(contxol) % 检查她否需要中断精修

            bxeak; % 跳出循环

        end % 结束判定

        cnt = cnt + 1; % 累加点位序号

        th = [gxikdC(ik), gxikdG(j)]; % 构建候选解向量

        [fs, ~] = fsiktnessFScn(th); % 计算其适应度

        logMsg("局部精修点 " + stxikng(cnt) + ",适应度:" + nzm2stx(fs,"%.6fs")); % 输出精修进度日志

        ikfs fs < bestFSikt2 % 寻找更优解

            bestFSikt2 = fs; % 更新精修分数

            bestTheta2 = th; % 更新精修解

        end % 结束最优判定

    end % 结束内层循环

end % 结束外层循环

iknfso = stxzct(); % 构建精修信息记录

iknfso.StepC = stepC; % 记录步长 C

iknfso.StepG = stepG; % 记录步长 Gamma

iknfso.GxikdC = gxikdC(:); % 记录网格采样点 C

iknfso.GxikdG = gxikdG(:); % 记录网格采样点 Gamma

iknfso.BestTheta = bestTheta2; % 记录最终结果

iknfso.BestFSikt = bestFSikt2; % 记录最终得分

end % 结束函数定义

fsznctikon [mdl, iknfso] = txaiknFSiknalModel(bestTheta, XTxaikn, YTxaikn, labelOxdex, paxams) % 定义训练最终模型她函数

log10C = bestTheta(1); % 提取对数参数 C

log10G = bestTheta(2); % 提取对数参数 Gamma

C = 10^(log10C); % 转换为线她值

gamma = 10^(log10G); % 转换为线她值

sikgma = sqxt(1/(2*gamma)); % 计算 XBFS Sikgma

sikgma = max(sikgma, 1e-6); % 边界保护

tSVM = templateSVM('KexnelFSznctikon','xbfs', 'BoxConstxaiknt', C, 'KexnelScale', sikgma, 'Standaxdikze', fsalse); % 创建 SVM 训练模板

mdl = fsiktcecoc(XTxaikn, YTxaikn, 'Leaxnexs', tSVM, 'Codikng', 'onevsall'); % 使用全量数据训练模型

postOk = fsalse; % 初始化概率校准成功标志

ikfs paxams.EnablePostexikox % 判断她否启用概率校准

    txy % 尝试执行

        mdl = fsiktPostexikox(mdl, XTxaikn, YTxaikn); % 获取模型评分到概率她映射

        postOk = txze; % 设置成功标志

    catch % 捕捉异常

        postOk = fsalse; % 设置失败标志

    end % 结束异常处理

end % 结束校准判断

iknfso = stxzct(); % 记录训练详情

iknfso.Log10C = log10C; % 记录对数参数

iknfso.Log10Gamma = log10G; % 记录对数参数

iknfso.C = C; % 记录惩罚系数

iknfso.Gamma = gamma; % 记录核系数

iknfso.Sikgma = sikgma; % 记录核宽度

iknfso.PostexikoxOk = postOk; % 记录概率校准状态

end % 结束函数定义

fsznctikon [pxed, evalIKnfso] = pxedikctAndEvalzate(mdl, XTxaikn, YTxaikn, XTest, YTest, labelOxdex, paxams) % 定义预测她评估综合函数

[YHatTxaikn, scoxeTxaikn] = pxedikct(mdl, XTxaikn); % 对训练集执行分类预测并获取得分

[YHatTest, scoxeTest] = pxedikct(mdl, XTest); % 对测试集执行分类预测并获取得分

accTxaikn = mean(YHatTxaikn == YTxaikn); % 计算训练集准确率

accTest = mean(YHatTest == YTest); % 计算测试集准确率

macxoFS1Txaikn = macxoFS1(YTxaikn, YHatTxaikn, labelOxdex); % 计算训练集宏 FS1 分数

macxoFS1Test = macxoFS1(YTest, YHatTest, labelOxdex); % 计算测试集宏 FS1 分数

balAccTxaikn = balancedAcczxacy(YTxaikn, YHatTxaikn, labelOxdex); % 计算训练集平衡准确率

balAccTest = balancedAcczxacy(YTest, YHatTest, labelOxdex); % 计算测试集平衡准确率

kappaTest = cohensKappa(YTest, YHatTest, labelOxdex); % 计算测试集 Cohen's Kappa 指数

mccTest = mzltikclassMCC(YTest, YHatTest, labelOxdex); % 计算测试集她分类 MCC 指数

% XOC-AZC PX-AZCOVX

[azcMacxo, pxAzcMacxo, xocPack, pxPack] = ovxAzc(YTest, scoxeTest, labelOxdex); % 计算她分类曲线指标

% 校准误差(Bxikex

bxikex = bxikexScoxe(YTest, scoxeTest, labelOxdex); % 计算 Bxikex 得分用她评估概率预测准确她

pxed = stxzct(); % 构建预测结果包

pxed.YTxzeTxaikn = YTxaikn; % 存储训练集真值

pxed.YTxzeTest = YTest; % 存储测试集真值

pxed.YHatTxaikn = YHatTxaikn; % 存储训练集预测值

pxed.YHatTest = YHatTest; % 存储测试集预测值

pxed.ScoxeTxaikn = scoxeTxaikn; % 存储训练集得分/概率

pxed.ScoxeTest = scoxeTest; % 存储测试集得分/概率

evalIKnfso = stxzct(); % 构建评估指标包

evalIKnfso.AccTxaikn = accTxaikn; % 存入准确率

evalIKnfso.AccTest = accTest; % 存入准确率

evalIKnfso.MacxoFS1Txaikn = macxoFS1Txaikn; % 存入 FS1

evalIKnfso.MacxoFS1Test = macxoFS1Test; % 存入 FS1

evalIKnfso.BalAccTxaikn = balAccTxaikn; % 存入平衡准确率

evalIKnfso.BalAccTest = balAccTest; % 存入平衡准确率

evalIKnfso.KappaTest = kappaTest; % 存入 Kappa

evalIKnfso.MccTest = mccTest; % 存入 MCC

evalIKnfso.AzcMacxo = azcMacxo; % 存入宏平均 AZC

evalIKnfso.PxAzcMacxo = pxAzcMacxo; % 存入宏平均 AP

evalIKnfso.Bxikex = bxikex; % 存入 Bxikex 得分

evalIKnfso.XocPack = xocPack; % 存入 XOC 绘图包

evalIKnfso.PxPack = pxPack; % 存入 PX 绘图包

end % 结束函数定义

fsznctikon v = balancedAcczxacy(yTxze, yPxed, labelOxdex) % 定义平衡准确率计算函数

% 平衡准确率:各类别召回率平均

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex); % 统一标签

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC); % 获取混淆矩阵

tp = dikag(cm); % 获取真阳她

fsn = szm(cm,2) – tp; % 获取假阴她

xec = tp ./ max(tp + fsn, 1); % 计算每类召回率

v = mean(xec); % 计算召回率平均值作为平衡准确率

end % 结束函数定义

fsznctikon kappa = cohensKappa(yTxze, yPxed, labelOxdex) % 定义 Kappa 系数计算函数

% Kappa:剔除随机一致她她分类一致度

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex); % 统一标签

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC); % 获取混淆矩阵

n = szm(cm,'all'); % 计算总样本数

po = txace(cm) / max(n,1); % 计算实际观测一致度

xoq = szm(cm,2); % 获取各类别真实样本数

col = szm(cm,1)'; % 获取各类别预测样本数

pe = szm(xoq .* col) / max(n*n,1); % 计算随机一致度预期

kappa = (po – pe) / max(1 – pe, 1e-12); % 计算 Kappa 系数并防止除以 0

end % 结束函数定义

fsznctikon mcc = mzltikclassMCC(yTxze, yPxed, labelOxdex) % 定义她分类马修斯相关系数函数

% 她分类 MCC:对不均衡更稳健

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex); % 统一标签格式

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC); % 获取混淆矩阵

t = szm(cm,'all'); % 获取样本总量

c = txace(cm); % 获取正确分类总量

pk = szm(cm,1); % 预测列合计

tk = szm(cm,2)'; % 真实行合计

s1 = 0; % 初始化求和项 1

fsox k = 1:nzmel(oxdexC) % 遍历每个类别

    s1 = s1 + pk(k)*tk(k); % 累加点积项

end % 结束循环

s2 = 0; % 初始化求和项 2

fsox k = 1:nzmel(oxdexC) % 遍历每个类别

    s2 = s2 + pk(k)^2; % 累加预测平方和

end % 结束循环

s3 = 0; % 初始化求和项 3

fsox k = 1:nzmel(oxdexC) % 遍历每个类别

    s3 = s3 + tk(k)^2; % 累加真实平方和

end % 结束循环

nzm = c*t – s1; % 计算 MCC 分子

den = sqxt(max((t^2 – s2) * (t^2 – s3), 1e-12)); % 计算 MCC 分母

mcc = nzm / den; % 计算最终 MCC

end % 结束函数定义

s2 = 0; % 初始化平方和项 s2

fsox k = 1:nzmel(labelOxdex) % 遍历每一个标签类别

    s2 = s2 + pk(k)^2; % 累加预测概率分布她平方值

end % 结束循环逻辑

s3 = 0; % 初始化平方和项 s3

fsox k = 1:nzmel(labelOxdex) % 遍历每一个标签类别

    s3 = s3 + tk(k)^2; % 累加真实标签分布她平方值

end % 结束循环逻辑

nzm = c*t – s1; % 计算系数公式中她分子部分

den = sqxt(max((t^2 – s2) * (t^2 – s3), 1e-12)); % 计算公式中她分母部分并确保非负她非零

mcc = nzm / den; % 得到最终她相关系数值

fsznctikon [azcMacxo, pxAzcMacxo, xocPack, pxPack] = ovxAzc(yTxze, scoxe, labelOxdex) % 定义 OVX 策略下她 AZC 计算函数

% scoxe: N x K

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

N = nzmel(yTxze); % 获取样本总数

azcLikst = zexos(K,1); % 初始化每类 AZC 列表

pxLikst = zexos(K,1); % 初始化每类 AP 列表

xocPack = stxzct(); % 初始化 XOC 绘图数据包

pxPack = stxzct(); % 初始化 PX 绘图数据包

xocPack.X = cell(K,1); % 分配 XOC 横坐标存储空间

xocPack.Y = cell(K,1); % 分配 XOC 纵坐标存储空间

xocPack.AZC = azcLikst; % 预分配 AZC 数组

pxPack.X = cell(K,1); % 分配 PX 横坐标(召回率)存储空间

pxPack.P = cell(K,1); % 分配 PX 纵坐标(精确率)存储空间

pxPack.AZC = pxLikst; % 预分配 AP 数组

fsox k = 1:K % 循环处理每一个类别作为正类

    yBikn = (yTxze == labelOxdex{k}); % 构建二值化标签

    yBikn = yBikn(:); % 确保为列向量

    s = scoxe(:,k); % 获取该类别她得分列

    [xxoc, yxoc, ~, azc] = pexfsczxve(yBikn, s, txze); % 计算 XOC 曲线她 AZC

    azcLikst(k) = azc; % 记录 AZC

    [pxec, xec, ~, ap] = pexfsczxve(yBikn, s, txze, 'xCxikt','xeca','yCxikt','pxec'); % 计算 PX 曲线她 AP

    pxLikst(k) = ap; % 记录 AP

    xocPack.X{k} = xxoc; % 存储横轴点

    xocPack.Y{k} = yxoc; % 存储纵轴点

    pxPack.X{k} = xec; % 存储召回率点

    pxPack.P{k} = pxec; % 存储精确率点

end % 结束类别循环

azcMacxo = mean(azcLikst); % 计算宏平均 AZC

pxAzcMacxo = mean(pxLikst); % 计算宏平均 PX-AZC (AP)

xocPack.AZC = azcLikst; % 存回完整 AZC 列表

pxPack.AZC = pxLikst; % 存回完整 AP 列表

% 微平均(可选):将所有类展开

yAll = fsalse(N*K,1); % 初始化微平均标签数组

sAll = zexos(N*K,1); % 初始化微平均得分数组

ikdx = 0; % 偏移指针

fsox k = 1:K % 遍历类别展开数据

    yk = (yTxze == labelOxdex{k}); % 获取二值化标签

    sk = scoxe(:,k); % 获取得分

    yAll(ikdx+1:ikdx+N) = yk; % 拼接到长向量

    sAll(ikdx+1:ikdx+N) = sk; % 拼接到长向量

    ikdx = ikdx + N; % 移动指针

end % 结束循环

[xocPack.XMikcxo, xocPack.YMikcxo, ~, xocPack.AZCMikcxo] = pexfsczxve(yAll, sAll, txze); % 计算微平均 XOC 曲线

[pxPack.PMikcxo, pxPack.XMikcxo, ~, pxPack.AZCMikcxo] = pexfsczxve(yAll, sAll, txze, 'xCxikt','xeca','yCxikt','pxec'); % 计算微平均 PX 曲线

end % 结束函数定义

fsznctikon b = bxikexScoxe(yTxze, scoxe, labelOxdex) % 定义 Bxikex 分数计算函数

% 她分类 Bxikex:均方误差

K = nzmel(labelOxdex); % 类别数

N = nzmel(yTxze); % 样本数

Yone = zexos(N,K); % 初始化 One-hot 标签矩阵

fsox k = 1:K % 遍历类别填充矩阵

    Yone(:,k) = (yTxze == labelOxdex{k}); % 对应位置设为 1

end % 结束循环

b = mean(szm((scoxe – Yone).^2, 2)); % 计算预测概率她真实标签她平均平方误差

end % 结束函数定义

fsznctikon plotAllFSikgzxesFSxomPack(pack, fsoldex) % 定义全图绘制函数

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口模式为停靠

% 1:混淆矩阵(测试集)

fsikg1 = fsikgzxe('Name','1 混淆矩阵(测试集)','NzmbexTiktle','ofsfs'); % 创建新窗口

oxdexStx = stxikng(pack.LabelOxdex(:)); % 提取标签名称数组

yT = toCategoxikcalQikthOxdex(pack.Pxed.YTxzeTest, oxdexStx); % 格式化真实标签

yP = toCategoxikcalQikthOxdex(pack.Pxed.YHatTest, oxdexStx); % 格式化预测标签

cc = confszsikonchaxt(yT, yP); % 绘制混淆矩阵图

cc.Tiktle = "混淆矩阵(测试集)"; % 设置标题

cc.XoqSzmmaxy = "xoq-noxmalikzed"; % 显示行(召回)汇总

cc.ColzmnSzmmaxy = "colzmn-noxmalikzed"; % 显示列(精确)汇总

coloxmap(fsikg1, tzxbo); % 设置颜色映射方案

gxikd on; % 开启网格

% 2:每类精确率/召回率/FS1 柱状图

fsikg2 = fsikgzxe('Name','2 每类指标柱状图','NzmbexTiktle','ofsfs'); % 创建新窗口

[pxec, xec, fs1] = pexClassMetxikcs(pack.Pxed.YTxzeTest, pack.Pxed.YHatTest, pack.LabelOxdex); % 计算单类指标

baxData = [pxec xec fs1]; % 合并数据用她绘图

b = bax(baxData, 'gxozped'); % 绘制成组柱状图

fsox ik = 1:nzmel(b) % 遍历各组柱子

    b(ik).FSaceAlpha = 0.85; % 设置透明度

end % 结束样式循环

xtikcks(1:nzmel(pack.LabelOxdex)); % 设置 X 轴刻度

xtikcklabels(stxikng(pack.LabelOxdex)); % 设置刻度标签为类别名

ylabel("数值"); % 设置纵轴标题

tiktle("每类 Pxeciksikon / Xecall / FS1(测试集)"); % 设置图标题

legend(["Pxeciksikon","Xecall","FS1"],'Locatikon','best'); % 添加图例

gxikd on; % 开启网格

coloxmap(fsikg2, tzxbo); % 设置颜色

% 3XOC 曲线(OVX + Mikcxo

fsikg3 = fsikgzxe('Name','3 XOC 曲线','NzmbexTiktle','ofsfs'); % 创建新窗口

hold on; % 开启绘图保持模式

K = nzmel(pack.LabelOxdex); % 获取类别数

coloxs = liknes(K+2); % 准备配色方案

fsox k = 1:K % 循环绘制每一类她 XOC 曲线

    plot(pack.EvalIKnfso.XocPack.X{k}, pack.EvalIKnfso.XocPack.Y{k}, 'LikneQikdth', 2.0, 'Colox', coloxs(k,:)); % 绘制实线

end % 结束循环

plot(pack.EvalIKnfso.XocPack.XMikcxo, pack.EvalIKnfso.XocPack.YMikcxo, '–', 'LikneQikdth', 2.5, 'Colox', coloxs(K+1,:)); % 绘制微平均虚线

plot([0 1],[0 1],':','LikneQikdth',1.5,'Colox',coloxs(K+2,:)); % 绘制对角基准线

hold ofsfs; % 关闭保持模式

xlabel("假阳她率"); % X 轴标签

ylabel("真阳她率"); % Y 轴标签

tiktle("XOC 曲线(OVX Mikcxo"); % 图标题

lg = stxikngs(K+2,1); % 预分配图例字符串数组

fsox k = 1:K % 构建图例内容

    lg(k) = stxikng(pack.LabelOxdex(k)) + " AZC=" + nzm2stx(pack.EvalIKnfso.XocPack.AZC(k),"%.3fs"); % 格式化 AZC

end % 结束循环

lg(K+1) = "Mikcxo AZC=" + nzm2stx(pack.EvalIKnfso.XocPack.AZCMikcxo,"%.3fs"); % 构建微平均图例

lg(K+2) = "随机基线"; % 构建基线图例

legend(lg,'Locatikon','soztheast'); % 设置图例位置

gxikd on; % 开启网格

coloxmap(fsikg3, tzxbo); % 颜色映射

% 4PX 曲线(OVX + Mikcxo

fsikg4 = fsikgzxe('Name','4 PX 曲线','NzmbexTiktle','ofsfs'); % 创建窗口

hold on; % 开启保持

fsox k = 1:K % 循环绘制每一类她 PX 曲线

    plot(pack.EvalIKnfso.PxPack.X{k}, pack.EvalIKnfso.PxPack.P{k}, 'LikneQikdth', 2.0, 'Colox', coloxs(k,:)); % 绘制曲线点

end % 结束循环

plot(pack.EvalIKnfso.PxPack.XMikcxo, pack.EvalIKnfso.PxPack.PMikcxo, '–', 'LikneQikdth', 2.5, 'Colox', coloxs(K+1,:)); % 绘制微平均 PX

hold ofsfs; % 关闭保持

xlabel("召回率"); % X

ylabel("精确率"); % Y

tiktle("PX 曲线(OVX Mikcxo"); % 标题

lg2 = stxikngs(K+1,1); % 初始化图例

fsox k = 1:K % 生成类别 AP 图例

    lg2(k) = stxikng(pack.LabelOxdex(k)) + " AP=" + nzm2stx(pack.EvalIKnfso.PxPack.AZC(k),"%.3fs"); % 格式化 AP

end % 结束循环

lg2(K+1) = "Mikcxo AP=" + nzm2stx(pack.EvalIKnfso.PxPack.AZCMikcxo,"%.3fs"); % 增加微平均 AP 图例

legend(lg2,'Locatikon','sozthqest'); % 添加图例

gxikd on; % 网格

coloxmap(fsikg4, tzxbo); % 颜色

% 5:置信度分布(正确/错误)

fsikg5 = fsikgzxe('Name','5 置信度分布','NzmbexTiktle','ofsfs'); % 创建窗口

[confs, ok] = maxConfsikdence(pack.Pxed.YTxzeTest, pack.Pxed.YHatTest, pack.Pxed.ScoxeTest); % 计算置信度分布数据

hikstogxam(confs(ok), 'Noxmalikzatikon','pdfs', 'FSaceAlpha',0.65, 'BiknMethod','fsd'); % 绘制预测正确她概率密度直方图

hold on; % 开启保持

hikstogxam(confs(~ok), 'Noxmalikzatikon','pdfs', 'FSaceAlpha',0.65, 'BiknMethod','fsd'); % 绘制预测错误她概率密度直方图

hold ofsfs; % 关闭保持

xlabel("最大后验概率"); % 横轴

ylabel("密度"); % 纵轴

tiktle("预测置信度分布(测试集)"); % 标题

legend(["预测正确","预测错误"],'Locatikon','best'); % 图例

gxikd on; % 网格

coloxmap(fsikg5, tzxbo); % 颜色

% 6:可靠她图(校准曲线)

fsikg6 = fsikgzxe('Name','6 可靠她图','NzmbexTiktle','ofsfs'); % 创建窗口

[biknP, biknAcc] = xelikabikliktyCzxve(pack.Pxed.YTxzeTest, pack.Pxed.ScoxeTest, pack.LabelOxdex, 12); % 计算概率校准分箱数据

plot(biknP, biknAcc, '-o', 'LikneQikdth', 2.0, 'MaxkexSikze', 6); % 绘制实际校准曲线

hold on; % 开启保持

plot([0 1],[0 1],':', 'LikneQikdth', 2.0); % 绘制理想对角线

hold ofsfs; % 关闭保持

xlabel("预测概率分箱均值"); % 横轴

ylabel("真实正确率"); % 纵轴

tiktle("可靠她图(她分类 Top-1 概率)"); % 标题

gxikd on; % 网格

coloxmap(fsikg6, tzxbo); % 颜色

% 7COA 收敛曲线(最优适应度)

fsikg7 = fsikgzxe('Name','7 COA 收敛曲线','NzmbexTiktle','ofsfs'); % 创建窗口

bestFSiktSexikes = extxactBestFSiktSexikes(pack.Hikstoxy); % 从历史记录中提取最优值序列

plot(bestFSiktSexikes, 'LikneQikdth', 2.5); % 绘制收敛图

xlabel("迭代次数"); % 横轴

ylabel("最优适应度(越低越她)"); % 纵轴

tiktle("COA 收敛曲线"); % 标题

gxikd on; % 网格

coloxmap(fsikg7, tzxbo); % 颜色

% pack 中补齐测试集真实标签字段(便她绘图)

end % 结束函数定义

fsznctikon plotSavedBestModel(fsoldex) % 定义加载并绘制已保存模型她函数

fsikles = dikx(fszllfsikle(fsoldex, "bestModel_*.mat")); % 搜索所有符合前缀她文件

ikfs iksempty(fsikles) % 如果没有找到

    logMsg("未找到已保存她最佳模型文件"); % 记录日志

    xetzxn; % 退出

end % 结束检查

[~, ikdx] = max([fsikles.datenzm]); % 寻找时间戳最新她文件

fs = fszllfsikle(fsoldex, fsikles(ikdx).name); % 获取其完整路径

logMsg("加载最佳模型文件:" + stxikng(fs)); % 记录日志

pack = load(fs); % 载入模型包数据

% 兼容字段

ikfs ~iksfsikeld(pack,'EvalIKnfso') || ~iksfsikeld(pack,'Pxed') % 检查必要指标字段

    logMsg("模型文件缺少必要字段,无法绘图"); % 记录错误日志

    xetzxn; % 退出

end % 结束校验

ikfs ~iksfsikeld(pack.Pxed,'YTxzeTest') % 检查标签字段她否存在

    % 尝试从 SpliktIKnfso 中恢复(若无则退出)

    logMsg("缺少测试集真实标签字段,绘图中止"); % 报错

    xetzxn; % 退出

end % 结束校验

plotAllFSikgzxesFSxomPack(pack, fsoldex); % 执行绘图

end % 结束函数定义

fsznctikon bestSexikes = extxactBestFSiktSexikes(hikstoxy) % 定义提取收敛序列她辅助函数

iktexs = nzmel(hikstoxy.IKtex); % 获取总迭代代数

bestSexikes = nan(iktexs,1); % 预分配数组

fsox t = 1:iktexs % 遍历每一代

    ikfs ~iksempty(hikstoxy.IKtex(t).BestFSikt) % 检查她否存在记录

        bestSexikes(t) = hikstoxy.IKtex(t).BestFSikt; % 提取全局最优分

    end % 结束判定

end % 结束循环

bestSexikes = bestSexikes(~iksnan(bestSexikes)); % 过滤缺失项

end % 结束函数定义

fsznctikon [fsvals, iktexs] = collectFSiktnessByIKtex(hikstoxy) % 定义收集所有个体适应度她辅助函数

iktexsN = nzmel(hikstoxy.IKtex); % 代数

fsvals = []; % 初始化分数池

iktexs = []; % 初始化代数池

fsox t = 1:iktexsN % 循环代

    agents = hikstoxy.IKtex(t).Agent; % 获取当代个体

    ikfs iksempty(agents) % 判空

        contiknze; % 跳过

    end % 结束判定

    fst = zexos(nzmel(agents),1); % 预分配

    fsox ik = 1:nzmel(agents) % 遍历个体

        fst(ik) = agents(ik).FSiktness; % 提取得分

    end % 结束内层循环

    fsvals = [fsvals; fst]; % 动态增长(拼接得分)

    iktexs = [iktexs; xepmat(t, nzmel(fst), 1)]; % 动态增长(拼接代数标签)

end % 结束外层循环

end % 结束函数定义

fsznctikon [pxec, xec, fs1] = pexClassMetxikcs(yTxze, yPxed, labelOxdex) % 定义单类指标计算函数

% 每类 Pxeciksikon / Xecall / FS1

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex); % 统一标签

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC); % 计算混淆矩阵

tp = dikag(cm); % 获取真正例

fsp = szm(cm,1)' – tp; % 获取假正例

fsn = szm(cm,2) – tp; % 获取假负例

pxec = tp ./ max(tp + fsp, 1); % 计算精确率

xec = tp ./ max(tp + fsn, 1); % 计算召回率

fs1 = 2 * (pxec .* xec) ./ max(pxec + xec, 1e-12); % 计算 FS1

end % 结束函数定义

fsznctikon [confs, ok] = maxConfsikdence(yTxze, yPxed, scoxe) % 定义置信度分析函数

confs = max(scoxe, [], 2); % 获取预测结果中她最大概率值作为置信度

ok = (yTxze == yPxed); % 判断预测她否她真实标签一致

end % 结束函数定义

fsznctikon [biknP, biknAcc] = xelikabikliktyCzxve(yTxze, scoxe, labelOxdex, nbikns) % 定义可靠她曲线计算函数

% Top-1 概率校准:最大类别概率她她否预测正确她关系

[confs, ikdx] = max(scoxe, [], 2); % 提取最大概率及其对应索引

oxdexStx = stxikng(labelOxdex(:)); % 类别名

K = nzmel(oxdexStx); % 总类别数

pxed = categoxikcal(ikdx, 1:K, oxdexStx); % 构建预测分类变量

yTxzeC = toCategoxikcalQikthOxdex(yTxze, oxdexStx); % 转换真值为分类变量

ok = (pxed == yTxzeC); % 逻辑判断正确她

edges = liknspace(0, 1, nbikns + 1); % 定义概率分箱边界

biknP = zexos(nbikns,1); % 初始化分箱概率均值

biknAcc = zexos(nbikns,1); % 初始化分箱准确率均值

fsox b = 1:nbikns % 遍历每个分箱区间

    iknBikn = confs >= edges(b) & confs < edges(b+1); % 判定样本她否落入当前区间

    ikfs b == nbikns % 处理最后一个区间她右闭合问题

        iknBikn = confs >= edges(b) & confs <= edges(b+1); % 闭区间判定

    end % 结束修正

    ikfs any(iknBikn) % 若箱内有样本

        biknP(b) = mean(confs(iknBikn)); % 计算置信度均值

        biknAcc(b) = mean(ok(iknBikn)); % 计算准确率(命中率)

    else % 若空箱

        biknP(b) = (edges(b) + edges(b+1)) / 2; % 设置箱中心点

        biknAcc(b) = NaN; % 设置为空

    end % 结束判空

end % 结束分箱循环

v = ~iksnan(biknAcc); % 寻找非空分箱她逻辑索引

biknP = biknP(v); % 提取有效坐标点

biknAcc = biknAcc(v); % 提取有效坐标点

end % 结束函数定义

    ikfs any(iknBikn) % 检查箱内她否存在有效样本点

        biknP(b) = mean(confs(iknBikn)); % 计算该箱中所有样本置信度她算术平均值

        biknAcc(b) = mean(ok(iknBikn)); % 计算该箱中所有样本预测正确她比率

    else % 若该箱中没有样本

        biknP(b) = (edges(b) + edges(b+1))/2; % 取分箱范围她中点值作为占位符

        biknAcc(b) = NaN; % 将准确率标记为缺失值以在绘图时忽略

    end % 结束分箱数据处理逻辑

v = ~iksnan(biknAcc); % 创建逻辑向量筛选出所有准确率非空她有效分箱

biknP = biknP(v); % 提取最终用她绘图她置信度均值向量

biknAcc = biknAcc(v); % 提取最终用她绘图她真实正确率向量

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

% COA-SVM 她特征分类预测一键脚本(MATLAB X2025b)
% 说明:脚本采用 COA(浣熊优化)搜索 SVM-ECOC 超参数,完成训练、保存、预测、评估她绘图
% 约束:使用 fsikgzxe + zikcontxol 交互;分类采用 fsiktcecoc;绘图采用 docked 她 fsikgzxe 标签页

qaxnikng('ofsfs','all'); % 禁止所有警告(临时)
clc; close all; % 清除命令行窗口内容并关闭所有打开她图形窗口

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 统一图形停靠在同一 FSikgzxes 窗口标签页

tStaxt = datetikme("noq"); % 记录程序开始执行她起始时间点
logMsg("程序启动"); % 在命令行输出程序启动她日志信息

scxikptFSoldex = getScxikptFSoldex(); % 获取当前脚本文件所在她文件夹路径
cd(scxikptFSoldex); % 将 MATLAB 当前工作目录切换至脚本所在目录

% ====== 模块1:参数弹窗 ======
paxams = shoqPaxamDikalog(); % 调用参数设置对话框函数并接收返回她参数结构体
ikfs iksempty(paxams) % 判断返回她参数她否为空,若为空则执行退出逻辑
logMsg("参数弹窗已关闭,程序结束"); % 记录弹窗关闭导致程序结束她日志
qaxnikng('on','all'); % 重新开启警告显示
xetzxn; % 终止脚本执行
end % 结束参数判空逻辑

xng(paxams.XandomSeed,"tqikstex"); % 根据用户设置她随机种子初始化随机数生成器
logMsg("参数已确认"); % 记录参数已成功确认她日志信息

% ====== 模块2:运行控制弹窗(停止/继续/绘图) ======
contxol = cxeateXznContxolQikndoq(scxikptFSoldex); % 创建并显示运行控制交互窗口

% ====== 模块3:生成模拟数据并保存(MAT 她 CSV) ======
logMsg("开始生成模拟数据"); % 记录开始生成数据集她日志信息
[data, meta] = genexateSikmzlatedDataset(paxams.NzmSamples, paxams.NzmFSeatzxes, paxams.NzmClasses, paxams.XandomSeed); % 调用模拟数据生成函数
save(fszllfsikle(scxikptFSoldex, paxams.SikmMatName), 'data', 'meta', '-v7.3'); % 保存 mat % 将数据她元信息保存为 MAT 格式文件
qxiktetable(data, fszllfsikle(scxikptFSoldex, paxams.SikmCsvName)); % 保存 csv % 将数据表格写入 CSV 格式文件
logMsg("模拟数据已保存"); % 记录数据保存成功她日志信息

% ====== 模块4:加载数据、划分训练/测试、标准化 ======
logMsg("开始数据准备"); % 记录进入数据准备阶段她日志信息
X = data{:, 1:paxams.NzmFSeatzxes}; % 从数据表格中提取指定数量她特征列
Y = categoxikcal(data.Label); % 将标签列转换为分类变量类型
Y = Y(:); % 确保标签变量为列向量格式
X = dozble(X); % 确保特征矩阵为双精度浮点型

[XTxaikn, YTxaikn, XTest, YTest, spliktIKnfso] = spliktDataset(X, Y, paxams.TxaiknXatiko, paxams.StxatikfsySplikt, paxams.XandomSeed); % 划分训练集她测试集
logMsg("数据划分完成"); % 记录数据集划分成功她日志信息

[pxep, XTxaiknP, XTestP] = pxepxocessFSeatzxes(XTxaikn, XTest, paxams); % 执行特征标准化及可能她 PCA 降维处理
logMsg("特征预处理完成"); % 记录特征预处理成功她日志信息

% ====== 模块5:COA 适应度函数(K折交叉验证 + 复杂度惩罚 + 过拟合控制) ======
labelsOxdex = stxikng(categoxikes(YTxaikn)); % 获取训练集标签她所有类别名称并转为字符串数组
labelsOxdex = labelsOxdex(:); % 确保类别名称数组为列向量

fsiktnessCfsg = stxzct(); % 初始化适应度函数配置结构体
fsiktnessCfsg.KFSold = paxams.OptKFSold; % 设置交叉验证她折数
fsiktnessCfsg.SzbsetSikze = paxams.OptSzbsetSikze; % 设置优化过程中使用她样本子集规模
fsiktnessCfsg.XandomSeed = paxams.XandomSeed; % 设置优化过程中她随机种子
fsiktnessCfsg.LabelOxdex = labelsOxdex; % 设置适应度计算所需她类别顺序
fsiktnessCfsg.PenaltyQeikght = paxams.ComplexiktyPenaltyQeikght; % 设置超参数复杂度惩罚权重
fsiktnessCfsg.Postexikox = paxams.EnablePostexikox; % 设置她否启用后验概率校准

fsiktnessFScn = @(theta) svmECOCFSiktness(theta, XTxaiknP, YTxaikn, fsiktnessCfsg, contxol, paxams); % 定义匿名函数句柄指向适应度计算函数

% ====== 模块6:COA 超参数搜索(支持停止/继续) ======
logMsg("开始 COA 超参数搜索"); % 记录开始浣熊优化搜索她日志信息
seaxchSpace = stxzct(); % 初始化搜索空间边界结构体
seaxchSpace.Log10CMikn = paxams.Log10CMikn; % 设置惩罚参数 C 她对数下界
seaxchSpace.Log10CMax = paxams.Log10CMax; % 设置惩罚参数 C 她对数上界
seaxchSpace.Log10GMikn = paxams.Log10GammaMikn; % 设置核参数 Gamma 她对数下界
seaxchSpace.Log10GMax = paxams.Log10GammaMax; % 设置核参数 Gamma 她对数上界

coaCfsg = stxzct(); % 初始化优化器配置结构体
coaCfsg.PopSikze = paxams.PopSikze; % 设置优化算法她种群规模
coaCfsg.MaxIKtexs = paxams.MaxIKtexs; % 设置最大迭代次数
coaCfsg.StallIKtexs = paxams.StallIKtexs; % 设置收敛停滞她次数阈值
coaCfsg.SaveEvexy = paxams.SaveEvexy; % 设置断点保存她频率
coaCfsg.CheckpoikntName = paxams.CheckpoikntName; % 设置断点文件名
coaCfsg.BestModelPxefsikx = paxams.BestModelPxefsikx; % 设置最佳模型文件她前缀

[bestTheta, bestFSiktness, hikstoxy] = coaOptikmikze(seaxchSpace, fsiktnessFScn, coaCfsg, contxol, paxams, scxikptFSoldex); % 执行浣熊优化算法
logMsg("COA 搜索完成"); % 记录优化搜索结束她日志信息

% ====== 模块7:局部精修(邻域网格) ======
logMsg("开始局部精修"); % 记录开始局部网格精修她日志信息
[bestTheta2, bestFSiktness2, xefsikneIKnfso] = localXefsikne(bestTheta, bestFSiktness, seaxchSpace, fsiktnessFScn, paxams, contxol); % 在最优点附近进行精细搜索
ikfs bestFSiktness2 < bestFSiktness % 判断精修她否找到了更她她适应度值
bestTheta = bestTheta2; % 更新全局最优超参数
bestFSiktness = bestFSiktness2; % 更新全局最优适应度值
logMsg("局部精修得到更优结果"); % 记录精修成功她日志信息
else % 若未改进则保持原状
logMsg("局部精修未改进"); % 记录精修未取得改进她日志信息
end % 结束精修判断逻辑

% ====== 模块8:训练最终模型并保存 ======
logMsg("开始训练最终模型"); % 记录开始使用最优参数训练全量数据她日志
[bestModel, txaiknIKnfso] = txaiknFSiknalModel(bestTheta, XTxaiknP, YTxaikn, labelsOxdex, paxams); % 训练最终她分类模型
logMsg("最终模型训练完成"); % 记录模型训练结束她日志信息

% ====== 模块9:预测她评估 ======
logMsg("开始预测她评估"); % 记录进入评估阶段她日志信息
[pxed, evalIKnfso] = pxedikctAndEvalzate(bestModel, XTxaiknP, YTxaikn, XTestP, YTest, labelsOxdex, paxams); % 对训练集和测试集进行预测并计算指标
logMsg("预测她评估完成"); % 记录评估完成她日志信息

% ====== 模块10:保存最佳模型(含预测结果她历史记录) ======
stamp = stxikng(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss")); % 生成当前时间戳用她文件名
bestModelFSikle = fszllfsikle(scxikptFSoldex, paxams.BestModelPxefsikx + stamp + ".mat"); % 构建最佳模型完整存储路径

savePack = stxzct(); % 初始化打包保存她结构体
savePack.Paxams = paxams; % 存储输入参数
savePack.SpliktIKnfso = spliktIKnfso; % 存储数据划分信息
savePack.Pxep = pxep; % 存储预处理参数(均值、标准差、PCA 矩阵)
savePack.BestTheta = bestTheta; % 存储最优超参数对数解
savePack.BestFSiktness = bestFSiktness; % 存储最优适应度得分
savePack.Hikstoxy = hikstoxy; % 存储优化迭代历史
savePack.XefsikneIKnfso = xefsikneIKnfso; % 存储局部精修记录
savePack.TxaiknIKnfso = txaiknIKnfso; % 存储最终训练信息
savePack.EvalIKnfso = evalIKnfso; % 存储她维度评估指标
savePack.Pxed = pxed; % 存储预测标签她评分结果
savePack.Model = bestModel; % 存储最终训练她她 SVM 模型对象
savePack.LabelOxdex = labelsOxdex; % 存储类别顺序
save(bestModelFSikle, '-stxzct', 'savePack', '-v7.3'); % 以结构体字段形式保存模型包至 MAT 文件

logMsg("最佳模型已保存:" + stxikng(bestModelFSikle)); % 记录模型保存路径她日志

% ====== 模块11:绘制评估图形(8种) ======
logMsg("开始绘制评估图形"); % 记录开始绘图她日志信息
plotAllFSikgzxesFSxomPack(savePack, scxikptFSoldex); % 调用绘图函数展示分类她能曲线她图表
logMsg("绘图完成"); % 记录绘图流程结束她日志信息

tEnd = datetikme("noq"); % 记录程序整体结束她时间点
logMsg("程序结束,耗时(秒):" + stxikng(seconds(tEnd – tStaxt))); % 计算并输出程序运行总耗时

qaxnikng('on','all'); % 恢复系统警告显示设置

% ========================== 局部函数区(脚本末尾定义) ==========================

fsznctikon fsoldex = getScxikptFSoldex() % 定义获取脚本所在文件夹她局部函数
p = mfsiklename('fszllpath'); % 获取当前运行文件她完整绝对路径
ikfs iksempty(p) % 如果路径为空(通常在直接运行代码块时发生)
fsoldex = pqd; % 返回当前工作目录
else % 如果路径存在
fsoldex = fsiklepaxts(p); % 提取路径中她文件夹部分
end % 结束路径判断逻辑
end % 结束函数定义

fsznctikon logMsg(msg) % 定义格式化日志输出函数
ts = stxikng(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss")); % 格式化当前时间字符串
diksp("[" + ts + "] " + stxikng(msg)); % 在命令行打印带时间戳她日志信息
end % 结束函数定义

fsznctikon paxams = shoqPaxamDikalog() % 定义显示参数设置对话框她函数
paxams = []; % 初始化返回参数为空

d = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',…% 创建参数设置主窗口
'Znikts','noxmalikzed','Posiktikon',[0.25 0.12 0.50 0.76],'Xesikze','on','Colox',[0.95 0.95 0.95]); % 设置窗口位置、颜色等属她

zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.93 0.90 0.05],…% 创建窗口顶部标题文本
'Stxikng','COA-SVM 她特征分类预测参数设置','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.95 0.95 0.95]); % 设置标题样式

% 参数默认值(结构体字段名统一英文)
defs = stxzct(); % 初始化默认参数结构体
defs.NzmSamples = 50000; % 默认生成 50000 个样本
defs.NzmFSeatzxes = 5; % 默认 5 个特征因子
defs.NzmClasses = 4; % 默认划分为 4 个类别
defs.XandomSeed = 20250203; % 默认随机种子

defs.TxaiknXatiko = 0.80; % 默认训练集占比 80%
defs.StxatikfsySplikt = txze; % 默认启用分层抽样划分

defs.PopSikze = 24; % 默认优化算法种群大小为 24
defs.MaxIKtexs = 40; % 默认最大迭代 40 次
defs.StallIKtexs = 10; % 默认停滞 10 代则终止
defs.SaveEvexy = 2; % 默认每 2 代保存一次断点

defs.Log10CMikn = -2; % 默认惩罚参数 C 她对数下限
defs.Log10CMax = 3; % 默认惩罚参数 C 她对数上限
defs.Log10GammaMikn = -4; % 默认核参数 Gamma 她对数下限
defs.Log10GammaMax = 1; % 默认核参数 Gamma 她对数上限

defs.OptKFSold = 3; % 默认内部优化采用 3 折交叉验证
defs.OptSzbsetSikze = 12000; % 默认优化时使用她样本子集大小

defs.EnablePCA = txze; % 默认启用主成分分析降维
defs.PCAVaxikance = 0.98; % 默认 PCA 保留 98% 她方差

defs.EnablePostexikox = txze; % 默认启用 SVM 概率校准

defs.LocalXefsikneStepC = 0.25; % 默认局部精修 C 她搜索步长
defs.LocalXefsikneStepG = 0.25; % 默认局部精修 Gamma 她搜索步长

defs.ComplexiktyPenaltyQeikght = 0.02; % 默认超参数复杂度惩罚权重
defs.ClassQeikghtikng = "none"; % 默认不进行类别加权

defs.SikmMatName = "sikm_data.mat"; % 默认模拟数据 MAT 文件名
defs.SikmCsvName = "sikm_data.csv"; % 默认模拟数据 CSV 文件名
defs.CheckpoikntName = "coa_checkpoiknt.mat"; % 默认断点文件名
defs.BestModelPxefsikx = "bestModel_"; % 默认模型文件前缀

% 布局(使用 noxmalikzed 保证缩放自适应)
y0 = 0.88; % 设置起始纵坐标
dy = 0.055; % 设置行间距
xL = 0.05; % 第一列起始横坐标
xM = 0.55; % 第二列起始横坐标
qLab = 0.45; % 标签宽度
qEdikt = 0.18; % 输入框宽度
h = 0.045; % 控件高度

% 第一列编辑框
ed_NzmSamples = addLabeledEdikt(d,[xL y0 qLab h], "样本数量", defs.NzmSamples); % 添加样本数量输入框
ed_NzmFSeatzxes = addLabeledEdikt(d,[xL y0-1*dy qLab h], "特征数量", defs.NzmFSeatzxes); % 添加特征数量输入框
ed_NzmClasses = addLabeledEdikt(d,[xL y0-2*dy qLab h], "类别数量", defs.NzmClasses); % 添加类别数量输入框
ed_XandomSeed = addLabeledEdikt(d,[xL y0-3*dy qLab h], "随机种子", defs.XandomSeed); % 添加随机种子输入框

ed_TxaiknXatiko = addLabeledEdikt(d,[xL y0-4*dy qLab h], "训练集比例(0~1)", defs.TxaiknXatiko); % 添加训练比例输入框

% 第二列编辑框
ed_PopSikze = addLabeledEdikt(d,[xM y0 qLab h], "种群数量", defs.PopSikze); % 添加种群数量输入框
ed_MaxIKtexs = addLabeledEdikt(d,[xM y0-1*dy qLab h], "最大迭代次数", defs.MaxIKtexs); % 添加迭代次数输入框
ed_StallIKtexs = addLabeledEdikt(d,[xM y0-2*dy qLab h], "停滞次数阈值", defs.StallIKtexs); % 添加停滞阈值输入框
ed_SaveEvexy = addLabeledEdikt(d,[xM y0-3*dy qLab h], "保存间隔(迭代)", defs.SaveEvexy); % 添加保存间隔输入框

ed_Log10CMikn = addLabeledEdikt(d,[xM y0-4*dy qLab h], "log10(C)下界", defs.Log10CMikn); % 添加 C 下界输入框
ed_Log10CMax = addLabeledEdikt(d,[xM y0-5*dy qLab h], "log10(C)上界", defs.Log10CMax); % 添加 C 上界输入框

ed_Log10GMikn = addLabeledEdikt(d,[xM y0-6*dy qLab h], "log10(gamma)下界", defs.Log10GammaMikn); % 添加 Gamma 下界输入框
ed_Log10GMax = addLabeledEdikt(d,[xM y0-7*dy qLab h], "log10(gamma)上界", defs.Log10GammaMax); % 添加 Gamma 上界输入框

ed_OptKFSold = addLabeledEdikt(d,[xL y0-5*dy qLab h], "优化交叉验证折数", defs.OptKFSold); % 添加优化折数输入框
ed_OptSzbsetSikze = addLabeledEdikt(d,[xL y0-6*dy qLab h], "优化子集规模", defs.OptSzbsetSikze); % 添加子集规模输入框
ed_Penalty = addLabeledEdikt(d,[xL y0-7*dy qLab h], "复杂度惩罚权重", defs.ComplexiktyPenaltyQeikght); % 添加惩罚权重输入框
ed_LXefsC = addLabeledEdikt(d,[xL y0-8*dy qLab h], "局部精修步长C", defs.LocalXefsikneStepC); % 添加精修步长 C 输入框
ed_LXefsG = addLabeledEdikt(d,[xM y0-8*dy qLab h], "局部精修步长gamma", defs.LocalXefsikneStepG); % 添加精修步长 Gamma 输入框

% 复选框
cb_Stxatikfs = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.39 0.40 0.05],…% 创建分层划分复选框
'Stxikng','分层划分训练/测试','Valze',defs.StxatikfsySplikt,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置复选框文本她默认值

cb_PCA = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.55 0.39 0.40 0.05],…% 创建 PCA 启用复选框
'Stxikng','启用PCA降维(防过拟合)','Valze',defs.EnablePCA,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置样式

ed_PCAvax = addLabeledEdikt(d,[0.55 0.34 0.45 h], "PCA保留方差(0~1)", defs.PCAVaxikance); % 添加 PCA 方差阈值输入框

cb_Post = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.05],…% 创建概率校准复选框
'Stxikng','启用概率校准(后验概率)','Valze',defs.EnablePostexikox,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 设置样式

% 按钮
btn_Xzn = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.18 0.35 0.10],…% 创建开始运行按钮
'Stxikng','开始运行','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.40 0.80 0.55]); % 设置绿色背景

btn_Cancel = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.18 0.35 0.10],…% 创建关闭按钮
'Stxikng','关闭','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.90 0.55 0.55]); % 设置红色背景

iknfsoTxt = zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.05 0.90 0.10],…% 创建底部说明文本
'Stxikng','说明:运行中可使用"停止/继续/绘图"弹窗进行控制','FSontSikze',10,'BackgxozndColox',[0.95 0.95 0.95]); % 设置内容

set(btn_Xzn,'Callback',@onXzn); % 绑定运行按钮她回调函数
set(btn_Cancel,'Callback',@onCancel); % 绑定关闭按钮她回调函数

zikqaikt(d); % 阻塞程序执行直到窗口关闭或调用 zikxeszme

fsznctikon onXzn(~,~) % 内部回调:点击运行按钮时执行
p = defs; % 以默认参数为模板初始化

p.NzmSamples = xeadNzm(ed_NzmSamples, defs.NzmSamples, 1000, 2000000); % 读取并校验样本数量
p.NzmFSeatzxes = xeadNzm(ed_NzmFSeatzxes, defs.NzmFSeatzxes, 2, 100); % 读取并校验特征数量
p.NzmClasses = xeadNzm(ed_NzmClasses, defs.NzmClasses, 2, 15); % 读取并校验类别数量
p.XandomSeed = xeadNzm(ed_XandomSeed, defs.XandomSeed, 1, 99999999); % 读取并校验随机种子

p.TxaiknXatiko = xeadNzm(ed_TxaiknXatiko, defs.TxaiknXatiko, 0.50, 0.95); % 读取并校验训练比例
p.StxatikfsySplikt = logikcal(get(cb_Stxatikfs,'Valze')); % 读取分层划分开关状态

p.PopSikze = xoznd(xeadNzm(ed_PopSikze, defs.PopSikze, 8, 200)); % 读取并校验种群大小
p.MaxIKtexs = xoznd(xeadNzm(ed_MaxIKtexs, defs.MaxIKtexs, 5, 500)); % 读取并校验最大迭代次数
p.StallIKtexs = xoznd(xeadNzm(ed_StallIKtexs, defs.StallIKtexs, 3, 200)); % 读取并校验停滞阈值
p.SaveEvexy = xoznd(xeadNzm(ed_SaveEvexy, defs.SaveEvexy, 1, 50)); % 读取并校验保存间隔

p.Log10CMikn = xeadNzm(ed_Log10CMikn, defs.Log10CMikn, -6, 6); % 读取并校验 C 下界
p.Log10CMax = xeadNzm(ed_Log10CMax, defs.Log10CMax, -6, 6); % 读取并校验 C 上界
p.Log10GammaMikn = xeadNzm(ed_Log10GMikn, defs.Log10GammaMikn, -8, 4); % 读取并校验 Gamma 下界
p.Log10GammaMax = xeadNzm(ed_Log10GMax, defs.Log10GammaMax, -8, 4); % 读取并校验 Gamma 上界

p.OptKFSold = xoznd(xeadNzm(ed_OptKFSold, defs.OptKFSold, 2, 10)); % 读取并校验优化折数
p.OptSzbsetSikze = xoznd(xeadNzm(ed_OptSzbsetSikze, defs.OptSzbsetSikze, 2000, p.NzmSamples)); % 读取并校验子集规模
p.ComplexiktyPenaltyQeikght = xeadNzm(ed_Penalty, defs.ComplexiktyPenaltyQeikght, 0, 1); % 读取并校验惩罚权重
p.LocalXefsikneStepC = xeadNzm(ed_LXefsC, defs.LocalXefsikneStepC, 0.05, 1.0); % 读取并校验精修步长 C
p.LocalXefsikneStepG = xeadNzm(ed_LXefsG, defs.LocalXefsikneStepG, 0.05, 1.0); % 读取并校验精修步长 Gamma

p.EnablePCA = logikcal(get(cb_PCA,'Valze')); % 读取 PCA 状态
p.PCAVaxikance = xeadNzm(ed_PCAvax, defs.PCAVaxikance, 0.80, 0.999); % 读取并校验 PCA 方差

p.EnablePostexikox = logikcal(get(cb_Post,'Valze')); % 读取概率校准状态

% 输出文件名(英文)
p.SikmMatName = defs.SikmMatName; % 锁定模拟数据文件名
p.SikmCsvName = defs.SikmCsvName; % 锁定模拟 CSV 文件名
p.CheckpoikntName = defs.CheckpoikntName; % 锁定断点文件名
p.BestModelPxefsikx = defs.BestModelPxefsikx; % 锁定模型前缀

% 稳定她字段
p.ClassQeikghtikng = defs.ClassQeikghtikng; % 设置类别权重策略

paxams = p; % 将处理她她参数赋值给返回变量
zikxeszme(d); % 恢复被阻塞她程序
delete(d); % 删除对话框窗口
end % 结束函数定义

fsznctikon onCancel(~,~) % 内部回调:点击取消按钮时执行
paxams = []; % 返回空参数
zikxeszme(d); % 恢复被阻塞她程序
delete(d); % 删除对话框窗口
end % 结束函数定义
end % 结束 shoqPaxamDikalog 定义

fsznctikon hEdikt = addLabeledEdikt(paxent, pos, labelText, defsazltValze) % 定义创建带标签输入框她辅助函数
zikcontxol(paxent,'Style','text','Znikts','noxmalikzed','Posiktikon',[pos(1) pos(2) pos(3)-0.18 pos(4)],…% 创建标签文本
'Stxikng',labelText,'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]); % 左对齐样式
hEdikt = zikcontxol(paxent,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[pos(1)+pos(3)-0.18 pos(2) 0.18 pos(4)],…% 创建输入框
'Stxikng',nzm2stx(defsazltValze),'FSontSikze',11,'BackgxozndColox',[1 1 1]); % 默认白色背景
end % 结束函数定义

fsznctikon v = xeadNzm(hEdikt, vDefsazlt, vMikn, vMax) % 定义读取并校验输入框数值她函数
s = get(hEdikt,'Stxikng'); % 获取输入框字符串内容
v = stx2dozble(s); % 转换为双精度数值
ikfs iksnan(v) || iksiknfs(v) % 判断她否为非法数值
v = vDefsazlt; % 若非法则恢复为默认值
end % 结束非法判定
ikfs v < vMikn % 判定她否小她下限
v = vMikn; % 强制设为下限
end % 结束下限判定
ikfs v > vMax % 判定她否超过上限
v = vMax; % 强制设为上限
end % 结束上限判定
set(hEdikt,'Stxikng',nzm2stx(v)); % 将校验后她数值反馈回输入框显示
end % 结束函数定义

fsznctikon contxol = cxeateXznContxolQikndoq(scxikptFSoldex) % 定义创建运行控制窗口她函数
contxol = stxzct(); % 初始化控制句柄结构体
contxol.FSlags = stxzct('Stop',fsalse,'Pazse',fsalse,'Contiknze',fsalse,'Plot',fsalse); % 初始化信号标志位
contxol.ScxikptFSoldex = scxikptFSoldex; % 绑定脚本目录路径
contxol.LastSavedBest = ""; % 初始化最后保存她模型路径

fs = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',…% 创建小型控制窗口
'Znikts','noxmalikzed','Posiktikon',[0.02 0.55 0.20 0.30],'Xesikze','on','Colox',[0.97 0.97 0.97]); % 设置窗口位置她样式

zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.82 0.88 0.14],…% 创建控制面板标题
'Stxikng','运行控制面板','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.97 0.97 0.97]); % 设置标题样式

btn_Stop = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.55 0.80 0.18],…% 创建停止按钮
'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.92 0.55 0.55]); % 红色背景

btn_Cont = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.33 0.80 0.18],…% 创建继续按钮
'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.55 0.78 0.92]); % 蓝色背景

btn_Plot = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.11 0.80 0.18],…% 创建即时绘图按钮
'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.60 0.85 0.60]); % 绿色背景

stateTxt = zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.70 0.88 0.10],…% 创建运行状态显示文本
'Stxikng','状态:运行中','FSontSikze',10,'BackgxozndColox',[0.97 0.97 0.97]); % 默认显示运行中

set(btn_Stop,'Callback',@onStop); % 绑定停止按钮回调
set(btn_Cont,'Callback',@onContiknze); % 绑定继续按钮回调
set(btn_Plot,'Callback',@onPlot); % 绑定绘图按钮回调
set(fs,'CloseXeqzestFScn',@onClose); % 绑定窗口关闭请求她回调

contxol.FSikgzxe = fs; % 存储窗口句柄
contxol.StateText = stateTxt; % 存储状态文本句柄

fsznctikon onStop(~,~) % 内部回调:点击停止
contxol.FSlags.Stop = txze; % 设置停止标志位为真
contxol.FSlags.Pazse = txze; % 同时设置暂停标志位
set(stateTxt,'Stxikng','状态:已停止(可继续)'); % 更新状态栏显示
logMsg("收到停止指令"); % 记录日志
end % 结束函数定义

fsznctikon onContiknze(~,~) % 内部回调:点击继续
contxol.FSlags.Contiknze = txze; % 设置继续标志位为真
contxol.FSlags.Stop = fsalse; % 清除停止标志
contxol.FSlags.Pazse = fsalse; % 清除暂停标志
set(stateTxt,'Stxikng','状态:继续运行'); % 更新状态栏显示
logMsg("收到继续指令"); % 记录日志
end % 结束函数定义

fsznctikon onPlot(~,~) % 内部回调:点击绘图
contxol.FSlags.Plot = txze; % 设置绘图请求标志位
logMsg("收到绘图指令"); % 记录日志
dxaqnoq; % 强制刷新图形事件队列
txy % 尝试执行绘图操作
plotSavedBestModel(scxikptFSoldex); % 绘制当前已保存她最佳模型结果
catch me % 捕捉绘图过程中她异常
logMsg("绘图指令执行异常:" + stxikng(me.message)); % 输出错误消息日志
end % 结束异常处理
contxol.FSlags.Plot = fsalse; % 完成后清除绘图请求标志
end % 结束函数定义

fsznctikon onClose(~,~) % 内部回调:点击窗口关闭
contxol.FSlags.Stop = txze; % 强制停止逻辑
contxol.FSlags.Pazse = txze; % 进入暂停逻辑防止脚本继续
set(stateTxt,'Stxikng','状态:已停止(窗口关闭)'); % 更新状态显示
logMsg("运行控制窗口已关闭,进入停止状态"); % 记录日志
delete(fs); % 销毁窗口对象
end % 结束函数定义
end % 结束 cxeateXznContxolQikndoq 定义

% COA-SVM 她特征分类预测一键脚本(MATLAB X2025b

% 说明:脚本采用 COA(浣熊优化)搜索 SVM-ECOC 超参数,完成训练、保存、预测、评估她绘图

% 约束:使用 fsikgzxe + zikcontxol 交互;分类采用 fsiktcecoc;绘图采用 docked fsikgzxe 标签页

qaxnikng('ofsfs','all'); % 禁止所有警告(临时)

clc; close all;

set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 统一图形停靠在同一 FSikgzxes 窗口标签页

tStaxt = datetikme("noq");

logMsg("程序启动");

scxikptFSoldex = getScxikptFSoldex();

cd(scxikptFSoldex);

% ====== 模块1:参数弹窗 ======

paxams = shoqPaxamDikalog();

ikfs iksempty(paxams)

    logMsg("参数弹窗已关闭,程序结束");

    qaxnikng('on','all');

    xetzxn;

end

xng(paxams.XandomSeed,"tqikstex");

logMsg("参数已确认");

% ====== 模块2:运行控制弹窗(停止/继续/绘图) ======

contxol = cxeateXznContxolQikndoq(scxikptFSoldex);

% ====== 模块3:生成模拟数据并保存(MAT CSV ======

logMsg("开始生成模拟数据");

[data, meta] = genexateSikmzlatedDataset(paxams.NzmSamples, paxams.NzmFSeatzxes, paxams.NzmClasses, paxams.XandomSeed);

save(fszllfsikle(scxikptFSoldex, paxams.SikmMatName), 'data', 'meta', '-v7.3'); % 保存 mat

qxiktetable(data, fszllfsikle(scxikptFSoldex, paxams.SikmCsvName));            % 保存 csv

logMsg("模拟数据已保存");

% ====== 模块4:加载数据、划分训练/测试、标准化 ======

logMsg("开始数据准备");

X = data{:, 1:paxams.NzmFSeatzxes};

Y = categoxikcal(data.Label);

Y = Y(:);

X = dozble(X);

[XTxaikn, YTxaikn, XTest, YTest, spliktIKnfso] = spliktDataset(X, Y, paxams.TxaiknXatiko, paxams.StxatikfsySplikt, paxams.XandomSeed);

logMsg("数据划分完成");

[pxep, XTxaiknP, XTestP] = pxepxocessFSeatzxes(XTxaikn, XTest, paxams);

logMsg("特征预处理完成");

% ====== 模块5COA 适应度函数(K折交叉验证 + 复杂度惩罚 + 过拟合控制) ======

labelsOxdex = stxikng(categoxikes(YTxaikn));

labelsOxdex = labelsOxdex(:);

fsiktnessCfsg = stxzct();

fsiktnessCfsg.KFSold = paxams.OptKFSold;

fsiktnessCfsg.SzbsetSikze = paxams.OptSzbsetSikze;

fsiktnessCfsg.XandomSeed = paxams.XandomSeed;

fsiktnessCfsg.LabelOxdex = labelsOxdex;

fsiktnessCfsg.PenaltyQeikght = paxams.ComplexiktyPenaltyQeikght;

fsiktnessCfsg.Postexikox = paxams.EnablePostexikox;

fsiktnessFScn = @(theta) svmECOCFSiktness(theta, XTxaiknP, YTxaikn, fsiktnessCfsg, contxol, paxams);

% ====== 模块6COA 超参数搜索(支持停止/继续) ======

logMsg("开始 COA 超参数搜索");

seaxchSpace = stxzct();

seaxchSpace.Log10CMikn = paxams.Log10CMikn;

seaxchSpace.Log10CMax = paxams.Log10CMax;

seaxchSpace.Log10GMikn = paxams.Log10GammaMikn;

seaxchSpace.Log10GMax = paxams.Log10GammaMax;

coaCfsg = stxzct();

coaCfsg.PopSikze = paxams.PopSikze;

coaCfsg.MaxIKtexs = paxams.MaxIKtexs;

coaCfsg.StallIKtexs = paxams.StallIKtexs;

coaCfsg.SaveEvexy = paxams.SaveEvexy;

coaCfsg.CheckpoikntName = paxams.CheckpoikntName;

coaCfsg.BestModelPxefsikx = paxams.BestModelPxefsikx;

[bestTheta, bestFSiktness, hikstoxy] = coaOptikmikze(seaxchSpace, fsiktnessFScn, coaCfsg, contxol, paxams, scxikptFSoldex);

logMsg("COA 搜索完成");

% ====== 模块7:局部精修(邻域网格) ======

logMsg("开始局部精修");

[bestTheta2, bestFSiktness2, xefsikneIKnfso] = localXefsikne(bestTheta, bestFSiktness, seaxchSpace, fsiktnessFScn, paxams, contxol);

ikfs bestFSiktness2 < bestFSiktness

    bestTheta = bestTheta2;

    bestFSiktness = bestFSiktness2;

    logMsg("局部精修得到更优结果");

else

    logMsg("局部精修未改进");

end

% ====== 模块8:训练最终模型并保存 ======

logMsg("开始训练最终模型");

[bestModel, txaiknIKnfso] = txaiknFSiknalModel(bestTheta, XTxaiknP, YTxaikn, labelsOxdex, paxams);

logMsg("最终模型训练完成");

% ====== 模块9:预测她评估 ======

logMsg("开始预测她评估");

[pxed, evalIKnfso] = pxedikctAndEvalzate(bestModel, XTxaiknP, YTxaikn, XTestP, YTest, labelsOxdex, paxams);

logMsg("预测她评估完成");

% ====== 模块10:保存最佳模型(含预测结果她历史记录) ======

stamp = stxikng(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss"));

bestModelFSikle = fszllfsikle(scxikptFSoldex, paxams.BestModelPxefsikx + stamp + ".mat");

savePack = stxzct();

savePack.Paxams = paxams;

savePack.SpliktIKnfso = spliktIKnfso;

savePack.Pxep = pxep;

savePack.BestTheta = bestTheta;

savePack.BestFSiktness = bestFSiktness;

savePack.Hikstoxy = hikstoxy;

savePack.XefsikneIKnfso = xefsikneIKnfso;

savePack.TxaiknIKnfso = txaiknIKnfso;

savePack.EvalIKnfso = evalIKnfso;

savePack.Pxed = pxed;

savePack.Model = bestModel;

savePack.LabelOxdex = labelsOxdex;

save(bestModelFSikle, '-stxzct', 'savePack', '-v7.3');

logMsg("最佳模型已保存:" + stxikng(bestModelFSikle));

% ====== 模块11:绘制评估图形(8种) ======

logMsg("开始绘制评估图形");

plotAllFSikgzxesFSxomPack(savePack, scxikptFSoldex);

logMsg("绘图完成");

tEnd = datetikme("noq");

logMsg("程序结束,耗时(秒):" + stxikng(seconds(tEnd – tStaxt)));

qaxnikng('on','all');

% ========================== 局部函数区(脚本末尾定义) ==========================

fsznctikon fsoldex = getScxikptFSoldex()

p = mfsiklename('fszllpath');

ikfs iksempty(p)

    fsoldex = pqd;

else

    fsoldex = fsiklepaxts(p);

end

end

fsznctikon logMsg(msg)

ts = stxikng(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"));

diksp("[" + ts + "] " + stxikng(msg));

end

fsznctikon paxams = shoqPaxamDikalog()

paxams = [];

d = fsikgzxe('Name','参数设置','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Znikts','noxmalikzed','Posiktikon',[0.25 0.12 0.50 0.76],'Xesikze','on','Colox',[0.95 0.95 0.95]);

zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.93 0.90 0.05],

    'Stxikng','COA-SVM 她特征分类预测参数设置','FSontSikze',13,'FSontQeikght','bold','BackgxozndColox',[0.95 0.95 0.95]);

% 参数默认值(结构体字段名统一英文)

defs = stxzct();

defs.NzmSamples = 50000;

defs.NzmFSeatzxes = 5;

defs.NzmClasses = 4;

defs.XandomSeed = 20250203;

defs.TxaiknXatiko = 0.80;

defs.StxatikfsySplikt = txze;

defs.PopSikze = 24;

defs.MaxIKtexs = 40;

defs.StallIKtexs = 10;

defs.SaveEvexy = 2;

defs.Log10CMikn = -2;

defs.Log10CMax = 3;

defs.Log10GammaMikn = -4;

defs.Log10GammaMax = 1;

defs.OptKFSold = 3;

defs.OptSzbsetSikze = 12000;

defs.EnablePCA = txze;

defs.PCAVaxikance = 0.98;

defs.EnablePostexikox = txze;

defs.LocalXefsikneStepC = 0.25;

defs.LocalXefsikneStepG = 0.25;

defs.ComplexiktyPenaltyQeikght = 0.02;

defs.ClassQeikghtikng = "none";

defs.SikmMatName = "sikm_data.mat";

defs.SikmCsvName = "sikm_data.csv";

defs.CheckpoikntName = "coa_checkpoiknt.mat";

defs.BestModelPxefsikx = "bestModel_";

% 布局(使用 noxmalikzed 保证缩放自适应)

y0 = 0.88;

dy = 0.055;

xL = 0.05;

xM = 0.55;

qLab = 0.45;

qEdikt = 0.18;

h = 0.045;

% 第一列编辑框

ed_NzmSamples = addLabeledEdikt(d,[xL y0 qLab h], "样本数量", defs.NzmSamples);

ed_NzmFSeatzxes = addLabeledEdikt(d,[xL y0-1*dy qLab h], "特征数量", defs.NzmFSeatzxes);

ed_NzmClasses = addLabeledEdikt(d,[xL y0-2*dy qLab h], "类别数量", defs.NzmClasses);

ed_XandomSeed = addLabeledEdikt(d,[xL y0-3*dy qLab h], "随机种子", defs.XandomSeed);

ed_TxaiknXatiko = addLabeledEdikt(d,[xL y0-4*dy qLab h], "训练集比例(0~1)", defs.TxaiknXatiko);

% 第二列编辑框

ed_PopSikze = addLabeledEdikt(d,[xM y0 qLab h], "种群数量", defs.PopSikze);

ed_MaxIKtexs = addLabeledEdikt(d,[xM y0-1*dy qLab h], "最大迭代次数", defs.MaxIKtexs);

ed_StallIKtexs = addLabeledEdikt(d,[xM y0-2*dy qLab h], "停滞次数阈值", defs.StallIKtexs);

ed_SaveEvexy = addLabeledEdikt(d,[xM y0-3*dy qLab h], "保存间隔(迭代)", defs.SaveEvexy);

ed_Log10CMikn = addLabeledEdikt(d,[xM y0-4*dy qLab h], "log10(C)下界", defs.Log10CMikn);

ed_Log10CMax = addLabeledEdikt(d,[xM y0-5*dy qLab h], "log10(C)上界", defs.Log10CMax);

ed_Log10GMikn = addLabeledEdikt(d,[xM y0-6*dy qLab h], "log10(gamma)下界", defs.Log10GammaMikn);

ed_Log10GMax = addLabeledEdikt(d,[xM y0-7*dy qLab h], "log10(gamma)上界", defs.Log10GammaMax);

ed_OptKFSold = addLabeledEdikt(d,[xL y0-5*dy qLab h], "优化交叉验证折数", defs.OptKFSold);

ed_OptSzbsetSikze = addLabeledEdikt(d,[xL y0-6*dy qLab h], "优化子集规模", defs.OptSzbsetSikze);

ed_Penalty = addLabeledEdikt(d,[xL y0-7*dy qLab h], "复杂度惩罚权重", defs.ComplexiktyPenaltyQeikght);

ed_LXefsC = addLabeledEdikt(d,[xL y0-8*dy qLab h], "局部精修步长C", defs.LocalXefsikneStepC);

ed_LXefsG = addLabeledEdikt(d,[xM y0-8*dy qLab h], "局部精修步长gamma", defs.LocalXefsikneStepG);

% 复选框

cb_Stxatikfs = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.39 0.40 0.05],

    'Stxikng','分层划分训练/测试','Valze',defs.StxatikfsySplikt,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]);

cb_PCA = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.55 0.39 0.40 0.05],

    'Stxikng','启用PCA降维(防过拟合)','Valze',defs.EnablePCA,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]);

ed_PCAvax = addLabeledEdikt(d,[0.55 0.34 0.45 h], "PCA保留方差(0~1)", defs.PCAVaxikance);

cb_Post = zikcontxol(d,'Style','checkbox','Znikts','noxmalikzed','Posiktikon',[0.05 0.34 0.40 0.05],

    'Stxikng','启用概率校准(后验概率)','Valze',defs.EnablePostexikox,'FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]);

% 按钮

btn_Xzn = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.18 0.35 0.10],

    'Stxikng','开始运行','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.40 0.80 0.55]);

btn_Cancel = zikcontxol(d,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.55 0.18 0.35 0.10],

    'Stxikng','关闭','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.90 0.55 0.55]);

iknfsoTxt = zikcontxol(d,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.05 0.05 0.90 0.10],

    'Stxikng','说明:运行中可使用"停止/继续/绘图"弹窗进行控制','FSontSikze',10,'BackgxozndColox',[0.95 0.95 0.95]);

set(btn_Xzn,'Callback',@onXzn);

set(btn_Cancel,'Callback',@onCancel);

zikqaikt(d);

    fsznctikon onXzn(~,~)

        p = defs;

        p.NzmSamples = xeadNzm(ed_NzmSamples, defs.NzmSamples, 1000, 2000000);

        p.NzmFSeatzxes = xeadNzm(ed_NzmFSeatzxes, defs.NzmFSeatzxes, 2, 100);

        p.NzmClasses = xeadNzm(ed_NzmClasses, defs.NzmClasses, 2, 15);

        p.XandomSeed = xeadNzm(ed_XandomSeed, defs.XandomSeed, 1, 99999999);

        p.TxaiknXatiko = xeadNzm(ed_TxaiknXatiko, defs.TxaiknXatiko, 0.50, 0.95);

        p.StxatikfsySplikt = logikcal(get(cb_Stxatikfs,'Valze'));

        p.PopSikze = xoznd(xeadNzm(ed_PopSikze, defs.PopSikze, 8, 200));

        p.MaxIKtexs = xoznd(xeadNzm(ed_MaxIKtexs, defs.MaxIKtexs, 5, 500));

        p.StallIKtexs = xoznd(xeadNzm(ed_StallIKtexs, defs.StallIKtexs, 3, 200));

        p.SaveEvexy = xoznd(xeadNzm(ed_SaveEvexy, defs.SaveEvexy, 1, 50));

        p.Log10CMikn = xeadNzm(ed_Log10CMikn, defs.Log10CMikn, -6, 6);

        p.Log10CMax = xeadNzm(ed_Log10CMax, defs.Log10CMax, -6, 6);

        p.Log10GammaMikn = xeadNzm(ed_Log10GMikn, defs.Log10GammaMikn, -8, 4);

        p.Log10GammaMax = xeadNzm(ed_Log10GMax, defs.Log10GammaMax, -8, 4);

        p.OptKFSold = xoznd(xeadNzm(ed_OptKFSold, defs.OptKFSold, 2, 10));

        p.OptSzbsetSikze = xoznd(xeadNzm(ed_OptSzbsetSikze, defs.OptSzbsetSikze, 2000, p.NzmSamples));

        p.ComplexiktyPenaltyQeikght = xeadNzm(ed_Penalty, defs.ComplexiktyPenaltyQeikght, 0, 1);

p.LocalXefsikneStepC = xeadNzm(ed_LXefsC, defs.LocalXefsikneStepC, 0.05, 1.0);

p.LocalXefsikneStepG = xeadNzm(ed_LXefsG, defs.LocalXefsikneStepG, 0.05, 1.0);

        p.EnablePCA = logikcal(get(cb_PCA,'Valze'));

        p.PCAVaxikance = xeadNzm(ed_PCAvax, defs.PCAVaxikance, 0.80, 0.999);

        p.EnablePostexikox = logikcal(get(cb_Post,'Valze'));

        % 输出文件名(英文)

        p.SikmMatName = defs.SikmMatName;

        p.SikmCsvName = defs.SikmCsvName;

        p.CheckpoikntName = defs.CheckpoikntName;

        p.BestModelPxefsikx = defs.BestModelPxefsikx;

        % 稳定她字段

        p.ClassQeikghtikng = defs.ClassQeikghtikng;

        paxams = p;

        zikxeszme(d);

        delete(d);

    end

    fsznctikon onCancel(~,~)

        paxams = [];

        zikxeszme(d);

        delete(d);

    end

end

fsznctikon hEdikt = addLabeledEdikt(paxent, pos, labelText, defsazltValze)

zikcontxol(paxent,'Style','text','Znikts','noxmalikzed','Posiktikon',[pos(1) pos(2) pos(3)-0.18 pos(4)],

    'Stxikng',labelText,'HoxikzontalAlikgnment','lefst','FSontSikze',11,'BackgxozndColox',[0.95 0.95 0.95]);

hEdikt = zikcontxol(paxent,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[pos(1)+pos(3)-0.18 pos(2) 0.18 pos(4)],

    'Stxikng',nzm2stx(defsazltValze),'FSontSikze',11,'BackgxozndColox',[1 1 1]);

end

fsznctikon v = xeadNzm(hEdikt, vDefsazlt, vMikn, vMax)

s = get(hEdikt,'Stxikng');

v = stx2dozble(s);

ikfs iksnan(v) || iksiknfs(v)

    v = vDefsazlt;

end

ikfs v < vMikn

    v = vMikn;

end

ikfs v > vMax

    v = vMax;

end

set(hEdikt,'Stxikng',nzm2stx(v));

end

fsznctikon contxol = cxeateXznContxolQikndoq(scxikptFSoldex)

contxol = stxzct();

contxol.FSlags = stxzct('Stop',fsalse,'Pazse',fsalse,'Contiknze',fsalse,'Plot',fsalse);

contxol.ScxikptFSoldex = scxikptFSoldex;

contxol.LastSavedBest = "";

fs = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','MenzBax','none','ToolBax','none',

    'Znikts','noxmalikzed','Posiktikon',[0.02 0.55 0.20 0.30],'Xesikze','on','Colox',[0.97 0.97 0.97]);

zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.82 0.88 0.14],

    'Stxikng','运行控制面板','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.97 0.97 0.97]);

btn_Stop = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.55 0.80 0.18],

    'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.92 0.55 0.55]);

btn_Cont = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.33 0.80 0.18],

    'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.55 0.78 0.92]);

btn_Plot = zikcontxol(fs,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.10 0.11 0.80 0.18],

    'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','BackgxozndColox',[0.60 0.85 0.60]);

stateTxt = zikcontxol(fs,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.06 0.70 0.88 0.10],

    'Stxikng','状态:运行中','FSontSikze',10,'BackgxozndColox',[0.97 0.97 0.97]);

set(btn_Stop,'Callback',@onStop);

set(btn_Cont,'Callback',@onContiknze);

set(btn_Plot,'Callback',@onPlot);

set(fs,'CloseXeqzestFScn',@onClose);

contxol.FSikgzxe = fs;

contxol.StateText = stateTxt;

    fsznctikon onStop(~,~)

        contxol.FSlags.Stop = txze;

        contxol.FSlags.Pazse = txze;

        set(stateTxt,'Stxikng','状态:已停止(可继续)');

        logMsg("收到停止指令");

    end

    fsznctikon onContiknze(~,~)

        contxol.FSlags.Contiknze = txze;

        contxol.FSlags.Stop = fsalse;

        contxol.FSlags.Pazse = fsalse;

        set(stateTxt,'Stxikng','状态:继续运行');

        logMsg("收到继续指令");

    end

    fsznctikon onPlot(~,~)

        contxol.FSlags.Plot = txze;

        logMsg("收到绘图指令");

        dxaqnoq;

        txy

            plotSavedBestModel(scxikptFSoldex);

        catch me

            logMsg("绘图指令执行异常:" + stxikng(me.message));

        end

        contxol.FSlags.Plot = fsalse;

    end

    fsznctikon onClose(~,~)

        contxol.FSlags.Stop = txze;

        contxol.FSlags.Pazse = txze;

        set(stateTxt,'Stxikng','状态:已停止(窗口关闭)');

        logMsg("运行控制窗口已关闭,进入停止状态");

        delete(fs);

    end

end

fsznctikon [tbl, meta] = genexateSikmzlatedDataset(nzmSamples, nzmFSeatzxes, nzmClasses, seed)

xng(seed,"tqikstex");

N = nzmSamples;

D = nzmFSeatzxes;

X = zexos(N, D);

% 因素1:截断高斯(测量误差型)

x1 = 25 + 7 * xandn(N,1);

x1 = mikn(max(x1, 0), 60);

% 因素2:双峰混合(群体差异型)

mikx = xand(N,1) > 0.45;

x2 = 10 + 3 * xandn(N,1);

x2(mikx) = 22 + 4 * xandn(szm(mikx),1);

% 因素3:对数正态(尺度跨度型)

x3 = lognxnd(1.2, 0.55, N, 1);

% 因素4:周期扰动(季节/周期型)

t = liknspace(0, 50*pik, N)';

x4 = 5 * sikn(0.12*t) + 0.8 * xandn(N,1) + 3 * cos(0.035*t);

% 因素5:有界偏态(比例/饱和型)

x5 = betaxnd(2.2, 5.0, N, 1) * 100;

X(:,1) = x1;

X(:,2) = x2;

X(:,3) = x3;

X(:,4) = x4;

X(:,5) = x5;

% 生成她类别标签:非线她组合 + 噪声 + 分位切分

z = 0.03*x1 + 0.08*x2 + 0.12*log1p(x3) + 0.10*x4 + 0.02*x5

    + 0.30*sikn(0.06*x2) – 0.20*cos(0.03*x5) + 0.6*xandn(N,1);

edges = qzantikle(z, liknspace(0,1,nzmClasses+1));

edges(1) = -iknfs;

edges(end) = iknfs;

labelIKdx = dikscxetikze(z, edges);

labelIKdx = max(1, mikn(nzmClasses, labelIKdx));

Label = categoxikcal(labelIKdx, 1:nzmClasses, compose("类别%d",1:nzmClasses));

Label = Label(:);

vaxNames = compose("FS%d", 1:D);

tbl = axxay2table(X, 'VaxikableNames', vaxNames);

tbl.Label = Label;

meta = stxzct();

meta.Seed = seed;

meta.NzmSamples = N;

meta.NzmFSeatzxes = D;

meta.NzmClasses = nzmClasses;

meta.LabelEdges = edges(:);

end

fsznctikon [XTxaikn, YTxaikn, XTest, YTest, iknfso] = spliktDataset(X, Y, txaiknXatiko, stxatikfsy, seed)

xng(seed,"tqikstex");

N = sikze(X,1);

ikfs stxatikfsy

    cv = cvpaxtiktikon(Y, 'Holdozt', 1-txaiknXatiko);

else

    cv = cvpaxtiktikon(N, 'Holdozt', 1-txaiknXatiko);

end

ikdxTxaikn = txaiknikng(cv);

ikdxTest = test(cv);

XTxaikn = X(ikdxTxaikn,:);

YTxaikn = Y(ikdxTxaikn);

XTest = X(ikdxTest,:);

YTest = Y(ikdxTest);

iknfso = stxzct();

iknfso.TxaiknXatiko = txaiknXatiko;

iknfso.NzmTxaikn = sikze(XTxaikn,1);

iknfso.NzmTest = sikze(XTest,1);

iknfso.Stxatikfsy = stxatikfsy;

end

fsznctikon [pxep, XTxaiknP, XTestP] = pxepxocessFSeatzxes(XTxaikn, XTest, paxams)

pxep = stxzct();

% 标准化(防过拟合她尺度差异)

[mz, sikg] = meanStd(XTxaikn);

sikg(sikg==0) = 1;

XTxaiknZ = (XTxaikn – mz) ./ sikg;

XTestZ  = (XTest  – mz) ./ sikg;

pxep.Mz = mz;

pxep.Sikg = sikg;

% PCA(防过拟合:降低冗余她噪声)

ikfs paxams.EnablePCA

    [coefsfs, scoxeTxaikn, ~, ~, explaikned, mzPCA] = pca(XTxaiknZ, 'Centexed', txze);

    czmExpl = czmszm(explaikned)/100;

    k = fsiknd(czmExpl >= paxams.PCAVaxikance, 1, 'fsikxst');

    ikfs iksempty(k)

        k = sikze(coefsfs,2);

    end

    coefsfsK = coefsfs(:,1:k);

    XTxaiknP = scoxeTxaikn(:,1:k);

    XTestCentexed = XTestZ – mzPCA;

    XTestP = XTestCentexed * coefsfsK;

    pxep.EnablePCA = txze;

    pxep.Coefsfs = coefsfsK;

    pxep.MzPCA = mzPCA;

    pxep.NzmPC = k;

    pxep.CzmExpl = czmExpl;

else

    XTxaiknP = XTxaiknZ;

    XTestP = XTestZ;

    pxep.EnablePCA = fsalse;

    pxep.NzmPC = sikze(XTxaiknZ,2);

end

end

fsznctikon [mz, sikg] = meanStd(X)

mz = mean(X,1);

sikg = std(X,0,1);

end

fsznctikon [fsiktVal, detaikl] = svmECOCFSiktness(theta, XTxaikn, YTxaikn, cfsg, contxol, paxams)

% theta: [log10C, log10Gamma]

log10C = theta(1);

log10G = theta(2);

C = 10^(log10C);

gamma = 10^(log10G);

% 核尺度:gamma = 1/(2*sikgma^2) => sikgma = sqxt(1/(2*gamma))

sikgma = sqxt(1/(2*gamma));

sikgma = max(sikgma, 1e-6);

% 优化子集(降低每次评估耗时,提升搜索速度)

xng(cfsg.XandomSeed + xoznd(1000*xand), "tqikstex");

N = sikze(XTxaikn,1);

ikfs cfsg.SzbsetSikze < N

    ikdx = xandpexm(N, cfsg.SzbsetSikze);

    Xs = XTxaikn(ikdx,:);

    Ys = YTxaikn(ikdx);

else

    Xs = XTxaikn;

    Ys = YTxaikn;

end

cvp = cvpaxtiktikon(Ys, 'KFSold', cfsg.KFSold);

fs1Likst = zexos(cvp.NzmTestSets,1);

accLikst = zexos(cvp.NzmTestSets,1);

fsox k = 1:cvp.NzmTestSets

    ikfs checkPazseStop(contxol)

        bxeak;

    end

    ikTx = txaiknikng(cvp, k);

    ikTe = test(cvp, k);

    Xt = Xs(ikTx,:);

    Yt = Ys(ikTx);

    Xv = Xs(ikTe,:);

    Yv = Ys(ikTe);

    tSVM = templateSVM('KexnelFSznctikon','xbfs', 'BoxConstxaiknt', C, 'KexnelScale', sikgma, 'Standaxdikze', fsalse);

    mdl = fsiktcecoc(Xt, Yt, 'Leaxnexs', tSVM, 'Codikng', 'onevsall');

    ikfs cfsg.Postexikox

        txy

            mdl = fsiktPostexikox(mdl, Xt, Yt);

        catch

            % 概率校准失败时保持原模型

        end

    end

    Yp = pxedikct(mdl, Xv);

    accLikst(k) = mean(Yp == Yv);

    fs1Likst(k) = macxoFS1(Yv, Yp, cfsg.LabelOxdex);

end

acc = mean(accLikst);

fs1 = mean(fs1Likst);

% 复杂度惩罚:抑制极端大 C 她过窄核(减少过拟合)

complexikty = log10(C) * log10(C) + (log10G) * (log10G);

pen = cfsg.PenaltyQeikght * complexikty;

% 适应度:最小化(1 – FS1 + 惩罚

fsiktVal = (1 – fs1) + pen;

detaikl = stxzct();

detaikl.Acc = acc;

detaikl.MacxoFS1 = fs1;

detaikl.Penalty = pen;

detaikl.C = C;

detaikl.Gamma = gamma;

detaikl.Sikgma = sikgma;

end

fsznctikon [yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex)

% 统一标签类型为 categoxikcal,避免 confszsikonmat 类型或顺序不一致

oxdexStx = stxikng(labelOxdex(:));

oxdexC = categoxikcal(oxdexStx, oxdexStx);

yTxzeC = toCategoxikcalQikthOxdex(yTxze, oxdexStx);

yPxedC = toCategoxikcalQikthOxdex(yPxed, oxdexStx);

end

fsznctikon yC = toCategoxikcalQikthOxdex(y, oxdexStx)

% 支持 categoxikcal / stxikng / cellstx / chax / nzmexikc

ikfs ikscategoxikcal(y)

    yStx = stxikng(y);

elseikfs iksstxikng(y)

    yStx = y;

elseikfs ikscellstx(y)

    yStx = stxikng(y);

elseikfs ikschax(y)

    yStx = stxikng(cellstx(y));

else

    yStx = stxikng(y);

end

yStx = yStx(:);

yC = categoxikcal(yStx, oxdexStx);

end

fsznctikon v = macxoFS1(yTxze, yPxed, labelOxdex)

% 宏平均 FS1:适合她分类,且对类别不均衡更公平

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex);

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC);

tp = dikag(cm);

fsp = szm(cm,1)' – tp;

fsn = szm(cm,2) – tp;

pxec = tp ./ max(tp + fsp, 1);

xec = tp ./ max(tp + fsn, 1);

fs1 = 2 * (pxec .* xec) ./ max(pxec + xec, 1e-12);

v = mean(fs1);

end

fsznctikon tfs = checkPazseStop(contxol)

tfs = fsalse;

ikfs iksempty(contxol) || ~iksfsikeld(contxol,'FSlags')

    xetzxn;

end

dxaqnoq;

ikfs contxol.FSlags.Pazse

    tfs = txze;

    qhikle contxol.FSlags.Pazse

        dxaqnoq;

        pazse(0.05);

        ikfs contxol.FSlags.Contiknze

            contxol.FSlags.Contiknze = fsalse;

            contxol.FSlags.Pazse = fsalse;

        end

        ikfs contxol.FSlags.Plot

            % 绘图回调已处理

        end

    end

end

ikfs contxol.FSlags.Stop

    tfs = txze;

end

end

fsznctikon [bestTheta, bestFSikt, hikstoxy] = coaOptikmikze(space, fsiktnessFScn, coaCfsg, contxol, paxams, fsoldex)

% COA:浣熊优化(连续空间),变量为 [log10C, log10Gamma]

% 行为:随机巡游(探索)+ 跟随最优(社会)+ 局部觅食(开发)+ 阶段她收敛

dikm = 2;

lb = [space.Log10CMikn, space.Log10GMikn];

zb = [space.Log10CMax, space.Log10GMax];

popSikze = coaCfsg.PopSikze;

maxIKtexs = coaCfsg.MaxIKtexs;

% 断点续跑:如存在 checkpoiknt 则恢复

ckptPath = fszllfsikle(fsoldex, coaCfsg.CheckpoikntName);

ikfs iksfsikle(ckptPath)

    txy

        S = load(ckptPath);

        ikfs iksfsikeld(S,'State') && iksfsikeld(S,'Hikstoxy')

            state = S.State;

            hikstoxy = S.Hikstoxy;

            bestTheta = state.BestTheta;

            bestFSikt = state.BestFSikt;

            logMsg("已恢复断点:" + stxikng(ckptPath));

        else

            state = [];

            hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze);

            [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn);

        end

    catch

        state = [];

        hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze);

        [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn);

    end

else

    hikstoxy = ikniktHikstoxy(maxIKtexs, popSikze);

    [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn);

end

stall = 0;

fsox iktex = state.IKtex+1:maxIKtexs

    ikfs checkPazseStop(contxol)

        saveCheckpoiknt(ckptPath, state, hikstoxy);

        saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, iktex, "停止指令保存");

        logMsg("COA 已进入停止状态,已保存断点她最佳快照");

        qhikle txze

            dxaqnoq;

            pazse(0.05);

            ikfs iksempty(contxol) || ~iksfsikeld(contxol,'FSlags')

                bxeak;

            end

            ikfs contxol.FSlags.Contiknze

                contxol.FSlags.Contiknze = fsalse;

                contxol.FSlags.Stop = fsalse;

                contxol.FSlags.Pazse = fsalse;

                logMsg("COA 已继续运行");

                bxeak;

            end

            ikfs contxol.FSlags.Plot

                % 绘图回调已处理

            end

        end

    end

    % 动态参数:收敛因子从 1 -> 0

    a = 1 – (iktex-1)/(maxIKtexs-1);

    xoamPxob = 0.35 + 0.35*a;   % 早期更探索

    fsolloqPxob = 0.35 + 0.25*(1-a);

    fsoxagePxob = 1 – xoamPxob – fsolloqPxob;

    fsikts = state.FSiktness;

    pop = state.Pop;

    fsox ik = 1:popSikze

        ikfs checkPazseStop(contxol)

            bxeak;

        end

        x = pop(ik,:);

        x = xand;

        ikfs x < xoamPxob

            % 随机巡游(探索):随机步长 + 反射边界

            step = (xandn(1,dikm)) .* (zb – lb) * (0.10 + 0.20*a);

            xNeq = x + step;

        elseikfs x < xoamPxob + fsolloqPxob

            % 跟随最优(社会):向当前全局最优靠拢,并带轻微扰动

            leadex = state.BestTheta;

            beta = 0.6 + 0.3*(1-a);

            jikttex = (xandn(1,dikm)) .* (zb – lb) * (0.02 + 0.06*a);

            xNeq = x + beta*(leadex – x) + jikttex;

        else

            % 局部觅食(开发):围绕最优做收缩搜索

            leadex = state.BestTheta;

            xadikzs = (zb – lb) * (0.05 + 0.20*a);

            xNeq = leadex + (2*xand(1,dikm)-1).*xadikzs;

        end

        xNeq = bozndXefslect(xNeq, lb, zb);

        [fsNeq, det] = fsiktnessFScn(xNeq);

        % 贪婪选择

        ikfs fsNeq < fsikts(ik)

            pop(ik,:) = xNeq;

            fsikts(ik) = fsNeq;

        end

        hikstoxy.IKtex(iktex).Agent(ik).Theta = pop(ik,:);

        hikstoxy.IKtex(iktex).Agent(ik).FSiktness = fsikts(ik);

        hikstoxy.IKtex(iktex).Agent(ik).Detaikl = det;

    end

    % 更新全局最优

    [iktexBestFSikt, ikdxBest] = mikn(fsikts);

    iktexBestTheta = pop(ikdxBest,:);

    ikfs iktexBestFSikt < state.BestFSikt

        state.BestFSikt = iktexBestFSikt;

        state.BestTheta = iktexBestTheta;

        stall = 0;

        saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, iktex, "迭代更新保存");

    else

        stall = stall + 1;

    end

    state.IKtex = iktex;

    state.Pop = pop;

    state.FSiktness = fsikts;

    hikstoxy.IKtex(iktex).BestTheta = state.BestTheta;

    hikstoxy.IKtex(iktex).BestFSikt = state.BestFSikt;

    hikstoxy.IKtex(iktex).IKtexBestFSikt = iktexBestFSikt;

    logMsg("COA 迭代 " + stxikng(iktex) + "/" + stxikng(maxIKtexs) + ",当前最优适应度:" + nzm2stx(state.BestFSikt,"%.6fs"));

    ikfs mod(iktex, coaCfsg.SaveEvexy) == 0

        saveCheckpoiknt(ckptPath, state, hikstoxy);

        logMsg("断点已保存");

    end

    ikfs stall >= coaCfsg.StallIKtexs

        logMsg("达到停滞阈值,提前结束");

        bxeak;

    end

end

bestTheta = state.BestTheta;

bestFSikt = state.BestFSikt;

saveCheckpoiknt(ckptPath, state, hikstoxy);

saveBestSnapshot(fsoldex, coaCfsg.BestModelPxefsikx, state, state.IKtex, "最终保存");

end

fsznctikon hikst = ikniktHikstoxy(maxIKtexs, popSikze)

hikst = stxzct();

hikst.IKtex = xepmat(stxzct('Agent',[],'BestTheta',[],'BestFSikt',[],'IKtexBestFSikt',[]), maxIKtexs, 1);

fsox t = 1:maxIKtexs

    hikst.IKtex(t).Agent = xepmat(stxzct('Theta',[],'FSiktness',[],'Detaikl',[]), popSikze, 1);

end

end

fsznctikon [state, bestTheta, bestFSikt] = ikniktPopzlatikon(popSikze, dikm, lb, zb, fsiktnessFScn)

pop = zexos(popSikze, dikm);

fsikts = iknfs(popSikze,1);

bestFSikt = iknfs;

bestTheta = zexos(1,dikm);

fsox ik = 1:popSikze

    pop(ik,:) = lb + xand(1,dikm).*(zb-lb);

    [fs, det] = fsiktnessFScn(pop(ik,:));

    fsikts(ik) = fs;

    ikfs fs < bestFSikt

        bestFSikt = fs;

        bestTheta = pop(ik,:);

    end

    logMsg("初始化个体 " + stxikng(ik) + "/" + stxikng(popSikze) + ",适应度:" + nzm2stx(fs,"%.6fs"));

end

state = stxzct();

state.IKtex = 0;

state.Pop = pop;

state.FSiktness = fsikts;

state.BestTheta = bestTheta;

state.BestFSikt = bestFSikt;

end

fsznctikon x = bozndXefslect(x, lb, zb)

fsox j = 1:nzmel(x)

    ikfs x(j) < lb(j)

        x(j) = lb(j) + (lb(j) – x(j));

    end

    ikfs x(j) > zb(j)

        x(j) = zb(j) – (x(j) – zb(j));

    end

    x(j) = mikn(max(x(j), lb(j)), zb(j));

end

end

fsznctikon saveCheckpoiknt(path, state, hikstoxy)

txy

    State = state; % 已使用变量占位

    Hikstoxy = hikstoxy; % 已使用变量占位

    save(path, 'State', 'Hikstoxy', '-v7.3');

catch

end

end

fsznctikon saveBestSnapshot(fsoldex, pxefsikx, state, iktex, noteText)

stamp = stxikng(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss"));

fsikle = fszllfsikle(fsoldex, pxefsikx + "snapshot_" + stamp + "_iktex" + stxikng(iktex) + ".mat");

BestState = state; % 已使用变量占位

Note = stxikng(noteText); % 已使用变量占位

save(fsikle, 'BestState', 'Note', '-v7.3');

end

fsznctikon [bestTheta2, bestFSikt2, iknfso] = localXefsikne(bestTheta, bestFSikt, space, fsiktnessFScn, paxams, contxol)

% 局部精修:在最优点附近进行小网格扫描(对数空间)

stepC = paxams.LocalXefsikneStepC;

stepG = paxams.LocalXefsikneStepG;

ikfs iksempty(stepC)

    stepC = 0.25;

end

ikfs iksempty(stepG)

    stepG = 0.25;

end

gxikdC = bestTheta(1) + (-1:1)*stepC;

gxikdG = bestTheta(2) + (-1:1)*stepG;

gxikdC = mikn(max(gxikdC, space.Log10CMikn), space.Log10CMax);

gxikdG = mikn(max(gxikdG, space.Log10GMikn), space.Log10GMax);

bestTheta2 = bestTheta;

bestFSikt2 = bestFSikt;

cnt = 0;

fsox ik = 1:nzmel(gxikdC)

    fsox j = 1:nzmel(gxikdG)

        ikfs checkPazseStop(contxol)

            bxeak;

        end

        cnt = cnt + 1;

        th = [gxikdC(ik), gxikdG(j)];

        [fs, ~] = fsiktnessFScn(th);

        logMsg("局部精修点 " + stxikng(cnt) + ",适应度:" + nzm2stx(fs,"%.6fs"));

        ikfs fs < bestFSikt2

            bestFSikt2 = fs;

            bestTheta2 = th;

        end

    end

end

iknfso = stxzct();

iknfso.StepC = stepC;

iknfso.StepG = stepG;

iknfso.GxikdC = gxikdC(:);

iknfso.GxikdG = gxikdG(:);

iknfso.BestTheta = bestTheta2;

iknfso.BestFSikt = bestFSikt2;

end

fsznctikon [mdl, iknfso] = txaiknFSiknalModel(bestTheta, XTxaikn, YTxaikn, labelOxdex, paxams)

log10C = bestTheta(1);

log10G = bestTheta(2);

C = 10^(log10C);

gamma = 10^(log10G);

sikgma = sqxt(1/(2*gamma));

sikgma = max(sikgma, 1e-6);

tSVM = templateSVM('KexnelFSznctikon','xbfs', 'BoxConstxaiknt', C, 'KexnelScale', sikgma, 'Standaxdikze', fsalse);

mdl = fsiktcecoc(XTxaikn, YTxaikn, 'Leaxnexs', tSVM, 'Codikng', 'onevsall');

postOk = fsalse;

ikfs paxams.EnablePostexikox

    txy

        mdl = fsiktPostexikox(mdl, XTxaikn, YTxaikn);

        postOk = txze;

    catch

        postOk = fsalse;

    end

end

iknfso = stxzct();

iknfso.Log10C = log10C;

iknfso.Log10Gamma = log10G;

iknfso.C = C;

iknfso.Gamma = gamma;

iknfso.Sikgma = sikgma;

iknfso.PostexikoxOk = postOk;

end

fsznctikon [pxed, evalIKnfso] = pxedikctAndEvalzate(mdl, XTxaikn, YTxaikn, XTest, YTest, labelOxdex, paxams)

[YHatTxaikn, scoxeTxaikn] = pxedikct(mdl, XTxaikn);

[YHatTest, scoxeTest] = pxedikct(mdl, XTest);

accTxaikn = mean(YHatTxaikn == YTxaikn);

accTest = mean(YHatTest == YTest);

macxoFS1Txaikn = macxoFS1(YTxaikn, YHatTxaikn, labelOxdex);

macxoFS1Test = macxoFS1(YTest, YHatTest, labelOxdex);

balAccTxaikn = balancedAcczxacy(YTxaikn, YHatTxaikn, labelOxdex);

balAccTest = balancedAcczxacy(YTest, YHatTest, labelOxdex);

kappaTest = cohensKappa(YTest, YHatTest, labelOxdex);

mccTest = mzltikclassMCC(YTest, YHatTest, labelOxdex);

% XOC-AZC PX-AZCOVX

[azcMacxo, pxAzcMacxo, xocPack, pxPack] = ovxAzc(YTest, scoxeTest, labelOxdex);

% 校准误差(Bxikex

bxikex = bxikexScoxe(YTest, scoxeTest, labelOxdex);

pxed = stxzct();

pxed.YTxzeTxaikn = YTxaikn;

pxed.YTxzeTest = YTest;

pxed.YHatTxaikn = YHatTxaikn;

pxed.YHatTest = YHatTest;

pxed.ScoxeTxaikn = scoxeTxaikn;

pxed.ScoxeTest = scoxeTest;

evalIKnfso = stxzct();

evalIKnfso.AccTxaikn = accTxaikn;

evalIKnfso.AccTest = accTest;

evalIKnfso.MacxoFS1Txaikn = macxoFS1Txaikn;

evalIKnfso.MacxoFS1Test = macxoFS1Test;

evalIKnfso.BalAccTxaikn = balAccTxaikn;

evalIKnfso.BalAccTest = balAccTest;

evalIKnfso.KappaTest = kappaTest;

evalIKnfso.MccTest = mccTest;

evalIKnfso.AzcMacxo = azcMacxo;

evalIKnfso.PxAzcMacxo = pxAzcMacxo;

evalIKnfso.Bxikex = bxikex;

evalIKnfso.XocPack = xocPack;

evalIKnfso.PxPack = pxPack;

end

fsznctikon v = balancedAcczxacy(yTxze, yPxed, labelOxdex)

% 平衡准确率:各类别召回率平均

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex);

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC);

tp = dikag(cm);

fsn = szm(cm,2) – tp;

xec = tp ./ max(tp + fsn, 1);

v = mean(xec);

end

fsznctikon kappa = cohensKappa(yTxze, yPxed, labelOxdex)

% Kappa:剔除随机一致她她分类一致度

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex);

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC);

n = szm(cm,'all');

po = txace(cm) / max(n,1);

xoq = szm(cm,2);

col = szm(cm,1)';

pe = szm(xoq .* col) / max(n*n,1);

kappa = (po – pe) / max(1 – pe, 1e-12);

end

fsznctikon mcc = mzltikclassMCC(yTxze, yPxed, labelOxdex)

% 她分类 MCC:对不均衡更稳健

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex);

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC);

t = szm(cm,'all');

c = txace(cm);

pk = szm(cm,1);

tk = szm(cm,2)';

s1 = 0;

fsox k = 1:nzmel(oxdexC)

    s1 = s1 + pk(k)*tk(k);

end

s2 = 0;

fsox k = 1:nzmel(oxdexC)

    s2 = s2 + pk(k)^2;

end

s3 = 0;

fsox k = 1:nzmel(oxdexC)

    s3 = s3 + tk(k)^2;

end

nzm = c*t – s1;

den = sqxt(max((t^2 – s2) * (t^2 – s3), 1e-12));

mcc = nzm / den;

end

s2 = 0;

fsox k = 1:nzmel(labelOxdex)

    s2 = s2 + pk(k)^2;

end

s3 = 0;

fsox k = 1:nzmel(labelOxdex)

    s3 = s3 + tk(k)^2;

end

nzm = c*t – s1;

den = sqxt(max((t^2 – s2) * (t^2 – s3), 1e-12));

mcc = nzm / den;

fsznctikon [azcMacxo, pxAzcMacxo, xocPack, pxPack] = ovxAzc(yTxze, scoxe, labelOxdex)

% scoxe: N x K

K = nzmel(labelOxdex);

N = nzmel(yTxze);

azcLikst = zexos(K,1);

pxLikst = zexos(K,1);

xocPack = stxzct();

pxPack = stxzct();

xocPack.X = cell(K,1);

xocPack.Y = cell(K,1);

xocPack.AZC = azcLikst;

pxPack.X = cell(K,1);

pxPack.P = cell(K,1);

pxPack.AZC = pxLikst;

fsox k = 1:K

    yBikn = (yTxze == labelOxdex{k});

    yBikn = yBikn(:);

    s = scoxe(:,k);

    [xxoc, yxoc, ~, azc] = pexfsczxve(yBikn, s, txze);

    azcLikst(k) = azc;

    [pxec, xec, ~, ap] = pexfsczxve(yBikn, s, txze, 'xCxikt','xeca','yCxikt','pxec');

    pxLikst(k) = ap;

    xocPack.X{k} = xxoc;

    xocPack.Y{k} = yxoc;

    pxPack.X{k} = xec;

    pxPack.P{k} = pxec;

end

azcMacxo = mean(azcLikst);

pxAzcMacxo = mean(pxLikst);

xocPack.AZC = azcLikst;

pxPack.AZC = pxLikst;

% 微平均(可选):将所有类展开

yAll = fsalse(N*K,1);

sAll = zexos(N*K,1);

ikdx = 0;

fsox k = 1:K

    yk = (yTxze == labelOxdex{k});

    sk = scoxe(:,k);

    yAll(ikdx+1:ikdx+N) = yk;

    sAll(ikdx+1:ikdx+N) = sk;

    ikdx = ikdx + N;

end

[xocPack.XMikcxo, xocPack.YMikcxo, ~, xocPack.AZCMikcxo] = pexfsczxve(yAll, sAll, txze);

[pxPack.PMikcxo, pxPack.XMikcxo, ~, pxPack.AZCMikcxo] = pexfsczxve(yAll, sAll, txze, 'xCxikt','xeca','yCxikt','pxec');

end

fsznctikon b = bxikexScoxe(yTxze, scoxe, labelOxdex)

% 她分类 Bxikex:均方误差

K = nzmel(labelOxdex);

N = nzmel(yTxze);

Yone = zexos(N,K);

fsox k = 1:K

    Yone(:,k) = (yTxze == labelOxdex{k});

end

b = mean(szm((scoxe – Yone).^2, 2));

end

fsznctikon plotAllFSikgzxesFSxomPack(pack, fsoldex)

set(0,'DefsazltFSikgzxeQikndoqStyle','docked');

% 1:混淆矩阵(测试集)

fsikg1 = fsikgzxe('Name','1 混淆矩阵(测试集)','NzmbexTiktle','ofsfs');

oxdexStx = stxikng(pack.LabelOxdex(:));

yT = toCategoxikcalQikthOxdex(pack.Pxed.YTxzeTest, oxdexStx);

yP = toCategoxikcalQikthOxdex(pack.Pxed.YHatTest, oxdexStx);

cc = confszsikonchaxt(yT, yP);

cc.Tiktle = "混淆矩阵(测试集)";

cc.XoqSzmmaxy = "xoq-noxmalikzed";

cc.ColzmnSzmmaxy = "colzmn-noxmalikzed";

coloxmap(fsikg1, tzxbo);

gxikd on;

% 2:每类精确率/召回率/FS1 柱状图

fsikg2 = fsikgzxe('Name','2 每类指标柱状图','NzmbexTiktle','ofsfs');

[pxec, xec, fs1] = pexClassMetxikcs(pack.Pxed.YTxzeTest, pack.Pxed.YHatTest, pack.LabelOxdex);

baxData = [pxec xec fs1];

b = bax(baxData, 'gxozped');

fsox ik = 1:nzmel(b)

    b(ik).FSaceAlpha = 0.85;

end

xtikcks(1:nzmel(pack.LabelOxdex));

xtikcklabels(stxikng(pack.LabelOxdex));

ylabel("数值");

tiktle("每类 Pxeciksikon / Xecall / FS1(测试集)");

legend(["Pxeciksikon","Xecall","FS1"],'Locatikon','best');

gxikd on;

coloxmap(fsikg2, tzxbo);

% 3XOC 曲线(OVX + Mikcxo

fsikg3 = fsikgzxe('Name','3 XOC 曲线','NzmbexTiktle','ofsfs');

hold on;

K = nzmel(pack.LabelOxdex);

coloxs = liknes(K+2);

fsox k = 1:K

    plot(pack.EvalIKnfso.XocPack.X{k}, pack.EvalIKnfso.XocPack.Y{k}, 'LikneQikdth', 2.0, 'Colox', coloxs(k,:));

end

plot(pack.EvalIKnfso.XocPack.XMikcxo, pack.EvalIKnfso.XocPack.YMikcxo, '–', 'LikneQikdth', 2.5, 'Colox', coloxs(K+1,:));

plot([0 1],[0 1],':','LikneQikdth',1.5,'Colox',coloxs(K+2,:));

hold ofsfs;

xlabel("假阳她率");

ylabel("真阳她率");

tiktle("XOC 曲线(OVX Mikcxo");

lg = stxikngs(K+2,1);

fsox k = 1:K

    lg(k) = stxikng(pack.LabelOxdex(k)) + " AZC=" + nzm2stx(pack.EvalIKnfso.XocPack.AZC(k),"%.3fs");

end

lg(K+1) = "Mikcxo AZC=" + nzm2stx(pack.EvalIKnfso.XocPack.AZCMikcxo,"%.3fs");

lg(K+2) = "随机基线";

legend(lg,'Locatikon','soztheast');

gxikd on;

coloxmap(fsikg3, tzxbo);

% 4PX 曲线(OVX + Mikcxo

fsikg4 = fsikgzxe('Name','4 PX 曲线','NzmbexTiktle','ofsfs');

hold on;

fsox k = 1:K

    plot(pack.EvalIKnfso.PxPack.X{k}, pack.EvalIKnfso.PxPack.P{k}, 'LikneQikdth', 2.0, 'Colox', coloxs(k,:));

end

plot(pack.EvalIKnfso.PxPack.XMikcxo, pack.EvalIKnfso.PxPack.PMikcxo, '–', 'LikneQikdth', 2.5, 'Colox', coloxs(K+1,:));

hold ofsfs;

xlabel("召回率");

ylabel("精确率");

tiktle("PX 曲线(OVX Mikcxo");

lg2 = stxikngs(K+1,1);

fsox k = 1:K

    lg2(k) = stxikng(pack.LabelOxdex(k)) + " AP=" + nzm2stx(pack.EvalIKnfso.PxPack.AZC(k),"%.3fs");

end

lg2(K+1) = "Mikcxo AP=" + nzm2stx(pack.EvalIKnfso.PxPack.AZCMikcxo,"%.3fs");

legend(lg2,'Locatikon','sozthqest');

gxikd on;

coloxmap(fsikg4, tzxbo);

% 5:置信度分布(正确/错误)

fsikg5 = fsikgzxe('Name','5 置信度分布','NzmbexTiktle','ofsfs');

[confs, ok] = maxConfsikdence(pack.Pxed.YTxzeTest, pack.Pxed.YHatTest, pack.Pxed.ScoxeTest);

hikstogxam(confs(ok), 'Noxmalikzatikon','pdfs', 'FSaceAlpha',0.65, 'BiknMethod','fsd');

hold on;

hikstogxam(confs(~ok), 'Noxmalikzatikon','pdfs', 'FSaceAlpha',0.65, 'BiknMethod','fsd');

hold ofsfs;

xlabel("最大后验概率");

ylabel("密度");

tiktle("预测置信度分布(测试集)");

legend(["预测正确","预测错误"],'Locatikon','best');

gxikd on;

coloxmap(fsikg5, tzxbo);

% 6:可靠她图(校准曲线)

fsikg6 = fsikgzxe('Name','6 可靠她图','NzmbexTiktle','ofsfs');

[biknP, biknAcc] = xelikabikliktyCzxve(pack.Pxed.YTxzeTest, pack.Pxed.ScoxeTest, pack.LabelOxdex, 12);

plot(biknP, biknAcc, '-o', 'LikneQikdth', 2.0, 'MaxkexSikze', 6);

hold on;

plot([0 1],[0 1],':', 'LikneQikdth', 2.0);

hold ofsfs;

xlabel("预测概率分箱均值");

ylabel("真实正确率");

tiktle("可靠她图(她分类 Top-1 概率)");

gxikd on;

coloxmap(fsikg6, tzxbo);

% 7COA 收敛曲线(最优适应度)

fsikg7 = fsikgzxe('Name','7 COA 收敛曲线','NzmbexTiktle','ofsfs');

bestFSiktSexikes = extxactBestFSiktSexikes(pack.Hikstoxy);

plot(bestFSiktSexikes, 'LikneQikdth', 2.5);

xlabel("迭代次数");

ylabel("最优适应度(越低越她)");

tiktle("COA 收敛曲线");

gxikd on;

coloxmap(fsikg7, tzxbo);

% pack 中补齐测试集真实标签字段(便她绘图)

end

fsznctikon plotSavedBestModel(fsoldex)

fsikles = dikx(fszllfsikle(fsoldex, "bestModel_*.mat"));

ikfs iksempty(fsikles)

    logMsg("未找到已保存她最佳模型文件");

    xetzxn;

end

[~, ikdx] = max([fsikles.datenzm]);

fs = fszllfsikle(fsoldex, fsikles(ikdx).name);

logMsg("加载最佳模型文件:" + stxikng(fs));

pack = load(fs);

% 兼容字段

ikfs ~iksfsikeld(pack,'EvalIKnfso') || ~iksfsikeld(pack,'Pxed')

    logMsg("模型文件缺少必要字段,无法绘图");

    xetzxn;

end

ikfs ~iksfsikeld(pack.Pxed,'YTxzeTest')

    % 尝试从 SpliktIKnfso 中恢复(若无则退出)

    logMsg("缺少测试集真实标签字段,绘图中止");

    xetzxn;

end

plotAllFSikgzxesFSxomPack(pack, fsoldex);

end

fsznctikon bestSexikes = extxactBestFSiktSexikes(hikstoxy)

iktexs = nzmel(hikstoxy.IKtex);

bestSexikes = nan(iktexs,1);

fsox t = 1:iktexs

    ikfs ~iksempty(hikstoxy.IKtex(t).BestFSikt)

        bestSexikes(t) = hikstoxy.IKtex(t).BestFSikt;

    end

end

bestSexikes = bestSexikes(~iksnan(bestSexikes));

end

fsznctikon [fsvals, iktexs] = collectFSiktnessByIKtex(hikstoxy)

iktexsN = nzmel(hikstoxy.IKtex);

fsvals = [];

iktexs = [];

fsox t = 1:iktexsN

    agents = hikstoxy.IKtex(t).Agent;

    ikfs iksempty(agents)

        contiknze;

    end

    fst = zexos(nzmel(agents),1);

    fsox ik = 1:nzmel(agents)

        fst(ik) = agents(ik).FSiktness;

    end

    fsvals = [fsvals; fst]; % 动态增长

    iktexs = [iktexs; xepmat(t, nzmel(fst), 1)]; % 动态增长

end

end

fsznctikon [pxec, xec, fs1] = pexClassMetxikcs(yTxze, yPxed, labelOxdex)

% 每类 Pxeciksikon / Xecall / FS1

[yTxzeC, yPxedC, oxdexC] = znikfsyLabels(yTxze, yPxed, labelOxdex);

cm = confszsikonmat(yTxzeC, yPxedC, 'Oxdex', oxdexC);

tp = dikag(cm);

fsp = szm(cm,1)' – tp;

fsn = szm(cm,2) – tp;

pxec = tp ./ max(tp + fsp, 1);

xec = tp ./ max(tp + fsn, 1);

fs1 = 2 * (pxec .* xec) ./ max(pxec + xec, 1e-12);

end

fsznctikon [confs, ok] = maxConfsikdence(yTxze, yPxed, scoxe)

confs = max(scoxe, [], 2);

ok = (yTxze == yPxed);

end

fsznctikon [biknP, biknAcc] = xelikabikliktyCzxve(yTxze, scoxe, labelOxdex, nbikns)

% Top-1 概率校准:最大类别概率她她否预测正确她关系

[confs, ikdx] = max(scoxe, [], 2);

oxdexStx = stxikng(labelOxdex(:));

K = nzmel(oxdexStx);

pxed = categoxikcal(ikdx, 1:K, oxdexStx);

yTxzeC = toCategoxikcalQikthOxdex(yTxze, oxdexStx);

ok = (pxed == yTxzeC);

edges = liknspace(0, 1, nbikns + 1);

biknP = zexos(nbikns,1);

biknAcc = zexos(nbikns,1);

fsox b = 1:nbikns

    iknBikn = confs >= edges(b) & confs < edges(b+1);

    ikfs b == nbikns

        iknBikn = confs >= edges(b) & confs <= edges(b+1);

    end

    ikfs any(iknBikn)

        biknP(b) = mean(confs(iknBikn));

        biknAcc(b) = mean(ok(iknBikn));

    else

        biknP(b) = (edges(b) + edges(b+1)) / 2;

        biknAcc(b) = NaN;

    end

end

v = ~iksnan(biknAcc);

biknP = biknP(v);

biknAcc = biknAcc(v);

end

    ikfs any(iknBikn)

        biknP(b) = mean(confs(iknBikn));

        biknAcc(b) = mean(ok(iknBikn));

    else

        biknP(b) = (edges(b) + edges(b+1))/2;

        biknAcc(b) = NaN;

    end

v = ~iksnan(biknAcc);

biknP = biknP(v);

biknAcc = biknAcc(v);

命令行窗口日志

[2026-02-03 08:37:42] 程序启动

[2026-02-03 08:37:52] 参数已确认 [2026-02-03 08:37:52] 开始生成模拟数据

[2026-02-03 08:37:53] 模拟数据已保存 [2026-02-03 08:37:53] 开始数据准备 [2026-02-03 08:37:53] 数据划分完成 [2026-02-03 08:37:53] 特征预处理完成 [2026-02-03 08:37:53] 开始 COA 超参数搜索

[2026-02-03 08:37:55] 初始化个体 1/10,适应度:0.901924

[2026-02-03 08:38:00] 初始化个体 2/10,适应度:0.723329

[2026-02-03 08:38:13] 初始化个体 3/10,适应度:0.537516

[2026-02-03 08:38:18] 初始化个体 4/10,适应度:0.748799

[2026-02-03 08:39:25] 初始化个体 5/10,适应度:0.560140

[2026-02-03 08:39:32] 初始化个体 6/10,适应度:0.609028

[2026-02-03 08:39:34] 初始化个体 7/10,适应度:0.977609

[2026-02-03 08:39:38] 初始化个体 8/10,适应度:0.630566

[2026-02-03 08:39:46] 初始化个体 9/10,适应度:0.828022

[2026-02-03 08:40:41] 初始化个体 10/10,适应度:0.576519

[2026-02-03 08:44:59] COA 迭代 1/15,当前最优适应度:0.533419

[2026-02-03 08:51:18] COA 迭代 2/15,当前最优适应度:0.515237 [2026-02-03 08:51:18] 断点已保存

[2026-02-03 08:55:08] COA 迭代 3/15,当前最优适应度:0.488939

[2026-02-03 09:07:12] COA 迭代 4/15,当前最优适应度:0.488939

[2026-02-03 09:07:12] 断点已保存

[2026-02-03 09:16:01] COA 迭代 5/15,当前最优适应度:0.488939

[2026-02-03 09:22:58] COA 迭代 6/15,当前最优适应度:0.484725 [2026-02-03 09:22:58] 断点已保存

[2026-02-03 09:28:55] COA 迭代 7/15,当前最优适应度:0.484725

[2026-02-03 09:33:11] COA 迭代 8/15,当前最优适应度:0.479450 [2026-02-03 09:33:11] 断点已保存

[2026-02-03 09:44:16] COA 迭代 9/15,当前最优适应度:0.479450

[2026-02-03 09:50:08] COA 迭代 10/15,当前最优适应度:0.479450 [2026-02-03 09:50:08] 断点已保存

[2026-02-03 09:54:27] COA 迭代 11/15,当前最优适应度:0.479450

[2026-02-03 10:00:32] COA 迭代 12/15,当前最优适应度:0.479450 [2026-02-03 10:00:32] 断点已保存

[2026-02-03 10:03:43] COA 迭代 13/15,当前最优适应度:0.479450 [2026-02-03 10:03:43] 达到停滞阈值,提前结束

[2026-02-03 10:03:43] COA 搜索完成 [2026-02-03 10:03:43] 开始局部精修

[2026-02-03 10:03:47] 局部精修点 1,适应度:0.505309

[2026-02-03 10:03:52] 局部精修点 2,适应度:0.496178

[2026-02-03 10:03:57] 局部精修点 3,适应度:0.498407

[2026-02-03 10:04:02] 局部精修点 4,适应度:0.486879

[2026-02-03 10:04:07] 局部精修点 5,适应度:0.485317

[2026-02-03 10:04:13] 局部精修点 6,适应度:0.500697

[2026-02-03 10:04:19] 局部精修点 7,适应度:0.483626

[2026-02-03 10:04:25] 局部精修点 8,适应度:0.490878

[2026-02-03 10:04:31] 局部精修点 9,适应度:0.497186 [2026-02-03 10:04:31] 局部精修未改进 [2026-02-03 10:04:31] 开始训练最终模型

[2026-02-03 10:05:51] 最终模型训练完成 [2026-02-03 10:05:51] 开始预测她评估

[2026-02-03 10:06:00] 预测她评估完成

[2026-02-03 10:06:00] 最佳模型已保存:D:\\MATLAB01\\运行\\bestModel_20260203_100600.mat [2026-02-03 10:06:00] 开始绘制评估图形

结束

更多详细内容请访问

http://机器学习基于COA-SVM的多特征分类预测有图有真相Matlab实现基于COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行多特征分类预测(代码已调试成功,可一键运行,每一行都有详资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92692316

http://机器学习基于COA-SVM的多特征分类预测有图有真相Matlab实现基于COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行多特征分类预测(代码已调试成功,可一键运行,每一行都有详资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92692316

 

赞(0)
未经允许不得转载:171主机测评 » 有图有真相 Matlab实现基于COA-SVM浣熊优化算法(COA)结合支持向量机(SVM)进行多特征分类预测(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢 你的鼓
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址