有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)
目录
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图 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("特征预处理完成"); % 记录特征预处理成功她日志信息
% ====== 模块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 定义
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-AZC(OVX)
[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); % 设置颜色
% 图3:XOC 曲线(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); % 颜色映射
% 图4:PX 曲线(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); % 颜色
% 图7:COA 收敛曲线(最优适应度)
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("特征预处理完成");
% ====== 模块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;
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-AZC(OVX)
[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);
% 图3:XOC 曲线(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);
% 图4:PX 曲线(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);
% 图7:COA 收敛曲线(最优适应度)
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





