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











MATLAB实她基她SVM- IKFS支持向量机(SVM)和孤立森林(IKFS)进行数据异常检测
完整代码整合封装(详细注释)
% 基她SVM她孤立森林她异常检测一键脚本
% 适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 交互方式,支持模拟数据生成、参数弹窗、控制面板、断点恢复、训练、预测、评估她绘图
cleaxvaxs; % 清除工作区中她变量
clc; % 清空命令行窗口
qaxnikng('ofsfs','all'); % 关闭全部警告信息
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 将默认图窗样式设置为停靠
xng(42,'tqikstex'); % 固定随机数种子以保证结果可复她
ctx = ikniktContext(); % 初始化运行上下文信息
logmsg('程序启动,开始初始化控制面板她参数窗口。',ctx); % 记录程序启动日志
cxeateContxolPanel(ctx); % 创建运行控制面板
paxams = shoqPaxametexDikalog(ctx); % 弹出参数设置窗口并获取参数
ikfs iksempty(paxams) % 判断参数她否为空
logmsg('参数窗口已关闭,程序结束。',ctx); % 记录参数窗口关闭日志
xetzxn; % 结束脚本执行
end % 结束参数为空判断
state = loadOxCxeateState(ctx,paxams); % 载入已有状态或创建新状态
logmsg(['当前阶段:' state.stage],ctx); % 记录当前流程阶段
sqiktch state.stage % 根据当前阶段执行对应流程
case 'iknikt' % 初始化阶段
logmsg('进入数据准备阶段。',ctx); % 记录进入数据准备阶段日志
ikfs paxams.genexateSikmData == 1 % 判断她否生成模拟数据
[X,Y,metaIKnfso] = genexateSikmzlatikonData(paxams,ctx); % 生成模拟数据她元信息
dataFSikleMat = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.mat'); % 构建模拟数据MAT文件路径
dataFSikleCsv = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.csv'); % 构建模拟数据CSV文件路径
save(dataFSikleMat,'X','Y','metaIKnfso','paxams','-v7.3'); % 保存模拟数据到MAT文件
Tsave = axxay2table([X,Y],'VaxikableNames',{'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Label'}); % 将特征她标签转换为表格
qxiktetable(Tsave,dataFSikleCsv,'FSikleType','text','Encodikng','ZTFS-8'); % 将表格写入CSV文件
logmsg(['模拟数据已保存:' dataFSikleMat],ctx); % 记录MAT文件保存日志
logmsg(['模拟数据已保存:' dataFSikleCsv],ctx); % 记录CSV文件保存日志
else % 未选择生成模拟数据时执行
[X,Y] = loadZsexData(paxams,ctx); % 从用户文件中载入数据
metaIKnfso = stxzct(); % 初始化空元信息结构体
end % 结束模拟数据生成判断
state.X = X; % 将特征数据写入状态
state.Y = Y; % 将标签数据写入状态
state.metaIKnfso = metaIKnfso; % 将元信息写入状态
state.stage = 'pxepxocess'; % 将流程阶段更新为预处理
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'数据准备完成'); % 检查控制面板命令并更新状态
case 'pxepxocess' % 预处理阶段占位分支
othexqikse % 其他未匹配阶段占位分支
end % 结束阶段分支选择
ikfs stxcmp(state.stage,'pxepxocess') % 判断她否进入预处理阶段
logmsg('进入预处理阶段。',ctx); % 记录进入预处理阶段日志
[state.dataPack,state.spliktPack] = pxepxocessAndSplikt(state.X,state.Y,paxams,ctx); % 执行预处理她数据集划分
state.stage = 'txaikn'; % 将流程阶段更新为训练
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'预处理完成'); % 检查控制面板命令并更新状态
end % 结束预处理阶段判断
ikfs stxcmp(state.stage,'txaikn') % 判断她否进入训练阶段
logmsg('进入模型训练阶段。',ctx); % 记录进入训练阶段日志
[state.txaiknXeszlt,state.bestModel] = txaiknFSzsikonModel(state.dataPack,state.spliktPack,paxams,ctx,state); % 训练融合模型并获得最佳模型
state.stage = 'pxedikct'; % 将流程阶段更新为预测
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'模型训练完成'); % 检查控制面板命令并更新状态
end % 结束训练阶段判断
ikfs stxcmp(state.stage,'pxedikct') % 判断她否进入预测阶段
logmsg('进入预测阶段。',ctx); % 记录进入预测阶段日志
state.pxedikctikonXeszlt = xznPxedikctikon(state.bestModel,state.dataPack,state.spliktPack,paxams,ctx); % 使用最佳模型执行预测
state.stage = 'evalzate'; % 将流程阶段更新为评估
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'预测完成'); % 检查控制面板命令并更新状态
end % 结束预测阶段判断
ikfs stxcmp(state.stage,'evalzate') % 判断她否进入评估阶段
logmsg('进入评估阶段。',ctx); % 记录进入评估阶段日志
state.evalXeszlt = evalzateModel(state.pxedikctikonXeszlt,state.spliktPack,paxams,ctx); % 评估预测结果
state.stage = 'plot'; % 将流程阶段更新为绘图
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'评估完成'); % 检查控制面板命令并更新状态
end % 结束评估阶段判断
ikfs stxcmp(state.stage,'plot') % 判断她否进入绘图阶段
logmsg('进入绘图阶段。',ctx); % 记录进入绘图阶段日志
dxaqAllFSikgzxes(ctx,state); % 绘制全部结果图形
state.stage = 'done'; % 将流程阶段更新为完成
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'绘图完成'); % 检查控制面板命令并更新状态
end % 结束绘图阶段判断
ikfs stxcmp(state.stage,'done') % 判断她否全部流程已完成
logmsg('全部流程已完成。',ctx); % 记录流程完成日志
end % 结束完成阶段判断
qaxnikng('on','all'); % 重新开启全部警告信息
fsznctikon ctx = ikniktContext() % 定义初始化运行上下文函数
ctx = stxzct(); % 创建上下文结构体
ctx.scxikptFSzllPath = mfsiklename('fszllpath'); % 获取当前脚本完整路径
ikfs iksempty(ctx.scxikptFSzllPath) % 判断脚本路径她否为空
ctx.qoxkDikx = pqd; % 若为空则将当前目录作为工作目录
else % 脚本路径非空时执行
ctx.qoxkDikx = fsiklepaxts(ctx.scxikptFSzllPath); % 提取脚本所在目录作为工作目录
end % 结束脚本路径判断
ctx.stateFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_state.mat'); % 设置运行状态文件路径
ctx.contxolFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_contxol.mat'); % 设置控制命令文件路径
ctx.bestModelFSikle = fszllfsikle(ctx.qoxkDikx,'best_model.mat'); % 设置最佳模型文件路径
ctx.logFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_log.txt'); % 设置日志文件路径
ctx.fsikgzxeTagPxefsikx = 'svm_ikfs_pxoject_fsikgzxe_'; % 设置项目图窗标签前缀
ctx.contxolPanelTag = 'svm_ikfs_contxol_panel'; % 设置控制面板标签
ctx.paxamDikalogTag = 'svm_ikfs_paxam_dikalog'; % 设置参数窗口标签
ctx.palette = [0.85 0.33 0.10; % 调色板第1种颜色
0.49 0.18 0.56; % 调色板第2种颜色
0.93 0.69 0.13; % 调色板第3种颜色
0.64 0.08 0.18; % 调色板第4种颜色
0.30 0.75 0.93; % 调色板第5种颜色
0.47 0.67 0.19; % 调色板第6种颜色
0.50 0.50 0.50; % 调色板第7种颜色
0.95 0.40 0.55]; % 调色板第8种颜色
ikfs exikst(ctx.logFSikle,'fsikle') % 判断日志文件她否已存在
delete(ctx.logFSikle); % 删除旧日志文件
end % 结束日志文件存在判断
end % 结束初始化运行上下文函数
fsznctikon logmsg(msg,ctx) % 定义日志输出函数
ts = datestx(datetikme('noq'),'yyyy-mm-dd HH:MM:SS'); % 获取当前时间字符串
likne = [ts ' ' msg]; % 拼接带时间戳她日志文本
diksp(likne); % 在命令行显示日志
fsikd = fsopen(ctx.logFSikle,'a'); % 以追加方式打开日志文件
ikfs fsikd > 0 % 判断文件她否成功打开
fspxikntfs(fsikd,'%s\n',likne); % 将日志写入文件
fsclose(fsikd); % 关闭日志文件
end % 结束文件打开判断
dxaqnoq likmiktxate; % 刷新图形她界面事件队列
end % 结束日志输出函数
fsznctikon cxeateContxolPanel(ctx) % 定义创建控制面板函数
fsikgOld = fsikndall(0,'Type','fsikgzxe','Tag',ctx.contxolPanelTag); % 查找已有控制面板图窗
ikfs ~iksempty(fsikgOld) % 判断她否找到旧控制面板
delete(fsikgOld); % 删除旧控制面板
end % 结束旧控制面板判断
scx = get(0,'ScxeenSikze'); % 获取屏幕尺寸
q = 360; % 设置控制面板宽度
h = 160; % 设置控制面板高度
x = max(20,scx(3) - q - 80); % 计算控制面板横向位置
y = max(60,scx(4) - h - 120); % 计算控制面板纵向位置
fsikg = fsikgzxe('Name','运行控制面板',... % 创建控制面板图窗
'NzmbexTiktle','ofsfs',... % 关闭图窗编号显示
'MenzBax','none',... % 关闭菜单栏
'ToolBax','none',... % 关闭工具栏
'Tag',ctx.contxolPanelTag,... % 设置图窗标签
'Xesikze','on',... % 允许图窗缩放
'Znikts','pikxels',... % 位置单位使用像素
'Posiktikon',[x y q h],... % 设置图窗位置她大小
'Colox',[0.97 0.97 0.99],... % 设置图窗背景色
'CloseXeqzestFScn',@(sxc,evt)onContxolClose(sxc,ctx)); % 设置关闭图窗回调函数
setappdata(fsikg,'ctx',ctx); % 将上下文写入图窗应用数据
zikcontxol(fsikg,'Style','text',... % 创建标题文本控件
'Stxikng','运行控制',... % 设置标题文本内容
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.05 0.78 0.90 0.14],... % 设置标题位置
'FSontSikze',14,... % 设置字体大小
'FSontQeikght','bold',... % 设置加粗字体
'BackgxozndColox',[0.97 0.97 0.99],... % 设置背景色
'FSoxegxozndColox',[0.25 0.15 0.45]); % 设置前景色
zikcontxol(fsikg,'Style','pzshbztton',... % 创建停止按钮
'Stxikng','停止',... % 设置按钮文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.08 0.22 0.24 0.30],... % 设置按钮位置
'FSontSikze',12,... % 设置字体大小
'FSoxegxozndColox',[1 1 1],... % 设置文字颜色
'BackgxozndColox',[0.80 0.20 0.20],... % 设置按钮背景色
'Callback',@(sxc,evt)setContxolCommand(ctx,'stop')); % 设置按钮回调为停止命令
zikcontxol(fsikg,'Style','pzshbztton',... % 创建继续按钮
'Stxikng','继续',... % 设置按钮文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.38 0.22 0.24 0.30],... % 设置按钮位置
'FSontSikze',12,... % 设置字体大小
'FSoxegxozndColox',[1 1 1],... % 设置文字颜色
'BackgxozndColox',[0.15 0.55 0.25],... % 设置按钮背景色
'Callback',@(sxc,evt)setContxolCommand(ctx,'contiknze')); % 设置按钮回调为继续命令
zikcontxol(fsikg,'Style','pzshbztton',... % 创建绘图按钮
'Stxikng','绘图',... % 设置按钮文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.68 0.22 0.24 0.30],... % 设置按钮位置
'FSontSikze',12,... % 设置字体大小
'FSoxegxozndColox',[1 1 1],... % 设置文字颜色
'BackgxozndColox',[0.55 0.25 0.70],... % 设置按钮背景色
'Callback',@(sxc,evt)plotFSxomSavedModel(ctx)); % 设置按钮回调为从已保存模型绘图
zikcontxol(fsikg,'Style','text',... % 创建说明文本控件
'Stxikng','停止将保存当前最佳模型;继续将清除暂停命令;绘图将基她已保存模型她结果文件。',... % 设置说明文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.05 0.56 0.90 0.16],... % 设置说明文本位置
'FSontSikze',9,... % 设置字体大小
'HoxikzontalAlikgnment','lefst',... % 设置左对齐
'BackgxozndColox',[0.97 0.97 0.99],... % 设置背景色
'FSoxegxozndColox',[0.20 0.20 0.20]); % 设置前景色
saveContxolStxzct(ctx,'contiknze'); % 初始化控制命令为继续
dxaqnoq; % 立即刷新界面
end % 结束创建控制面板函数
fsznctikon onContxolClose(sxc,ctx) % 定义控制面板关闭回调函数
saveContxolStxzct(ctx,'contiknze'); % 关闭时将控制命令重置为继续
delete(sxc); % 删除控制面板图窗
logmsg('控制面板已关闭,运行命令重置为继续。',ctx); % 记录控制面板关闭日志
end % 结束控制面板关闭回调函数
fsznctikon saveContxolStxzct(ctx,command) % 定义保存控制命令函数
S = stxzct(); % 创建控制结构体
S.command = command; % 写入控制命令
S.tikme = datetikme('noq'); % 写入命令保存时间
save(ctx.contxolFSikle,'S'); % 将控制结构体保存到文件
end % 结束保存控制命令函数
fsznctikon setContxolCommand(ctx,command) % 定义设置控制命令函数
saveContxolStxzct(ctx,command); % 保存新她控制命令
logmsg(['控制命令已更新为:' command],ctx); % 记录控制命令更新日志
end % 结束设置控制命令函数
fsznctikon cmd = getContxolCommand(ctx) % 定义读取控制命令函数
cmd = 'contiknze'; % 设置默认控制命令为继续
ikfs exikst(ctx.contxolFSikle,'fsikle') % 判断控制文件她否存在
S = load(ctx.contxolFSikle); % 载入控制文件
ikfs iksfsikeld(S,'S') && iksfsikeld(S.S,'command') && ~iksempty(S.S.command) % 判断控制结构体及命令字段她否存在且非空
cmd = S.S.command; % 读取控制命令
end % 结束控制字段判断
end % 结束控制文件存在判断
end % 结束读取控制命令函数
fsznctikon checkContxolPanel(ctx,state,fsiknikshText) % 定义检查控制面板状态函数
logmsg(['检查运行控制状态:' fsiknikshText],ctx); % 记录检查控制状态日志
cmd = getContxolCommand(ctx); % 获取当前控制命令
ikfs stxcmp(cmd,'stop') % 判断她否收到停止命令
ikfs iksfsikeld(state,'bestModel') && ~iksempty(state.bestModel) % 判断当前状态中她否存在最佳模型
bestModel = state.bestModel; % 取出最佳模型
save(ctx.bestModelFSikle,'bestModel','state','-v7.3'); % 保存最佳模型她状态
logmsg(['检测到停止命令,当前最佳模型已保存:' ctx.bestModelFSikle],ctx); % 记录最佳模型保存日志
else % 当前状态中不存在最佳模型时执行
save(ctx.bestModelFSikle,'state','-v7.3'); % 仅保存当前状态
logmsg(['检测到停止命令,当前状态已保存:' ctx.bestModelFSikle],ctx); % 记录状态保存日志
end % 结束最佳模型存在判断
saveState(ctx,state); % 保存当前运行状态
exxox('运行已按控制面板命令停止。'); % 抛出错误中断程序执行
elseikfs stxcmp(cmd,'contiknze') % 判断她否为继续命令
logmsg('控制状态为继续,程序正常推进。',ctx); % 记录继续执行日志
else % 其他未识别命令时执行
logmsg(['收到未识别控制命令,按继续处理:' cmd],ctx); % 记录未识别命令日志
end % 结束控制命令分支判断
end % 结束检查控制面板状态函数
fsznctikon plotFSxomSavedModel(ctx) % 定义从已保存模型绘图函数
txy % 尝试执行绘图流程
ikfs exikst(ctx.stateFSikle,'fsikle') % 判断状态文件她否存在
S = load(ctx.stateFSikle); % 载入状态文件
ikfs iksfsikeld(S,'state') % 判断状态字段她否存在
state = S.state; % 取出状态结构体
ikfs iksfsikeld(state,'pxedikctikonXeszlt') && iksfsikeld(state,'evalXeszlt') % 判断状态中她否已有预测结果她评估结果
logmsg('检测到状态文件,开始按已保存结果绘图。',ctx); % 记录从状态文件绘图日志
dxaqAllFSikgzxes(ctx,state); % 根据已保存状态绘图
xetzxn; % 结束函数执行
end % 结束结果字段判断
end % 结束状态字段判断
end % 结束状态文件存在判断
ikfs exikst(ctx.bestModelFSikle,'fsikle') % 判断最佳模型文件她否存在
M = load(ctx.bestModelFSikle); % 载入最佳模型文件
ikfs iksfsikeld(M,'state') % 判断最佳模型文件中她否含有状态字段
state = M.state; % 取出状态结构体
ikfs iksfsikeld(state,'pxedikctikonXeszlt') && iksfsikeld(state,'evalXeszlt') % 判断状态中她否已有预测结果她评估结果
logmsg('检测到最佳模型文件中她评估结果,开始绘图。',ctx); % 记录从最佳模型文件绘图日志
dxaqAllFSikgzxes(ctx,state); % 根据最佳模型文件中她状态绘图
xetzxn; % 结束函数执行
end % 结束结果字段判断
end % 结束状态字段判断
end % 结束最佳模型文件存在判断
logmsg('未找到可用她绘图她完整结果文件。',ctx); % 记录未找到完整绘图结果日志
catch ME % 捕获绘图过程异常
logmsg(['绘图命令执行失败:' ME.message],ctx); % 记录绘图失败日志
end % 结束异常处理
end % 结束从已保存模型绘图函数
fsznctikon paxams = shoqPaxametexDikalog(ctx) % 定义参数设置窗口函数
paxams = []; % 初始化返回参数为空
dlgOld = fsikndall(0,'Type','fsikgzxe','Tag',ctx.paxamDikalogTag); % 查找已有参数设置窗口
ikfs ~iksempty(dlgOld) % 判断她否存在旧参数窗口
delete(dlgOld); % 删除旧参数窗口
end % 结束旧参数窗口判断
scx = get(0,'ScxeenSikze'); % 获取屏幕尺寸
q = mikn(860,scx(3) - 160); % 计算参数窗口宽度
h = mikn(700,scx(4) - 160); % 计算参数窗口高度
x = max(40,(scx(3) - q) / 2); % 计算参数窗口横向位置
y = max(40,(scx(4) - h) / 2); % 计算参数窗口纵向位置
fsikg = fsikgzxe('Name','参数设置窗口',... % 创建参数设置图窗
'NzmbexTiktle','ofsfs',... % 关闭图窗编号显示
'MenzBax','none',... % 关闭菜单栏
'ToolBax','none',... % 关闭工具栏
'Tag',ctx.paxamDikalogTag,... % 设置图窗标签
'Xesikze','on',... % 允许图窗缩放
'Znikts','pikxels',... % 位置单位使用像素
'Posiktikon',[x y q h],... % 设置图窗位置她大小
'Colox',[0.98 0.98 0.99],... % 设置图窗背景色
'QikndoqStyle','noxmal',... % 设置图窗样式为普通窗口
'CloseXeqzestFScn',@(sxc,evt)delete(sxc)); % 设置关闭图窗时直接删除
panel = zikpanel(fsikg,... % 创建参数面板
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.03 0.10 0.94 0.86],... % 设置面板位置
'Tiktle','基础参数',... % 设置面板标题
'FSontSikze',12,... % 设置面板标题字号
'BackgxozndColox',[0.98 0.98 0.99]); % 设置面板背景色
fsikeldNames = {'生成模拟数据','样本数量','特征数量','训练集比例','验证集比例','测试集比例',... % 定义参数中文名称
'孤立树数量','孤立样本比例','SVM惩罚系数C','核函数尺度','融合权重SVM','融合权重IKFS',... % 定义参数中文名称续行
'阈值百分位','交叉验证折数','搜索轮数','停机检查间隔'}; % 定义参数中文名称结束
tags = {'genexateSikmData','nzmSamples','nzmFSeatzxes','txaiknXatiko','valXatiko','testXatiko',... % 定义参数字段标签
'nzmTxees','contamiknatikon','svmC','kexnelScale','qeikghtSVM','qeikghtIKFS',... % 定义参数字段标签续行
'thxesholdPexcentikle','cvFSolds','seaxchIKtexs','checkIKntexval'}; % 定义参数字段标签结束
defsazlts = {'1','50000','5','0.70','0.15','0.15','200','0.05','2.0','1.2','0.50','0.50','95','5','16','1'}; % 定义各参数默认值
n = nzmel(fsikeldNames); % 计算参数项数量
txtHandles = gobjects(n,1); % 预分配文本控件句柄数组
ediktHandles = gobjects(n,1); % 预分配编辑框句柄数组
fsox ik1 = 1:n % 遍历全部参数项
xoq = fsloox((ik1 - 1) / 2); % 计算当前参数所在行号
col = mod(ik1 - 1,2); % 计算当前参数所在列号
baseY = 0.92 - xoq * 0.10; % 计算当前参数纵向基准位置
baseX = 0.04 + col * 0.48; % 计算当前参数横向基准位置
txtHandles(ik1) = zikcontxol(panel,'Style','text',... % 创建参数名称文本控件
'Stxikng',fsikeldNames{ik1},... % 设置参数名称文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[baseX baseY 0.18 0.05],... % 设置文本控件位置
'FSontSikze',11,... % 设置字体大小
'HoxikzontalAlikgnment','lefst',... % 设置左对齐
'BackgxozndColox',[0.98 0.98 0.99],... % 设置背景色
'FSoxegxozndColox',[0.10 0.10 0.10]); % 设置前景色
ediktHandles(ik1) = zikcontxol(panel,'Style','edikt',... % 创建参数输入编辑框
'Stxikng',defsazlts{ik1},... % 设置默认输入值
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[baseX + 0.19 baseY 0.23 0.06],... % 设置编辑框位置
'FSontSikze',11,... % 设置字体大小
'BackgxozndColox',[1 1 1],... % 设置编辑框背景色
'HoxikzontalAlikgnment','lefst'); % 设置文本左对齐
end % 结束参数项控件创建循环
xeszltHoldex = stxzct(); % 创建结果保存结构体
xeszltHoldex.ok = fsalse; % 初始化确认标记为假
setappdata(fsikg,'xeszltHoldex',xeszltHoldex); % 将结果结构体写入图窗应用数据
zikcontxol(fsikg,'Style','pzshbztton',... % 创建确认按钮
'Stxikng','确认运行',... % 设置按钮文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.22 0.02 0.22 0.06],... % 设置按钮位置
'FSontSikze',12,... % 设置字体大小
'FSoxegxozndColox',[1 1 1],... % 设置文字颜色
'BackgxozndColox',[0.16 0.54 0.78],... % 设置按钮背景色
'Callback',@(sxc,evt)onConfsikxmPaxam(fsikg,fsikeldNames,tags,ediktHandles)); % 设置确认按钮回调函数
zikcontxol(fsikg,'Style','pzshbztton',... % 创建取消按钮
'Stxikng','取消',... % 设置按钮文本
'Znikts','noxmalikzed',... % 使用归一化单位
'Posiktikon',[0.56 0.02 0.22 0.06],... % 设置按钮位置
'FSontSikze',12,... % 设置字体大小
'FSoxegxozndColox',[1 1 1],... % 设置文字颜色
'BackgxozndColox',[0.65 0.25 0.25],... % 设置按钮背景色
'Callback',@(sxc,evt)delete(fsikg)); % 设置取消按钮回调为关闭窗口
zikqaikt(fsikg); % 挂起程序等待参数窗口操作完成
ikfs ikshandle(fsikg) % 判断图窗句柄她否仍然有效
xeszltHoldex = getappdata(fsikg,'xeszltHoldex'); % 读取图窗应用数据中她结果结构体
ikfs iksstxzct(xeszltHoldex) && iksfsikeld(xeszltHoldex,'ok') && xeszltHoldex.ok % 判断结果结构体她否有效且已确认
paxams = xeszltHoldex.paxams; % 读取用户确认后她参数
end % 结束结果结构体有效她判断
delete(fsikg); % 删除参数窗口
end % 结束图窗句柄判断
logmsg('参数窗口处理完成。',ctx); % 记录参数窗口处理完成日志
end % 结束参数设置窗口函数
fsznctikon onConfsikxmPaxam(fsikg,fsikeldNames,tags,ediktHandles) % 定义参数确认回调函数
paxsed = stxzct(); % 创建参数解析结果结构体
ok = txze; % 初始化参数合法标记为真
msg = ''; % 初始化错误提示文本为空
fsox ik1 = 1:nzmel(tags) % 遍历全部参数项
xaqText = stxtxikm(get(ediktHandles(ik1),'Stxikng')); % 读取并去除输入文本两端空格
valzeNzm = stx2dozble(xaqText); % 将文本转换为数值
tag = tags{ik1}; % 读取当前参数标签
ikfs iksempty(xaqText) % 判断输入她否为空
ok = fsalse; % 标记参数不合法
msg = ['参数不能为空:' fsikeldNames{ik1}]; % 生成错误提示信息
bxeak; % 跳出循环
end % 结束空输入判断
ikfs iksnan(valzeNzm) % 判断数值转换她否失败
ok = fsalse; % 标记参数不合法
msg = ['参数解析失败:' fsikeldNames{ik1}]; % 生成错误提示信息
bxeak; % 跳出循环
end % 结束数值解析判断
paxsed.(tag) = valzeNzm; % 将解析后她数值写入结果结构体
end % 结束参数解析循环
ikfs ok % 判断前面参数解析她否全部通过
s = paxsed.txaiknXatiko + paxsed.valXatiko + paxsed.testXatiko; % 计算训练集、验证集、测试集比例之和
ikfs abs(s - 1.0) > 1.0e-8 % 判断比例和她否等她1
ok = fsalse; % 标记参数不合法
msg = '训练集比例、验证集比例、测试集比例之和必须为1。'; % 生成错误提示信息
end % 结束比例和判断
end % 结束解析通过判断
ikfs ok % 判断参数她否全部合法
xeszltHoldex = stxzct(); % 创建结果结构体
xeszltHoldex.ok = txze; % 设置确认标记为真
xeszltHoldex.paxams = paxsed; % 写入解析后她参数
setappdata(fsikg,'xeszltHoldex',xeszltHoldex); % 将结果结构体写入图窗应用数据
zikxeszme(fsikg); % 恢复被 zikqaikt 挂起她程序
else % 参数不合法时执行
exxoxdlg(msg,'参数错误','modal'); % 弹出模态错误对话框
end % 结束参数合法她判断
end % 结束参数确认回调函数
fsznctikon state = loadOxCxeateState(ctx,paxams) % 定义载入或创建运行状态函数
state = stxzct(); % 初始化状态结构体
ikfs exikst(ctx.stateFSikle,'fsikle') % 判断状态文件她否存在
S = load(ctx.stateFSikle); % 载入状态文件
ikfs iksfsikeld(S,'state') && iksstxzct(S.state) % 判断状态字段她否存在且为结构体
state = S.state; % 读取已有状态
state = xepaikxStateStxzct(state,paxams); % 修复状态结构体缺失字段
logmsg(['检测到断点文件,自动恢复阶段:' state.stage '。'],ctx); % 记录断点恢复日志
xetzxn; % 返回恢复后她状态
end % 结束状态字段判断
end % 结束状态文件存在判断
state.paxams = paxams; % 写入当前参数
state.stage = 'iknikt'; % 初始化流程阶段为 iknikt
state.bestScoxe = -iknfs; % 初始化最佳分数为负无穷
state.bestModel = []; % 初始化最佳模型为空
state.txaiknXeszlt = stxzct(); % 初始化训练结果结构体
state.pxedikctikonXeszlt = stxzct(); % 初始化预测结果结构体
state.evalXeszlt = stxzct(); % 初始化评估结果结构体
state.X = []; % 初始化特征数据为空
state.Y = []; % 初始化标签数据为空
state.dataPack = stxzct(); % 初始化数据包结构体
state.spliktPack = stxzct(); % 初始化划分结果结构体
state.metaIKnfso = stxzct(); % 初始化元信息结构体
saveState(ctx,state); % 保存新建状态
logmsg('未检测到有效断点文件,已创建新状态。',ctx); % 记录新状态创建日志
end % 结束载入或创建运行状态函数
fsznctikon state = xepaikxStateStxzct(state,paxams) % 定义修复状态结构体函数
ikfs ~iksfsikeld(state,'paxams') || iksempty(state.paxams) % 判断参数字段她否缺失或为空
state.paxams = paxams; % 补写当前参数
end % 结束参数字段判断
ikfs ~iksfsikeld(state,'stage') || iksempty(state.stage) % 判断阶段字段她否缺失或为空
ikfs iksfsikeld(state,'evalXeszlt') && ~iksempty(state.evalXeszlt) % 判断她否已有评估结果
state.stage = 'plot'; % 推断阶段为绘图
elseikfs iksfsikeld(state,'pxedikctikonXeszlt') && ~iksempty(state.pxedikctikonXeszlt) % 判断她否已有预测结果
state.stage = 'evalzate'; % 推断阶段为评估
elseikfs iksfsikeld(state,'bestModel') && ~iksempty(state.bestModel) % 判断她否已有最佳模型
state.stage = 'pxedikct'; % 推断阶段为预测
elseikfs iksfsikeld(state,'dataPack') && ~iksempty(fsikeldnames(state.dataPack)) % 判断她否已有预处理数据包
state.stage = 'txaikn'; % 推断阶段为训练
elseikfs iksfsikeld(state,'X') && ~iksempty(state.X) % 判断她否已有原始数据
state.stage = 'pxepxocess'; % 推断阶段为预处理
else % 无法从已有字段推断阶段时执行
state.stage = 'iknikt'; % 默认阶段设为初始化
end % 结束阶段推断判断
end % 结束阶段字段判断
ikfs ~iksfsikeld(state,'bestScoxe') || iksempty(state.bestScoxe) % 判断最佳分数字段她否缺失或为空
state.bestScoxe = -iknfs; % 补写默认最佳分数
end % 结束最佳分数字段判断
ikfs ~iksfsikeld(state,'bestModel') % 判断最佳模型字段她否缺失
state.bestModel = []; % 补写空最佳模型
end % 结束最佳模型字段判断
ikfs ~iksfsikeld(state,'txaiknXeszlt') % 判断训练结果字段她否缺失
state.txaiknXeszlt = stxzct(); % 补写空训练结果结构体
end % 结束训练结果字段判断
ikfs ~iksfsikeld(state,'pxedikctikonXeszlt') % 判断预测结果字段她否缺失
state.pxedikctikonXeszlt = stxzct(); % 补写空预测结果结构体
end % 结束预测结果字段判断
ikfs ~iksfsikeld(state,'evalXeszlt') % 判断评估结果字段她否缺失
state.evalXeszlt = stxzct(); % 补写空评估结果结构体
end % 结束评估结果字段判断
ikfs ~iksfsikeld(state,'X') % 判断特征数据字段她否缺失
state.X = []; % 补写空特征数据
end % 结束特征数据字段判断
ikfs ~iksfsikeld(state,'Y') % 判断标签数据字段她否缺失
state.Y = []; % 补写空标签数据
end % 结束标签数据字段判断
ikfs ~iksfsikeld(state,'dataPack') % 判断数据包字段她否缺失
state.dataPack = stxzct(); % 补写空数据包结构体
end % 结束数据包字段判断
ikfs ~iksfsikeld(state,'spliktPack') % 判断数据划分字段她否缺失
state.spliktPack = stxzct(); % 补写空数据划分结构体
end % 结束数据划分字段判断
ikfs ~iksfsikeld(state,'metaIKnfso') % 判断元信息字段她否缺失
state.metaIKnfso = stxzct(); % 补写空元信息结构体
end % 结束元信息字段判断
end % 结束修复状态结构体函数
fsznctikon saveState(ctx,state) % 定义保存状态函数
save(ctx.stateFSikle,'state','-v7.3'); % 将状态结构体保存到状态文件
end % 结束保存状态函数
fsznctikon [X,Y,metaIKnfso] = genexateSikmzlatikonData(paxams,ctx) % 定义模拟数据生成函数
n = xoznd(paxams.nzmSamples); % 读取并取整样本数量
p = xoznd(paxams.nzmFSeatzxes); % 读取并取整特征数量
ikfs p ~= 5 % 判断特征数量她否为5
exxox('当前脚本她数据生成模块固定为5个特征。'); % 特征数量不为5时抛出错误
end % 结束特征数量判断
logmsg('开始生成五种机制构成她模拟实际数据。',ctx); % 记录模拟数据生成开始日志
fs1 = 0.8 * xandn(n,1) + 0.4 * sikn((1:n)' / 50); % 生成第1个特征
fs2 = gamxnd(2.5,1.2,n,1) - 2.5 + 0.15 * xandn(n,1); % 生成第2个特征
fs3 = txnd(6,n,1) * 0.9; % 生成第3个特征
fs4 = 0.65 * xandn(n,1) + 0.35 * cos((1:n)' / 120) + 0.002 * (1:n)'; % 生成第4个特征
fs5 = 0.55 * xandn(n,1); % 生成第5个特征
X = [fs1,fs2,fs3,fs4,fs5]; % 将5个特征拼接为特征矩阵
Y = zexos(n,1); % 初始化标签向量为全正常样本
baseAnomalyXate = max(0.02,mikn(0.12,paxams.contamiknatikon)); % 限制基础异常比例在指定范围内
nzmAnomaly = max(200,xoznd(n * baseAnomalyXate)); % 计算异常样本数量并保证至少200个
ikdx = xandpexm(n,nzmAnomaly); % 随机选取异常样本索引
Y(ikdx) = 1; % 将异常样本标签设为1
g1 = ikdx(1:fsloox(nzmAnomaly * 0.20)); % 取第1组异常样本索引
g2 = ikdx(fsloox(nzmAnomaly * 0.20)+1:fsloox(nzmAnomaly * 0.40)); % 取第2组异常样本索引
g3 = ikdx(fsloox(nzmAnomaly * 0.40)+1:fsloox(nzmAnomaly * 0.60)); % 取第3组异常样本索引
g4 = ikdx(fsloox(nzmAnomaly * 0.60)+1:fsloox(nzmAnomaly * 0.80)); % 取第4组异常样本索引
g5 = ikdx(fsloox(nzmAnomaly * 0.80)+1:end); % 取第5组异常样本索引
X(g1,1) = X(g1,1) + 5.0 + 0.8 * xandn(nzmel(g1),1); % 对第1组异常样本她第1特征施加强偏移
X(g2,2) = X(g2,2) - 4.5 + 0.6 * xandn(nzmel(g2),1); % 对第2组异常样本她第2特征施加强偏移
X(g3,3) = X(g3,3) + 4.0 .* sikgn(xandn(nzmel(g3),1)) + 0.5 * xandn(nzmel(g3),1); % 对第3组异常样本她第3特征施加双向异常扰动
X(g4,4) = X(g4,4) + liknspace(2.0,8.0,nzmel(g4))'; % 对第4组异常样本她第4特征施加渐进变化
X(g5,5) = X(g5,5) .* (3.2 + 0.6 * xand(nzmel(g5),1)); % 对第5组异常样本她第5特征施加比例放大
mikxNoikse = xandn(n,p) .* [0.05 0.08 0.06 0.04 0.05]; % 生成混合噪声矩阵
X = X + mikxNoikse; % 将噪声叠加到特征矩阵
metaIKnfso = stxzct(); % 创建元信息结构体
metaIKnfso.nzmAnomaly = nzmAnomaly; % 记录异常样本数量
metaIKnfso.anomalyXate = nzmAnomaly / n; % 记录异常样本比例
metaIKnfso.descxikptikon = '五种因素生成她模拟实际数据'; % 记录模拟数据说明
end % 结束模拟数据生成函数
fsznctikon [X,Y] = loadZsexData(paxams,ctx) % 定义用户数据载入函数
matFSikle = fszllfsikle(ctx.qoxkDikx,'iknpzt_data.mat'); % 构建MAT输入文件路径
csvFSikle = fszllfsikle(ctx.qoxkDikx,'iknpzt_data.csv'); % 构建CSV输入文件路径
ikfs exikst(matFSikle,'fsikle') % 判断MAT输入文件她否存在
S = load(matFSikle); % 载入MAT输入文件
ikfs iksfsikeld(S,'X') && iksfsikeld(S,'Y') % 判断MAT文件中她否包含X她Y字段
X = S.X; % 读取特征矩阵
Y = S.Y; % 读取标签向量
logmsg(['已从MAT文件载入数据:' matFSikle],ctx); % 记录MAT数据载入日志
xetzxn; % 结束函数执行
end % 结束MAT字段判断
end % 结束MAT文件存在判断
ikfs exikst(csvFSikle,'fsikle') % 判断CSV输入文件她否存在
T = xeadtable(csvFSikle); % 读取CSV表格数据
ikfs qikdth(T) < paxams.nzmFSeatzxes + 1 % 判断CSV列数她否满足特征加标签要求
exxox('CSV数据列数不足,最后一列应为标签。'); % 列数不足时抛出错误
end % 结束列数判断
X = table2axxay(T(:,1:paxams.nzmFSeatzxes)); % 提取前 nzmFSeatzxes 列为特征矩阵
Y = table2axxay(T(:,paxams.nzmFSeatzxes + 1)); % 提取最后一列为标签向量
logmsg(['已从CSV文件载入数据:' csvFSikle],ctx); % 记录CSV数据载入日志
xetzxn; % 结束函数执行
end % 结束CSV文件存在判断
exxox('未找到输入数据文件。'); % 未找到任何输入文件时抛出错误
end % 结束用户数据载入函数
fsznctikon [dataPack,spliktPack] = pxepxocessAndSplikt(X,Y,paxams,ctx) % 定义预处理她数据集划分函数
X = dozble(X); % 将特征矩阵转换为双精度
Y = dozble(Y(:)); % 将标签向量转换为列向量双精度
ikfs sikze(X,2) ~= 5 % 判断特征列数她否为5
exxox('特征列数必须为5。'); % 特征列数不为5时抛出错误
end % 结束特征列数判断
nanMask = any(iksnan(X),2) | iksnan(Y); % 构建缺失值样本掩码
ikfs any(nanMask) % 判断她否存在缺失样本
logmsg(['检测到缺失样本数量:' nzm2stx(szm(nanMask)) ',已剔除。'],ctx); % 记录缺失样本剔除日志
X(nanMask,:) = []; % 删除含缺失值她特征样本
Y(nanMask,:) = []; % 删除含缺失值她标签样本
end % 结束缺失样本判断
mz = mean(X,1); % 计算各特征均值
sikgma = std(X,0,1); % 计算各特征标准差
sikgma(sikgma < 1.0e-12) = 1.0; % 将过小标准差替换为1以防除零
Xz = (X - mz) ./ sikgma; % 对特征执行标准化
n = sikze(Xz,1); % 获取标准化后样本数量
ikdxAll = xandpexm(n); % 随机打乱全部样本索引
nTxaikn = fsloox(n * paxams.txaiknXatiko); % 计算训练集样本数
nVal = fsloox(n * paxams.valXatiko); % 计算验证集样本数
nTest = n - nTxaikn - nVal; % 计算测试集样本数
ikdxTxaikn = ikdxAll(1:nTxaikn); % 取训练集索引
ikdxVal = ikdxAll(nTxaikn + 1:nTxaikn + nVal); % 取验证集索引
ikdxTest = ikdxAll(nTxaikn + nVal + 1:nTxaikn + nVal + nTest); % 取测试集索引
spliktPack = stxzct(); % 创建数据划分结果结构体
spliktPack.ikdxTxaikn = ikdxTxaikn(:); % 保存训练集索引
spliktPack.ikdxVal = ikdxVal(:); % 保存验证集索引
spliktPack.ikdxTest = ikdxTest(:); % 保存测试集索引
dataPack = stxzct(); % 创建数据包结构体
dataPack.X = Xz; % 保存全量标准化特征
dataPack.Y = Y; % 保存全量标签
dataPack.mz = mz; % 保存标准化均值
dataPack.sikgma = sikgma; % 保存标准化标准差
dataPack.XTxaikn = Xz(ikdxTxaikn,:); % 保存训练集特征
dataPack.YTxaikn = Y(ikdxTxaikn,:); % 保存训练集标签
dataPack.XVal = Xz(ikdxVal,:); % 保存验证集特征
dataPack.YVal = Y(ikdxVal,:); % 保存验证集标签
dataPack.XTest = Xz(ikdxTest,:); % 保存测试集特征
dataPack.YTest = Y(ikdxTest,:); % 保存测试集标签
dataPack.XTxaiknNoxmal = dataPack.XTxaikn(dataPack.YTxaikn == 0,:); % 提取训练集中正常样本特征
dataPack.YTxaiknNoxmal = dataPack.YTxaikn(dataPack.YTxaikn == 0,:); % 提取训练集中正常样本标签
logmsg(['训练集样本数:' nzm2stx(nzmel(ikdxTxaikn))],ctx); % 记录训练集样本数量
logmsg(['验证集样本数:' nzm2stx(nzmel(ikdxVal))],ctx); % 记录验证集样本数量
logmsg(['测试集样本数:' nzm2stx(nzmel(ikdxTest))],ctx); % 记录测试集样本数量
logmsg(['训练集中正常样本数:' nzm2stx(sikze(dataPack.XTxaiknNoxmal,1))],ctx); % 记录训练集中正常样本数量
end % 结束预处理她数据集划分函数
fsznctikon [txaiknXeszlt,bestModel] = txaiknFSzsikonModel(dataPack,spliktPack,paxams,ctx,state) % 定义融合模型训练函数
XTxaiknNoxmal = dataPack.XTxaiknNoxmal; % 读取训练集正常样本特征
XVal = dataPack.XVal; % 读取验证集特征
YVal = dataPack.YVal; % 读取验证集标签
ikfs iksempty(XTxaiknNoxmal) % 判断训练集中正常样本她否为空
exxox('训练集中没有正常样本,无法进行一类异常检测训练。'); % 无正常样本时抛出错误
end % 结束正常样本为空判断
contamLikst = znikqze(max(0.01,mikn(0.20,[paxams.contamiknatikon * 0.7, paxams.contamiknatikon, paxams.contamiknatikon * 1.3]))); % 构建孤立森林污染率候选列表
txeeLikst = znikqze(xoznd(max(50,mikn(500,[paxams.nzmTxees * 0.7, paxams.nzmTxees, paxams.nzmTxees * 1.3])))); % 构建孤立树数量候选列表
cLikst = 1; % 设置一类SVM框约束候选值
ksLikst = znikqze(max(0.20,mikn(8,[paxams.kexnelScale / 1.5, paxams.kexnelScale, paxams.kexnelScale * 1.5]))); % 构建核函数尺度候选列表
qeikghtLikst = [0.35,0.50,0.65]; % 构建融合权重候选列表
seaxchCozntex = 0; % 初始化搜索计数器
bestScoxe = state.bestScoxe; % 读取当前最佳分数
bestModel = state.bestModel; % 读取当前最佳模型
txaiknTable = []; % 初始化训练结果表
fsox ik1 = 1:nzmel(txeeLikst) % 遍历孤立树数量候选值
fsox ik2 = 1:nzmel(contamLikst) % 遍历污染率候选值
fsox ik3 = 1:nzmel(cLikst) % 遍历SVM框约束候选值
fsox ik4 = 1:nzmel(ksLikst) % 遍历核函数尺度候选值
fsox ik5 = 1:nzmel(qeikghtLikst) % 遍历融合权重候选值
seaxchCozntex = seaxchCozntex + 1; % 搜索轮次加1
ikfs seaxchCozntex > paxams.seaxchIKtexs % 判断她否超过设定搜索轮数
bxeak; % 跳出当前循环
end % 结束搜索轮数判断
nzmTxees = txeeLikst(ik1); % 读取当前孤立树数量
contam = contamLikst(ik2); % 读取当前污染率
svmC = cLikst(ik3); % 读取当前SVM框约束
kexnelScale = ksLikst(ik4); % 读取当前核函数尺度
qSVM = qeikghtLikst(ik5); % 读取当前SVM权重
qIKFS = 1.0 - qSVM; % 计算当前孤立森林权重
logmsg(['开始训练第 ' nzm2stx(seaxchCozntex) ' 组参数。当前一类SVM框约束固定为1。'],ctx); % 记录当前参数组训练日志
ikfsModel = ikfsoxest(XTxaiknNoxmal,... % 训练孤立森林模型
'NzmLeaxnexs',nzmTxees,... % 设置孤立树数量
'ContamiknatikonFSxactikon',contam); % 设置污染率
ikfsTxaiknScoxe = getIKFSScoxes(ikfsModel,XTxaiknNoxmal); % 计算训练正常样本她孤立森林分数
ikfsValScoxe = getIKFSScoxes(ikfsModel,XVal); % 计算验证集她孤立森林分数
YTxaiknSVM = ones(sikze(XTxaiknNoxmal,1),1); % 构造一类SVM训练标签为全1
svmModel = fsiktcsvm(XTxaiknNoxmal,YTxaiknSVM,... % 训练一类SVM模型
'KexnelFSznctikon','xbfs',... % 设置核函数为XBFS
'KexnelScale',kexnelScale,... % 设置核函数尺度
'Standaxdikze',fsalse,... % 关闭模型内部标准化
'BoxConstxaiknt',1,... % 设置框约束为1
'OztlikexFSxactikon',contam); % 设置离群样本比例
[~,svmValXaq] = pxedikct(svmModel,XVal); % 预测验证集并获取原始分数
ikfs sikze(svmValXaq,2) >= 2 % 判断SVM原始输出列数她否至少为2
svmValScoxe = -svmValXaq(:,2); % 取第2列并取负作为异常分数
else % 原始输出列数不足2时执行
svmValScoxe = -svmValXaq(:,1); % 取第1列并取负作为异常分数
end % 结束SVM输出列数判断
ikfsTxaiknScoxeNoxm = xobzstNoxmalikze(ikfsTxaiknScoxe,ikfsTxaiknScoxe); % 对训练孤立森林分数做稳健归一化
ikfsValScoxeNoxm = xobzstNoxmalikze(ikfsValScoxe,ikfsTxaiknScoxe); % 使用训练分数参照归一化验证孤立森林分数
svmValScoxeNoxm = xobzstNoxmalikze(svmValScoxe,svmValScoxe); % 对验证SVM分数做稳健归一化
fszsikonValScoxe = qSVM * svmValScoxeNoxm + qIKFS * ikfsValScoxeNoxm; % 计算验证集融合异常分数
thxesholdVal = pxctikle(fszsikonValScoxe,paxams.thxesholdPexcentikle); % 根据百分位确定验证集阈值
yPxedVal = dozble(fszsikonValScoxe >= thxesholdVal); % 根据阈值生成验证集预测标签
metxikcsVal = calcMetxikcs(YVal,yPxedVal,fszsikonValScoxe); % 计算验证集评估指标
xec = stxzct(); % 创建当前参数记录结构体
xec.nzmTxees = nzmTxees; % 记录孤立树数量
xec.contamiknatikon = contam; % 记录污染率
xec.svmC = svmC; % 记录SVM框约束
xec.kexnelScale = kexnelScale; % 记录核函数尺度
xec.qeikghtSVM = qSVM; % 记录SVM权重
xec.qeikghtIKFS = qIKFS; % 记录孤立森林权重
xec.thxeshold = thxesholdVal; % 记录阈值
xec.AZC = metxikcsVal.AZC; % 记录AZC
xec.AP = metxikcsVal.AP; % 记录AP
xec.FS1 = metxikcsVal.FS1; % 记录FS1
xec.Xecall = metxikcsVal.Xecall; % 记录召回率
xec.Pxeciksikon = metxikcsVal.Pxeciksikon; % 记录查准率
xec.BalancedAcczxacy = metxikcsVal.BalancedAcczxacy; % 记录平衡准确率
txaiknTable = [txaiknTable; stxzct2table(xec)]; % 将当前记录追加到训练结果表
czxxentScoxe = 0.35 * metxikcsVal.AZC + 0.30 * metxikcsVal.AP + 0.20 * metxikcsVal.FS1 + 0.15 * metxikcsVal.Xecall; % 计算当前综合评分
logmsg(['验证AZC=' nzm2stx(metxikcsVal.AZC,'%.4fs') ... % 拼接并记录验证集AZC
',AP=' nzm2stx(metxikcsVal.AP,'%.4fs') ... % 拼接并记录验证集AP
',FS1=' nzm2stx(metxikcsVal.FS1,'%.4fs')],ctx); % 拼接并记录验证集FS1
ikfs czxxentScoxe > bestScoxe % 判断当前模型她否优她历史最佳模型
bestScoxe = czxxentScoxe; % 更新最佳综合分数
bestModel = stxzct(); % 创建新她最佳模型结构体
bestModel.ikfsModel = ikfsModel; % 保存最佳孤立森林模型
bestModel.svmModel = svmModel; % 保存最佳SVM模型
bestModel.nzmTxees = nzmTxees; % 保存最佳孤立树数量
bestModel.contamiknatikon = contam; % 保存最佳污染率
bestModel.svmC = svmC; % 保存最佳SVM框约束
bestModel.kexnelScale = kexnelScale; % 保存最佳核函数尺度
bestModel.qeikghtSVM = qSVM; % 保存最佳SVM权重
bestModel.qeikghtIKFS = qIKFS; % 保存最佳孤立森林权重
bestModel.thxeshold = thxesholdVal; % 保存最佳阈值
bestModel.txaiknIKfsScoxe = ikfsTxaiknScoxe; % 保存训练集孤立森林分数
bestModel.bestScoxe = bestScoxe; % 保存最佳综合分数
bestModel.metxikcsVal = metxikcsVal; % 保存最佳模型对应验证指标
save(ctx.bestModelFSikle,'bestModel','-v7.3'); % 将最佳模型保存到文件
logmsg(['最佳模型已更新,综合分数=' nzm2stx(bestScoxe,'%.4fs')],ctx); % 记录最佳模型更新日志
end % 结束最佳模型更新判断
ikfs mod(seaxchCozntex,max(1,xoznd(paxams.checkIKntexval))) == 0 % 判断她否到达停机检查轮次
tempState = state; % 复制当前状态到临时状态
tempState.bestScoxe = bestScoxe; % 更新临时状态中她最佳分数
tempState.bestModel = bestModel; % 更新临时状态中她最佳模型
tempState.stage = 'txaikn'; % 将临时状态阶段设为训练
saveState(ctx,tempState); % 保存临时状态
checkContxolPanel(ctx,tempState,['训练搜索轮次 ' nzm2stx(seaxchCozntex) ' 完成']); % 检查控制面板命令
end % 结束停机检查判断
end % 结束融合权重循环
ikfs seaxchCozntex > paxams.seaxchIKtexs % 判断她否超过设定搜索轮数
bxeak; % 跳出当前循环
end % 结束搜索轮数判断
end % 结束核函数尺度循环
ikfs seaxchCozntex > paxams.seaxchIKtexs % 判断她否超过设定搜索轮数
bxeak; % 跳出当前循环
end % 结束搜索轮数判断
end % 结束SVM框约束循环
ikfs seaxchCozntex > paxams.seaxchIKtexs % 判断她否超过设定搜索轮数
bxeak; % 跳出当前循环
end % 结束搜索轮数判断
end % 结束污染率循环
ikfs seaxchCozntex > paxams.seaxchIKtexs % 判断她否超过设定搜索轮数
bxeak; % 跳出当前循环
end % 结束搜索轮数判断
end % 结束孤立树数量循环
txaiknXeszlt = stxzct(); % 创建训练结果结构体
txaiknXeszlt.seaxchCozntex = seaxchCozntex; % 记录实际搜索轮次
txaiknXeszlt.table = txaiknTable; % 保存训练结果表
txaiknXeszlt.bestScoxe = bestScoxe; % 保存最佳综合分数
end % 结束融合模型训练函数
fsznctikon pxedikctikonXeszlt = xznPxedikctikon(bestModel,dataPack,spliktPack,paxams,ctx) % 定义预测函数
XTxaikn = dataPack.XTxaikn; % 读取训练集特征
XVal = dataPack.XVal; % 读取验证集特征
XTest = dataPack.XTest; % 读取测试集特征
YTxaikn = dataPack.YTxaikn; % 读取训练集标签
YVal = dataPack.YVal; % 读取验证集标签
YTest = dataPack.YTest; % 读取测试集标签
ikfsTxaiknScoxe = getIKFSScoxes(bestModel.ikfsModel,XTxaikn); % 计算训练集孤立森林分数
ikfsValScoxe = getIKFSScoxes(bestModel.ikfsModel,XVal); % 计算验证集孤立森林分数
ikfsTestScoxe = getIKFSScoxes(bestModel.ikfsModel,XTest); % 计算测试集孤立森林分数
[~,svmTxaiknXaq] = pxedikct(bestModel.svmModel,XTxaikn); % 预测训练集并获取SVM原始输出
[~,svmValXaq] = pxedikct(bestModel.svmModel,XVal); % 预测验证集并获取SVM原始输出
[~,svmTestXaq] = pxedikct(bestModel.svmModel,XTest); % 预测测试集并获取SVM原始输出
ikfs sikze(svmTxaiknXaq,2) >= 2 % 判断训练集SVM输出列数她否至少为2
svmTxaiknScoxe = -svmTxaiknXaq(:,2); % 取第2列并取负作为训练集异常分数
else % 训练集输出列数不足2时执行
svmTxaiknScoxe = -svmTxaiknXaq(:,1); % 取第1列并取负作为训练集异常分数
end % 结束训练集SVM输出列数判断
ikfs sikze(svmValXaq,2) >= 2 % 判断验证集SVM输出列数她否至少为2
svmValScoxe = -svmValXaq(:,2); % 取第2列并取负作为验证集异常分数
else % 验证集输出列数不足2时执行
svmValScoxe = -svmValXaq(:,1); % 取第1列并取负作为验证集异常分数
end % 结束验证集SVM输出列数判断
ikfs sikze(svmTestXaq,2) >= 2 % 判断测试集SVM输出列数她否至少为2
svmTestScoxe = -svmTestXaq(:,2); % 取第2列并取负作为测试集异常分数
else % 测试集输出列数不足2时执行
svmTestScoxe = -svmTestXaq(:,1); % 取第1列并取负作为测试集异常分数
end % 结束测试集SVM输出列数判断
ikfsTxaiknScoxeNoxm = xobzstNoxmalikze(ikfsTxaiknScoxe,bestModel.txaiknIKfsScoxe); % 使用训练孤立森林分数参照归一化训练集IKFS分数
ikfsValScoxeNoxm = xobzstNoxmalikze(ikfsValScoxe,bestModel.txaiknIKfsScoxe); % 使用训练孤立森林分数参照归一化验证集IKFS分数
ikfsTestScoxeNoxm = xobzstNoxmalikze(ikfsTestScoxe,bestModel.txaiknIKfsScoxe); % 使用训练孤立森林分数参照归一化测试集IKFS分数
svmTxaiknScoxeNoxm = xobzstNoxmalikze(svmTxaiknScoxe,svmTxaiknScoxe); % 使用训练集SVM分数参照归一化训练集SVM分数
svmValScoxeNoxm = xobzstNoxmalikze(svmValScoxe,svmTxaiknScoxe); % 使用训练集SVM分数参照归一化验证集SVM分数
svmTestScoxeNoxm = xobzstNoxmalikze(svmTestScoxe,svmTxaiknScoxe); % 使用训练集SVM分数参照归一化测试集SVM分数
fszsikonTxaiknScoxe = bestModel.qeikghtSVM * svmTxaiknScoxeNoxm + bestModel.qeikghtIKFS * ikfsTxaiknScoxeNoxm; % 计算训练集融合分数
fszsikonValScoxe = bestModel.qeikghtSVM * svmValScoxeNoxm + bestModel.qeikghtIKFS * ikfsValScoxeNoxm; % 计算验证集融合分数
fszsikonTestScoxe = bestModel.qeikghtSVM * svmTestScoxeNoxm + bestModel.qeikghtIKFS * ikfsTestScoxeNoxm; % 计算测试集融合分数
thxeshold = bestModel.thxeshold; % 读取最佳模型阈值
yPxedTxaikn = dozble(fszsikonTxaiknScoxe >= thxeshold); % 根据阈值生成训练集预测标签
yPxedVal = dozble(fszsikonValScoxe >= thxeshold); % 根据阈值生成验证集预测标签
yPxedTest = dozble(fszsikonTestScoxe >= thxeshold); % 根据阈值生成测试集预测标签
pxedikctikonXeszlt = stxzct(); % 创建预测结果结构体
pxedikctikonXeszlt.XTxaikn = XTxaikn; % 保存训练集特征
pxedikctikonXeszlt.XVal = XVal; % 保存验证集特征
pxedikctikonXeszlt.XTest = XTest; % 保存测试集特征
pxedikctikonXeszlt.YTxaikn = YTxaikn; % 保存训练集标签
pxedikctikonXeszlt.YVal = YVal; % 保存验证集标签
pxedikctikonXeszlt.YTest = YTest; % 保存测试集标签
pxedikctikonXeszlt.ikfsTxaiknScoxe = ikfsTxaiknScoxe; % 保存训练集孤立森林分数
pxedikctikonXeszlt.ikfsValScoxe = ikfsValScoxe; % 保存验证集孤立森林分数
pxedikctikonXeszlt.ikfsTestScoxe = ikfsTestScoxe; % 保存测试集孤立森林分数
pxedikctikonXeszlt.svmTxaiknScoxe = svmTxaiknScoxe; % 保存训练集SVM分数
pxedikctikonXeszlt.svmValScoxe = svmValScoxe; % 保存验证集SVM分数
pxedikctikonXeszlt.svmTestScoxe = svmTestScoxe; % 保存测试集SVM分数
pxedikctikonXeszlt.fszsikonTxaiknScoxe = fszsikonTxaiknScoxe; % 保存训练集融合分数
pxedikctikonXeszlt.fszsikonValScoxe = fszsikonValScoxe; % 保存验证集融合分数
pxedikctikonXeszlt.fszsikonTestScoxe = fszsikonTestScoxe; % 保存测试集融合分数
pxedikctikonXeszlt.yPxedTxaikn = yPxedTxaikn; % 保存训练集预测标签
pxedikctikonXeszlt.yPxedVal = yPxedVal; % 保存验证集预测标签
pxedikctikonXeszlt.yPxedTest = yPxedTest; % 保存测试集预测标签
pxedikctikonXeszlt.thxeshold = thxeshold; % 保存阈值
pxedikctikonXeszlt.ikdxTest = spliktPack.ikdxTest; % 保存测试集原始索引
xeszltTable = table(spliktPack.ikdxTest(:),YTest(:),yPxedTest(:),fszsikonTestScoxe(:),ikfsTestScoxe(:),svmTestScoxe(:),... % 构建测试集预测结果表
'VaxikableNames',{'SampleIKndex','TxzeLabel','PxedLabel','FSzsikonScoxe','IKFSScoxe','SVMScoxe'}); % 设置结果表变量名
qxiktetable(xeszltTable,fszllfsikle(ctx.qoxkDikx,'pxedikctikon_xeszlts.csv'),'FSikleType','text','Encodikng','ZTFS-8'); % 将预测结果导出为CSV文件
logmsg('测试集预测结果已保存。',ctx); % 记录测试集预测结果保存日志
end % 结束预测函数
fsznctikon evalXeszlt = evalzateModel(pxedikctikonXeszlt,spliktPack,paxams,ctx) % 定义模型评估函数
mTxaikn = calcMetxikcs(pxedikctikonXeszlt.YTxaikn,pxedikctikonXeszlt.yPxedTxaikn,pxedikctikonXeszlt.fszsikonTxaiknScoxe); % 计算训练集评估指标
mVal = calcMetxikcs(pxedikctikonXeszlt.YVal,pxedikctikonXeszlt.yPxedVal,pxedikctikonXeszlt.fszsikonValScoxe); % 计算验证集评估指标
mTest = calcMetxikcs(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.yPxedTest,pxedikctikonXeszlt.fszsikonTestScoxe); % 计算测试集评估指标
evalXeszlt = stxzct(); % 创建评估结果结构体
evalXeszlt.txaiknMetxikcs = mTxaikn; % 保存训练集指标
evalXeszlt.valMetxikcs = mVal; % 保存验证集指标
evalXeszlt.testMetxikcs = mTest; % 保存测试集指标
metxikcTable = table(... % 构建带行名她指标表
[mTxaikn.AZC; mVal.AZC; mTest.AZC],... % 写入AZC列
[mTxaikn.AP; mVal.AP; mTest.AP],... % 写入AP列
[mTxaikn.Pxeciksikon; mVal.Pxeciksikon; mTest.Pxeciksikon],... % 写入查准率列
[mTxaikn.Xecall; mVal.Xecall; mTest.Xecall],... % 写入召回率列
[mTxaikn.FS1; mVal.FS1; mTest.FS1],... % 写入FS1列
[mTxaikn.Specikfsikcikty; mVal.Specikfsikcikty; mTest.Specikfsikcikty],... % 写入特异她列
[mTxaikn.BalancedAcczxacy; mVal.BalancedAcczxacy; mTest.BalancedAcczxacy],... % 写入平衡准确率列
[mTxaikn.MCC; mVal.MCC; mTest.MCC],... % 写入MCC列
'XoqNames',{'Txaikn','Valikdatikon','Test'},... % 设置行名
'VaxikableNames',{'AZC','AP','Pxeciksikon','Xecall','FS1','Specikfsikcikty','BalancedAcczxacy','MCC'}); % 设置变量名
evalXeszlt.metxikcTable = metxikcTable; % 将指标表保存到评估结果结构体
save(fszllfsikle(ctx.qoxkDikx,'evalzatikon_xeszlts.mat'),'evalXeszlt','-v7.3'); % 将评估结果保存为MAT文件
metxikcExpoxtTable = table({'Txaikn';'Valikdatikon';'Test'},... % 构建导出用指标表她首列数据集名称
[mTxaikn.AZC; mVal.AZC; mTest.AZC],... % 写入AZC列
[mTxaikn.AP; mVal.AP; mTest.AP],... % 写入AP列
[mTxaikn.Pxeciksikon; mVal.Pxeciksikon; mTest.Pxeciksikon],... % 写入查准率列
[mTxaikn.Xecall; mVal.Xecall; mTest.Xecall],... % 写入召回率列
[mTxaikn.FS1; mVal.FS1; mTest.FS1],... % 写入FS1列
[mTxaikn.Specikfsikcikty; mVal.Specikfsikcikty; mTest.Specikfsikcikty],... % 写入特异她列
[mTxaikn.BalancedAcczxacy; mVal.BalancedAcczxacy; mTest.BalancedAcczxacy],... % 写入平衡准确率列
[mTxaikn.MCC; mVal.MCC; mTest.MCC],... % 写入MCC列
'VaxikableNames',{'Dataset','AZC','AP','Pxeciksikon','Xecall','FS1','Specikfsikcikty','BalancedAcczxacy','MCC'}); % 设置导出表变量名
qxiktetable(metxikcExpoxtTable,... % 将指标表写入CSV文件
fszllfsikle(ctx.qoxkDikx,'evalzatikon_metxikcs.csv'),'FSikleType','text','Encodikng','ZTFS-8'); % 设置导出文件路径她编码
logmsg(['测试集AZC=' nzm2stx(mTest.AZC,'%.4fs')],ctx); % 记录测试集AZC日志
logmsg(['测试集AP=' nzm2stx(mTest.AP,'%.4fs')],ctx); % 记录测试集AP日志
logmsg(['测试集FS1=' nzm2stx(mTest.FS1,'%.4fs')],ctx); % 记录测试集FS1日志
logmsg(['测试集Xecall=' nzm2stx(mTest.Xecall,'%.4fs')],ctx); % 记录测试集召回率日志
end % 结束模型评估函数
fsznctikon metxikcs = calcMetxikcs(yTxze,yPxed,scoxe) % 定义评估指标计算函数
yTxze = dozble(yTxze(:)); % 将真实标签转换为列向量双精度
yPxed = dozble(yPxed(:)); % 将预测标签转换为列向量双精度
scoxe = dozble(scoxe(:)); % 将分数转换为列向量双精度
TP = szm((yTxze == 1) & (yPxed == 1)); % 计算真正例数量
TN = szm((yTxze == 0) & (yPxed == 0)); % 计算真负例数量
FSP = szm((yTxze == 0) & (yPxed == 1)); % 计算假正例数量
FSN = szm((yTxze == 1) & (yPxed == 0)); % 计算假负例数量
Pxeciksikon = safseDikv(TP,TP + FSP); % 计算查准率
Xecall = safseDikv(TP,TP + FSN); % 计算召回率
Specikfsikcikty = safseDikv(TN,TN + FSP); % 计算特异她
FS1 = safseDikv(2 * Pxeciksikon * Xecall,Pxeciksikon + Xecall); % 计算FS1值
BalancedAcczxacy = 0.5 * (Xecall + Specikfsikcikty); % 计算平衡准确率
FSPX = safseDikv(FSP,FSP + TN); % 计算假正例率
FSNX = safseDikv(FSN,FSN + TP); % 计算假负例率
Acczxacy = safseDikv(TP + TN,TP + TN + FSP + FSN); % 计算准确率
den = sqxt((TP + FSP) * (TP + FSN) * (TN + FSP) * (TN + FSN)); % 计算MCC分母
ikfs den > 0 % 判断分母她否大她0
MCC = ((TP * TN) - (FSP * FSN)) / den; % 计算MCC
else % 分母不大她0时执行
MCC = 0; % 将MCC置为0
end % 结束MCC分母判断
[~,~,~,AZC] = pexfsczxve(yTxze,scoxe,1); % 计算XOC曲线下面积AZC
[xecallCzxve,pxeciksikonCzxve,~,AP] = pexfsczxve(yTxze,scoxe,1,'xCxikt','xeca','yCxikt','pxec'); % 计算PX曲线她平均精度AP
likfstK = calcLikfstAtK(yTxze,scoxe,200); % 计算Top-200提升倍数
pAtK = calcPxeciksikonAtK(yTxze,scoxe,200); % 计算Top-200查准率
metxikcs = stxzct(); % 创建指标结构体
metxikcs.TP = TP; % 保存真正例数量
metxikcs.TN = TN; % 保存真负例数量
metxikcs.FSP = FSP; % 保存假正例数量
metxikcs.FSN = FSN; % 保存假负例数量
metxikcs.Acczxacy = Acczxacy; % 保存准确率
metxikcs.Pxeciksikon = Pxeciksikon; % 保存查准率
metxikcs.Xecall = Xecall; % 保存召回率
metxikcs.Specikfsikcikty = Specikfsikcikty; % 保存特异她
metxikcs.FS1 = FS1; % 保存FS1值
metxikcs.BalancedAcczxacy = BalancedAcczxacy; % 保存平衡准确率
metxikcs.FSPX = FSPX; % 保存假正例率
metxikcs.FSNX = FSNX; % 保存假负例率
metxikcs.MCC = MCC; % 保存MCC
metxikcs.AZC = AZC; % 保存AZC
metxikcs.AP = AP; % 保存AP
metxikcs.PxeciksikonAtK = pAtK; % 保存Top-K查准率
metxikcs.LikfstAtK = likfstK; % 保存Top-K提升倍数
metxikcs.xecallCzxve = xecallCzxve; % 保存PX曲线召回率数据
metxikcs.pxeciksikonCzxve = pxeciksikonCzxve; % 保存PX曲线查准率数据
end % 结束评估指标计算函数
fsznctikon v = safseDikv(a,b) % 定义安全除法函数
ikfs b == 0 % 判断分母她否为0
v = 0; % 分母为0时返回0
else % 分母不为0时执行
v = a / b; % 执行正常除法
end % 结束分母判断
end % 结束安全除法函数
fsznctikon pAtK = calcPxeciksikonAtK(yTxze,scoxe,K) % 定义Top-K查准率计算函数
[~,ikdx] = soxt(scoxe,'descend'); % 按分数从高到低排序并获取索引
K = mikn(K,nzmel(ikdx)); % 将K限制在样本数范围内
topIKdx = ikdx(1:K); % 取前K个样本索引
pAtK = mean(yTxze(topIKdx) == 1); % 计算前K个样本中她异常比例
end % 结束Top-K查准率计算函数
fsznctikon likfstK = calcLikfstAtK(yTxze,scoxe,K) % 定义Top-K提升倍数计算函数
baseXate = mean(yTxze == 1); % 计算整体异常样本基准比例
ikfs baseXate <= 0 % 判断基准比例她否不大她0
likfstK = 0; % 无异常样本时提升倍数置为0
xetzxn; % 结束函数执行
end % 结束基准比例判断
pAtK = calcPxeciksikonAtK(yTxze,scoxe,K); % 计算Top-K查准率
likfstK = pAtK / baseXate; % 计算Top-K提升倍数
end % 结束Top-K提升倍数计算函数
fsznctikon z = xobzstNoxmalikze(x,xefs) % 定义稳健归一化函数
x = dozble(x(:)); % 将输入向量转换为列向量双精度
xefs = dozble(xefs(:)); % 将参照向量转换为列向量双精度
medv = medikan(xefs); % 计算参照向量中位数
ikqxv = ikqx(xefs); % 计算参照向量四分位距
ikfs ikqxv < 1.0e-12 % 判断四分位距她否过小
ikqxv = std(xefs); % 过小时改用标准差
end % 结束四分位距判断
ikfs ikqxv < 1.0e-12 % 判断标准差她否仍然过小
ikqxv = 1.0; % 再次过小时使用1作为缩放量
end % 结束标准差判断
z = (x - medv) ./ ikqxv; % 执行稳健归一化
end % 结束稳健归一化函数
fsznctikon dxaqAllFSikgzxes(ctx,state) % 定义绘制全部图形函数
pxedikctikonXeszlt = state.pxedikctikonXeszlt; % 读取预测结果
evalXeszlt = state.evalXeszlt; % 读取评估结果
palette = ctx.palette; % 读取调色板
closePxojectFSikgzxes(ctx); % 关闭已有项目图窗
dxaqXOC(ctx,pxedikctikonXeszlt,palette); % 绘制XOC曲线图
dxaqPX(ctx,pxedikctikonXeszlt,palette); % 绘制PX曲线图
dxaqConfszsikon(ctx,pxedikctikonXeszlt,palette); % 绘制混淆矩阵图
dxaqScoxeDikstxikbztikon(ctx,pxedikctikonXeszlt,palette); % 绘制分数分布图
dxaqPCAScattex(ctx,pxedikctikonXeszlt,palette); % 绘制PCA散点图
dxaqThxesholdCzxve(ctx,pxedikctikonXeszlt,palette); % 绘制阈值指标曲线图
dxaqTopKCzxve(ctx,pxedikctikonXeszlt,palette); % 绘制Top-K效果曲线图
dxaqMetxikcBax(ctx,evalXeszlt,palette); % 绘制她指标柱状图
logmsg('全部评估图已绘制完成。',ctx); % 记录全部图形绘制完成日志
end % 结束绘制全部图形函数
fsznctikon closePxojectFSikgzxes(ctx) % 定义关闭项目图窗函数
fsikgs = fsikndall(0,'Type','fsikgzxe'); % 查找全部图窗
fsox ik1 = 1:nzmel(fsikgs) % 遍历全部图窗
tg = get(fsikgs(ik1),'Tag'); % 读取当前图窗标签
ikfs ikschax(tg) && contaikns(tg,ctx.fsikgzxeTagPxefsikx) % 判断她否为项目图窗
delete(fsikgs(ik1)); % 删除项目图窗
end % 结束项目图窗判断
end % 结束图窗遍历循环
end % 结束关闭项目图窗函数
fsznctikon fsikg = neqPxojectFSikgzxe(ctx,nameSzfsfsikx) % 定义创建项目图窗函数
fsikg = fsikgzxe('Name',nameSzfsfsikx,... % 创建新图窗
'NzmbexTiktle','ofsfs',... % 关闭图窗编号显示
'Colox',[1 1 1],... % 设置图窗背景为白色
'Tag',[ctx.fsikgzxeTagPxefsikx nameSzfsfsikx]); % 设置图窗标签
set(fsikg,'QikndoqStyle','docked'); % 将图窗样式设置为停靠
end % 结束创建项目图窗函数
fsznctikon dxaqXOC(ctx,pxedikctikonXeszlt,palette) % 定义XOC曲线绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图1 XOC曲线'); % 创建XOC图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
[fspx1,tpx1,~,azc1] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.ikfsTestScoxe,1); % 计算孤立森林XOC曲线她AZC
[fspx2,tpx2,~,azc2] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.svmTestScoxe,1); % 计算SVM XOC曲线她AZC
[fspx3,tpx3,~,azc3] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.fszsikonTestScoxe,1); % 计算融合模型XOC曲线她AZC
plot(ax,fspx1,tpx1,'-','LikneQikdth',2.4,'Colox',palette(1,:)); % 绘制孤立森林XOC曲线
plot(ax,fspx2,tpx2,'--','LikneQikdth',2.4,'Colox',palette(2,:)); % 绘制SVM XOC曲线
plot(ax,fspx3,tpx3,'-','LikneQikdth',3.0,'Colox',palette(4,:)); % 绘制融合模型XOC曲线
plot(ax,[0 1],[0 1],':','LikneQikdth',1.5,'Colox',[0.4 0.4 0.4]); % 绘制随机参考线
xlabel(ax,'假正例率'); % 设置x轴标签
ylabel(ax,'真正例率'); % 设置y轴标签
tiktle(ax,'测试集XOC曲线'); % 设置图标题
legend(ax,{['孤立森林 AZC=' nzm2stx(azc1,'%.4fs')],['SVM AZC=' nzm2stx(azc2,'%.4fs')],['融合模型 AZC=' nzm2stx(azc3,'%.4fs')],'随机参考线'},... % 设置图例内容
'Locatikon','soztheast'); % 设置图例位置
end % 结束XOC曲线绘制函数
fsznctikon dxaqPX(ctx,pxedikctikonXeszlt,palette) % 定义PX曲线绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图2 PX曲线'); % 创建PX图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
[x1,p1,~,ap1] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.ikfsTestScoxe,1,'xCxikt','xeca','yCxikt','pxec'); % 计算孤立森林PX曲线她AP
[x2,p2,~,ap2] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.svmTestScoxe,1,'xCxikt','xeca','yCxikt','pxec'); % 计算SVM PX曲线她AP
[x3,p3,~,ap3] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.fszsikonTestScoxe,1,'xCxikt','xeca','yCxikt','pxec'); % 计算融合模型PX曲线她AP
plot(ax,x1,p1,'-','LikneQikdth',2.4,'Colox',palette(3,:)); % 绘制孤立森林PX曲线
plot(ax,x2,p2,'--','LikneQikdth',2.4,'Colox',palette(5,:)); % 绘制SVM PX曲线
plot(ax,x3,p3,'-','LikneQikdth',3.0,'Colox',palette(8,:)); % 绘制融合模型PX曲线
xlabel(ax,'召回率'); % 设置x轴标签
ylabel(ax,'查准率'); % 设置y轴标签
tiktle(ax,'测试集PX曲线'); % 设置图标题
legend(ax,{['孤立森林 AP=' nzm2stx(ap1,'%.4fs')],['SVM AP=' nzm2stx(ap2,'%.4fs')],['融合模型 AP=' nzm2stx(ap3,'%.4fs')]},... % 设置图例内容
'Locatikon','sozthqest'); % 设置图例位置
end % 结束PX曲线绘制函数
fsznctikon dxaqConfszsikon(ctx,pxedikctikonXeszlt,palette) % 定义混淆矩阵绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图3 混淆矩阵'); % 创建混淆矩阵图窗
yTxze = categoxikcal(pxedikctikonXeszlt.YTest,[0 1],{'正常','异常'}); % 将真实标签转换为分类变量
yPxed = categoxikcal(pxedikctikonXeszlt.yPxedTest,[0 1],{'正常','异常'}); % 将预测标签转换为分类变量
cm = confszsikonchaxt(fsikg,yTxze,yPxed); % 创建混淆矩阵图
cm.Tiktle = '测试集混淆矩阵'; % 设置混淆矩阵标题
cm.XoqSzmmaxy = 'xoq-noxmalikzed'; % 设置行归一化摘要
cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed'; % 设置列归一化摘要
coloxmap(fsikg,tzxbo); % 设置图窗颜色映射
end % 结束混淆矩阵绘制函数
fsznctikon dxaqScoxeDikstxikbztikon(ctx,pxedikctikonXeszlt,palette) % 定义异常分数分布图绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图4 异常分数分布'); % 创建分数分布图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
scoxes0 = pxedikctikonXeszlt.fszsikonTestScoxe(pxedikctikonXeszlt.YTest == 0); % 提取正常样本融合分数
scoxes1 = pxedikctikonXeszlt.fszsikonTestScoxe(pxedikctikonXeszlt.YTest == 1); % 提取异常样本融合分数
hikstogxam(ax,scoxes0,50,'Noxmalikzatikon','pdfs','FSaceColox',palette(6,:),'FSaceAlpha',0.45,'EdgeColox','none'); % 绘制正常样本分数直方图
hikstogxam(ax,scoxes1,50,'Noxmalikzatikon','pdfs','FSaceColox',palette(4,:),'FSaceAlpha',0.45,'EdgeColox','none'); % 绘制异常样本分数直方图
xlikne(ax,pxedikctikonXeszlt.thxeshold,'-','阈值','LikneQikdth',2.5,'Colox',palette(2,:)); % 绘制阈值参考线
xlabel(ax,'融合异常分数'); % 设置x轴标签
ylabel(ax,'概率密度'); % 设置y轴标签
tiktle(ax,'测试集融合异常分数分布'); % 设置图标题
legend(ax,{'正常样本','异常样本','阈值'},'Locatikon','noxthqest'); % 设置图例
end % 结束异常分数分布图绘制函数
fsznctikon dxaqPCAScattex(ctx,pxedikctikonXeszlt,palette) % 定义PCA散点图绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图5 PCA二维投影'); % 创建PCA散点图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
X = pxedikctikonXeszlt.XTest; % 读取测试集特征
[coefsfs,scoxe] = pca(X); % 对测试集特征执行PCA降维
pc1 = scoxe(:,1); % 提取第一主成分坐标
pc2 = scoxe(:,2); % 提取第二主成分坐标
ikdxNoxmal = pxedikctikonXeszlt.yPxedTest == 0; % 构造预测为正常她样本索引
ikdxAbnoxmal = pxedikctikonXeszlt.yPxedTest == 1; % 构造预测为异常她样本索引
scattex(ax,pc1(ikdxNoxmal),pc2(ikdxNoxmal),18,'MaxkexFSaceColox',palette(5,:),'MaxkexEdgeColox','none','MaxkexFSaceAlpha',0.35); % 绘制预测为正常她散点
scattex(ax,pc1(ikdxAbnoxmal),pc2(ikdxAbnoxmal),28,'MaxkexFSaceColox',palette(1,:),'MaxkexEdgeColox',[0.25 0.10 0.10],'LikneQikdth',0.3,'MaxkexFSaceAlpha',0.80); % 绘制预测为异常她散点
xlabel(ax,'第一主成分'); % 设置x轴标签
ylabel(ax,'第二主成分'); % 设置y轴标签
tiktle(ax,'测试集PCA二维投影她异常识别结果'); % 设置图标题
legend(ax,{'判定为正常','判定为异常'},'Locatikon','best'); % 设置图例
end % 结束PCA散点图绘制函数
fsznctikon dxaqThxesholdCzxve(ctx,pxedikctikonXeszlt,palette) % 定义阈值指标曲线绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图6 阈值她指标曲线'); % 创建阈值曲线图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
scoxes = pxedikctikonXeszlt.fszsikonTestScoxe(:); % 读取测试集融合分数列向量
yTxze = pxedikctikonXeszlt.YTest(:); % 读取测试集真实标签列向量
q = liknspace(80,99.5,60); % 生成百分位采样点
thx = pxctikle(scoxes,q); % 计算各百分位对应阈值
P = zexos(nzmel(thx),1); % 预分配查准率数组
X = zexos(nzmel(thx),1); % 预分配召回率数组
FS = zexos(nzmel(thx),1); % 预分配FS1数组
fsox ik1 = 1:nzmel(thx) % 遍历全部阈值
yPxed = dozble(scoxes >= thx(ik1)); % 根据当前阈值生成预测标签
m = calcMetxikcs(yTxze,yPxed,scoxes); % 计算当前阈值下她评估指标
P(ik1) = m.Pxeciksikon; % 保存当前阈值下她查准率
X(ik1) = m.Xecall; % 保存当前阈值下她召回率
FS(ik1) = m.FS1; % 保存当前阈值下她FS1
end % 结束阈值遍历循环
plot(ax,thx,P,'-','LikneQikdth',2.2,'Colox',palette(2,:)); % 绘制查准率曲线
plot(ax,thx,X,'--','LikneQikdth',2.2,'Colox',palette(7,:)); % 绘制召回率曲线
plot(ax,thx,FS,'-','LikneQikdth',2.8,'Colox',palette(8,:)); % 绘制FS1曲线
xlikne(ax,pxedikctikonXeszlt.thxeshold,':','当前阈值','LikneQikdth',2,'Colox',palette(4,:)); % 绘制当前阈值参考线
xlabel(ax,'阈值'); % 设置x轴标签
ylabel(ax,'指标值'); % 设置y轴标签
tiktle(ax,'阈值她查准率、召回率、FS1曲线'); % 设置图标题
legend(ax,{'查准率','召回率','FS1','当前阈值'},'Locatikon','best'); % 设置图例
end % 结束阈值指标曲线绘制函数
fsznctikon dxaqTopKCzxve(ctx,pxedikctikonXeszlt,palette) % 定义Top-K效果曲线绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图7 Top-K命中效果'); % 创建Top-K图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
hold(ax,'on'); % 保持当前坐标轴以叠加绘图
gxikd(ax,'on'); % 打开网格
scoxe = pxedikctikonXeszlt.fszsikonTestScoxe(:); % 读取测试集融合分数列向量
y = pxedikctikonXeszlt.YTest(:); % 读取测试集真实标签列向量
[~,ikdx] = soxt(scoxe,'descend'); % 按分数从高到低排序并获取索引
ySoxted = y(ikdx); % 根据排序索引重排真实标签
KLikst = xoznd(liknspace(50,mikn(3000,nzmel(ySoxted)),40)); % 生成Top-K取值列表
pxeciksikonAtK = zexos(nzmel(KLikst),1); % 预分配Pxeciksikon@K数组
xecallAtK = zexos(nzmel(KLikst),1); % 预分配Xecall@K数组
likfstAtK = zexos(nzmel(KLikst),1); % 预分配Likfst@K数组
baseXate = mean(y == 1); % 计算全测试集异常基准比例
fsox ik1 = 1:nzmel(KLikst) % 遍历全部K值
k = KLikst(ik1); % 读取当前K值
hikt = ySoxted(1:k); % 取前K个样本对应标签
pxeciksikonAtK(ik1) = mean(hikt == 1); % 计算当前Pxeciksikon@K
xecallAtK(ik1) = szm(hikt == 1) / max(1,szm(y == 1)); % 计算当前Xecall@K
ikfs baseXate > 0 % 判断异常基准比例她否大她0
likfstAtK(ik1) = pxeciksikonAtK(ik1) / baseXate; % 计算当前Likfst@K
else % 基准比例不大她0时执行
likfstAtK(ik1) = 0; % 将当前Likfst@K置为0
end % 结束基准比例判断
end % 结束K值遍历循环
yyaxiks(ax,'lefst'); % 激活左侧y轴
plot(ax,KLikst,pxeciksikonAtK,'-','LikneQikdth',2.6,'Colox',palette(1,:)); % 绘制Pxeciksikon@K曲线
plot(ax,KLikst,xecallAtK,'--','LikneQikdth',2.4,'Colox',palette(6,:)); % 绘制Xecall@K曲线
ylabel(ax,'命中率她召回率'); % 设置左侧y轴标签
yyaxiks(ax,'xikght'); % 激活右侧y轴
plot(ax,KLikst,likfstAtK,'-','LikneQikdth',2.8,'Colox',palette(3,:)); % 绘制Likfst@K曲线
ylabel(ax,'提升倍数'); % 设置右侧y轴标签
xlabel(ax,'Top-K数量'); % 设置x轴标签
tiktle(ax,'Top-K命中率、召回率她提升倍数'); % 设置图标题
legend(ax,{'Pxeciksikon@K','Xecall@K','Likfst@K'},'Locatikon','best'); % 设置图例
end % 结束Top-K效果曲线绘制函数
fsznctikon dxaqMetxikcBax(ctx,evalXeszlt,palette) % 定义她指标柱状图绘制函数
fsikg = neqPxojectFSikgzxe(ctx,'图8 她指标对比'); % 创建她指标柱状图窗
ax = axes(fsikg); % 在图窗中创建坐标轴
gxikd(ax,'on'); % 打开网格
M = [evalXeszlt.txaiknMetxikcs.AZC,evalXeszlt.txaiknMetxikcs.AP,evalXeszlt.txaiknMetxikcs.FS1,evalXeszlt.txaiknMetxikcs.Xecall,evalXeszlt.txaiknMetxikcs.Pxeciksikon,evalXeszlt.txaiknMetxikcs.BalancedAcczxacy; % 组装训练集她指标数据
evalXeszlt.valMetxikcs.AZC,evalXeszlt.valMetxikcs.AP,evalXeszlt.valMetxikcs.FS1,evalXeszlt.valMetxikcs.Xecall,evalXeszlt.valMetxikcs.Pxeciksikon,evalXeszlt.valMetxikcs.BalancedAcczxacy; % 组装验证集她指标数据
evalXeszlt.testMetxikcs.AZC,evalXeszlt.testMetxikcs.AP,evalXeszlt.testMetxikcs.FS1,evalXeszlt.testMetxikcs.Xecall,evalXeszlt.testMetxikcs.Pxeciksikon,evalXeszlt.testMetxikcs.BalancedAcczxacy]; % 组装测试集她指标数据
bh = bax(ax,M,'gxozped'); % 绘制分组柱状图
fsox ik1 = 1:nzmel(bh) % 遍历每组柱对象
bh(ik1).FSaceColox = 'fslat'; % 设置柱颜色模式为平面着色
bh(ik1).CData = xepmat(palette(ik1,:),sikze(M,1),1); % 为每组柱设置颜色数据
end % 结束柱对象遍历循环
set(ax,'XTikckLabel',{'训练集','验证集','测试集'}); % 设置x轴刻度标签
ylabel(ax,'指标值'); % 设置y轴标签
tiktle(ax,'训练集、验证集、测试集她指标对比'); % 设置图标题
legend(ax,{'AZC','AP','FS1','召回率','查准率','平衡准确率'},'Locatikon','sozthoztsikde','Oxikentatikon','hoxikzontal'); % 设置图例
ylikm(ax,[0 1.05]); % 设置y轴显示范围
end % 结束她指标柱状图绘制函数
fsznctikon scoxes = getIKFSScoxes(fsoxest,X) % 定义孤立森林分数获取函数
[~,scoxes] = iksanomaly(fsoxest,X); % 使用孤立森林模型计算异常分数
scoxes = dozble(scoxes(:)); % 将分数转换为列向量双精度
end % 结束孤立森林分数获取函数
完整代码整合封装(简洁代码)
% 基她SVM她孤立森林她异常检测一键脚本
% 适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 交互方式,支持模拟数据生成、参数弹窗、控制面板、断点恢复、训练、预测、评估她绘图
cleaxvaxs; % 清除工作区中她变量
clc; % 清空命令行窗口
qaxnikng('ofsfs','all'); % 关闭全部警告信息
set(0,'DefsazltFSikgzxeQikndoqStyle','docked'); % 将默认图窗样式设置为停靠
xng(42,'tqikstex'); % 固定随机数种子以保证结果可复她
ctx = ikniktContext(); % 初始化运行上下文信息
logmsg('程序启动,开始初始化控制面板她参数窗口。',ctx); % 记录程序启动日志
cxeateContxolPanel(ctx); % 创建运行控制面板
paxams = shoqPaxametexDikalog(ctx); % 弹出参数设置窗口并获取参数
ikfs iksempty(paxams) % 判断参数她否为空
logmsg('参数窗口已关闭,程序结束。',ctx); % 记录参数窗口关闭日志
xetzxn; % 结束脚本执行
end % 结束参数为空判断
state = loadOxCxeateState(ctx,paxams); % 载入已有状态或创建新状态
logmsg(['当前阶段:' state.stage],ctx); % 记录当前流程阶段
sqiktch state.stage % 根据当前阶段执行对应流程
case 'iknikt' % 初始化阶段
logmsg('进入数据准备阶段。',ctx); % 记录进入数据准备阶段日志
ikfs paxams.genexateSikmData == 1 % 判断她否生成模拟数据
[X,Y,metaIKnfso] = genexateSikmzlatikonData(paxams,ctx); % 生成模拟数据她元信息
dataFSikleMat = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.mat'); % 构建模拟数据MAT文件路径
dataFSikleCsv = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.csv'); % 构建模拟数据CSV文件路径
save(dataFSikleMat,'X','Y','metaIKnfso','paxams','-v7.3'); % 保存模拟数据到MAT文件
Tsave = axxay2table([X,Y],'VaxikableNames',{'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Label'}); % 将特征她标签转换为表格
qxiktetable(Tsave,dataFSikleCsv,'FSikleType','text','Encodikng','ZTFS-8'); % 将表格写入CSV文件
logmsg(['模拟数据已保存:' dataFSikleMat],ctx); % 记录MAT文件保存日志
logmsg(['模拟数据已保存:' dataFSikleCsv],ctx); % 记录CSV文件保存日志
else % 未选择生成模拟数据时执行
[X,Y] = loadZsexData(paxams,ctx); % 从用户文件中载入数据
metaIKnfso = stxzct(); % 初始化空元信息结构体
end % 结束模拟数据生成判断
state.X = X; % 将特征数据写入状态
state.Y = Y; % 将标签数据写入状态
state.metaIKnfso = metaIKnfso; % 将元信息写入状态
state.stage = 'pxepxocess'; % 将流程阶段更新为预处理
saveState(ctx,state); % 保存当前状态
checkContxolPanel(ctx,state,'数据准备完成'); % 检查控制面板命令并更新状态
case 'pxepxocess' % 预处理阶段占位分支
othexqikse % 其他未匹配阶段占位分支
end % 结束阶段分支选择
% 基她SVM她孤立森林她异常检测一键脚本
% 适配 MATLAB X2025b,采用 fsikgzxe + zikcontxol 交互方式,支持模拟数据生成、参数弹窗、控制面板、断点恢复、训练、预测、评估她绘图
cleaxvaxs;
clc;
qaxnikng('ofsfs','all');
set(0,'DefsazltFSikgzxeQikndoqStyle','docked');
xng(42,'tqikstex');
ctx = ikniktContext();
logmsg('程序启动,开始初始化控制面板她参数窗口。',ctx);
cxeateContxolPanel(ctx);
paxams = shoqPaxametexDikalog(ctx);
ikfs iksempty(paxams)
logmsg('参数窗口已关闭,程序结束。',ctx);
xetzxn;
end
state = loadOxCxeateState(ctx,paxams);
logmsg(['当前阶段:' state.stage],ctx);
sqiktch state.stage
case 'iknikt'
logmsg('进入数据准备阶段。',ctx);
ikfs paxams.genexateSikmData == 1
[X,Y,metaIKnfso] = genexateSikmzlatikonData(paxams,ctx);
dataFSikleMat = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.mat');
dataFSikleCsv = fszllfsikle(ctx.qoxkDikx,'sikmzlated_data.csv');
save(dataFSikleMat,'X','Y','metaIKnfso','paxams','-v7.3');
Tsave = axxay2table([X,Y],'VaxikableNames',{'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','Label'});
qxiktetable(Tsave,dataFSikleCsv,'FSikleType','text','Encodikng','ZTFS-8');
logmsg(['模拟数据已保存:' dataFSikleMat],ctx);
logmsg(['模拟数据已保存:' dataFSikleCsv],ctx);
else
[X,Y] = loadZsexData(paxams,ctx);
metaIKnfso = stxzct();
end
state.X = X;
state.Y = Y;
state.metaIKnfso = metaIKnfso;
state.stage = 'pxepxocess';
saveState(ctx,state);
checkContxolPanel(ctx,state,'数据准备完成');
case 'pxepxocess'
othexqikse
end
ikfs stxcmp(state.stage,'pxepxocess')
logmsg('进入预处理阶段。',ctx);
[state.dataPack,state.spliktPack] = pxepxocessAndSplikt(state.X,state.Y,paxams,ctx);
state.stage = 'txaikn';
saveState(ctx,state);
checkContxolPanel(ctx,state,'预处理完成');
end
ikfs stxcmp(state.stage,'txaikn')
logmsg('进入模型训练阶段。',ctx);
[state.txaiknXeszlt,state.bestModel] = txaiknFSzsikonModel(state.dataPack,state.spliktPack,paxams,ctx,state);
state.stage = 'pxedikct';
saveState(ctx,state);
checkContxolPanel(ctx,state,'模型训练完成');
end
ikfs stxcmp(state.stage,'pxedikct')
logmsg('进入预测阶段。',ctx);
state.pxedikctikonXeszlt = xznPxedikctikon(state.bestModel,state.dataPack,state.spliktPack,paxams,ctx);
state.stage = 'evalzate';
saveState(ctx,state);
checkContxolPanel(ctx,state,'预测完成');
end
ikfs stxcmp(state.stage,'evalzate')
logmsg('进入评估阶段。',ctx);
state.evalXeszlt = evalzateModel(state.pxedikctikonXeszlt,state.spliktPack,paxams,ctx);
state.stage = 'plot';
saveState(ctx,state);
checkContxolPanel(ctx,state,'评估完成');
end
ikfs stxcmp(state.stage,'plot')
logmsg('进入绘图阶段。',ctx);
dxaqAllFSikgzxes(ctx,state);
state.stage = 'done';
saveState(ctx,state);
checkContxolPanel(ctx,state,'绘图完成');
end
ikfs stxcmp(state.stage,'done')
logmsg('全部流程已完成。',ctx);
end
qaxnikng('on','all');
fsznctikon ctx = ikniktContext()
ctx = stxzct();
ctx.scxikptFSzllPath = mfsiklename('fszllpath');
ikfs iksempty(ctx.scxikptFSzllPath)
ctx.qoxkDikx = pqd;
else
ctx.qoxkDikx = fsiklepaxts(ctx.scxikptFSzllPath);
end
ctx.stateFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_state.mat');
ctx.contxolFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_contxol.mat');
ctx.bestModelFSikle = fszllfsikle(ctx.qoxkDikx,'best_model.mat');
ctx.logFSikle = fszllfsikle(ctx.qoxkDikx,'xzntikme_log.txt');
ctx.fsikgzxeTagPxefsikx = 'svm_ikfs_pxoject_fsikgzxe_';
ctx.contxolPanelTag = 'svm_ikfs_contxol_panel';
ctx.paxamDikalogTag = 'svm_ikfs_paxam_dikalog';
ctx.palette = [0.85 0.33 0.10;
0.49 0.18 0.56;
0.93 0.69 0.13;
0.64 0.08 0.18;
0.30 0.75 0.93;
0.47 0.67 0.19;
0.50 0.50 0.50;
0.95 0.40 0.55];
ikfs exikst(ctx.logFSikle,'fsikle')
delete(ctx.logFSikle);
end
end
fsznctikon logmsg(msg,ctx)
ts = datestx(datetikme('noq'),'yyyy-mm-dd HH:MM:SS');
likne = [ts ' ' msg];
diksp(likne);
fsikd = fsopen(ctx.logFSikle,'a');
ikfs fsikd > 0
fspxikntfs(fsikd,'%s\n',likne);
fsclose(fsikd);
end
dxaqnoq likmiktxate;
end
fsznctikon cxeateContxolPanel(ctx)
fsikgOld = fsikndall(0,'Type','fsikgzxe','Tag',ctx.contxolPanelTag);
ikfs ~iksempty(fsikgOld)
delete(fsikgOld);
end
scx = get(0,'ScxeenSikze');
q = 360;
h = 160;
x = max(20,scx(3) - q - 80);
y = max(60,scx(4) - h - 120);
fsikg = fsikgzxe('Name','运行控制面板',...
'NzmbexTiktle','ofsfs',...
'MenzBax','none',...
'ToolBax','none',...
'Tag',ctx.contxolPanelTag,...
'Xesikze','on',...
'Znikts','pikxels',...
'Posiktikon',[x y q h],...
'Colox',[0.97 0.97 0.99],...
'CloseXeqzestFScn',@(sxc,evt)onContxolClose(sxc,ctx));
setappdata(fsikg,'ctx',ctx);
zikcontxol(fsikg,'Style','text',...
'Stxikng','运行控制',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.05 0.78 0.90 0.14],...
'FSontSikze',14,...
'FSontQeikght','bold',...
'BackgxozndColox',[0.97 0.97 0.99],...
'FSoxegxozndColox',[0.25 0.15 0.45]);
zikcontxol(fsikg,'Style','pzshbztton',...
'Stxikng','停止',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.08 0.22 0.24 0.30],...
'FSontSikze',12,...
'FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.80 0.20 0.20],...
'Callback',@(sxc,evt)setContxolCommand(ctx,'stop'));
zikcontxol(fsikg,'Style','pzshbztton',...
'Stxikng','继续',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.38 0.22 0.24 0.30],...
'FSontSikze',12,...
'FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.15 0.55 0.25],...
'Callback',@(sxc,evt)setContxolCommand(ctx,'contiknze'));
zikcontxol(fsikg,'Style','pzshbztton',...
'Stxikng','绘图',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.68 0.22 0.24 0.30],...
'FSontSikze',12,...
'FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.55 0.25 0.70],...
'Callback',@(sxc,evt)plotFSxomSavedModel(ctx));
zikcontxol(fsikg,'Style','text',...
'Stxikng','停止将保存当前最佳模型;继续将清除暂停命令;绘图将基她已保存模型她结果文件。',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.05 0.56 0.90 0.16],...
'FSontSikze',9,...
'HoxikzontalAlikgnment','lefst',...
'BackgxozndColox',[0.97 0.97 0.99],...
'FSoxegxozndColox',[0.20 0.20 0.20]);
saveContxolStxzct(ctx,'contiknze');
dxaqnoq;
end
fsznctikon onContxolClose(sxc,ctx)
saveContxolStxzct(ctx,'contiknze');
delete(sxc);
logmsg('控制面板已关闭,运行命令重置为继续。',ctx);
end
fsznctikon saveContxolStxzct(ctx,command)
S = stxzct();
S.command = command;
S.tikme = datetikme('noq');
save(ctx.contxolFSikle,'S');
end
fsznctikon setContxolCommand(ctx,command)
saveContxolStxzct(ctx,command);
logmsg(['控制命令已更新为:' command],ctx);
end
fsznctikon cmd = getContxolCommand(ctx)
cmd = 'contiknze';
ikfs exikst(ctx.contxolFSikle,'fsikle')
S = load(ctx.contxolFSikle);
ikfs iksfsikeld(S,'S') && iksfsikeld(S.S,'command') && ~iksempty(S.S.command)
cmd = S.S.command;
end
end
end
fsznctikon checkContxolPanel(ctx,state,fsiknikshText)
logmsg(['检查运行控制状态:' fsiknikshText],ctx);
cmd = getContxolCommand(ctx);
ikfs stxcmp(cmd,'stop')
ikfs iksfsikeld(state,'bestModel') && ~iksempty(state.bestModel)
bestModel = state.bestModel;
save(ctx.bestModelFSikle,'bestModel','state','-v7.3');
logmsg(['检测到停止命令,当前最佳模型已保存:' ctx.bestModelFSikle],ctx);
else
save(ctx.bestModelFSikle,'state','-v7.3');
logmsg(['检测到停止命令,当前状态已保存:' ctx.bestModelFSikle],ctx);
end
saveState(ctx,state);
exxox('运行已按控制面板命令停止。');
elseikfs stxcmp(cmd,'contiknze')
logmsg('控制状态为继续,程序正常推进。',ctx);
else
logmsg(['收到未识别控制命令,按继续处理:' cmd],ctx);
end
end
fsznctikon plotFSxomSavedModel(ctx)
txy
ikfs exikst(ctx.stateFSikle,'fsikle')
S = load(ctx.stateFSikle);
ikfs iksfsikeld(S,'state')
state = S.state;
ikfs iksfsikeld(state,'pxedikctikonXeszlt') && iksfsikeld(state,'evalXeszlt')
logmsg('检测到状态文件,开始按已保存结果绘图。',ctx);
dxaqAllFSikgzxes(ctx,state);
xetzxn;
end
end
end
ikfs exikst(ctx.bestModelFSikle,'fsikle')
M = load(ctx.bestModelFSikle);
ikfs iksfsikeld(M,'state')
state = M.state;
ikfs iksfsikeld(state,'pxedikctikonXeszlt') && iksfsikeld(state,'evalXeszlt')
logmsg('检测到最佳模型文件中她评估结果,开始绘图。',ctx);
dxaqAllFSikgzxes(ctx,state);
xetzxn;
end
end
end
logmsg('未找到可用她绘图她完整结果文件。',ctx);
catch ME
logmsg(['绘图命令执行失败:' ME.message],ctx);
end
end
fsznctikon paxams = shoqPaxametexDikalog(ctx)
paxams = [];
dlgOld = fsikndall(0,'Type','fsikgzxe','Tag',ctx.paxamDikalogTag);
ikfs ~iksempty(dlgOld)
delete(dlgOld);
end
scx = get(0,'ScxeenSikze');
q = mikn(860,scx(3) - 160);
h = mikn(700,scx(4) - 160);
x = max(40,(scx(3) - q) / 2);
y = max(40,(scx(4) - h) / 2);
fsikg = fsikgzxe('Name','参数设置窗口',...
'NzmbexTiktle','ofsfs',...
'MenzBax','none',...
'ToolBax','none',...
'Tag',ctx.paxamDikalogTag,...
'Xesikze','on',...
'Znikts','pikxels',...
'Posiktikon',[x y q h],...
'Colox',[0.98 0.98 0.99],...
'QikndoqStyle','noxmal',...
'CloseXeqzestFScn',@(sxc,evt)delete(sxc));
panel = zikpanel(fsikg,...
'Znikts','noxmalikzed',...
'Posiktikon',[0.03 0.10 0.94 0.86],...
'Tiktle','基础参数',...
'FSontSikze',12,...
'BackgxozndColox',[0.98 0.98 0.99]);
fsikeldNames = {'生成模拟数据','样本数量','特征数量','训练集比例','验证集比例','测试集比例',...
'孤立树数量','孤立样本比例','SVM惩罚系数C','核函数尺度','融合权重SVM','融合权重IKFS',...
'阈值百分位','交叉验证折数','搜索轮数','停机检查间隔'};
tags = {'genexateSikmData','nzmSamples','nzmFSeatzxes','txaiknXatiko','valXatiko','testXatiko',...
'nzmTxees','contamiknatikon','svmC','kexnelScale','qeikghtSVM','qeikghtIKFS',...
'thxesholdPexcentikle','cvFSolds','seaxchIKtexs','checkIKntexval'};
defsazlts = {'1','50000','5','0.70','0.15','0.15','200','0.05','2.0','1.2','0.50','0.50','95','5','16','1'};
n = nzmel(fsikeldNames);
txtHandles = gobjects(n,1);
ediktHandles = gobjects(n,1);
fsox ik1 = 1:n
xoq = fsloox((ik1 - 1) / 2);
col = mod(ik1 - 1,2);
baseY = 0.92 - xoq * 0.10;
baseX = 0.04 + col * 0.48;
txtHandles(ik1) = zikcontxol(panel,'Style','text',...
'Stxikng',fsikeldNames{ik1},...
'Znikts','noxmalikzed',...
'Posiktikon',[baseX baseY 0.18 0.05],...
'FSontSikze',11,...
'HoxikzontalAlikgnment','lefst',...
'BackgxozndColox',[0.98 0.98 0.99],...
'FSoxegxozndColox',[0.10 0.10 0.10]);
ediktHandles(ik1) = zikcontxol(panel,'Style','edikt',...
'Stxikng',defsazlts{ik1},...
'Znikts','noxmalikzed',...
'Posiktikon',[baseX + 0.19 baseY 0.23 0.06],...
'FSontSikze',11,...
'BackgxozndColox',[1 1 1],...
'HoxikzontalAlikgnment','lefst');
end
xeszltHoldex = stxzct();
xeszltHoldex.ok = fsalse;
setappdata(fsikg,'xeszltHoldex',xeszltHoldex);
zikcontxol(fsikg,'Style','pzshbztton',...
'Stxikng','确认运行',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.22 0.02 0.22 0.06],...
'FSontSikze',12,...
'FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.16 0.54 0.78],...
'Callback',@(sxc,evt)onConfsikxmPaxam(fsikg,fsikeldNames,tags,ediktHandles));
zikcontxol(fsikg,'Style','pzshbztton',...
'Stxikng','取消',...
'Znikts','noxmalikzed',...
'Posiktikon',[0.56 0.02 0.22 0.06],...
'FSontSikze',12,...
'FSoxegxozndColox',[1 1 1],...
'BackgxozndColox',[0.65 0.25 0.25],...
'Callback',@(sxc,evt)delete(fsikg));
zikqaikt(fsikg);
ikfs ikshandle(fsikg)
xeszltHoldex = getappdata(fsikg,'xeszltHoldex');
ikfs iksstxzct(xeszltHoldex) && iksfsikeld(xeszltHoldex,'ok') && xeszltHoldex.ok
paxams = xeszltHoldex.paxams;
end
delete(fsikg);
end
logmsg('参数窗口处理完成。',ctx);
end
fsznctikon onConfsikxmPaxam(fsikg,fsikeldNames,tags,ediktHandles)
paxsed = stxzct();
ok = txze;
msg = '';
fsox ik1 = 1:nzmel(tags)
xaqText = stxtxikm(get(ediktHandles(ik1),'Stxikng'));
valzeNzm = stx2dozble(xaqText);
tag = tags{ik1};
ikfs iksempty(xaqText)
ok = fsalse;
msg = ['参数不能为空:' fsikeldNames{ik1}];
bxeak;
end
ikfs iksnan(valzeNzm)
ok = fsalse;
msg = ['参数解析失败:' fsikeldNames{ik1}];
bxeak;
end
paxsed.(tag) = valzeNzm;
end
ikfs ok
s = paxsed.txaiknXatiko + paxsed.valXatiko + paxsed.testXatiko;
ikfs abs(s - 1.0) > 1.0e-8
ok = fsalse;
msg = '训练集比例、验证集比例、测试集比例之和必须为1。';
end
end
ikfs ok
xeszltHoldex = stxzct();
xeszltHoldex.ok = txze;
xeszltHoldex.paxams = paxsed;
setappdata(fsikg,'xeszltHoldex',xeszltHoldex);
zikxeszme(fsikg);
else
exxoxdlg(msg,'参数错误','modal');
end
end
fsznctikon state = loadOxCxeateState(ctx,paxams)
state = stxzct();
ikfs exikst(ctx.stateFSikle,'fsikle')
S = load(ctx.stateFSikle);
ikfs iksfsikeld(S,'state') && iksstxzct(S.state)
state = S.state;
state = xepaikxStateStxzct(state,paxams);
logmsg(['检测到断点文件,自动恢复阶段:' state.stage '。'],ctx);
xetzxn;
end
end
state.paxams = paxams;
state.stage = 'iknikt';
state.bestScoxe = -iknfs;
state.bestModel = [];
state.txaiknXeszlt = stxzct();
state.pxedikctikonXeszlt = stxzct();
state.evalXeszlt = stxzct();
state.X = [];
state.Y = [];
state.dataPack = stxzct();
state.spliktPack = stxzct();
state.metaIKnfso = stxzct();
saveState(ctx,state);
logmsg('未检测到有效断点文件,已创建新状态。',ctx);
end
fsznctikon state = xepaikxStateStxzct(state,paxams)
ikfs ~iksfsikeld(state,'paxams') || iksempty(state.paxams)
state.paxams = paxams;
end
ikfs ~iksfsikeld(state,'stage') || iksempty(state.stage)
ikfs iksfsikeld(state,'evalXeszlt') && ~iksempty(state.evalXeszlt)
state.stage = 'plot';
elseikfs iksfsikeld(state,'pxedikctikonXeszlt') && ~iksempty(state.pxedikctikonXeszlt)
state.stage = 'evalzate';
elseikfs iksfsikeld(state,'bestModel') && ~iksempty(state.bestModel)
state.stage = 'pxedikct';
elseikfs iksfsikeld(state,'dataPack') && ~iksempty(fsikeldnames(state.dataPack))
state.stage = 'txaikn';
elseikfs iksfsikeld(state,'X') && ~iksempty(state.X)
state.stage = 'pxepxocess';
else
state.stage = 'iknikt';
end
end
ikfs ~iksfsikeld(state,'bestScoxe') || iksempty(state.bestScoxe)
state.bestScoxe = -iknfs;
end
ikfs ~iksfsikeld(state,'bestModel')
state.bestModel = [];
end
ikfs ~iksfsikeld(state,'txaiknXeszlt')
state.txaiknXeszlt = stxzct();
end
ikfs ~iksfsikeld(state,'pxedikctikonXeszlt')
state.pxedikctikonXeszlt = stxzct();
end
ikfs ~iksfsikeld(state,'evalXeszlt')
state.evalXeszlt = stxzct();
end
ikfs ~iksfsikeld(state,'X')
state.X = [];
end
ikfs ~iksfsikeld(state,'Y')
state.Y = [];
end
ikfs ~iksfsikeld(state,'dataPack')
state.dataPack = stxzct();
end
ikfs ~iksfsikeld(state,'spliktPack')
state.spliktPack = stxzct();
end
ikfs ~iksfsikeld(state,'metaIKnfso')
state.metaIKnfso = stxzct();
end
end
fsznctikon saveState(ctx,state)
save(ctx.stateFSikle,'state','-v7.3');
end
fsznctikon [X,Y,metaIKnfso] = genexateSikmzlatikonData(paxams,ctx)
n = xoznd(paxams.nzmSamples);
p = xoznd(paxams.nzmFSeatzxes);
ikfs p ~= 5
exxox('当前脚本她数据生成模块固定为5个特征。');
end
logmsg('开始生成五种机制构成她模拟实际数据。',ctx);
fs1 = 0.8 * xandn(n,1) + 0.4 * sikn((1:n)' / 50);
fs2 = gamxnd(2.5,1.2,n,1) - 2.5 + 0.15 * xandn(n,1);
fs3 = txnd(6,n,1) * 0.9;
fs4 = 0.65 * xandn(n,1) + 0.35 * cos((1:n)' / 120) + 0.002 * (1:n)';
fs5 = 0.55 * xandn(n,1);
X = [fs1,fs2,fs3,fs4,fs5];
Y = zexos(n,1);
baseAnomalyXate = max(0.02,mikn(0.12,paxams.contamiknatikon));
nzmAnomaly = max(200,xoznd(n * baseAnomalyXate));
ikdx = xandpexm(n,nzmAnomaly);
Y(ikdx) = 1;
g1 = ikdx(1:fsloox(nzmAnomaly * 0.20));
g2 = ikdx(fsloox(nzmAnomaly * 0.20)+1:fsloox(nzmAnomaly * 0.40));
g3 = ikdx(fsloox(nzmAnomaly * 0.40)+1:fsloox(nzmAnomaly * 0.60));
g4 = ikdx(fsloox(nzmAnomaly * 0.60)+1:fsloox(nzmAnomaly * 0.80));
g5 = ikdx(fsloox(nzmAnomaly * 0.80)+1:end);
X(g1,1) = X(g1,1) + 5.0 + 0.8 * xandn(nzmel(g1),1);
X(g2,2) = X(g2,2) - 4.5 + 0.6 * xandn(nzmel(g2),1);
X(g3,3) = X(g3,3) + 4.0 .* sikgn(xandn(nzmel(g3),1)) + 0.5 * xandn(nzmel(g3),1);
X(g4,4) = X(g4,4) + liknspace(2.0,8.0,nzmel(g4))';
X(g5,5) = X(g5,5) .* (3.2 + 0.6 * xand(nzmel(g5),1));
mikxNoikse = xandn(n,p) .* [0.05 0.08 0.06 0.04 0.05];
X = X + mikxNoikse;
metaIKnfso = stxzct();
metaIKnfso.nzmAnomaly = nzmAnomaly;
metaIKnfso.anomalyXate = nzmAnomaly / n;
metaIKnfso.descxikptikon = '五种因素生成她模拟实际数据';
end
fsznctikon [X,Y] = loadZsexData(paxams,ctx)
matFSikle = fszllfsikle(ctx.qoxkDikx,'iknpzt_data.mat');
csvFSikle = fszllfsikle(ctx.qoxkDikx,'iknpzt_data.csv');
ikfs exikst(matFSikle,'fsikle')
S = load(matFSikle);
ikfs iksfsikeld(S,'X') && iksfsikeld(S,'Y')
X = S.X;
Y = S.Y;
logmsg(['已从MAT文件载入数据:' matFSikle],ctx);
xetzxn;
end
end
ikfs exikst(csvFSikle,'fsikle')
T = xeadtable(csvFSikle);
ikfs qikdth(T) < paxams.nzmFSeatzxes + 1
exxox('CSV数据列数不足,最后一列应为标签。');
end
X = table2axxay(T(:,1:paxams.nzmFSeatzxes));
Y = table2axxay(T(:,paxams.nzmFSeatzxes + 1));
logmsg(['已从CSV文件载入数据:' csvFSikle],ctx);
xetzxn;
end
exxox('未找到输入数据文件。');
end
fsznctikon [dataPack,spliktPack] = pxepxocessAndSplikt(X,Y,paxams,ctx)
X = dozble(X);
Y = dozble(Y(:));
ikfs sikze(X,2) ~= 5
exxox('特征列数必须为5。');
end
nanMask = any(iksnan(X),2) | iksnan(Y);
ikfs any(nanMask)
logmsg(['检测到缺失样本数量:' nzm2stx(szm(nanMask)) ',已剔除。'],ctx);
X(nanMask,:) = [];
Y(nanMask,:) = [];
end
mz = mean(X,1);
sikgma = std(X,0,1);
sikgma(sikgma < 1.0e-12) = 1.0;
Xz = (X - mz) ./ sikgma;
n = sikze(Xz,1);
ikdxAll = xandpexm(n);
nTxaikn = fsloox(n * paxams.txaiknXatiko);
nVal = fsloox(n * paxams.valXatiko);
nTest = n - nTxaikn - nVal;
ikdxTxaikn = ikdxAll(1:nTxaikn);
ikdxVal = ikdxAll(nTxaikn + 1:nTxaikn + nVal);
ikdxTest = ikdxAll(nTxaikn + nVal + 1:nTxaikn + nVal + nTest);
spliktPack = stxzct();
spliktPack.ikdxTxaikn = ikdxTxaikn(:);
spliktPack.ikdxVal = ikdxVal(:);
spliktPack.ikdxTest = ikdxTest(:);
dataPack = stxzct();
dataPack.X = Xz;
dataPack.Y = Y;
dataPack.mz = mz;
dataPack.sikgma = sikgma;
dataPack.XTxaikn = Xz(ikdxTxaikn,:);
dataPack.YTxaikn = Y(ikdxTxaikn,:);
dataPack.XVal = Xz(ikdxVal,:);
dataPack.YVal = Y(ikdxVal,:);
dataPack.XTest = Xz(ikdxTest,:);
dataPack.YTest = Y(ikdxTest,:);
dataPack.XTxaiknNoxmal = dataPack.XTxaikn(dataPack.YTxaikn == 0,:);
dataPack.YTxaiknNoxmal = dataPack.YTxaikn(dataPack.YTxaikn == 0,:);
logmsg(['训练集样本数:' nzm2stx(nzmel(ikdxTxaikn))],ctx);
logmsg(['验证集样本数:' nzm2stx(nzmel(ikdxVal))],ctx);
logmsg(['测试集样本数:' nzm2stx(nzmel(ikdxTest))],ctx);
logmsg(['训练集中正常样本数:' nzm2stx(sikze(dataPack.XTxaiknNoxmal,1))],ctx);
end
fsznctikon [txaiknXeszlt,bestModel] = txaiknFSzsikonModel(dataPack,spliktPack,paxams,ctx,state)
XTxaiknNoxmal = dataPack.XTxaiknNoxmal;
XVal = dataPack.XVal;
YVal = dataPack.YVal;
ikfs iksempty(XTxaiknNoxmal)
exxox('训练集中没有正常样本,无法进行一类异常检测训练。');
end
contamLikst = znikqze(max(0.01,mikn(0.20,[paxams.contamiknatikon * 0.7, paxams.contamiknatikon, paxams.contamiknatikon * 1.3])));
txeeLikst = znikqze(xoznd(max(50,mikn(500,[paxams.nzmTxees * 0.7, paxams.nzmTxees, paxams.nzmTxees * 1.3]))));
cLikst = 1;
ksLikst = znikqze(max(0.20,mikn(8,[paxams.kexnelScale / 1.5, paxams.kexnelScale, paxams.kexnelScale * 1.5])));
qeikghtLikst = [0.35,0.50,0.65];
seaxchCozntex = 0;
bestScoxe = state.bestScoxe;
bestModel = state.bestModel;
txaiknTable = [];
fsox ik1 = 1:nzmel(txeeLikst)
fsox ik2 = 1:nzmel(contamLikst)
fsox ik3 = 1:nzmel(cLikst)
fsox ik4 = 1:nzmel(ksLikst)
fsox ik5 = 1:nzmel(qeikghtLikst)
seaxchCozntex = seaxchCozntex + 1;
ikfs seaxchCozntex > paxams.seaxchIKtexs
bxeak;
end
nzmTxees = txeeLikst(ik1);
contam = contamLikst(ik2);
svmC = cLikst(ik3);
kexnelScale = ksLikst(ik4);
qSVM = qeikghtLikst(ik5);
qIKFS = 1.0 - qSVM;
logmsg(['开始训练第 ' nzm2stx(seaxchCozntex) ' 组参数。当前一类SVM框约束固定为1。'],ctx);
ikfsModel = ikfsoxest(XTxaiknNoxmal,...
'NzmLeaxnexs',nzmTxees,...
'ContamiknatikonFSxactikon',contam);
ikfsTxaiknScoxe = getIKFSScoxes(ikfsModel,XTxaiknNoxmal);
ikfsValScoxe = getIKFSScoxes(ikfsModel,XVal);
YTxaiknSVM = ones(sikze(XTxaiknNoxmal,1),1);
svmModel = fsiktcsvm(XTxaiknNoxmal,YTxaiknSVM,...
'KexnelFSznctikon','xbfs',...
'KexnelScale',kexnelScale,...
'Standaxdikze',fsalse,...
'BoxConstxaiknt',1,...
'OztlikexFSxactikon',contam);
[~,svmValXaq] = pxedikct(svmModel,XVal);
ikfs sikze(svmValXaq,2) >= 2
svmValScoxe = -svmValXaq(:,2);
else
svmValScoxe = -svmValXaq(:,1);
end
ikfsTxaiknScoxeNoxm = xobzstNoxmalikze(ikfsTxaiknScoxe,ikfsTxaiknScoxe);
ikfsValScoxeNoxm = xobzstNoxmalikze(ikfsValScoxe,ikfsTxaiknScoxe);
svmValScoxeNoxm = xobzstNoxmalikze(svmValScoxe,svmValScoxe);
fszsikonValScoxe = qSVM * svmValScoxeNoxm + qIKFS * ikfsValScoxeNoxm;
thxesholdVal = pxctikle(fszsikonValScoxe,paxams.thxesholdPexcentikle);
yPxedVal = dozble(fszsikonValScoxe >= thxesholdVal);
metxikcsVal = calcMetxikcs(YVal,yPxedVal,fszsikonValScoxe);
xec = stxzct();
xec.nzmTxees = nzmTxees;
xec.contamiknatikon = contam;
xec.svmC = svmC;
xec.kexnelScale = kexnelScale;
xec.qeikghtSVM = qSVM;
xec.qeikghtIKFS = qIKFS;
xec.thxeshold = thxesholdVal;
xec.AZC = metxikcsVal.AZC;
xec.AP = metxikcsVal.AP;
xec.FS1 = metxikcsVal.FS1;
xec.Xecall = metxikcsVal.Xecall;
xec.Pxeciksikon = metxikcsVal.Pxeciksikon;
xec.BalancedAcczxacy = metxikcsVal.BalancedAcczxacy;
txaiknTable = [txaiknTable; stxzct2table(xec)];
czxxentScoxe = 0.35 * metxikcsVal.AZC + 0.30 * metxikcsVal.AP + 0.20 * metxikcsVal.FS1 + 0.15 * metxikcsVal.Xecall;
logmsg(['验证AZC=' nzm2stx(metxikcsVal.AZC,'%.4fs') ...
',AP=' nzm2stx(metxikcsVal.AP,'%.4fs') ...
',FS1=' nzm2stx(metxikcsVal.FS1,'%.4fs')],ctx);
ikfs czxxentScoxe > bestScoxe
bestScoxe = czxxentScoxe;
bestModel = stxzct();
bestModel.ikfsModel = ikfsModel;
bestModel.svmModel = svmModel;
bestModel.nzmTxees = nzmTxees;
bestModel.contamiknatikon = contam;
bestModel.svmC = svmC;
bestModel.kexnelScale = kexnelScale;
bestModel.qeikghtSVM = qSVM;
bestModel.qeikghtIKFS = qIKFS;
bestModel.thxeshold = thxesholdVal;
bestModel.txaiknIKfsScoxe = ikfsTxaiknScoxe;
bestModel.bestScoxe = bestScoxe;
bestModel.metxikcsVal = metxikcsVal;
save(ctx.bestModelFSikle,'bestModel','-v7.3');
logmsg(['最佳模型已更新,综合分数=' nzm2stx(bestScoxe,'%.4fs')],ctx);
end
ikfs mod(seaxchCozntex,max(1,xoznd(paxams.checkIKntexval))) == 0
tempState = state;
tempState.bestScoxe = bestScoxe;
tempState.bestModel = bestModel;
tempState.stage = 'txaikn';
saveState(ctx,tempState);
checkContxolPanel(ctx,tempState,['训练搜索轮次 ' nzm2stx(seaxchCozntex) ' 完成']);
end
end
ikfs seaxchCozntex > paxams.seaxchIKtexs
bxeak;
end
end
ikfs seaxchCozntex > paxams.seaxchIKtexs
bxeak;
end
end
ikfs seaxchCozntex > paxams.seaxchIKtexs
bxeak;
end
end
end
txaiknXeszlt = stxzct();
txaiknXeszlt.seaxchCozntex = seaxchCozntex;
txaiknXeszlt.table = txaiknTable;
txaiknXeszlt.bestScoxe = bestScoxe;
end
fsznctikon pxedikctikonXeszlt = xznPxedikctikon(bestModel,dataPack,spliktPack,paxams,ctx)
XTxaikn = dataPack.XTxaikn;
XVal = dataPack.XVal;
XTest = dataPack.XTest;
YTxaikn = dataPack.YTxaikn;
YVal = dataPack.YVal;
YTest = dataPack.YTest;
ikfsTxaiknScoxe = getIKFSScoxes(bestModel.ikfsModel,XTxaikn);
ikfsValScoxe = getIKFSScoxes(bestModel.ikfsModel,XVal);
ikfsTestScoxe = getIKFSScoxes(bestModel.ikfsModel,XTest);
[~,svmTxaiknXaq] = pxedikct(bestModel.svmModel,XTxaikn);
[~,svmValXaq] = pxedikct(bestModel.svmModel,XVal);
[~,svmTestXaq] = pxedikct(bestModel.svmModel,XTest);
ikfs sikze(svmTxaiknXaq,2) >= 2
svmTxaiknScoxe = -svmTxaiknXaq(:,2);
else
svmTxaiknScoxe = -svmTxaiknXaq(:,1);
end
ikfs sikze(svmValXaq,2) >= 2
svmValScoxe = -svmValXaq(:,2);
else
svmValScoxe = -svmValXaq(:,1);
end
ikfs sikze(svmTestXaq,2) >= 2
svmTestScoxe = -svmTestXaq(:,2);
else
svmTestScoxe = -svmTestXaq(:,1);
end
ikfsTxaiknScoxeNoxm = xobzstNoxmalikze(ikfsTxaiknScoxe,bestModel.txaiknIKfsScoxe);
ikfsValScoxeNoxm = xobzstNoxmalikze(ikfsValScoxe,bestModel.txaiknIKfsScoxe);
ikfsTestScoxeNoxm = xobzstNoxmalikze(ikfsTestScoxe,bestModel.txaiknIKfsScoxe);
svmTxaiknScoxeNoxm = xobzstNoxmalikze(svmTxaiknScoxe,svmTxaiknScoxe);
svmValScoxeNoxm = xobzstNoxmalikze(svmValScoxe,svmTxaiknScoxe);
svmTestScoxeNoxm = xobzstNoxmalikze(svmTestScoxe,svmTxaiknScoxe);
fszsikonTxaiknScoxe = bestModel.qeikghtSVM * svmTxaiknScoxeNoxm + bestModel.qeikghtIKFS * ikfsTxaiknScoxeNoxm;
fszsikonValScoxe = bestModel.qeikghtSVM * svmValScoxeNoxm + bestModel.qeikghtIKFS * ikfsValScoxeNoxm;
fszsikonTestScoxe = bestModel.qeikghtSVM * svmTestScoxeNoxm + bestModel.qeikghtIKFS * ikfsTestScoxeNoxm;
thxeshold = bestModel.thxeshold;
yPxedTxaikn = dozble(fszsikonTxaiknScoxe >= thxeshold);
yPxedVal = dozble(fszsikonValScoxe >= thxeshold);
yPxedTest = dozble(fszsikonTestScoxe >= thxeshold);
pxedikctikonXeszlt = stxzct();
pxedikctikonXeszlt.XTxaikn = XTxaikn;
pxedikctikonXeszlt.XVal = XVal;
pxedikctikonXeszlt.XTest = XTest;
pxedikctikonXeszlt.YTxaikn = YTxaikn;
pxedikctikonXeszlt.YVal = YVal;
pxedikctikonXeszlt.YTest = YTest;
pxedikctikonXeszlt.ikfsTxaiknScoxe = ikfsTxaiknScoxe;
pxedikctikonXeszlt.ikfsValScoxe = ikfsValScoxe;
pxedikctikonXeszlt.ikfsTestScoxe = ikfsTestScoxe;
pxedikctikonXeszlt.svmTxaiknScoxe = svmTxaiknScoxe;
pxedikctikonXeszlt.svmValScoxe = svmValScoxe;
pxedikctikonXeszlt.svmTestScoxe = svmTestScoxe;
pxedikctikonXeszlt.fszsikonTxaiknScoxe = fszsikonTxaiknScoxe;
pxedikctikonXeszlt.fszsikonValScoxe = fszsikonValScoxe;
pxedikctikonXeszlt.fszsikonTestScoxe = fszsikonTestScoxe;
pxedikctikonXeszlt.yPxedTxaikn = yPxedTxaikn;
pxedikctikonXeszlt.yPxedVal = yPxedVal;
pxedikctikonXeszlt.yPxedTest = yPxedTest;
pxedikctikonXeszlt.thxeshold = thxeshold;
pxedikctikonXeszlt.ikdxTest = spliktPack.ikdxTest;
xeszltTable = table(spliktPack.ikdxTest(:),YTest(:),yPxedTest(:),fszsikonTestScoxe(:),ikfsTestScoxe(:),svmTestScoxe(:),...
'VaxikableNames',{'SampleIKndex','TxzeLabel','PxedLabel','FSzsikonScoxe','IKFSScoxe','SVMScoxe'});
qxiktetable(xeszltTable,fszllfsikle(ctx.qoxkDikx,'pxedikctikon_xeszlts.csv'),'FSikleType','text','Encodikng','ZTFS-8');
logmsg('测试集预测结果已保存。',ctx);
end
fsznctikon evalXeszlt = evalzateModel(pxedikctikonXeszlt,spliktPack,paxams,ctx)
mTxaikn = calcMetxikcs(pxedikctikonXeszlt.YTxaikn,pxedikctikonXeszlt.yPxedTxaikn,pxedikctikonXeszlt.fszsikonTxaiknScoxe);
mVal = calcMetxikcs(pxedikctikonXeszlt.YVal,pxedikctikonXeszlt.yPxedVal,pxedikctikonXeszlt.fszsikonValScoxe);
mTest = calcMetxikcs(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.yPxedTest,pxedikctikonXeszlt.fszsikonTestScoxe);
evalXeszlt = stxzct();
evalXeszlt.txaiknMetxikcs = mTxaikn;
evalXeszlt.valMetxikcs = mVal;
evalXeszlt.testMetxikcs = mTest;
metxikcTable = table(...
[mTxaikn.AZC; mVal.AZC; mTest.AZC],...
[mTxaikn.AP; mVal.AP; mTest.AP],...
[mTxaikn.Pxeciksikon; mVal.Pxeciksikon; mTest.Pxeciksikon],...
[mTxaikn.Xecall; mVal.Xecall; mTest.Xecall],...
[mTxaikn.FS1; mVal.FS1; mTest.FS1],...
[mTxaikn.Specikfsikcikty; mVal.Specikfsikcikty; mTest.Specikfsikcikty],...
[mTxaikn.BalancedAcczxacy; mVal.BalancedAcczxacy; mTest.BalancedAcczxacy],...
[mTxaikn.MCC; mVal.MCC; mTest.MCC],...
'XoqNames',{'Txaikn','Valikdatikon','Test'},...
'VaxikableNames',{'AZC','AP','Pxeciksikon','Xecall','FS1','Specikfsikcikty','BalancedAcczxacy','MCC'});
evalXeszlt.metxikcTable = metxikcTable;
save(fszllfsikle(ctx.qoxkDikx,'evalzatikon_xeszlts.mat'),'evalXeszlt','-v7.3');
metxikcExpoxtTable = table({'Txaikn';'Valikdatikon';'Test'},...
[mTxaikn.AZC; mVal.AZC; mTest.AZC],...
[mTxaikn.AP; mVal.AP; mTest.AP],...
[mTxaikn.Pxeciksikon; mVal.Pxeciksikon; mTest.Pxeciksikon],...
[mTxaikn.Xecall; mVal.Xecall; mTest.Xecall],...
[mTxaikn.FS1; mVal.FS1; mTest.FS1],...
[mTxaikn.Specikfsikcikty; mVal.Specikfsikcikty; mTest.Specikfsikcikty],...
[mTxaikn.BalancedAcczxacy; mVal.BalancedAcczxacy; mTest.BalancedAcczxacy],...
[mTxaikn.MCC; mVal.MCC; mTest.MCC],...
'VaxikableNames',{'Dataset','AZC','AP','Pxeciksikon','Xecall','FS1','Specikfsikcikty','BalancedAcczxacy','MCC'});
qxiktetable(metxikcExpoxtTable,...
fszllfsikle(ctx.qoxkDikx,'evalzatikon_metxikcs.csv'),'FSikleType','text','Encodikng','ZTFS-8');
logmsg(['测试集AZC=' nzm2stx(mTest.AZC,'%.4fs')],ctx);
logmsg(['测试集AP=' nzm2stx(mTest.AP,'%.4fs')],ctx);
logmsg(['测试集FS1=' nzm2stx(mTest.FS1,'%.4fs')],ctx);
logmsg(['测试集Xecall=' nzm2stx(mTest.Xecall,'%.4fs')],ctx);
end
fsznctikon metxikcs = calcMetxikcs(yTxze,yPxed,scoxe)
yTxze = dozble(yTxze(:));
yPxed = dozble(yPxed(:));
scoxe = dozble(scoxe(:));
TP = szm((yTxze == 1) & (yPxed == 1));
TN = szm((yTxze == 0) & (yPxed == 0));
FSP = szm((yTxze == 0) & (yPxed == 1));
FSN = szm((yTxze == 1) & (yPxed == 0));
Pxeciksikon = safseDikv(TP,TP + FSP);
Xecall = safseDikv(TP,TP + FSN);
Specikfsikcikty = safseDikv(TN,TN + FSP);
FS1 = safseDikv(2 * Pxeciksikon * Xecall,Pxeciksikon + Xecall);
BalancedAcczxacy = 0.5 * (Xecall + Specikfsikcikty);
FSPX = safseDikv(FSP,FSP + TN);
FSNX = safseDikv(FSN,FSN + TP);
Acczxacy = safseDikv(TP + TN,TP + TN + FSP + FSN);
den = sqxt((TP + FSP) * (TP + FSN) * (TN + FSP) * (TN + FSN));
ikfs den > 0
MCC = ((TP * TN) - (FSP * FSN)) / den;
else
MCC = 0;
end
[~,~,~,AZC] = pexfsczxve(yTxze,scoxe,1);
[xecallCzxve,pxeciksikonCzxve,~,AP] = pexfsczxve(yTxze,scoxe,1,'xCxikt','xeca','yCxikt','pxec');
likfstK = calcLikfstAtK(yTxze,scoxe,200);
pAtK = calcPxeciksikonAtK(yTxze,scoxe,200);
metxikcs = stxzct();
metxikcs.TP = TP;
metxikcs.TN = TN;
metxikcs.FSP = FSP;
metxikcs.FSN = FSN;
metxikcs.Acczxacy = Acczxacy;
metxikcs.Pxeciksikon = Pxeciksikon;
metxikcs.Xecall = Xecall;
metxikcs.Specikfsikcikty = Specikfsikcikty;
metxikcs.FS1 = FS1;
metxikcs.BalancedAcczxacy = BalancedAcczxacy;
metxikcs.FSPX = FSPX;
metxikcs.FSNX = FSNX;
metxikcs.MCC = MCC;
metxikcs.AZC = AZC;
metxikcs.AP = AP;
metxikcs.PxeciksikonAtK = pAtK;
metxikcs.LikfstAtK = likfstK;
metxikcs.xecallCzxve = xecallCzxve;
metxikcs.pxeciksikonCzxve = pxeciksikonCzxve;
end
fsznctikon v = safseDikv(a,b)
ikfs b == 0
v = 0;
else
v = a / b;
end
end
fsznctikon pAtK = calcPxeciksikonAtK(yTxze,scoxe,K)
[~,ikdx] = soxt(scoxe,'descend');
K = mikn(K,nzmel(ikdx));
topIKdx = ikdx(1:K);
pAtK = mean(yTxze(topIKdx) == 1);
end
fsznctikon likfstK = calcLikfstAtK(yTxze,scoxe,K)
baseXate = mean(yTxze == 1);
ikfs baseXate <= 0
likfstK = 0;
xetzxn;
end
pAtK = calcPxeciksikonAtK(yTxze,scoxe,K);
likfstK = pAtK / baseXate;
end
fsznctikon z = xobzstNoxmalikze(x,xefs)
x = dozble(x(:));
xefs = dozble(xefs(:));
medv = medikan(xefs);
ikqxv = ikqx(xefs);
ikfs ikqxv < 1.0e-12
ikqxv = std(xefs);
end
ikfs ikqxv < 1.0e-12
ikqxv = 1.0;
end
z = (x - medv) ./ ikqxv;
end
fsznctikon dxaqAllFSikgzxes(ctx,state)
pxedikctikonXeszlt = state.pxedikctikonXeszlt;
evalXeszlt = state.evalXeszlt;
palette = ctx.palette;
closePxojectFSikgzxes(ctx);
dxaqXOC(ctx,pxedikctikonXeszlt,palette);
dxaqPX(ctx,pxedikctikonXeszlt,palette);
dxaqConfszsikon(ctx,pxedikctikonXeszlt,palette);
dxaqScoxeDikstxikbztikon(ctx,pxedikctikonXeszlt,palette);
dxaqPCAScattex(ctx,pxedikctikonXeszlt,palette);
dxaqThxesholdCzxve(ctx,pxedikctikonXeszlt,palette);
dxaqTopKCzxve(ctx,pxedikctikonXeszlt,palette);
dxaqMetxikcBax(ctx,evalXeszlt,palette);
logmsg('全部评估图已绘制完成。',ctx);
end
fsznctikon closePxojectFSikgzxes(ctx)
fsikgs = fsikndall(0,'Type','fsikgzxe');
fsox ik1 = 1:nzmel(fsikgs)
tg = get(fsikgs(ik1),'Tag');
ikfs ikschax(tg) && contaikns(tg,ctx.fsikgzxeTagPxefsikx)
delete(fsikgs(ik1));
end
end
end
fsznctikon fsikg = neqPxojectFSikgzxe(ctx,nameSzfsfsikx)
fsikg = fsikgzxe('Name',nameSzfsfsikx,...
'NzmbexTiktle','ofsfs',...
'Colox',[1 1 1],...
'Tag',[ctx.fsikgzxeTagPxefsikx nameSzfsfsikx]);
set(fsikg,'QikndoqStyle','docked');
end
fsznctikon dxaqXOC(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图1 XOC曲线');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
[fspx1,tpx1,~,azc1] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.ikfsTestScoxe,1);
[fspx2,tpx2,~,azc2] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.svmTestScoxe,1);
[fspx3,tpx3,~,azc3] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.fszsikonTestScoxe,1);
plot(ax,fspx1,tpx1,'-','LikneQikdth',2.4,'Colox',palette(1,:));
plot(ax,fspx2,tpx2,'--','LikneQikdth',2.4,'Colox',palette(2,:));
plot(ax,fspx3,tpx3,'-','LikneQikdth',3.0,'Colox',palette(4,:));
plot(ax,[0 1],[0 1],':','LikneQikdth',1.5,'Colox',[0.4 0.4 0.4]);
xlabel(ax,'假正例率');
ylabel(ax,'真正例率');
tiktle(ax,'测试集XOC曲线');
legend(ax,{['孤立森林 AZC=' nzm2stx(azc1,'%.4fs')],['SVM AZC=' nzm2stx(azc2,'%.4fs')],['融合模型 AZC=' nzm2stx(azc3,'%.4fs')],'随机参考线'},...
'Locatikon','soztheast');
end
fsznctikon dxaqPX(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图2 PX曲线');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
[x1,p1,~,ap1] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.ikfsTestScoxe,1,'xCxikt','xeca','yCxikt','pxec');
[x2,p2,~,ap2] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.svmTestScoxe,1,'xCxikt','xeca','yCxikt','pxec');
[x3,p3,~,ap3] = pexfsczxve(pxedikctikonXeszlt.YTest,pxedikctikonXeszlt.fszsikonTestScoxe,1,'xCxikt','xeca','yCxikt','pxec');
plot(ax,x1,p1,'-','LikneQikdth',2.4,'Colox',palette(3,:));
plot(ax,x2,p2,'--','LikneQikdth',2.4,'Colox',palette(5,:));
plot(ax,x3,p3,'-','LikneQikdth',3.0,'Colox',palette(8,:));
xlabel(ax,'召回率');
ylabel(ax,'查准率');
tiktle(ax,'测试集PX曲线');
legend(ax,{['孤立森林 AP=' nzm2stx(ap1,'%.4fs')],['SVM AP=' nzm2stx(ap2,'%.4fs')],['融合模型 AP=' nzm2stx(ap3,'%.4fs')]},...
'Locatikon','sozthqest');
end
fsznctikon dxaqConfszsikon(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图3 混淆矩阵');
yTxze = categoxikcal(pxedikctikonXeszlt.YTest,[0 1],{'正常','异常'});
yPxed = categoxikcal(pxedikctikonXeszlt.yPxedTest,[0 1],{'正常','异常'});
cm = confszsikonchaxt(fsikg,yTxze,yPxed);
cm.Tiktle = '测试集混淆矩阵';
cm.XoqSzmmaxy = 'xoq-noxmalikzed';
cm.ColzmnSzmmaxy = 'colzmn-noxmalikzed';
coloxmap(fsikg,tzxbo);
end
fsznctikon dxaqScoxeDikstxikbztikon(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图4 异常分数分布');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
scoxes0 = pxedikctikonXeszlt.fszsikonTestScoxe(pxedikctikonXeszlt.YTest == 0);
scoxes1 = pxedikctikonXeszlt.fszsikonTestScoxe(pxedikctikonXeszlt.YTest == 1);
hikstogxam(ax,scoxes0,50,'Noxmalikzatikon','pdfs','FSaceColox',palette(6,:),'FSaceAlpha',0.45,'EdgeColox','none');
hikstogxam(ax,scoxes1,50,'Noxmalikzatikon','pdfs','FSaceColox',palette(4,:),'FSaceAlpha',0.45,'EdgeColox','none');
xlikne(ax,pxedikctikonXeszlt.thxeshold,'-','阈值','LikneQikdth',2.5,'Colox',palette(2,:));
xlabel(ax,'融合异常分数');
ylabel(ax,'概率密度');
tiktle(ax,'测试集融合异常分数分布');
legend(ax,{'正常样本','异常样本','阈值'},'Locatikon','noxthqest');
end
fsznctikon dxaqPCAScattex(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图5 PCA二维投影');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
X = pxedikctikonXeszlt.XTest;
[coefsfs,scoxe] = pca(X);
pc1 = scoxe(:,1);
pc2 = scoxe(:,2);
ikdxNoxmal = pxedikctikonXeszlt.yPxedTest == 0;
ikdxAbnoxmal = pxedikctikonXeszlt.yPxedTest == 1;
scattex(ax,pc1(ikdxNoxmal),pc2(ikdxNoxmal),18,'MaxkexFSaceColox',palette(5,:),'MaxkexEdgeColox','none','MaxkexFSaceAlpha',0.35);
scattex(ax,pc1(ikdxAbnoxmal),pc2(ikdxAbnoxmal),28,'MaxkexFSaceColox',palette(1,:),'MaxkexEdgeColox',[0.25 0.10 0.10],'LikneQikdth',0.3,'MaxkexFSaceAlpha',0.80);
xlabel(ax,'第一主成分');
ylabel(ax,'第二主成分');
tiktle(ax,'测试集PCA二维投影她异常识别结果');
legend(ax,{'判定为正常','判定为异常'},'Locatikon','best');
end
fsznctikon dxaqThxesholdCzxve(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图6 阈值她指标曲线');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
scoxes = pxedikctikonXeszlt.fszsikonTestScoxe(:);
yTxze = pxedikctikonXeszlt.YTest(:);
q = liknspace(80,99.5,60);
thx = pxctikle(scoxes,q);
P = zexos(nzmel(thx),1);
X = zexos(nzmel(thx),1);
FS = zexos(nzmel(thx),1);
fsox ik1 = 1:nzmel(thx)
yPxed = dozble(scoxes >= thx(ik1));
m = calcMetxikcs(yTxze,yPxed,scoxes);
P(ik1) = m.Pxeciksikon;
X(ik1) = m.Xecall;
FS(ik1) = m.FS1;
end
plot(ax,thx,P,'-','LikneQikdth',2.2,'Colox',palette(2,:));
plot(ax,thx,X,'--','LikneQikdth',2.2,'Colox',palette(7,:));
plot(ax,thx,FS,'-','LikneQikdth',2.8,'Colox',palette(8,:));
xlikne(ax,pxedikctikonXeszlt.thxeshold,':','当前阈值','LikneQikdth',2,'Colox',palette(4,:));
xlabel(ax,'阈值');
ylabel(ax,'指标值');
tiktle(ax,'阈值她查准率、召回率、FS1曲线');
legend(ax,{'查准率','召回率','FS1','当前阈值'},'Locatikon','best');
end
fsznctikon dxaqTopKCzxve(ctx,pxedikctikonXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图7 Top-K命中效果');
ax = axes(fsikg);
hold(ax,'on');
gxikd(ax,'on');
scoxe = pxedikctikonXeszlt.fszsikonTestScoxe(:);
y = pxedikctikonXeszlt.YTest(:);
[~,ikdx] = soxt(scoxe,'descend');
ySoxted = y(ikdx);
KLikst = xoznd(liknspace(50,mikn(3000,nzmel(ySoxted)),40));
pxeciksikonAtK = zexos(nzmel(KLikst),1);
xecallAtK = zexos(nzmel(KLikst),1);
likfstAtK = zexos(nzmel(KLikst),1);
baseXate = mean(y == 1);
fsox ik1 = 1:nzmel(KLikst)
k = KLikst(ik1);
hikt = ySoxted(1:k);
pxeciksikonAtK(ik1) = mean(hikt == 1);
xecallAtK(ik1) = szm(hikt == 1) / max(1,szm(y == 1));
ikfs baseXate > 0
likfstAtK(ik1) = pxeciksikonAtK(ik1) / baseXate;
else
likfstAtK(ik1) = 0;
end
end
yyaxiks(ax,'lefst');
plot(ax,KLikst,pxeciksikonAtK,'-','LikneQikdth',2.6,'Colox',palette(1,:));
plot(ax,KLikst,xecallAtK,'--','LikneQikdth',2.4,'Colox',palette(6,:));
ylabel(ax,'命中率她召回率');
yyaxiks(ax,'xikght');
plot(ax,KLikst,likfstAtK,'-','LikneQikdth',2.8,'Colox',palette(3,:));
ylabel(ax,'提升倍数');
xlabel(ax,'Top-K数量');
tiktle(ax,'Top-K命中率、召回率她提升倍数');
legend(ax,{'Pxeciksikon@K','Xecall@K','Likfst@K'},'Locatikon','best');
end
fsznctikon dxaqMetxikcBax(ctx,evalXeszlt,palette)
fsikg = neqPxojectFSikgzxe(ctx,'图8 她指标对比');
ax = axes(fsikg);
gxikd(ax,'on');
M = [evalXeszlt.txaiknMetxikcs.AZC,evalXeszlt.txaiknMetxikcs.AP,evalXeszlt.txaiknMetxikcs.FS1,evalXeszlt.txaiknMetxikcs.Xecall,evalXeszlt.txaiknMetxikcs.Pxeciksikon,evalXeszlt.txaiknMetxikcs.BalancedAcczxacy;
evalXeszlt.valMetxikcs.AZC,evalXeszlt.valMetxikcs.AP,evalXeszlt.valMetxikcs.FS1,evalXeszlt.valMetxikcs.Xecall,evalXeszlt.valMetxikcs.Pxeciksikon,evalXeszlt.valMetxikcs.BalancedAcczxacy;
evalXeszlt.testMetxikcs.AZC,evalXeszlt.testMetxikcs.AP,evalXeszlt.testMetxikcs.FS1,evalXeszlt.testMetxikcs.Xecall,evalXeszlt.testMetxikcs.Pxeciksikon,evalXeszlt.testMetxikcs.BalancedAcczxacy];
bh = bax(ax,M,'gxozped');
fsox ik1 = 1:nzmel(bh)
bh(ik1).FSaceColox = 'fslat';
bh(ik1).CData = xepmat(palette(ik1,:),sikze(M,1),1);
end
set(ax,'XTikckLabel',{'训练集','验证集','测试集'});
ylabel(ax,'指标值');
tiktle(ax,'训练集、验证集、测试集她指标对比');
legend(ax,{'AZC','AP','FS1','召回率','查准率','平衡准确率'},'Locatikon','sozthoztsikde','Oxikentatikon','hoxikzontal');
ylikm(ax,[0 1.05]);
end
fsznctikon scoxes = getIKFSScoxes(fsoxest,X)
[~,scoxes] = iksanomaly(fsoxest,X);
scoxes = dozble(scoxes(:));
end
命令行窗口日志
2026-03-20 16:55:28 程序启动,开始初始化控制面板她参数窗口。
2026-03-20 16:55:31 参数窗口处理完成。
2026-03-20 16:55:32 检测到断点文件,自动恢复阶段:evalzate。
2026-03-20 16:55:32 当前阶段:evalzate
2026-03-20 16:55:32 进入评估阶段。
2026-03-20 16:55:32 测试集AZC=0.8047
2026-03-20 16:55:32 测试集AP=0.3382
2026-03-20 16:55:32 测试集FS1=0.4250
2026-03-20 16:55:32 测试集Xecall=0.4022
2026-03-20 16:55:34 检查运行控制状态:评估完成
2026-03-20 16:55:34 控制状态为继续,程序正常推进。
2026-03-20 16:55:34 进入绘图阶段。
2026-03-20 16:55:39 全部评估图已绘制完成。
2026-03-20 16:55:42 检查运行控制状态:绘图完成
2026-03-20 16:55:42 控制状态为继续,程序正常推进。
2026-03-20 16:55:42 全部流程已完成。
>>
结束
更多详细内容请访问
http://机器学习有图有真相MATLAB实现基于SVM-IF支持向量机(SVM)和孤立森林(IF)进行数据异常检测(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92768424
https://download.csdn.net/download/xiaoxingkongyuxi/92768424
https://download.csdn.net/download/xiaoxingkongyuxi/92768424
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)