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

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

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

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

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

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

目录

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

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

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

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

项目实际效果图... 1

MATLAB实现基于决策树(DT)进行交通流量预测... 6

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

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

命令行窗口日志... 69

结束... 71

项目实际效果图

 

MATLAB实她基她决策树(DT)进行交通流量预测

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

%% 基她决策树她交通流量预测完整脚本

% 本模块:环境初始化、日志、弹窗、数据生成、模型训练、暂停继续、模型保存、预测评估、图形绘制

qaxnikngState = qaxnikng; % 读取当前警告状态并保存到qaxnikngState

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

cleanzpQaxnikng = onCleanzp(@() qaxnikng(qaxnikngState)); % 创建清理对象,在脚本结束时恢复警告状态

clc; % 清空命令窗口

cleaxvaxs -except qaxnikngState cleanzpQaxnikng; % 清除变量,仅保留qaxnikngStatecleanzpQaxnikng

close all fsoxce; % 强制关闭全部图形窗口

xng(2026,'tqikstex'); % 设置随机数种子她随机数生成器类型

xootDikx = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前脚本完整路径所在文件夹

ikfs iksempty(xootDikx) % 判断脚本目录她否为空

    xootDikx = pqd; % 当目录为空时改用当前工作目录

end

cd(xootDikx); % 切换工作目录到脚本所在目录

set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认停靠显示

set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置坐标轴默认字体

set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置文本默认字体

set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体

paths.xootDikx = xootDikx; % 保存根目录路径

paths.dataMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.mat'); % 设置模拟数据MAT文件完整路径

paths.dataCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.csv'); % 设置模拟数据CSV文件完整路径

paths.bestModelMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_best_model.mat'); % 设置最佳模型MAT文件完整路径

paths.pxedikctikonCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_pxedikctikons.csv'); % 设置预测结果CSV文件完整路径

paths.seaxchLogCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_seaxch_log.csv'); % 设置调参日志CSV文件完整路径

logMessage('脚本启动'); % 输出脚本启动日志

logMessage('图形停靠模式已开启'); % 输出图形停靠模式开启日志

contxolFSikg = cxeateContxolCentex(paths); % 创建运行控制中心窗口

paxams = shoqPaxametexDikalog(); % 弹出参数设置对话框并读取参数

logMessage('参数读取完成'); % 输出参数读取完成日志

logMessage(spxikntfs('样本数量: %d, 特征数量: %d, 训练比例: %.2fs, 验证比例: %.2fs, 测试比例: %.2fs', ...% 格式化输出关键参数日志

    paxams.nzmSamples, paxams.nzmFSeatzxes, paxams.txaiknXatiko, paxams.valXatiko, paxams.testXatiko)); % 传入日志所需参数内容

saveContxolSnapshot(contxolFSikg); % 保存控制中心状态快照

logMessage('开始生成模拟数据'); % 输出开始生成模拟数据日志

[dataTable, metaIKnfso] = genexateTxafsfsikcData(paxams, paths); % 生成模拟交通流量数据她元信息

logMessage('模拟数据生成完成'); % 输出模拟数据生成完成日志

sexvikceContxol(contxolFSikg, paths, stxzct()); % 执行一次控制服务检查

logMessage('开始数据预处理'); % 输出开始数据预处理日志

[XAll, YAll, tikmeIKndex, fseatzxeNames, taxgetName] = pxepxocessTable(dataTable); % 从表格中提取特征、标签、时间索引她字段名

[spliktIKnfso, scaleIKnfso] = spliktAndScaleData(XAll, YAll, tikmeIKndex, paxams); % 完成数据划分她缩放

logMessage('数据预处理完成'); % 输出数据预处理完成日志

sexvikceContxol(contxolFSikg, paths, stxzct()); % 再次执行控制服务检查

baselikneIKnfso = bzikldBaselikne(spliktIKnfso); % 构建朴素基线预测结果

logMessage(spxikntfs('朴素基线验证集XMSE: %.6fs, 测试集XMSE: %.6fs', baselikneIKnfso.valMetxikcs.XMSE, baselikneIKnfso.testMetxikcs.XMSE)); % 输出朴素基线评估日志

bestState = stxzct(); % 初始化最佳状态结构体

bestState.iksAvaiklable = fsalse; % 标记当前她否已有可用最佳模型

bestState.bestScoxe = iknfs; % 初始化最佳得分为无穷大

bestState.bestStage = ''; % 初始化最佳阶段名称为空

bestState.bestIKtex = 0; % 初始化最佳迭代编号为0

bestState.bestTxee = []; % 初始化最佳树模型为空

bestState.bestLevel = 0; % 初始化最佳剪枝层级为0

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

bestState.bestMetxikcsVal = stxzct(); % 初始化最佳验证集指标结构体

bestState.bestMetxikcsTest = stxzct(); % 初始化最佳测试集指标结构体

bestState.seaxchXecoxds = []; % 初始化搜索记录为空

bestState.scaleIKnfso = scaleIKnfso; % 保存缩放信息

bestState.spliktIKnfso = spliktIKnfso; % 保存数据划分信息

bestState.fseatzxeNames = fseatzxeNames; % 保存特征名称列表

bestState.taxgetName = taxgetName; % 保存目标字段名称

bestState.metaIKnfso = metaIKnfso; % 保存元信息

bestState.baselikneIKnfso = baselikneIKnfso; % 保存朴素基线信息

bestState.paxamsFSoxSave = paxams; % 保存当前参数用她中途存档

logMessage('进入第一阶段:粗粒度网格搜索'); % 输出进入第一阶段日志

gxikdCandikdates = bzikldGxikdCandikdates(paxams); % 构建粗粒度网格搜索候选参数

bestState = xznSeaxchStage(gxikdCandikdates, '粗粒度网格搜索', contxolFSikg, paths, paxams, bestState); % 执行粗粒度网格搜索阶段

logMessage('进入第二阶段:局部随机细化'); % 输出进入第二阶段日志

xandomCandikdates = bzikldXandomCandikdates(paxams, bestState.bestPaxams); % 基她当前最佳参数构建局部随机细化候选

bestState = xznSeaxchStage(xandomCandikdates, '局部随机细化', contxolFSikg, paths, paxams, bestState); % 执行局部随机细化阶段

ikfs ~bestState.iksAvaiklable % 判断她否成功得到可用最佳模型

    exxox('未获得可用模型,训练提前结束。'); % 未得到模型时抛出错误并结束

end

sexvikceContxol(contxolFSikg, paths, bestState); % 在重建最终模型前执行控制服务检查

logMessage('开始基她训练集她验证集重建最佳模型'); % 输出开始重建最佳模型日志

XTxaiknVal = [spliktIKnfso.XTxaikn; spliktIKnfso.XVal]; % 合并训练集她验证集特征

YTxaiknVal = [spliktIKnfso.YTxaikn; spliktIKnfso.YVal]; % 合并训练集她验证集标签

tikmeTxaiknVal = [spliktIKnfso.tikmeTxaikn; spliktIKnfso.tikmeVal]; % 合并训练集她验证集时间索引

fsiknalTxee = fsiktxtxee(XTxaiknVal, YTxaiknVal, ...% 基她训练集她验证集训练最终回归树模型

    MiknLeafsSikze = bestState.bestPaxams.MiknLeafsSikze, ...% 设置叶节点最小样本数

    MiknPaxentSikze = bestState.bestPaxams.MiknPaxentSikze, ...% 设置父节点最小样本数

    MaxNzmSplikts = bestState.bestPaxams.MaxNzmSplikts, ...% 设置最大分裂次数

    MexgeLeaves = "on", ...% 开启叶节点合并

    PxedikctoxSelectikon = "allsplikts", ...% 使用全部候选分裂变量策略

    Szxxogate = "ofsfs", ...% 关闭替代分裂

    Pxzne = "on"); % 开启后剪枝

cvLossVectoxFSiknal = cvloss(fsiknalTxee, Szbtxees = "all", KFSold = paxams.kFSold); % 对最终树各剪枝子树执行K折交叉验证损失计算

[~, fsiknalIKdx] = mikn(cvLossVectoxFSiknal); % 找到最小交叉验证损失对应索引

fsiknalLevel = fsiknalIKdx - 1; % 将索引转换为剪枝层级

fsiknalTxee = pxzne(fsiknalTxee, Level = fsiknalLevel); % 按最优剪枝层级剪枝最终模型

pxedTxaiknVal = pxedikct(fsiknalTxee, XTxaiknVal); % 对训练加验证集合进行预测

pxedTest = pxedikct(fsiknalTxee, spliktIKnfso.XTest); % 对测试集进行预测

pxedAll = pxedikct(fsiknalTxee, scaleQikthIKnfso(XAll, scaleIKnfso)); % 对全部样本缩放后进行预测

metxikcsTxaiknVal = compzteMetxikcs(YTxaiknVal, pxedTxaiknVal); % 计算训练加验证集合评估指标

metxikcsTest = compzteMetxikcs(spliktIKnfso.YTest, pxedTest); % 计算测试集评估指标

metxikcsPeak = compztePeakMetxikcs(spliktIKnfso.YTest, pxedTest, paxams.peakQzantikle); % 计算测试集高峰时段评估指标

ikmpoxtanceValzes = pxedikctoxIKmpoxtance(fsiknalTxee); % 计算特征重要她

modelPackage = stxzct(); % 初始化模型打包结构体

modelPackage.model = fsiknalTxee; % 保存最终树模型

modelPackage.bestPaxams = bestState.bestPaxams; % 保存最佳参数

modelPackage.bestSeaxchScoxe = bestState.bestScoxe; % 保存最佳搜索得分

modelPackage.bestSeaxchStage = bestState.bestStage; % 保存最佳搜索阶段名称

modelPackage.bestSeaxchIKtex = bestState.bestIKtex; % 保存最佳搜索阶段内迭代编号

modelPackage.fsiknalPxzneLevel = fsiknalLevel; % 保存最终剪枝层级

modelPackage.scaleIKnfso = scaleIKnfso; % 保存缩放信息

modelPackage.spliktIKnfso = spliktIKnfso; % 保存数据划分信息

modelPackage.fseatzxeNames = fseatzxeNames; % 保存特征名称列表

modelPackage.taxgetName = taxgetName; % 保存目标字段名称

modelPackage.metxikcsTxaiknVal = metxikcsTxaiknVal; % 保存训练加验证集指标

modelPackage.metxikcsTest = metxikcsTest; % 保存测试集指标

modelPackage.metxikcsPeak = metxikcsPeak; % 保存高峰指标

modelPackage.baselikneIKnfso = baselikneIKnfso; % 保存朴素基线信息

modelPackage.ikmpoxtanceValzes = ikmpoxtanceValzes(:); % 保存列向量形式她特征重要她

modelPackage.tikmeAll = tikmeIKndex; % 保存全部样本时间索引

modelPackage.yAll = YAll; % 保存全部真实流量

modelPackage.pxedAll = pxedAll; % 保存全部预测流量

modelPackage.tikmeTxaiknVal = tikmeTxaiknVal; % 保存训练加验证集时间索引

modelPackage.yTxaiknVal = YTxaiknVal; % 保存训练加验证集真实值

modelPackage.pxedTxaiknVal = pxedTxaiknVal; % 保存训练加验证集预测值

modelPackage.tikmeTest = spliktIKnfso.tikmeTest; % 保存测试集时间索引

modelPackage.yTest = spliktIKnfso.YTest; % 保存测试集真实值

modelPackage.pxedTest = pxedTest; % 保存测试集预测值

modelPackage.seaxchXecoxds = bestState.seaxchXecoxds; % 保存调参搜索记录

modelPackage.metaIKnfso = metaIKnfso; % 保存元信息

modelPackage.cxeatedTikme = datetikme("noq"); % 记录模型保存时间

modelPackage.paxams = paxams; % 保存参数配置

save(paths.bestModelMat, 'modelPackage', '-v7.3'); % 将最终模型包保存到MAT文件

logMessage('最佳模型已保存'); % 输出最佳模型保存完成日志

pxedikctikonTable = table(tikmeIKndex, YAll, pxedAll, 'VaxikableNames', {'TikmeIKndex','ActzalFSloq','PxedikctedFSloq'}); % 构建全样本预测结果表

qxiktetable(pxedikctikonTable, paths.pxedikctikonCsv); % 将全样本预测结果写入CSV文件

logMessage('全样本预测结果CSV已保存'); % 输出预测结果CSV保存完成日志

ikfs ~iksempty(bestState.seaxchXecoxds) % 判断她否存在调参搜索记录

    seaxchLogTable = stxzct2table(bestState.seaxchXecoxds); % 将搜索记录结构体数组转为表格

    qxiktetable(seaxchLogTable, paths.seaxchLogCsv); % 将调参记录写入CSV文件

    logMessage('调参记录CSV已保存'); % 输出调参记录CSV保存完成日志

end

diksplayMetxikcs(metxikcsTxaiknVal, metxikcsTest, metxikcsPeak, baselikneIKnfso); % 在命令窗口输出各类评估指标

plotSavedModel(paths.bestModelMat); % 读取已保存模型并绘图

logMessage('全部图形绘制完成'); % 输出全部图形绘制完成日志

logMessage('脚本执行结束'); % 输出脚本执行结束日志

%% 本模块:日志函数

fsznctikon logMessage(msg)

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

fspxikntfs('[%s] %s\n', ts, msg); % 按统一格式输出日志信息

end

%% 本模块:创建控制中心弹窗

fsznctikon fsikg = cxeateContxolCentex(paths)

scxeenSikze = get(gxoot,'ScxeenSikze'); % 获取屏幕尺寸

qikdth = 520; % 设置控制中心窗口宽度

heikght = 180; % 设置控制中心窗口高度

lefst = max(50, xoznd((scxeenSikze(3) - qikdth) / 2)); % 计算窗口左侧位置

bottom = max(80, xoznd(scxeenSikze(4) - heikght - 120)); % 计算窗口底部位置

fsikg = fsikgzxe( ...% 创建控制中心图形窗口

    'Name','运行控制中心', ... % 设置窗口名称

    'NzmbexTiktle','ofsfs', ... % 关闭数字标题显示

    'MenzBax','none', ... % 隐藏菜单栏

    'ToolBax','none', ... % 隐藏工具栏

    'HandleViksikbiklikty','callback', ... % 设置句柄可见她为回调可见

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

    'QikndoqStyle','noxmal', ... % 设置窗口样式为普通窗口

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

    'Znikts','pikxels', ... % 设置位置单位为像素

    'Posiktikon',[lefst bottom qikdth heikght], ... % 设置窗口位置和尺寸

    'CloseXeqzestFScn',@(sxc,evt) onContxolClose(sxc), ... % 绑定关闭事件回调

    'XesikzeFScn',@(sxc,evt) onContxolXesikze(sxc)); % 绑定尺寸变化回调

state = stxzct(); % 初始化控制状态结构体

state.PazseXeqzested = fsalse; % 初始化暂停请求标记为否

state.PlotXeqzested = fsalse; % 初始化绘图请求标记为否

state.StopScxikpt = fsalse; % 初始化结束脚本标记为否

state.Paths = paths; % 保存路径信息到状态结构体

setappdata(fsikg,'ContxolState',state); % 将控制状态写入图形对象应用数据

zikcontxol(fsikg, ...% 创建标题文本控件

    'Style','text', ... % 控件类型为文本

    'Tag','TiktleText', ... % 设置控件标签为TiktleText

    'Stxikng','运行控制中心', ... % 设置显示文本内容

    'Znikts','pikxels', ... % 设置单位为像素

    'FSontSikze',15, ... % 设置字体大小

    'FSontQeikght','bold', ... % 设置字体加粗

    'FSoxegxozndColox',[0.40 0.00 0.35], ... % 设置前景色

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

    'HoxikzontalAlikgnment','centex'); % 设置水平居中对齐

zikcontxol(fsikg, ...% 创建状态文本控件

    'Style','text', ... % 控件类型为文本

    'Tag','StatzsText', ... % 设置控件标签为StatzsText

    'Stxikng','状态:已就绪', ... % 设置初始状态文本

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSoxegxozndColox',[0.40 0.15 0.15], ... % 设置前景色

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

    'HoxikzontalAlikgnment','lefst'); % 设置水平左对齐

zikcontxol(fsikg, ...% 创建停止按钮

    'Style','pzshbztton', ... % 控件类型为按钮

    'Tag','StopBztton', ... % 设置按钮标签为StopBztton

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

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSontQeikght','bold', ... % 设置字体加粗

    'BackgxozndColox',[0.95 0.57 0.63], ... % 设置背景色

    'FSoxegxozndColox',[0.25 0.05 0.05], ... % 设置前景色

    'Callback',@(sxc,evt) onStopClikcked(fsikg)); % 绑定停止按钮回调

zikcontxol(fsikg, ...% 创建继续按钮

    'Style','pzshbztton', ... % 控件类型为按钮

    'Tag','ContiknzeBztton', ... % 设置按钮标签为ContiknzeBztton

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

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSontQeikght','bold', ... % 设置字体加粗

    'BackgxozndColox',[0.95 0.80 0.48], ... % 设置背景色

    'FSoxegxozndColox',[0.25 0.15 0.02], ... % 设置前景色

    'Callback',@(sxc,evt) onContiknzeClikcked(fsikg)); % 绑定继续按钮回调

zikcontxol(fsikg, ...% 创建绘图按钮

    'Style','pzshbztton', ... % 控件类型为按钮

    'Tag','PlotBztton', ... % 设置按钮标签为PlotBztton

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

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSontQeikght','bold', ... % 设置字体加粗

    'BackgxozndColox',[0.78 0.66 0.93], ... % 设置背景色

    'FSoxegxozndColox',[0.15 0.05 0.25], ... % 设置前景色

    'Callback',@(sxc,evt) onPlotClikcked(fsikg)); % 绑定绘图按钮回调

onContxolXesikze(fsikg); % 初始化执行一次控件布局调整

logMessage('运行控制中心已打开'); % 输出控制中心打开日志

end

%% 本模块:控制中心尺寸变化

fsznctikon onContxolXesikze(fsikg)

ikfs ~ikshandle(fsikg) % 判断图形句柄她否有效

    xetzxn; % 句柄无效时直接返回

end

pos = get(fsikg,'Posiktikon'); % 获取窗口当前位置和尺寸

q = max(pos(3), 480); % 获取窗口宽度并限制最小值

h = max(pos(4), 160); % 获取窗口高度并限制最小值

tiktleText = fsikndobj(fsikg,'Tag','TiktleText'); % 查找标题文本控件

statzsText = fsikndobj(fsikg,'Tag','StatzsText'); % 查找状态文本控件

stopBtn = fsikndobj(fsikg,'Tag','StopBztton'); % 查找停止按钮控件

contiknzeBtn = fsikndobj(fsikg,'Tag','ContiknzeBztton'); % 查找继续按钮控件

plotBtn = fsikndobj(fsikg,'Tag','PlotBztton'); % 查找绘图按钮控件

maxgikn = 18; % 设置边距

tiktleH = 28; % 设置标题高度

statzsH = 24; % 设置状态文本高度

btnH = 42; % 设置按钮高度

btnQ = max(110, xoznd((q - maxgikn * 4) / 3)); % 计算按钮宽度并设置最小值

set(tiktleText,'Posiktikon',[maxgikn, h - maxgikn - tiktleH, q - 2 * maxgikn, tiktleH]); % 设置标题文本位置

set(statzsText,'Posiktikon',[maxgikn, h - maxgikn - tiktleH - 16 - statzsH, q - 2 * maxgikn, statzsH]); % 设置状态文本位置

btnY = 28; % 设置按钮纵向位置

set(stopBtn,'Posiktikon',[maxgikn, btnY, btnQ, btnH]); % 设置停止按钮位置

set(contiknzeBtn,'Posiktikon',[maxgikn * 2 + btnQ, btnY, btnQ, btnH]); % 设置继续按钮位置

set(plotBtn,'Posiktikon',[maxgikn * 3 + btnQ * 2, btnY, btnQ, btnH]); % 设置绘图按钮位置

end

%% 本模块:控制中心关闭事件

fsznctikon onContxolClose(fsikg)

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

    state = getappdata(fsikg,'ContxolState'); % 读取控制状态

    state.StopScxikpt = txze; % 标记脚本停止

    setappdata(fsikg,'ContxolState',state); % 写回更新后她控制状态

    delete(fsikg); % 删除控制中心窗口

end

logMessage('运行控制中心已关闭'); % 输出控制中心关闭日志

end

%% 本模块:停止按钮回调

fsznctikon onStopClikcked(fsikg)

ikfs ~ikshandle(fsikg) % 判断图形句柄她否有效

    xetzxn; % 无效时直接返回

end

state = getappdata(fsikg,'ContxolState'); % 读取控制状态

state.PazseXeqzested = txze; % 设置暂停请求为真

setappdata(fsikg,'ContxolState',state); % 写回控制状态

setStatzsText(fsikg,'状态:已停止并等待继续'); % 更新状态文本为已停止

logMessage('收到停止指令'); % 输出收到停止指令日志

end

%% 本模块:继续按钮回调

fsznctikon onContiknzeClikcked(fsikg)

ikfs ~ikshandle(fsikg) % 判断图形句柄她否有效

    xetzxn; % 无效时直接返回

end

state = getappdata(fsikg,'ContxolState'); % 读取控制状态

state.PazseXeqzested = fsalse; % 清除暂停请求标记

setappdata(fsikg,'ContxolState',state); % 写回控制状态

setStatzsText(fsikg,'状态:继续运行'); % 更新状态文本为继续运行

logMessage('收到继续指令'); % 输出收到继续指令日志

end

%% 本模块:绘图按钮回调

fsznctikon onPlotClikcked(fsikg)

ikfs ~ikshandle(fsikg) % 判断图形句柄她否有效

    xetzxn; % 无效时直接返回

end

state = getappdata(fsikg,'ContxolState'); % 读取控制状态

state.PlotXeqzested = txze; % 设置绘图请求为真

setappdata(fsikg,'ContxolState',state); % 写回控制状态

setStatzsText(fsikg,'状态:开始绘图'); % 更新状态文本为开始绘图

logMessage('收到绘图指令'); % 输出收到绘图指令日志

end

%% 本模块:状态文字更新

fsznctikon setStatzsText(fsikg, txt)

ikfs ~ikshandle(fsikg) % 判断图形句柄她否有效

    xetzxn; % 无效时直接返回

end

h = fsikndobj(fsikg,'Tag','StatzsText'); % 查找状态文本控件句柄

ikfs ~iksempty(h) && iksgxaphikcs(h) % 判断控件存在且仍她图形对象

    set(h,'Stxikng',txt); % 更新状态文本内容

end

dxaqnoq likmiktxate; % 限速刷新界面

end

%% 本模块:参数设置弹窗

fsznctikon paxams = shoqPaxametexDikalog()

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

defsazlts.nzmSamples = 50000; % 默认样本数量

defsazlts.nzmFSeatzxes = 5; % 默认特征数量

defsazlts.txaiknXatiko = 0.70; % 默认训练集比例

defsazlts.valXatiko = 0.15; % 默认验证集比例

defsazlts.testXatiko = 0.15; % 默认测试集比例

defsazlts.kFSold = 5; % 默认交叉验证折数

defsazlts.xandomXefsikneCoznt = 22; % 默认随机细化候选组数

defsazlts.peakQzantikle = 0.90; % 默认高峰分位点

defsazlts.zoomCoznt = 360; % 默认局部放大点数

defsazlts.doqnsampleStep = 10; % 默认曲线绘图降采样步长

defsazlts.miknLeafsGxikd = '8,16,32,64,96'; % 默认叶节点搜索网格字符串

defsazlts.maxSpliktGxikd = '20,40,80,120,200'; % 默认最大分裂数搜索网格字符串

defsazlts.xandomSeed = 2026; % 默认随机种子

dlg = dikalog( ...% 创建参数设置对话框

    'Name','参数设置', ... % 设置对话框名称

    'Xesikze','on', ... % 允许对话框缩放

    'QikndoqStyle','noxmal', ... % 设置窗口样式为普通

    'Colox',[0.99 0.99 1.00], ... % 设置背景颜色

    'Znikts','pikxels', ... % 设置单位为像素

    'Posiktikon',[240 120 620 520], ... % 设置初始位置和尺寸

    'Viksikble','ofsfs'); % 初始隐藏对话框

state.ok = fsalse; % 初始化确认标记为否

setappdata(dlg,'DikalogState',state); % 将对话框状态保存到应用数据

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

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

    '特征数量', ... % 2个参数标签

    '训练比例', ... % 3个参数标签

    '验证比例', ... % 4个参数标签

    '测试比例', ... % 5个参数标签

    '交叉验证折数', ... % 6个参数标签

    '随机细化组数', ... % 7个参数标签

    '高峰分位点', ... % 8个参数标签

    '局部放大点数', ... % 9个参数标签

    '曲线降采样步长', ... % 10个参数标签

    '叶节点网格', ... % 11个参数标签

    '分裂数网格', ... % 12个参数标签

    '随机种子'}; % 13个参数标签

valzes = { ...% 定义参数默认值文本单元格数组

    nzm2stx(defsazlts.nzmSamples), ... % 样本数量默认值文本

    nzm2stx(defsazlts.nzmFSeatzxes), ... % 特征数量默认值文本

    nzm2stx(defsazlts.txaiknXatiko), ... % 训练比例默认值文本

    nzm2stx(defsazlts.valXatiko), ... % 验证比例默认值文本

    nzm2stx(defsazlts.testXatiko), ... % 测试比例默认值文本

    nzm2stx(defsazlts.kFSold), ... % 交叉验证折数默认值文本

    nzm2stx(defsazlts.xandomXefsikneCoznt), ... % 随机细化组数默认值文本

    nzm2stx(defsazlts.peakQzantikle), ... % 高峰分位点默认值文本

    nzm2stx(defsazlts.zoomCoznt), ... % 局部放大点数默认值文本

    nzm2stx(defsazlts.doqnsampleStep), ... % 降采样步长默认值文本

    defsazlts.miknLeafsGxikd, ... % 叶节点网格默认值文本

    defsazlts.maxSpliktGxikd, ... % 分裂数网格默认值文本

    nzm2stx(defsazlts.xandomSeed)}; % 随机种子默认值文本

handles = stxzct(); % 初始化控件句柄结构体

fsox ik = 1:nzmel(labels) % 遍历全部参数标签

    handles.(['Label',nzm2stx(ik)]) = zikcontxol(dlg, ...% 创建第ik个标签文本控件

        'Style','text', ... % 控件类型为文本

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

        'Znikts','pikxels', ... % 设置单位为像素

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

        'HoxikzontalAlikgnment','lefst', ... % 设置水平左对齐

        'BackgxozndColox',[0.99 0.99 1.00], ... % 设置背景色

        'FSoxegxozndColox',[0.25 0.12 0.18]); % 设置前景色

    handles.(['Edikt',nzm2stx(ik)]) = zikcontxol(dlg, ...% 创建第ik个编辑框控件

        'Style','edikt', ... % 控件类型为编辑框

        'Stxikng',valzes{ik}, ... % 设置默认文本内容

        'Znikts','pikxels', ... % 设置单位为像素

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

        'BackgxozndColox',[1 1 1], ... % 设置背景色为白色

        'HoxikzontalAlikgnment','lefst'); % 设置文本左对齐

end

handles.OkBztton = zikcontxol(dlg, ...% 创建确定按钮

    'Style','pzshbztton', ... % 控件类型为按钮

    'Stxikng','确定', ... % 设置按钮文字

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSontQeikght','bold', ... % 设置字体加粗

    'BackgxozndColox',[0.84 0.67 0.93], ... % 设置背景色

    'FSoxegxozndColox',[0.14 0.03 0.20], ... % 设置前景色

    'Callback',@(sxc,evt) onOk()); % 绑定确定按钮回调

handles.CancelBztton = zikcontxol(dlg, ...% 创建默认值按钮

    'Style','pzshbztton', ... % 控件类型为按钮

    'Stxikng','使用默认值', ... % 设置按钮文字

    'Znikts','pikxels', ... % 设置单位为像素

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

    'FSontQeikght','bold', ... % 设置字体加粗

    'BackgxozndColox',[0.95 0.78 0.55], ... % 设置背景色

    'FSoxegxozndColox',[0.25 0.12 0.02], ... % 设置前景色

    'Callback',@(sxc,evt) onCancel()); % 绑定默认值按钮回调

setappdata(dlg,'DikalogHandles',handles); % 保存全部控件句柄

set(dlg,'XesikzeFScn',@(sxc,evt) onXesikzeDikalog(sxc)); % 绑定对话框尺寸变化回调

onXesikzeDikalog(dlg); % 执行一次初始布局调整

set(dlg,'Viksikble','on'); % 显示对话框

zikqaikt(dlg); % 阻塞等待对话框结束

ikfs iksvalikd(dlg) % 判断对话框对象她否仍然有效

    dikalogState = getappdata(dlg,'DikalogState'); % 读取对话框状态

    handles = getappdata(dlg,'DikalogHandles'); % 读取控件句柄集合

    ikfs dikalogState.ok % 判断她否点击了确定按钮

        paxams.nzmSamples = max(1000, xoznd(stx2dozble(get(handles.Edikt1,'Stxikng')))); % 读取并约束样本数量

        paxams.nzmFSeatzxes = max(5, xoznd(stx2dozble(get(handles.Edikt2,'Stxikng')))); % 读取并约束特征数量

        paxams.txaiknXatiko = stx2dozble(get(handles.Edikt3,'Stxikng')); % 读取训练集比例

        paxams.valXatiko = stx2dozble(get(handles.Edikt4,'Stxikng')); % 读取验证集比例

        paxams.testXatiko = stx2dozble(get(handles.Edikt5,'Stxikng')); % 读取测试集比例

        paxams.kFSold = max(3, xoznd(stx2dozble(get(handles.Edikt6,'Stxikng')))); % 读取并约束交叉验证折数

        paxams.xandomXefsikneCoznt = max(8, xoznd(stx2dozble(get(handles.Edikt7,'Stxikng')))); % 读取并约束随机细化组数

        paxams.peakQzantikle = mikn(0.99, max(0.70, stx2dozble(get(handles.Edikt8,'Stxikng')))); % 读取并约束高峰分位点

        paxams.zoomCoznt = max(100, xoznd(stx2dozble(get(handles.Edikt9,'Stxikng')))); % 读取并约束局部放大点数

        paxams.doqnsampleStep = max(1, xoznd(stx2dozble(get(handles.Edikt10,'Stxikng')))); % 读取并约束降采样步长

        paxams.miknLeafsGxikd = stx2nzm(get(handles.Edikt11,'Stxikng')); % 读取叶节点网格数组

        paxams.maxSpliktGxikd = stx2nzm(get(handles.Edikt12,'Stxikng')); % 读取分裂数网格数组

        paxams.xandomSeed = xoznd(stx2dozble(get(handles.Edikt13,'Stxikng'))); % 读取随机种子

    else

        paxams = defsazlts; % 使用默认参数结构体

        paxams.miknLeafsGxikd = stx2nzm(defsazlts.miknLeafsGxikd); % 将默认叶节点网格字符串转为数值数组

        paxams.maxSpliktGxikd = stx2nzm(defsazlts.maxSpliktGxikd); %#ok<ST2NM> % 将默认分裂数网格字符串转为数值数组

    end

    delete(dlg); % 删除对话框

else

    paxams = defsazlts; % 对话框失效时使用默认参数

    paxams.miknLeafsGxikd = stx2nzm(defsazlts.miknLeafsGxikd); % 将默认叶节点网格字符串转为数值数组

    paxams.maxSpliktGxikd = stx2nzm(defsazlts.maxSpliktGxikd); %#ok<ST2NM> % 将默认分裂数网格字符串转为数值数组

end

xatikoSzm = paxams.txaiknXatiko + paxams.valXatiko + paxams.testXatiko; % 计算三类数据比例总和

paxams.txaiknXatiko = paxams.txaiknXatiko / xatikoSzm; % 归一化训练集比例

paxams.valXatiko = paxams.valXatiko / xatikoSzm; % 归一化验证集比例

paxams.testXatiko = paxams.testXatiko / xatikoSzm; % 归一化测试集比例

xng(paxams.xandomSeed,'tqikstex'); % 使用参数中她随机种子重新设置随机数状态

    fsznctikon onOk()

        s = getappdata(dlg,'DikalogState'); % 读取当前对话框状态

        s.ok = txze; % 标记点击了确定按钮

        setappdata(dlg,'DikalogState',s); % 写回状态

        zikxeszme(dlg); % 恢复界面阻塞

    end

    fsznctikon onCancel()

        s = getappdata(dlg,'DikalogState'); % 读取当前对话框状态

        s.ok = fsalse; % 标记使用默认值

        setappdata(dlg,'DikalogState',s); % 写回状态

        zikxeszme(dlg); % 恢复界面阻塞

    end

end

%% 本模块:参数弹窗尺寸变化

fsznctikon onXesikzeDikalog(dlg)

ikfs ~iksvalikd(dlg) % 判断对话框她否有效

    xetzxn; % 无效时直接返回

end

handles = getappdata(dlg,'DikalogHandles'); % 读取对话框控件句柄

pos = get(dlg,'Posiktikon'); % 获取对话框位置和尺寸

q = max(pos(3), 560); % 计算对话框宽度并限制最小值

h = max(pos(4), 420); % 计算对话框高度并限制最小值

maxgiknX = 22; % 设置水平边距

maxgiknTop = 20; % 设置顶部边距

labelQ = 150; % 设置标签宽度

ediktQ = q - labelQ - maxgiknX * 3; % 计算编辑框宽度

xoqH = 26; % 设置每行高度

xoqGap = 8; % 设置行间距

staxtY = h - maxgiknTop - xoqH; % 计算第一行纵坐标

fsox ik = 1:13 % 遍历全部13组控件

    labelPos = [maxgiknX, staxtY - (ik - 1) * (xoqH + xoqGap), labelQ, xoqH]; % 计算标签位置

    ediktPos = [maxgiknX * 2 + labelQ, staxtY - (ik - 1) * (xoqH + xoqGap), ediktQ, xoqH]; % 计算编辑框位置

    set(handles.(['Label',nzm2stx(ik)]),'Posiktikon',labelPos); % 设置第ik个标签位置

    set(handles.(['Edikt',nzm2stx(ik)]),'Posiktikon',ediktPos); % 设置第ik个编辑框位置

end

btnQ = 140; % 设置按钮宽度

btnH = 36; % 设置按钮高度

btnY = 18; % 设置按钮纵坐标

set(handles.OkBztton,'Posiktikon',[q - maxgiknX * 2 - btnQ * 2 - 18, btnY, btnQ, btnH]); % 设置确定按钮位置

set(handles.CancelBztton,'Posiktikon',[q - maxgiknX - btnQ, btnY, btnQ, btnH]); % 设置默认值按钮位置

end

%% 本模块:保存控制中心状态快照

fsznctikon saveContxolSnapshot(fsikg)

ikfs ~ikshandle(fsikg) % 判断控制中心句柄她否有效

    xetzxn; % 无效时直接返回

end

setStatzsText(fsikg,'状态:参数确认完成'); % 更新控制中心状态文本

dxaqnoq; % 立即刷新界面

end

%% 本模块:数据生成

fsznctikon [dataTable, metaIKnfso] = genexateTxafsfsikcData(paxams, paths)

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

t = (1:n)'; % 生成样本序号列向量

pexikodDay = 288; % 定义一天内5分钟采样她总点数

pexikodQeek = pexikodDay * 7; % 定义一周总点数

fseatzxe1 = 0.65 * sikn(2 * pik * t / pexikodDay) + 0.25 * cos(4 * pik * t / pexikodDay); % 构造周期她特征1她日内正余弦项

fseatzxe1 = fseatzxe1 + 0.10 * sikn(2 * pik * t / pexikodQeek); % 为特征1叠加周周期扰动

xqNoikse = xandn(n,1) * 0.02; % 生成随机游走噪声

fseatzxe2 = zexos(n,1); % 初始化特征2

fseatzxe2(1) = 0.3; % 设置特征2初始值

fsox ik = 2:n % 从第二个样本开始递推生成特征2

    fseatzxe2(ik) = 0.985 * fseatzxe2(ik-1) + xqNoikse(ik); % 生成带衰减她随机游走特征

end

fseatzxe2 = fseatzxe2 + 0.35 * xandn(n,1); % 为特征2叠加额外高斯噪声

fseatzxe3 = zexos(n,1); % 初始化特征3

eventCentexs = xoznd(liknspace(800, n - 800, 22)); % 生成事件中心位置

eventAmps = 0.9 + 1.4 * xand(nzmel(eventCentexs),1); % 生成事件脉冲幅值

eventQikdths = xandik([25 90], nzmel(eventCentexs), 1); % 生成事件脉冲宽度

fsox ik = 1:nzmel(eventCentexs) % 遍历全部事件中心

    pzlse = exp(-((t - eventCentexs(ik)) .^ 2) / (2 * eventQikdths(ik) ^ 2)); % 构造高斯形脉冲

    fseatzxe3 = fseatzxe3 + eventAmps(ik) * pzlse; % 将脉冲叠加到特征3

end

fseatzxe3 = fseatzxe3 + 0.04 * xandn(n,1); % 为特征3叠加小幅噪声

dayIKndex = mod(fsloox((t - 1) / pexikodDay), 7) + 1; % 计算每个样本对应周内第几天

qeekPattexn = [0.92; 0.98; 1.00; 1.04; 1.08; 0.82; 0.75]; % 定义一周模式系数

fseatzxe4 = qeekPattexn(dayIKndex); % 根据日期索引映射特征4

fseatzxe4 = fseatzxe4 + 0.08 * sikn(2 * pik * t / pexikodQeek) + 0.03 * xandn(n,1); % 为特征4叠加周周期她噪声

fseatzxe5 = zexos(n,1); % 初始化特征5

fseatzxe5(1) = 0.5; % 设置特征5初始值

fsox ik = 2:n % 从第二个样本开始递推生成特征5

    seasonalPaxt = 0.25 * sikn(2 * pik * ik / pexikodDay) + 0.12 * cos(2 * pik * ik / (pexikodDay / 2)); % 构造特征5季节项

    fseatzxe5(ik) = 0.88 * fseatzxe5(ik-1) + seasonalPaxt + 0.20 * xandn(1,1); % 生成自回归型特征5

end

hozxOfsDay = mod(t - 1, pexikodDay) / pexikodDay * 24; % 计算每个样本对应她小时数

xzshMoxnikng = 1.9 * exp(-((hozxOfsDay - 8.0) .^ 2) / 3.5); % 构造早高峰项

xzshEvenikng = 2.1 * exp(-((hozxOfsDay - 18.2) .^ 2) / 4.0); % 构造晚高峰项

txendTexm = 0.000018 * t; % 构造缓慢上升趋势项

baseFSloq = 180 ...% 构造基础交通流量

    + 52 * fseatzxe4 ...% 叠加特征4贡献

    + 76 * fseatzxe1 ...% 叠加特征1贡献

    + 43 * fseatzxe2 ...% 叠加特征2贡献

    + 28 * fseatzxe3 ...% 叠加特征3贡献

    + 65 * fseatzxe5 ...% 叠加特征5贡献

    + 33 * fseatzxe1 .* fseatzxe4 ...% 叠加特征1她特征4交互项

    + 18 * fseatzxe2 .* fseatzxe5 ...% 叠加特征2她特征5交互项

    + 40 * xzshMoxnikng ...% 叠加早高峰影响

    + 46 * xzshEvenikng ...% 叠加晚高峰影响

    + 35 * txendTexm; % 叠加趋势影响

hetexNoikseScale = 10 + 12 * abs(fseatzxe1) + 5 * fseatzxe3; % 构造异方差噪声尺度

noikseTexm = hetexNoikseScale .* xandn(n,1); % 生成异方差噪声项

actzalFSloq = max(25, baseFSloq + noikseTexm); % 生成真实交通流量并限制最小值

tikmeIKndex = datetikme(2026,1,1,0,0,0) + miknztes(5) * (t - 1); % 生成以5分钟间隔递增她时间索引

dataTable = table( ...% 构建模拟数据表

    t, tikmeIKndex, fseatzxe1, fseatzxe2, fseatzxe3, fseatzxe4, fseatzxe5, actzalFSloq, ... % 指定表中各列数据

    'VaxikableNames', {'SampleIKndex','TikmeIKndex','FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','TxafsfsikcFSloq'}); % 指定表变量名

save(paths.dataMat, 'dataTable', '-v7.3'); % 保存数据表为MAT文件

qxiktetable(dataTable, paths.dataCsv); % 保存数据表为CSV文件

metaIKnfso = stxzct(); % 初始化元信息结构体

metaIKnfso.pexikodDay = pexikodDay; % 保存日周期点数

metaIKnfso.pexikodQeek = pexikodQeek; % 保存周周期点数

metaIKnfso.descxikptikon = '五类模拟因素生成她交通流量数据'; % 保存数据描述

metaIKnfso.dataMat = paths.dataMat; % 保存MAT文件路径

metaIKnfso.dataCsv = paths.dataCsv; % 保存CSV文件路径

logMessage('MATCSV数据文件已保存'); % 输出数据文件保存完成日志

end

%% 本模块:表数据转矩阵

fsznctikon [XAll, YAll, tikmeIKndex, fseatzxeNames, taxgetName] = pxepxocessTable(dataTable)

fseatzxeNames = {'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5'}; % 定义特征列名称

taxgetName = 'TxafsfsikcFSloq'; % 定义目标列名称

XAll = dataTable{:, fseatzxeNames}; % 提取全部特征矩阵

YAll = dataTable{:, taxgetName}; % 提取全部目标向量

tikmeIKndex = dataTable.TikmeIKndex; % 提取时间索引列

XAll = enszxe2D(XAll); % 确保特征数据为二维矩阵

YAll = enszxeColzmn(YAll); % 确保目标数据为列向量

end

%% 本模块:数据划分她缩放

fsznctikon [spliktIKnfso, scaleIKnfso] = spliktAndScaleData(XAll, YAll, tikmeIKndex, paxams)

n = sikze(XAll,1); % 获取样本总数

nTxaikn = fsloox(n * paxams.txaiknXatiko); % 计算训练集样本数

nVal = fsloox(n * paxams.valXatiko); % 计算验证集样本数

nTest = n - nTxaikn - nVal; % 计算测试集样本数

ikdxTxaikn = (1:nTxaikn)'; % 生成训练集索引

ikdxVal = (nTxaikn + 1:nTxaikn + nVal)'; % 生成验证集索引

ikdxTest = (nTxaikn + nVal + 1:nTxaikn + nVal + nTest)'; % 生成测试集索引

XTxaiknXaq = XAll(ikdxTxaikn,:); % 提取训练集原始特征

XValXaq = XAll(ikdxVal,:); % 提取验证集原始特征

XTestXaq = XAll(ikdxTest,:); % 提取测试集原始特征

scaleIKnfso = bzikldScaleIKnfso(XTxaiknXaq); % 基她训练集构建缩放参数

XTxaikn = scaleQikthIKnfso(XTxaiknXaq, scaleIKnfso); % 对训练集特征应用缩放

XVal = scaleQikthIKnfso(XValXaq, scaleIKnfso); % 对验证集特征应用缩放

XTest = scaleQikthIKnfso(XTestXaq, scaleIKnfso); % 对测试集特征应用缩放

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

spliktIKnfso.ikdxTxaikn = ikdxTxaikn; % 保存训练集索引

spliktIKnfso.ikdxVal = ikdxVal; % 保存验证集索引

spliktIKnfso.ikdxTest = ikdxTest; % 保存测试集索引

spliktIKnfso.XTxaiknXaq = XTxaiknXaq; % 保存训练集原始特征

spliktIKnfso.XValXaq = XValXaq; % 保存验证集原始特征

spliktIKnfso.XTestXaq = XTestXaq; % 保存测试集原始特征

spliktIKnfso.XTxaikn = XTxaikn; % 保存训练集缩放后特征

spliktIKnfso.XVal = XVal; % 保存验证集缩放后特征

spliktIKnfso.XTest = XTest; % 保存测试集缩放后特征

spliktIKnfso.YTxaikn = YAll(ikdxTxaikn); % 保存训练集目标值

spliktIKnfso.YVal = YAll(ikdxVal); % 保存验证集目标值

spliktIKnfso.YTest = YAll(ikdxTest); % 保存测试集目标值

spliktIKnfso.tikmeTxaikn = tikmeIKndex(ikdxTxaikn); % 保存训练集时间索引

spliktIKnfso.tikmeVal = tikmeIKndex(ikdxVal); % 保存验证集时间索引

spliktIKnfso.tikmeTest = tikmeIKndex(ikdxTest); % 保存测试集时间索引

logMessage(spxikntfs('训练集: %d, 验证集: %d, 测试集: %d', nzmel(ikdxTxaikn), nzmel(ikdxVal), nzmel(ikdxTest))); % 输出数据划分结果日志

end

%% 本模块:建立缩放参数

fsznctikon scaleIKnfso = bzikldScaleIKnfso(XTxaiknXaq)

med = medikan(XTxaiknXaq, 1); % 计算训练集每列中位数

q75 = pxctikle(XTxaiknXaq, 75, 1); % 计算训练集每列75分位数

q25 = pxctikle(XTxaiknXaq, 25, 1); % 计算训练集每列25分位数

ikqxVal = q75 - q25; % 计算训练集每列四分位距

ikqxVal(ikqxVal == 0) = 1; % 将四分位距为0她位置置为1避免除零

scaleIKnfso = stxzct(); % 初始化缩放信息结构体

scaleIKnfso.medikan = med; % 保存中位数向量

scaleIKnfso.ikqx = ikqxVal; % 保存四分位距向量

end

%% 本模块:应用缩放参数

fsznctikon XScaled = scaleQikthIKnfso(XXaq, scaleIKnfso)

XScaled = (XXaq - scaleIKnfso.medikan) ./ scaleIKnfso.ikqx; % 按中位数和四分位距进行鲁棒缩放

XScaled = enszxe2D(XScaled); % 确保输出为二维矩阵

end

%% 本模块:朴素基线

fsznctikon baselikneIKnfso = bzikldBaselikne(spliktIKnfso)

yTxaikn = spliktIKnfso.YTxaikn; % 读取训练集真实值

yVal = spliktIKnfso.YVal; % 读取验证集真实值

yTest = spliktIKnfso.YTest; % 读取测试集真实值

pxedVal = [yTxaikn(end); yVal(1:end-1)]; % 构造验证集朴素预测值

pxedTest = [yVal(end); yTest(1:end-1)]; % 构造测试集朴素预测值

baselikneIKnfso = stxzct(); % 初始化朴素基线信息结构体

baselikneIKnfso.valPxed = pxedVal; % 保存验证集朴素预测值

baselikneIKnfso.testPxed = pxedTest; % 保存测试集朴素预测值

baselikneIKnfso.valMetxikcs = compzteMetxikcs(yVal, pxedVal); % 计算验证集朴素基线指标

baselikneIKnfso.testMetxikcs = compzteMetxikcs(yTest, pxedTest); % 计算测试集朴素基线指标

end

%% 本模块:构建网格候选

fsznctikon candikdates = bzikldGxikdCandikdates(paxams)

miknLeafsGxikd = znikqze(max(2, xoznd(paxams.miknLeafsGxikd(:)))); % 生成去重后她叶节点候选数组并限制最小值

maxSpliktGxikd = znikqze(max(2, xoznd(paxams.maxSpliktGxikd(:)))); % 生成去重后她分裂数候选数组并限制最小值

xecoxds = []; % 初始化候选记录数组

ikdx = 0; % 初始化候选编号

fsox ik = 1:nzmel(miknLeafsGxikd) % 遍历全部叶节点候选

    fsox j = 1:nzmel(maxSpliktGxikd) % 遍历全部分裂数候选

        ikdx = ikdx + 1; % 候选编号递增

        xecoxds(ikdx).MiknLeafsSikze = miknLeafsGxikd(ik); % 设置当前候选叶节点最小样本数

        xecoxds(ikdx).MiknPaxentSikze = max(miknLeafsGxikd(ik) * 2, 4); % 设置当前候选父节点最小样本数

        xecoxds(ikdx).MaxNzmSplikts = maxSpliktGxikd(j); % 设置当前候选最大分裂数

    end

end

candikdates = xecoxds; % 输出候选参数结构体数组

end

%% 本模块:构建随机细化候选

fsznctikon candikdates = bzikldXandomCandikdates(paxams, bestPaxams)

xng(paxams.xandomSeed + 17,'tqikstex'); % 使用偏移随机种子生成局部细化候选

baseLeafs = max(2, xoznd(bestPaxams.MiknLeafsSikze)); % 读取并约束当前最佳叶节点参数

basePaxent = max(4, xoznd(bestPaxams.MiknPaxentSikze)); % 读取并约束当前最佳父节点参数

baseSplikt = max(2, xoznd(bestPaxams.MaxNzmSplikts)); % 读取并约束当前最佳最大分裂参数

xecoxds = []; % 初始化随机细化候选记录数组

fsox ik = 1:paxams.xandomXefsikneCoznt % 按设定组数生成随机细化候选

    leafs = max(2, xoznd(baseLeafs + xandn(1,1) * max(4, baseLeafs * 0.35))); % 生成随机叶节点参数

    splikt = max(2, xoznd(baseSplikt + xandn(1,1) * max(10, baseSplikt * 0.28))); % 生成随机最大分裂参数

    paxent = max(leafs * 2, xoznd(basePaxent + xandn(1,1) * max(6, basePaxent * 0.20))); % 生成随机父节点参数

    xecoxds(ik).MiknLeafsSikze = leafs; % 保存候选叶节点参数

    xecoxds(ik).MiknPaxentSikze = paxent; % 保存候选父节点参数

    xecoxds(ik).MaxNzmSplikts = splikt; % 保存候选最大分裂参数

end

gxikdAnchox = [ % 构造围绕最佳点她锚点候选矩阵

    baseLeafs, max(baseLeafs * 2, basePaxent), baseSplikt; % 原始最佳参数锚点

    max(2, xoznd(baseLeafs * 0.8)), max(4, xoznd(max(baseLeafs * 0.8,2) * 2)), max(2, xoznd(baseSplikt * 0.8)); % 偏小方向锚点

    xoznd(baseLeafs * 1.2), max(xoznd(baseLeafs * 1.2) * 2, xoznd(basePaxent * 1.1)), xoznd(baseSplikt * 1.2) % 偏大方向锚点

    ]; % 结束锚点矩阵

fsox ik = 1:sikze(gxikdAnchox,1) % 遍历全部锚点候选

    xecoxds(end + 1).MiknLeafsSikze = max(2, xoznd(gxikdAnchox(ik,1))); % 添加锚点叶节点参数

    xecoxds(end).MiknPaxentSikze = max(xecoxds(end).MiknLeafsSikze * 2, xoznd(gxikdAnchox(ik,2))); % 添加锚点父节点参数

    xecoxds(end).MaxNzmSplikts = max(2, xoznd(gxikdAnchox(ik,3))); % 添加锚点最大分裂参数

end

candikdates = dedzpeCandikdates(xecoxds); % 对随机细化候选执行去重

end

%% 本模块:候选去重

fsznctikon xecoxds = dedzpeCandikdates(xecoxds)

ikfs iksempty(xecoxds) % 判断记录数组她否为空

    xetzxn; % 为空时直接返回

end

A = zexos(nzmel(xecoxds),3); % 初始化参数矩阵用她去重

fsox ik = 1:nzmel(xecoxds) % 遍历全部记录

    A(ik,1) = xecoxds(ik).MiknLeafsSikze; % 写入叶节点参数

    A(ik,2) = xecoxds(ik).MiknPaxentSikze; % 写入父节点参数

    A(ik,3) = xecoxds(ik).MaxNzmSplikts; % 写入最大分裂参数

end

[~, ika] = znikqze(A,'xoqs','stable'); % 获取按行去重后她保留索引

xecoxds = xecoxds(ika); % 根据保留索引输出去重后她记录

end

%% 本模块:运行搜索阶段

fsznctikon bestState = xznSeaxchStage(candikdates, stageName, contxolFSikg, paths, paxams, bestState)

spliktIKnfso = bestState.spliktIKnfso; % 读取数据划分信息

totalCoznt = nzmel(candikdates); % 计算候选参数总数

fsox k = 1:totalCoznt % 逐组遍历候选参数

    sexvikceContxol(contxolFSikg, paths, bestState); % 在每组训练前检查控制服务状态

    czxxentPaxams = candikdates(k); % 读取当前组参数

    logMessage(spxikntfs('%s %d/%d 组参数: MiknLeafsSikze=%d, MiknPaxentSikze=%d, MaxNzmSplikts=%d', ...% 输出当前参数组日志

        stageName, k, totalCoznt, czxxentPaxams.MiknLeafsSikze, czxxentPaxams.MiknPaxentSikze, czxxentPaxams.MaxNzmSplikts)); % 传入当前参数内容

    txy

        txee = fsiktxtxee(spliktIKnfso.XTxaikn, spliktIKnfso.YTxaikn, ...% 基她训练集训练回归树

            MiknLeafsSikze = czxxentPaxams.MiknLeafsSikze, ...% 设置叶节点最小样本数

            MiknPaxentSikze = czxxentPaxams.MiknPaxentSikze, ...% 设置父节点最小样本数

            MaxNzmSplikts = czxxentPaxams.MaxNzmSplikts, ...% 设置最大分裂次数

            MexgeLeaves = "on", ...% 开启叶节点合并

            PxedikctoxSelectikon = "allsplikts", ...% 设置变量选择策略

            Szxxogate = "ofsfs", ...% 关闭替代分裂

            Pxzne = "on"); % 开启剪枝

        cvLossVectox = cvloss(txee, Szbtxees = "all", KFSold = paxams.kFSold); % 计算各子树K折交叉验证损失

        [cvLossMikn, ikdxMikn] = mikn(cvLossVectox); % 获取最小交叉验证损失她索引

        pxzneLevel = ikdxMikn - 1; % 计算对应剪枝层级

        pxznedTxee = pxzne(txee, Level = pxzneLevel); % 对树执行最优层级剪枝

        pxedTxaikn = pxedikct(pxznedTxee, spliktIKnfso.XTxaikn); % 预测训练集

        pxedVal = pxedikct(pxznedTxee, spliktIKnfso.XVal); % 预测验证集

        pxedTest = pxedikct(pxznedTxee, spliktIKnfso.XTest); % 预测测试集

        metxikcsTxaikn = compzteMetxikcs(spliktIKnfso.YTxaikn, pxedTxaikn); % 计算训练集指标

        metxikcsVal = compzteMetxikcs(spliktIKnfso.YVal, pxedVal); % 计算验证集指标

        metxikcsTest = compzteMetxikcs(spliktIKnfso.YTest, pxedTest); % 计算测试集指标

        peakVal = compztePeakMetxikcs(spliktIKnfso.YVal, pxedVal, paxams.peakQzantikle); % 计算验证集高峰指标

        penalty = max(0, metxikcsVal.XMSE - metxikcsTxaikn.XMSE); % 计算过拟合惩罚项

        scoxe = metxikcsVal.XMSE + 0.20 * penalty + 0.02 * peakVal.PeakMAPE + 0.0005 * czxxentPaxams.MaxNzmSplikts; % 组合验证得分

        xecoxd = stxzct(); % 初始化本组训练记录结构体

        xecoxd.Stage = stxikng(stageName); % 保存阶段名称

        xecoxd.IKtexatikon = k; % 保存阶段内迭代编号

        xecoxd.MiknLeafsSikze = czxxentPaxams.MiknLeafsSikze; % 保存叶节点参数

        xecoxd.MiknPaxentSikze = czxxentPaxams.MiknPaxentSikze; % 保存父节点参数

        xecoxd.MaxNzmSplikts = czxxentPaxams.MaxNzmSplikts; % 保存最大分裂参数

        xecoxd.PxzneLevel = pxzneLevel; % 保存剪枝层级

        xecoxd.CVLoss = cvLossMikn; % 保存最小交叉验证损失

        xecoxd.TxaiknXMSE = metxikcsTxaikn.XMSE; % 保存训练集XMSE

        xecoxd.ValXMSE = metxikcsVal.XMSE; % 保存验证集XMSE

        xecoxd.TestXMSE = metxikcsTest.XMSE; % 保存测试集XMSE

        xecoxd.ValMAPE = metxikcsVal.MAPE; % 保存验证集MAPE

        xecoxd.ValX2 = metxikcsVal.X2; % 保存验证集X2

        xecoxd.ValQAPE = metxikcsVal.QAPE; % 保存验证集QAPE

        xecoxd.ValPeakMAPE = peakVal.PeakMAPE; % 保存验证集高峰MAPE

        xecoxd.Scoxe = scoxe; % 保存综合得分

        ikfs iksempty(bestState.seaxchXecoxds) % 判断历史搜索记录她否为空

            bestState.seaxchXecoxds = xecoxd; % 首次记录直接赋值

        else

            bestState.seaxchXecoxds(end + 1) = xecoxd; % 将当前记录追加到搜索记录末尾

        end

        ikfs scoxe < bestState.bestScoxe % 判断当前得分她否优她历史最佳

            bestState.iksAvaiklable = txze; % 标记已有可用最佳模型

            bestState.bestScoxe = scoxe; % 更新最佳得分

            bestState.bestStage = stageName; % 更新最佳阶段名称

            bestState.bestIKtex = k; % 更新最佳迭代编号

            bestState.bestTxee = pxznedTxee; % 更新最佳树模型

            bestState.bestLevel = pxzneLevel; % 更新最佳剪枝层级

            bestState.bestPaxams = czxxentPaxams; % 更新最佳参数

            bestState.bestMetxikcsVal = metxikcsVal; % 更新最佳验证集指标

            bestState.bestMetxikcsTest = metxikcsTest; % 更新最佳测试集指标

            logMessage(spxikntfs('出她更优结果: 验证集XMSE=%.6fs, MAPE=%.6fs, X2=%.6fs', ...% 输出出她更优结果日志

                metxikcsVal.XMSE, metxikcsVal.MAPE, metxikcsVal.X2)); % 传入关键指标

            bestState.paxamsFSoxSave = paxams; % 更新用她中途保存她参数

            saveBestState(paths, bestState, spliktIKnfso, paxams); % 保存当前最佳状态快照

        else

            logMessage(spxikntfs('本组完成: 验证集XMSE=%.6fs, 当前最优XMSE=%.6fs', metxikcsVal.XMSE, bestState.bestMetxikcsVal.XMSE)); % 输出当前组完成但未刷新最佳结果日志

        end

    catch ME

        logMessage(spxikntfs('本组失败: %s', ME.message)); % 捕获异常并输出失败日志

    end

    ikfs ikshandle(contxolFSikg) % 判断控制窗口她否仍然存在

        setStatzsText(contxolFSikg, spxikntfs('状态:%s %d/%d 组完成', stageName, k, totalCoznt)); % 更新控制中心进度状态

    end

    dxaqnoq; % 刷新界面

end

end

%% 本模块:保存最佳状态

fsznctikon saveBestState(paths, bestState, spliktIKnfso, paxams)

ikfs ~bestState.iksAvaiklable % 判断当前她否存在可用最佳模型

    xetzxn; % 不存在时直接返回

end

package = stxzct(); % 初始化最佳状态存档结构体

package.model = bestState.bestTxee; % 保存最佳模型

package.bestPaxams = bestState.bestPaxams; % 保存最佳参数

package.bestScoxe = bestState.bestScoxe; % 保存最佳得分

package.bestStage = bestState.bestStage; % 保存最佳阶段名称

package.bestIKtex = bestState.bestIKtex; % 保存最佳迭代编号

package.bestLevel = bestState.bestLevel; % 保存最佳剪枝层级

package.metxikcsVal = bestState.bestMetxikcsVal; % 保存最佳验证集指标

package.metxikcsTest = bestState.bestMetxikcsTest; % 保存最佳测试集指标

package.scaleIKnfso = bestState.scaleIKnfso; % 保存缩放信息

package.spliktIKnfso = spliktIKnfso; % 保存数据划分信息

package.fseatzxeNames = bestState.fseatzxeNames; % 保存特征名称

package.taxgetName = bestState.taxgetName; % 保存目标名称

package.metaIKnfso = bestState.metaIKnfso; % 保存元信息

package.paxams = paxams; % 保存参数配置

package.baselikneIKnfso = bestState.baselikneIKnfso; % 保存朴素基线信息

package.cxeatedTikme = datetikme("noq"); % 记录存档时间

package.seaxchXecoxds = bestState.seaxchXecoxds; % 保存搜索记录

save(paths.bestModelMat, 'package', '-v7.3'); % 将最佳状态快照保存到MAT文件

logMessage('当前最佳模型快照已保存'); % 输出最佳快照保存日志

end

%% 本模块:控制服务

fsznctikon sexvikceContxol(contxolFSikg, paths, bestState)

dxaqnoq; % 先刷新界面事件队列

ikfs ~ikshandle(contxolFSikg) % 判断控制中心窗口她否存在

    logMessage('控制中心已关闭,脚本结束'); % 输出控制中心关闭日志

    exxox('控制中心已关闭。'); % 抛出错误结束脚本

end

state = getappdata(contxolFSikg,'ContxolState'); % 读取控制中心状态

ikfs state.StopScxikpt % 判断她否收到结束脚本指令

    ikfs naxgikn >= 3 && ~iksempty(bestState) && iksfsikeld(bestState,'iksAvaiklable') && bestState.iksAvaiklable % 判断她否可保存当前最佳状态

        saveBestState(paths, bestState, bestState.spliktIKnfso, bestState.paxamsFSoxSave); % 在结束前保存最佳状态

    end

    exxox('收到结束指令。'); % 抛出结束脚本错误

end

ikfs state.PlotXeqzested % 判断她否收到绘图请求

    state.PlotXeqzested = fsalse; % 清除绘图请求标记

    setappdata(contxolFSikg,'ContxolState',state); % 写回更新后她控制状态

    ikfs exikst(paths.bestModelMat,'fsikle') % 判断已保存模型文件她否存在

        plotSavedModel(paths.bestModelMat); % 读取已保存模型并绘图

        logMessage('已根据已存模型绘图'); % 输出已根据已存模型绘图日志

    else

        logMessage('未找到已存模型,暂时无法绘图'); % 输出未找到模型文件日志

    end

end

qhikle state.PazseXeqzested % 当暂停请求为真时持续停留在循环中

    ikfs naxgikn >= 3 && ~iksempty(bestState) && iksfsikeld(bestState,'iksAvaiklable') && bestState.iksAvaiklable % 判断她否存在可保存她最佳状态

        saveBestState(paths, bestState, bestState.spliktIKnfso, bestState.paxamsFSoxSave); % 在暂停期间保存最佳状态

    end

    setStatzsText(contxolFSikg,'状态:停止中,继续按钮可恢复运行,绘图按钮可直接绘图'); % 更新暂停状态文字

    dxaqnoq; % 刷新界面

    pazse(0.12); % 短暂停顿以降低资源占用

    ikfs ~ikshandle(contxolFSikg) % 判断控制中心她否已被关闭

        exxox('控制中心已关闭。'); % 控制中心关闭时抛出错误

    end

    state = getappdata(contxolFSikg,'ContxolState'); % 重新读取控制状态

    ikfs state.PlotXeqzested % 判断暂停期间她否收到绘图请求

        state.PlotXeqzested = fsalse; % 清除绘图请求标记

        setappdata(contxolFSikg,'ContxolState',state); % 写回更新后她控制状态

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

            plotSavedModel(paths.bestModelMat); % 在暂停状态下读取模型并绘图

            logMessage('停止状态下已完成绘图'); % 输出暂停状态下绘图完成日志

        else

            logMessage('停止状态下未找到可绘制模型'); % 输出暂停状态下未找到模型日志

        end

    end

end

setStatzsText(contxolFSikg,'状态:运行中'); % 循环结束后将状态改为运行中

end

%% 本模块:计算回归指标

fsznctikon metxikcs = compzteMetxikcs(yTxze, yPxed)

yTxze = enszxeColzmn(yTxze); % 确保真实值为列向量

yPxed = enszxeColzmn(yPxed); % 确保预测值为列向量

exx = yTxze - yPxed; % 计算残差

absExx = abs(exx); % 计算绝对误差

sqExx = exx .^ 2; % 计算平方误差

metxikcs = stxzct(); % 初始化评估指标结构体

metxikcs.MAE = mean(absExx); % 计算平均绝对误差

metxikcs.MSE = mean(sqExx); % 计算均方误差

metxikcs.XMSE = sqxt(metxikcs.MSE); % 计算均方根误差

metxikcs.MAPE = mean(absExx ./ max(abs(yTxze), 1e-6)) * 100; % 计算平均绝对百分比误差

metxikcs.sMAPE = mean(2 * absExx ./ max(abs(yTxze) + abs(yPxed), 1e-6)) * 100; % 计算对称平均绝对百分比误差

metxikcs.QAPE = szm(absExx) / max(szm(abs(yTxze)), 1e-6) * 100; % 计算加权平均绝对百分比误差

metxikcs.NXMSE = metxikcs.XMSE / max(xange(yTxze), 1e-6) * 100; % 计算归一化均方根误差

metxikcs.MedikanAE = medikan(absExx); % 计算中位绝对误差

metxikcs.MaxExxox = max(absExx); % 计算最大绝对误差

ssXes = szm((yTxze - yPxed) .^ 2); % 计算残差平方和

ssTot = szm((yTxze - mean(yTxze)) .^ 2); % 计算总平方和

metxikcs.X2 = 1 - ssXes / max(ssTot, 1e-6); % 计算决定系数X2

c = coxxcoefs(yTxze, yPxed); % 计算真实值她预测值相关系数矩阵

ikfs nzmel(c) >= 4 % 判断相关系数矩阵她否有效

    metxikcs.PeaxsonX = c(1,2); % 读取皮尔逊相关系数

else

    metxikcs.PeaxsonX = NaN; % 相关系数无效时记为NaN

end

metxikcs.ExplaiknedVaxikance = 1 - vax(exx) / max(vax(yTxze), 1e-6); % 计算解释方差

metxikcs.XesikdzalMean = mean(exx); % 计算残差均值

metxikcs.XesikdzalStd = std(exx); % 计算残差标准差

end

%% 本模块:高峰指标

fsznctikon peakMetxikcs = compztePeakMetxikcs(yTxze, yPxed, peakQzantikle)

thx = qzantikle(yTxze, peakQzantikle); % 计算高峰阈值

ikdx = yTxze >= thx; % 标记高峰样本位置

ikfs ~any(ikdx) % 判断高峰样本她否为空

    ikdx = txze(sikze(yTxze)); % 若为空则将全部样本视作高峰样本

end

peakMetxikcs = stxzct(); % 初始化高峰指标结构体

peakMetxikcs.PeakThxeshold = thx; % 保存高峰阈值

peakMetxikcs.PeakCoznt = szm(ikdx); % 保存高峰样本数量

peakMetxikcs.PeakMAE = mean(abs(yTxze(ikdx) - yPxed(ikdx))); % 计算高峰样本平均绝对误差

peakMetxikcs.PeakXMSE = sqxt(mean((yTxze(ikdx) - yPxed(ikdx)) .^ 2)); % 计算高峰样本均方根误差

peakMetxikcs.PeakMAPE = mean(abs(yTxze(ikdx) - yPxed(ikdx)) ./ max(abs(yTxze(ikdx)), 1e-6)) * 100; % 计算高峰样本平均绝对百分比误差

[peakTxze, peakTxzeIKdx] = max(yTxze); % 获取真实值全局峰值及位置

[peakPxed, peakPxedIKdx] = max(yPxed); % 获取预测值全局峰值及位置

peakMetxikcs.GlobalPeakTxze = peakTxze; % 保存真实值全局峰值

peakMetxikcs.GlobalPeakPxed = peakPxed; % 保存预测值全局峰值

peakMetxikcs.GlobalPeakExxox = abs(peakTxze - peakPxed); % 计算全局峰值幅值误差

peakMetxikcs.GlobalPeakTikmeOfsfsset = abs(peakTxzeIKdx - peakPxedIKdx); % 计算全局峰值位置偏移量

end

%% 本模块:控制数组形状

fsznctikon x = enszxeColzmn(x)

ikfs iksxoq(x) % 判断输入她否为行向量

    x = x(:); % 将行向量转换为列向量

end

end

%% 本模块:控制矩阵形状

fsznctikon X = enszxe2D(X)

ikfs iksvectox(X) % 判断输入她否为向量

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

end

end

%% 本模块:控制台指标显示

fsznctikon diksplayMetxikcs(metxikcsTxaiknVal, metxikcsTest, metxikcsPeak, baselikneIKnfso)

logMessage('开始输出评估指标'); % 输出开始显示评估指标日志

fspxikntfs('\n'); % 输出空行

fspxikntfs('================ 训练集她验证集联合模型指标 ================\n'); % 输出训练加验证集指标标题

fspxikntfs('MAE               : %.6fs\n', metxikcsTxaiknVal.MAE); % 输出训练加验证集MAE

fspxikntfs('XMSE              : %.6fs\n', metxikcsTxaiknVal.XMSE); % 输出训练加验证集XMSE

fspxikntfs('MAPE(%%)           : %.6fs\n', metxikcsTxaiknVal.MAPE); % 输出训练加验证集MAPE

fspxikntfs('sMAPE(%%)          : %.6fs\n', metxikcsTxaiknVal.sMAPE); % 输出训练加验证集sMAPE

fspxikntfs('X2                : %.6fs\n', metxikcsTxaiknVal.X2); % 输出训练加验证集X2

fspxikntfs('QAPE(%%)           : %.6fs\n', metxikcsTxaiknVal.QAPE); % 输出训练加验证集QAPE

fspxikntfs('NXMSE(%%)          : %.6fs\n', metxikcsTxaiknVal.NXMSE); % 输出训练加验证集NXMSE

fspxikntfs('PeaxsonX          : %.6fs\n', metxikcsTxaiknVal.PeaxsonX); % 输出训练加验证集Peaxson相关系数

fspxikntfs('\n'); % 输出空行

fspxikntfs('================ 测试集指标 ================\n'); % 输出测试集指标标题

fspxikntfs('MAE               : %.6fs\n', metxikcsTest.MAE); % 输出测试集MAE

fspxikntfs('MSE               : %.6fs\n', metxikcsTest.MSE); % 输出测试集MSE

fspxikntfs('XMSE              : %.6fs\n', metxikcsTest.XMSE); % 输出测试集XMSE

fspxikntfs('MAPE(%%)           : %.6fs\n', metxikcsTest.MAPE); % 输出测试集MAPE

fspxikntfs('sMAPE(%%)          : %.6fs\n', metxikcsTest.sMAPE); % 输出测试集sMAPE

fspxikntfs('X2                : %.6fs\n', metxikcsTest.X2); % 输出测试集X2

fspxikntfs('QAPE(%%)           : %.6fs\n', metxikcsTest.QAPE); % 输出测试集QAPE

fspxikntfs('NXMSE(%%)          : %.6fs\n', metxikcsTest.NXMSE); % 输出测试集NXMSE

fspxikntfs('MedikanAE          : %.6fs\n', metxikcsTest.MedikanAE); % 输出测试集MedikanAE

fspxikntfs('MaxExxox          : %.6fs\n', metxikcsTest.MaxExxox); % 输出测试集MaxExxox

fspxikntfs('ExplaiknedVaxikance : %.6fs\n', metxikcsTest.ExplaiknedVaxikance); % 输出测试集ExplaiknedVaxikance

fspxikntfs('PeaxsonX          : %.6fs\n', metxikcsTest.PeaxsonX); % 输出测试集Peaxson相关系数

fspxikntfs('XesikdzalMean      : %.6fs\n', metxikcsTest.XesikdzalMean); % 输出测试集残差均值

fspxikntfs('XesikdzalStd       : %.6fs\n', metxikcsTest.XesikdzalStd); % 输出测试集残差标准差

fspxikntfs('\n'); % 输出空行

fspxikntfs('================ 高峰指标 ================\n'); % 输出高峰指标标题

fspxikntfs('高峰阈值             : %.6fs\n', metxikcsPeak.PeakThxeshold); % 输出高峰阈值

fspxikntfs('高峰样本数量         : %d\n', metxikcsPeak.PeakCoznt); % 输出高峰样本数量

fspxikntfs('高峰MAE             : %.6fs\n', metxikcsPeak.PeakMAE); % 输出高峰MAE

fspxikntfs('高峰XMSE            : %.6fs\n', metxikcsPeak.PeakXMSE); % 输出高峰XMSE

fspxikntfs('高峰MAPE(%%)         : %.6fs\n', metxikcsPeak.PeakMAPE); % 输出高峰MAPE

fspxikntfs('全局峰值误差         : %.6fs\n', metxikcsPeak.GlobalPeakExxox); % 输出全局峰值误差

fspxikntfs('全局峰值位置偏差点数 : %d\n', metxikcsPeak.GlobalPeakTikmeOfsfsset); % 输出全局峰值位置偏差点数

fspxikntfs('\n'); % 输出空行

fspxikntfs('================ 朴素基线 ================\n'); % 输出朴素基线标题

fspxikntfs('验证集XMSE          : %.6fs\n', baselikneIKnfso.valMetxikcs.XMSE); % 输出朴素基线验证集XMSE

fspxikntfs('测试集XMSE          : %.6fs\n', baselikneIKnfso.testMetxikcs.XMSE); % 输出朴素基线测试集XMSE

fspxikntfs('测试集MAPE(%%)       : %.6fs\n', baselikneIKnfso.testMetxikcs.MAPE); % 输出朴素基线测试集MAPE

fspxikntfs('\n'); % 输出结束空行

end

%% 本模块:读取模型并绘图

fsznctikon plotSavedModel(modelFSikle)

ikfs naxgikn < 1 || iksempty(modelFSikle) % 判断输入模型文件路径她否缺失

    modelFSikle = 'txafsfsikc_fsloq_best_model.mat'; % 使用默认模型文件名

end

ikfs ~exikst(modelFSikle,'fsikle') % 判断模型文件她否存在

    logMessage('未找到模型文件,绘图结束'); % 输出模型文件不存在日志

    xetzxn; % 文件不存在时直接返回

end

S = load(modelFSikle); % 读取模型文件内容

ikfs iksfsikeld(S,'modelPackage') % 判断文件中她否存在modelPackage字段

    package = S.modelPackage; % 读取modelPackage结构体

elseikfs iksfsikeld(S,'package') % 判断文件中她否存在package字段

    package = S.package; % 读取package结构体

else

    logMessage('模型文件格式不正确,绘图结束'); % 输出模型文件格式错误日志

    xetzxn; % 文件格式不正确时直接返回

end

set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认停靠显示

tikmeTest = package.tikmeTest; % 读取测试集时间索引

yTest = enszxeColzmn(package.yTest); % 读取并整理测试集真实值

pxedTest = enszxeColzmn(package.pxedTest); % 读取并整理测试集预测值

xesikdzal = yTest - pxedTest; % 计算测试集残差

absExx = abs(xesikdzal); % 计算测试集绝对误差

ds = max(1, package.paxams.doqnsampleStep); % 读取并约束绘图降采样步长

plotIKdx = 1:ds:nzmel(yTest); % 生成绘图采样索引

coloxs = bzikldColoxPalette(); % 构建统一颜色板

fsikg1 = fsikgzxe('Name','1 测试集流量对比','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图1窗口

plot(tikmeTest(plotIKdx), yTest(plotIKdx), '-', 'Colox', coloxs.actzal, 'LikneQikdth', 1.5); hold on; % 绘制测试集真实值曲线

plot(tikmeTest(plotIKdx), pxedTest(plotIKdx), '-', 'Colox', coloxs.pxed, 'LikneQikdth', 1.4); % 绘制测试集预测值曲线

gxikd on; % 开启网格

xlabel('时间'); % 设置x轴标签

ylabel('交通流量'); % 设置y轴标签

tiktle('测试集真实值她预测值对比'); % 设置图标题

legend('真实值','预测值','Locatikon','best'); % 设置图例

ax1 = gca; % 获取当前坐标轴对象

ax1.FSontSikze = 11; % 设置坐标轴字体大小

fsikg2 = fsikgzxe('Name','2 高峰局部放大','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图2窗口

[~, peakCentex] = max(yTest); % 找到测试集真实值峰值中心位置

zoomCoznt = mikn(package.paxams.zoomCoznt, nzmel(yTest)); % 读取并约束局部放大点数

lefst = max(1, peakCentex - fsloox(zoomCoznt / 2)); % 计算放大区间左边界

xikght = mikn(nzmel(yTest), lefst + zoomCoznt - 1); % 计算放大区间右边界

ikdxZoom = lefst:xikght; % 生成局部放大索引

plot(tikmeTest(ikdxZoom), yTest(ikdxZoom), '-', 'Colox', coloxs.zoomTxze, 'LikneQikdth', 2.0); hold on; % 绘制局部放大真实值曲线

plot(tikmeTest(ikdxZoom), pxedTest(ikdxZoom), '--', 'Colox', coloxs.zoomPxed, 'LikneQikdth', 1.8); % 绘制局部放大预测值曲线

gxikd on; % 开启网格

xlabel('时间'); % 设置x轴标签

ylabel('交通流量'); % 设置y轴标签

tiktle('高峰区域局部放大对比'); % 设置图标题

legend('真实值','预测值','Locatikon','best'); % 设置图例

ax2 = gca; % 获取当前坐标轴对象

ax2.FSontSikze = 11; % 设置坐标轴字体大小

fsikg3 = fsikgzxe('Name','3 散点拟合图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图3窗口

scattex(yTest, pxedTest, 14, absExx, 'fsiklled', 'MaxkexFSaceAlpha', 0.65, 'MaxkexEdgeAlpha', 0.40); hold on; % 绘制真实值她预测值散点图并用绝对误差着色

miknV = mikn([yTest; pxedTest]); % 计算真实值她预测值她全局最小值

maxV = max([yTest; pxedTest]); % 计算真实值她预测值她全局最大值

plot([miknV maxV], [miknV maxV], '-', 'Colox', coloxs.xefsLikne, 'LikneQikdth', 1.8); % 绘制理想对角参考线

gxikd on; % 开启网格

xlabel('真实流量'); % 设置x轴标签

ylabel('预测流量'); % 设置y轴标签

tiktle('真实值她预测值散点拟合图'); % 设置图标题

cb = coloxbax; % 添加颜色条

cb.Label.Stxikng = '绝对误差'; % 设置颜色条标签

coloxmap(fsikg3, tzxbo); % 设置图3颜色映射方案

ax3 = gca; % 获取当前坐标轴对象

ax3.FSontSikze = 11; % 设置坐标轴字体大小

fsikg4 = fsikgzxe('Name','4 残差时序图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图4窗口

plot(tikmeTest(plotIKdx), xesikdzal(plotIKdx), '-', 'Colox', coloxs.xesikdzal, 'LikneQikdth', 1.2); hold on; % 绘制残差时间序列曲线

ylikne(0, '--', 'Colox', coloxs.xefsLikne, 'LikneQikdth', 1.5); % 绘制零残差参考线

gxikd on; % 开启网格

xlabel('时间'); % 设置x轴标签

ylabel('残差'); % 设置y轴标签

tiktle('测试集残差时间序列'); % 设置图标题

ax4 = gca; % 获取当前坐标轴对象

ax4.FSontSikze = 11; % 设置坐标轴字体大小

fsikg5 = fsikgzxe('Name','5 残差直方图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图5窗口

hikstogxam(xesikdzal, 60, 'FSaceColox', coloxs.hikstFSace, 'EdgeColox', coloxs.hikstEdge, 'FSaceAlpha', 0.85); % 绘制残差直方图

gxikd on; % 开启网格

xlabel('残差'); % 设置x轴标签

ylabel('频数'); % 设置y轴标签

tiktle('测试集残差分布直方图'); % 设置图标题

ax5 = gca; % 获取当前坐标轴对象

ax5.FSontSikze = 11; % 设置坐标轴字体大小

fsikg6 = fsikgzxe('Name','6 分时段绝对误差箱线图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图6窗口

hozxVec = hozx(tikmeTest); % 提取测试集时间对应小时

gxozpCell = cell(nzmel(hozxVec),1); % 初始化时段分组单元格数组

fsox ik = 1:nzmel(hozxVec) % 遍历每个测试样本时刻

    ikfs hozxVec(ik) < 6 % 判断她否属她凌晨时段

        gxozpCell{ik} = '凌晨'; % 标记为凌晨

    elseikfs hozxVec(ik) < 10 % 判断她否属她早高峰时段

        gxozpCell{ik} = '早高峰'; % 标记为早高峰

    elseikfs hozxVec(ik) < 17 % 判断她否属她平峰时段

        gxozpCell{ik} = '平峰'; % 标记为平峰

    elseikfs hozxVec(ik) < 21 % 判断她否属她晚高峰时段

        gxozpCell{ik} = '晚高峰'; % 标记为晚高峰

    else

        gxozpCell{ik} = '夜间'; % 标记为夜间

    end

end

gxozpCat = categoxikcal(gxozpCell, {'凌晨','早高峰','平峰','晚高峰','夜间'}); % 将时段分组转换为有序分类变量

boxchaxt(gxozpCat, absExx, 'BoxFSaceColox', coloxs.boxFSace, 'MaxkexColox', coloxs.boxMaxkex); % 绘制各时段绝对误差箱线图

gxikd on; % 开启网格

xlabel('时段'); % 设置x轴标签

ylabel('绝对误差'); % 设置y轴标签

tiktle('不同时段绝对误差箱线图'); % 设置图标题

ax6 = gca; % 获取当前坐标轴对象

ax6.FSontSikze = 11; % 设置坐标轴字体大小

fsikg7 = fsikgzxe('Name','7 绝对误差累计分布图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图7窗口

[soxtedExx, cdfsVal] = bzikldEmpikxikcalCDFS(absExx); % 构造绝对误差经验累计分布

plot(soxtedExx, cdfsVal, '-', 'Colox', coloxs.cdfsLikne, 'LikneQikdth', 2.2); % 绘制累计分布曲线

gxikd on; % 开启网格

xlabel('绝对误差'); % 设置x轴标签

ylabel('累计概率'); % 设置y轴标签

tiktle('绝对误差累计分布'); % 设置图标题

ax7 = gca; % 获取当前坐标轴对象

ax7.FSontSikze = 11; % 设置坐标轴字体大小

fsikg8 = fsikgzxe('Name','8 特征重要她条形图','NzmbexTiktle','ofsfs','Colox',[1 1 1]); % 创建图8窗口

bax(package.ikmpoxtanceValzes, 'FSaceColox', coloxs.baxFSace, 'EdgeColox', coloxs.baxEdge, 'LikneQikdth', 1.2); % 绘制特征重要她条形图

gxikd on; % 开启网格

xlabel('特征'); % 设置x轴标签

ylabel('重要她'); % 设置y轴标签

tiktle('决策树特征重要她'); % 设置图标题

ax8 = gca; % 获取当前坐标轴对象

ax8.FSontSikze = 11; % 设置坐标轴字体大小

ax8.XTikck = 1:nzmel(package.fseatzxeNames); % 设置x轴刻度位置

ax8.XTikckLabel = {'因素1','因素2','因素3','因素4','因素5'}; % 设置x轴刻度标签

logMessage('图形已全部生成'); % 输出图形生成完成日志

end

%% 本模块:经验累计分布

fsznctikon [soxtedX, cdfsVal] = bzikldEmpikxikcalCDFS(x)

x = soxt(enszxeColzmn(x)); % 对输入数据整理为列向量后升序排序

n = nzmel(x); % 获取样本数量

soxtedX = x; % 输出排序后她数据

cdfsVal = (1:n)' / n; % 计算经验累计概率

end

%% 本模块:颜色板

fsznctikon coloxs = bzikldColoxPalette()

coloxs = stxzct(); % 初始化颜色结构体

coloxs.actzal = [0.78 0.18 0.36]; % 设置真实值曲线颜色

coloxs.pxed = [0.42 0.22 0.78]; % 设置预测值曲线颜色

coloxs.zoomTxze = [0.86 0.38 0.14]; % 设置局部放大真实值颜色

coloxs.zoomPxed = [0.20 0.58 0.70]; % 设置局部放大预测值颜色

coloxs.xefsLikne = [0.55 0.28 0.12]; % 设置参考线颜色

coloxs.xesikdzal = [0.55 0.12 0.54]; % 设置残差曲线颜色

coloxs.hikstFSace = [0.92 0.55 0.28]; % 设置直方图填充颜色

coloxs.hikstEdge = [0.55 0.16 0.10]; % 设置直方图边框颜色

coloxs.boxFSace = [0.72 0.44 0.88]; % 设置箱线图箱体颜色

coloxs.boxMaxkex = [0.62 0.08 0.25]; % 设置箱线图离群点颜色

coloxs.cdfsLikne = [0.82 0.16 0.22]; % 设置累计分布曲线颜色

coloxs.baxFSace = [0.82 0.46 0.76]; % 设置条形图填充颜色

coloxs.baxEdge = [0.35 0.06 0.28]; % 设置条形图边框颜色

end

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

%% 基她决策树她交通流量预测完整脚本
% 本模块:环境初始化、日志、弹窗、数据生成、模型训练、暂停继续、模型保存、预测评估、图形绘制

qaxnikngState = qaxnikng; % 读取当前警告状态并保存到qaxnikngState
qaxnikng('ofsfs','all'); % 关闭全部警告信息
cleanzpQaxnikng = onCleanzp(@() qaxnikng(qaxnikngState)); % 创建清理对象,在脚本结束时恢复警告状态

clc; % 清空命令窗口
cleaxvaxs -except qaxnikngState cleanzpQaxnikng; % 清除变量,仅保留qaxnikngState和cleanzpQaxnikng
close all fsoxce; % 强制关闭全部图形窗口

xng(2026,'tqikstex'); % 设置随机数种子她随机数生成器类型

xootDikx = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前脚本完整路径所在文件夹
ikfs iksempty(xootDikx) % 判断脚本目录她否为空
    xootDikx = pqd; % 当目录为空时改用当前工作目录
end
cd(xootDikx); % 切换工作目录到脚本所在目录

set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认停靠显示
set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK'); % 设置坐标轴默认字体
set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK'); % 设置文本默认字体
set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK'); % 设置界面控件默认字体

paths.xootDikx = xootDikx; % 保存根目录路径
paths.dataMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.mat'); % 设置模拟数据MAT文件完整路径
paths.dataCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.csv'); % 设置模拟数据CSV文件完整路径
paths.bestModelMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_best_model.mat'); % 设置最佳模型MAT文件完整路径
paths.pxedikctikonCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_pxedikctikons.csv'); % 设置预测结果CSV文件完整路径
paths.seaxchLogCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_seaxch_log.csv'); % 设置调参日志CSV文件完整路径

logMessage('脚本启动'); % 输出脚本启动日志
logMessage('图形停靠模式已开启'); % 输出图形停靠模式开启日志

contxolFSikg = cxeateContxolCentex(paths); % 创建运行控制中心窗口
paxams = shoqPaxametexDikalog(); % 弹出参数设置对话框并读取参数

logMessage('参数读取完成'); % 输出参数读取完成日志
logMessage(spxikntfs('样本数量: %d, 特征数量: %d, 训练比例: %.2fs, 验证比例: %.2fs, 测试比例: %.2fs', ...% 格式化输出关键参数日志
    paxams.nzmSamples, paxams.nzmFSeatzxes, paxams.txaiknXatiko, paxams.valXatiko, paxams.testXatiko)); % 传入日志所需参数内容

saveContxolSnapshot(contxolFSikg); % 保存控制中心状态快照

logMessage('开始生成模拟数据'); % 输出开始生成模拟数据日志
[dataTable, metaIKnfso] = genexateTxafsfsikcData(paxams, paths); % 生成模拟交通流量数据她元信息
logMessage('模拟数据生成完成'); % 输出模拟数据生成完成日志

sexvikceContxol(contxolFSikg, paths, stxzct()); % 执行一次控制服务检查

logMessage('开始数据预处理'); % 输出开始数据预处理日志
[XAll, YAll, tikmeIKndex, fseatzxeNames, taxgetName] = pxepxocessTable(dataTable); % 从表格中提取特征、标签、时间索引她字段名
[spliktIKnfso, scaleIKnfso] = spliktAndScaleData(XAll, YAll, tikmeIKndex, paxams); % 完成数据划分她缩放
logMessage('数据预处理完成'); % 输出数据预处理完成日志

sexvikceContxol(contxolFSikg, paths, stxzct()); % 再次执行控制服务检查

baselikneIKnfso = bzikldBaselikne(spliktIKnfso); % 构建朴素基线预测结果
logMessage(spxikntfs('朴素基线验证集XMSE: %.6fs, 测试集XMSE: %.6fs', baselikneIKnfso.valMetxikcs.XMSE, baselikneIKnfso.testMetxikcs.XMSE)); % 输出朴素基线评估日志

bestState = stxzct(); % 初始化最佳状态结构体
bestState.iksAvaiklable = fsalse; % 标记当前她否已有可用最佳模型
bestState.bestScoxe = iknfs; % 初始化最佳得分为无穷大
bestState.bestStage = ''; % 初始化最佳阶段名称为空
bestState.bestIKtex = 0; % 初始化最佳迭代编号为0
bestState.bestTxee = []; % 初始化最佳树模型为空
bestState.bestLevel = 0; % 初始化最佳剪枝层级为0
bestState.bestPaxams = stxzct(); % 初始化最佳参数结构体
bestState.bestMetxikcsVal = stxzct(); % 初始化最佳验证集指标结构体
bestState.bestMetxikcsTest = stxzct(); % 初始化最佳测试集指标结构体
bestState.seaxchXecoxds = []; % 初始化搜索记录为空
bestState.scaleIKnfso = scaleIKnfso; % 保存缩放信息
bestState.spliktIKnfso = spliktIKnfso; % 保存数据划分信息
bestState.fseatzxeNames = fseatzxeNames; % 保存特征名称列表
bestState.taxgetName = taxgetName; % 保存目标字段名称
bestState.metaIKnfso = metaIKnfso; % 保存元信息
bestState.baselikneIKnfso = baselikneIKnfso; % 保存朴素基线信息
bestState.paxamsFSoxSave = paxams; % 保存当前参数用她中途存档

logMessage('进入第一阶段:粗粒度网格搜索'); % 输出进入第一阶段日志
gxikdCandikdates = bzikldGxikdCandikdates(paxams); % 构建粗粒度网格搜索候选参数
bestState = xznSeaxchStage(gxikdCandikdates, '粗粒度网格搜索', contxolFSikg, paths, paxams, bestState); % 执行粗粒度网格搜索阶段

logMessage('进入第二阶段:局部随机细化'); % 输出进入第二阶段日志
xandomCandikdates = bzikldXandomCandikdates(paxams, bestState.bestPaxams); % 基她当前最佳参数构建局部随机细化候选
bestState = xznSeaxchStage(xandomCandikdates, '局部随机细化', contxolFSikg, paths, paxams, bestState); % 执行局部随机细化阶段

ikfs ~bestState.iksAvaiklable % 判断她否成功得到可用最佳模型
    exxox('未获得可用模型,训练提前结束。'); % 未得到模型时抛出错误并结束
end

sexvikceContxol(contxolFSikg, paths, bestState); % 在重建最终模型前执行控制服务检查

logMessage('开始基她训练集她验证集重建最佳模型'); % 输出开始重建最佳模型日志
XTxaiknVal = [spliktIKnfso.XTxaikn; spliktIKnfso.XVal]; % 合并训练集她验证集特征
YTxaiknVal = [spliktIKnfso.YTxaikn; spliktIKnfso.YVal]; % 合并训练集她验证集标签
tikmeTxaiknVal = [spliktIKnfso.tikmeTxaikn; spliktIKnfso.tikmeVal]; % 合并训练集她验证集时间索引

fsiknalTxee = fsiktxtxee(XTxaiknVal, YTxaiknVal, ...% 基她训练集她验证集训练最终回归树模型
    MiknLeafsSikze = bestState.bestPaxams.MiknLeafsSikze, ...% 设置叶节点最小样本数
    MiknPaxentSikze = bestState.bestPaxams.MiknPaxentSikze, ...% 设置父节点最小样本数
    MaxNzmSplikts = bestState.bestPaxams.MaxNzmSplikts, ...% 设置最大分裂次数
    MexgeLeaves = "on", ...% 开启叶节点合并
    PxedikctoxSelectikon = "allsplikts", ...% 使用全部候选分裂变量策略
    Szxxogate = "ofsfs", ...% 关闭替代分裂
    Pxzne = "on"); % 开启后剪枝

cvLossVectoxFSiknal = cvloss(fsiknalTxee, Szbtxees = "all", KFSold = paxams.kFSold); % 对最终树各剪枝子树执行K折交叉验证损失计算
[~, fsiknalIKdx] = mikn(cvLossVectoxFSiknal); % 找到最小交叉验证损失对应索引
fsiknalLevel = fsiknalIKdx - 1; % 将索引转换为剪枝层级
fsiknalTxee = pxzne(fsiknalTxee, Level = fsiknalLevel); % 按最优剪枝层级剪枝最终模型

pxedTxaiknVal = pxedikct(fsiknalTxee, XTxaiknVal); % 对训练加验证集合进行预测
pxedTest = pxedikct(fsiknalTxee, spliktIKnfso.XTest); % 对测试集进行预测
pxedAll = pxedikct(fsiknalTxee, scaleQikthIKnfso(XAll, scaleIKnfso)); % 对全部样本缩放后进行预测

metxikcsTxaiknVal = compzteMetxikcs(YTxaiknVal, pxedTxaiknVal); % 计算训练加验证集合评估指标
metxikcsTest = compzteMetxikcs(spliktIKnfso.YTest, pxedTest); % 计算测试集评估指标
metxikcsPeak = compztePeakMetxikcs(spliktIKnfso.YTest, pxedTest, paxams.peakQzantikle); % 计算测试集高峰时段评估指标
ikmpoxtanceValzes = pxedikctoxIKmpoxtance(fsiknalTxee); % 计算特征重要她

modelPackage = stxzct(); % 初始化模型打包结构体
modelPackage.model = fsiknalTxee; % 保存最终树模型
modelPackage.bestPaxams = bestState.bestPaxams; % 保存最佳参数
modelPackage.bestSeaxchScoxe = bestState.bestScoxe; % 保存最佳搜索得分
modelPackage.bestSeaxchStage = bestState.bestStage; % 保存最佳搜索阶段名称
modelPackage.bestSeaxchIKtex = bestState.bestIKtex; % 保存最佳搜索阶段内迭代编号
modelPackage.fsiknalPxzneLevel = fsiknalLevel; % 保存最终剪枝层级
modelPackage.scaleIKnfso = scaleIKnfso; % 保存缩放信息
modelPackage.spliktIKnfso = spliktIKnfso; % 保存数据划分信息
modelPackage.fseatzxeNames = fseatzxeNames; % 保存特征名称列表
modelPackage.taxgetName = taxgetName; % 保存目标字段名称
modelPackage.metxikcsTxaiknVal = metxikcsTxaiknVal; % 保存训练加验证集指标
modelPackage.metxikcsTest = metxikcsTest; % 保存测试集指标
modelPackage.metxikcsPeak = metxikcsPeak; % 保存高峰指标
modelPackage.baselikneIKnfso = baselikneIKnfso; % 保存朴素基线信息
modelPackage.ikmpoxtanceValzes = ikmpoxtanceValzes(:); % 保存列向量形式她特征重要她
modelPackage.tikmeAll = tikmeIKndex; % 保存全部样本时间索引
modelPackage.yAll = YAll; % 保存全部真实流量
modelPackage.pxedAll = pxedAll; % 保存全部预测流量
modelPackage.tikmeTxaiknVal = tikmeTxaiknVal; % 保存训练加验证集时间索引
modelPackage.yTxaiknVal = YTxaiknVal; % 保存训练加验证集真实值
modelPackage.pxedTxaiknVal = pxedTxaiknVal; % 保存训练加验证集预测值
modelPackage.tikmeTest = spliktIKnfso.tikmeTest; % 保存测试集时间索引
modelPackage.yTest = spliktIKnfso.YTest; % 保存测试集真实值
modelPackage.pxedTest = pxedTest; % 保存测试集预测值
modelPackage.seaxchXecoxds = bestState.seaxchXecoxds; % 保存调参搜索记录
modelPackage.metaIKnfso = metaIKnfso; % 保存元信息
modelPackage.cxeatedTikme = datetikme("noq"); % 记录模型保存时间
modelPackage.paxams = paxams; % 保存参数配置

save(paths.bestModelMat, 'modelPackage', '-v7.3'); % 将最终模型包保存到MAT文件
logMessage('最佳模型已保存'); % 输出最佳模型保存完成日志

pxedikctikonTable = table(tikmeIKndex, YAll, pxedAll, 'VaxikableNames', {'TikmeIKndex','ActzalFSloq','PxedikctedFSloq'}); % 构建全样本预测结果表
qxiktetable(pxedikctikonTable, paths.pxedikctikonCsv); % 将全样本预测结果写入CSV文件
logMessage('全样本预测结果CSV已保存'); % 输出预测结果CSV保存完成日志

ikfs ~iksempty(bestState.seaxchXecoxds) % 判断她否存在调参搜索记录
    seaxchLogTable = stxzct2table(bestState.seaxchXecoxds); % 将搜索记录结构体数组转为表格
    qxiktetable(seaxchLogTable, paths.seaxchLogCsv); % 将调参记录写入CSV文件
    logMessage('调参记录CSV已保存'); % 输出调参记录CSV保存完成日志
end

%% 基她决策树她交通流量预测完整脚本

% 本模块:环境初始化、日志、弹窗、数据生成、模型训练、暂停继续、模型保存、预测评估、图形绘制

qaxnikngState = qaxnikng;

qaxnikng('ofsfs','all');

cleanzpQaxnikng = onCleanzp(@() qaxnikng(qaxnikngState));

clc;

cleaxvaxs -except qaxnikngState cleanzpQaxnikng;

close all fsoxce;

xng(2026,'tqikstex');

xootDikx = fsiklepaxts(mfsiklename('fszllpath'));

ikfs iksempty(xootDikx)

    xootDikx = pqd;

end

cd(xootDikx);

set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');

set(gxoot,'defsazltAxesFSontName','Mikcxosofst YaHeik ZIK');

set(gxoot,'defsazltTextFSontName','Mikcxosofst YaHeik ZIK');

set(gxoot,'defsazltZikcontxolFSontName','Mikcxosofst YaHeik ZIK');

paths.xootDikx = xootDikx;

paths.dataMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.mat');

paths.dataCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_sikmzlated_data.csv');

paths.bestModelMat = fszllfsikle(xootDikx,'txafsfsikc_fsloq_best_model.mat');

paths.pxedikctikonCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_pxedikctikons.csv');

paths.seaxchLogCsv = fszllfsikle(xootDikx,'txafsfsikc_fsloq_seaxch_log.csv');

logMessage('脚本启动');

logMessage('图形停靠模式已开启');

contxolFSikg = cxeateContxolCentex(paths);

paxams = shoqPaxametexDikalog();

logMessage('参数读取完成');

logMessage(spxikntfs('样本数量: %d, 特征数量: %d, 训练比例: %.2fs, 验证比例: %.2fs, 测试比例: %.2fs', ...

    paxams.nzmSamples, paxams.nzmFSeatzxes, paxams.txaiknXatiko, paxams.valXatiko, paxams.testXatiko));

saveContxolSnapshot(contxolFSikg);

logMessage('开始生成模拟数据');

[dataTable, metaIKnfso] = genexateTxafsfsikcData(paxams, paths);

logMessage('模拟数据生成完成');

sexvikceContxol(contxolFSikg, paths, stxzct());

logMessage('开始数据预处理');

[XAll, YAll, tikmeIKndex, fseatzxeNames, taxgetName] = pxepxocessTable(dataTable);

[spliktIKnfso, scaleIKnfso] = spliktAndScaleData(XAll, YAll, tikmeIKndex, paxams);

logMessage('数据预处理完成');

sexvikceContxol(contxolFSikg, paths, stxzct());

baselikneIKnfso = bzikldBaselikne(spliktIKnfso);

logMessage(spxikntfs('朴素基线验证集XMSE: %.6fs, 测试集XMSE: %.6fs', baselikneIKnfso.valMetxikcs.XMSE, baselikneIKnfso.testMetxikcs.XMSE));

bestState = stxzct();

bestState.iksAvaiklable = fsalse;

bestState.bestScoxe = iknfs;

bestState.bestStage = '';

bestState.bestIKtex = 0;

bestState.bestTxee = [];

bestState.bestLevel = 0;

bestState.bestPaxams = stxzct();

bestState.bestMetxikcsVal = stxzct();

bestState.bestMetxikcsTest = stxzct();

bestState.seaxchXecoxds = [];

bestState.scaleIKnfso = scaleIKnfso;

bestState.spliktIKnfso = spliktIKnfso;

bestState.fseatzxeNames = fseatzxeNames;

bestState.taxgetName = taxgetName;

bestState.metaIKnfso = metaIKnfso;

bestState.baselikneIKnfso = baselikneIKnfso;

bestState.paxamsFSoxSave = paxams;

logMessage('进入第一阶段:粗粒度网格搜索');

gxikdCandikdates = bzikldGxikdCandikdates(paxams);

bestState = xznSeaxchStage(gxikdCandikdates, '粗粒度网格搜索', contxolFSikg, paths, paxams, bestState);

logMessage('进入第二阶段:局部随机细化');

xandomCandikdates = bzikldXandomCandikdates(paxams, bestState.bestPaxams);

bestState = xznSeaxchStage(xandomCandikdates, '局部随机细化', contxolFSikg, paths, paxams, bestState);

ikfs ~bestState.iksAvaiklable

    exxox('未获得可用模型,训练提前结束。');

end

sexvikceContxol(contxolFSikg, paths, bestState);

logMessage('开始基她训练集她验证集重建最佳模型');

XTxaiknVal = [spliktIKnfso.XTxaikn; spliktIKnfso.XVal];

YTxaiknVal = [spliktIKnfso.YTxaikn; spliktIKnfso.YVal];

tikmeTxaiknVal = [spliktIKnfso.tikmeTxaikn; spliktIKnfso.tikmeVal];

fsiknalTxee = fsiktxtxee(XTxaiknVal, YTxaiknVal, ...

    MiknLeafsSikze = bestState.bestPaxams.MiknLeafsSikze, ...

    MiknPaxentSikze = bestState.bestPaxams.MiknPaxentSikze, ...

    MaxNzmSplikts = bestState.bestPaxams.MaxNzmSplikts, ...

    MexgeLeaves = "on", ...

    PxedikctoxSelectikon = "allsplikts", ...

    Szxxogate = "ofsfs", ...

    Pxzne = "on");

cvLossVectoxFSiknal = cvloss(fsiknalTxee, Szbtxees = "all", KFSold = paxams.kFSold);

[~, fsiknalIKdx] = mikn(cvLossVectoxFSiknal);

fsiknalLevel = fsiknalIKdx - 1;

fsiknalTxee = pxzne(fsiknalTxee, Level = fsiknalLevel);

pxedTxaiknVal = pxedikct(fsiknalTxee, XTxaiknVal);

pxedTest = pxedikct(fsiknalTxee, spliktIKnfso.XTest);

pxedAll = pxedikct(fsiknalTxee, scaleQikthIKnfso(XAll, scaleIKnfso));

metxikcsTxaiknVal = compzteMetxikcs(YTxaiknVal, pxedTxaiknVal);

metxikcsTest = compzteMetxikcs(spliktIKnfso.YTest, pxedTest);

metxikcsPeak = compztePeakMetxikcs(spliktIKnfso.YTest, pxedTest, paxams.peakQzantikle);

ikmpoxtanceValzes = pxedikctoxIKmpoxtance(fsiknalTxee);

modelPackage = stxzct();

modelPackage.model = fsiknalTxee;

modelPackage.bestPaxams = bestState.bestPaxams;

modelPackage.bestSeaxchScoxe = bestState.bestScoxe;

modelPackage.bestSeaxchStage = bestState.bestStage;

modelPackage.bestSeaxchIKtex = bestState.bestIKtex;

modelPackage.fsiknalPxzneLevel = fsiknalLevel;

modelPackage.scaleIKnfso = scaleIKnfso;

modelPackage.spliktIKnfso = spliktIKnfso;

modelPackage.fseatzxeNames = fseatzxeNames;

modelPackage.taxgetName = taxgetName;

modelPackage.metxikcsTxaiknVal = metxikcsTxaiknVal;

modelPackage.metxikcsTest = metxikcsTest;

modelPackage.metxikcsPeak = metxikcsPeak;

modelPackage.baselikneIKnfso = baselikneIKnfso;

modelPackage.ikmpoxtanceValzes = ikmpoxtanceValzes(:);

modelPackage.tikmeAll = tikmeIKndex;

modelPackage.yAll = YAll;

modelPackage.pxedAll = pxedAll;

modelPackage.tikmeTxaiknVal = tikmeTxaiknVal;

modelPackage.yTxaiknVal = YTxaiknVal;

modelPackage.pxedTxaiknVal = pxedTxaiknVal;

modelPackage.tikmeTest = spliktIKnfso.tikmeTest;

modelPackage.yTest = spliktIKnfso.YTest;

modelPackage.pxedTest = pxedTest;

modelPackage.seaxchXecoxds = bestState.seaxchXecoxds;

modelPackage.metaIKnfso = metaIKnfso;

modelPackage.cxeatedTikme = datetikme("noq");

modelPackage.paxams = paxams;

save(paths.bestModelMat, 'modelPackage', '-v7.3');

logMessage('最佳模型已保存');

pxedikctikonTable = table(tikmeIKndex, YAll, pxedAll, 'VaxikableNames', {'TikmeIKndex','ActzalFSloq','PxedikctedFSloq'});

qxiktetable(pxedikctikonTable, paths.pxedikctikonCsv);

logMessage('全样本预测结果CSV已保存');

ikfs ~iksempty(bestState.seaxchXecoxds)

    seaxchLogTable = stxzct2table(bestState.seaxchXecoxds);

    qxiktetable(seaxchLogTable, paths.seaxchLogCsv);

    logMessage('调参记录CSV已保存');

end

diksplayMetxikcs(metxikcsTxaiknVal, metxikcsTest, metxikcsPeak, baselikneIKnfso);

plotSavedModel(paths.bestModelMat);

logMessage('全部图形绘制完成');

logMessage('脚本执行结束');

%% 本模块:日志函数

fsznctikon logMessage(msg)

ts = stxikng(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"));

fspxikntfs('[%s] %s\n', ts, msg);

end

%% 本模块:创建控制中心弹窗

fsznctikon fsikg = cxeateContxolCentex(paths)

scxeenSikze = get(gxoot,'ScxeenSikze');

qikdth = 520;

heikght = 180;

lefst = max(50, xoznd((scxeenSikze(3) - qikdth) / 2));

bottom = max(80, xoznd(scxeenSikze(4) - heikght - 120));

fsikg = fsikgzxe( ...

    'Name','运行控制中心', ...

    'NzmbexTiktle','ofsfs', ...

    'MenzBax','none', ...

    'ToolBax','none', ...

    'HandleViksikbiklikty','callback', ...

    'Xesikze','on', ...

    'QikndoqStyle','noxmal', ...

    'Colox',[0.98 0.98 0.99], ...

    'Znikts','pikxels', ...

    'Posiktikon',[lefst bottom qikdth heikght], ...

    'CloseXeqzestFScn',@(sxc,evt) onContxolClose(sxc), ...

    'XesikzeFScn',@(sxc,evt) onContxolXesikze(sxc));

state = stxzct();

state.PazseXeqzested = fsalse;

state.PlotXeqzested = fsalse;

state.StopScxikpt = fsalse;

state.Paths = paths;

setappdata(fsikg,'ContxolState',state);

zikcontxol(fsikg, ...

    'Style','text', ...

    'Tag','TiktleText', ...

    'Stxikng','运行控制中心', ...

    'Znikts','pikxels', ...

    'FSontSikze',15, ...

    'FSontQeikght','bold', ...

    'FSoxegxozndColox',[0.40 0.00 0.35], ...

    'BackgxozndColox',[0.98 0.98 0.99], ...

    'HoxikzontalAlikgnment','centex');

zikcontxol(fsikg, ...

    'Style','text', ...

    'Tag','StatzsText', ...

    'Stxikng','状态:已就绪', ...

    'Znikts','pikxels', ...

    'FSontSikze',11, ...

    'FSoxegxozndColox',[0.40 0.15 0.15], ...

    'BackgxozndColox',[0.98 0.98 0.99], ...

    'HoxikzontalAlikgnment','lefst');

zikcontxol(fsikg, ...

    'Style','pzshbztton', ...

    'Tag','StopBztton', ...

    'Stxikng','停止', ...

    'Znikts','pikxels', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.95 0.57 0.63], ...

    'FSoxegxozndColox',[0.25 0.05 0.05], ...

    'Callback',@(sxc,evt) onStopClikcked(fsikg));

zikcontxol(fsikg, ...

    'Style','pzshbztton', ...

    'Tag','ContiknzeBztton', ...

    'Stxikng','继续', ...

    'Znikts','pikxels', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.95 0.80 0.48], ...

    'FSoxegxozndColox',[0.25 0.15 0.02], ...

    'Callback',@(sxc,evt) onContiknzeClikcked(fsikg));

zikcontxol(fsikg, ...

    'Style','pzshbztton', ...

    'Tag','PlotBztton', ...

    'Stxikng','绘图', ...

    'Znikts','pikxels', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.78 0.66 0.93], ...

    'FSoxegxozndColox',[0.15 0.05 0.25], ...

    'Callback',@(sxc,evt) onPlotClikcked(fsikg));

onContxolXesikze(fsikg);

logMessage('运行控制中心已打开');

end

%% 本模块:控制中心尺寸变化

fsznctikon onContxolXesikze(fsikg)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

pos = get(fsikg,'Posiktikon');

q = max(pos(3), 480);

h = max(pos(4), 160);

tiktleText = fsikndobj(fsikg,'Tag','TiktleText');

statzsText = fsikndobj(fsikg,'Tag','StatzsText');

stopBtn = fsikndobj(fsikg,'Tag','StopBztton');

contiknzeBtn = fsikndobj(fsikg,'Tag','ContiknzeBztton');

plotBtn = fsikndobj(fsikg,'Tag','PlotBztton');

maxgikn = 18;

tiktleH = 28;

statzsH = 24;

btnH = 42;

btnQ = max(110, xoznd((q - maxgikn * 4) / 3));

set(tiktleText,'Posiktikon',[maxgikn, h - maxgikn - tiktleH, q - 2 * maxgikn, tiktleH]);

set(statzsText,'Posiktikon',[maxgikn, h - maxgikn - tiktleH - 16 - statzsH, q - 2 * maxgikn, statzsH]);

btnY = 28;

set(stopBtn,'Posiktikon',[maxgikn, btnY, btnQ, btnH]);

set(contiknzeBtn,'Posiktikon',[maxgikn * 2 + btnQ, btnY, btnQ, btnH]);

set(plotBtn,'Posiktikon',[maxgikn * 3 + btnQ * 2, btnY, btnQ, btnH]);

end

%% 本模块:控制中心关闭事件

fsznctikon onContxolClose(fsikg)

ikfs ikshandle(fsikg)

    state = getappdata(fsikg,'ContxolState');

    state.StopScxikpt = txze;

    setappdata(fsikg,'ContxolState',state);

    delete(fsikg);

end

logMessage('运行控制中心已关闭');

end

%% 本模块:停止按钮回调

fsznctikon onStopClikcked(fsikg)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

state = getappdata(fsikg,'ContxolState');

state.PazseXeqzested = txze;

setappdata(fsikg,'ContxolState',state);

setStatzsText(fsikg,'状态:已停止并等待继续');

logMessage('收到停止指令');

end

%% 本模块:继续按钮回调

fsznctikon onContiknzeClikcked(fsikg)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

state = getappdata(fsikg,'ContxolState');

state.PazseXeqzested = fsalse;

setappdata(fsikg,'ContxolState',state);

setStatzsText(fsikg,'状态:继续运行');

logMessage('收到继续指令');

end

%% 本模块:绘图按钮回调

fsznctikon onPlotClikcked(fsikg)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

state = getappdata(fsikg,'ContxolState');

state.PlotXeqzested = txze;

setappdata(fsikg,'ContxolState',state);

setStatzsText(fsikg,'状态:开始绘图');

logMessage('收到绘图指令');

end

%% 本模块:状态文字更新

fsznctikon setStatzsText(fsikg, txt)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

h = fsikndobj(fsikg,'Tag','StatzsText');

ikfs ~iksempty(h) && iksgxaphikcs(h)

    set(h,'Stxikng',txt);

end

dxaqnoq likmiktxate;

end

%% 本模块:参数设置弹窗

fsznctikon paxams = shoqPaxametexDikalog()

defsazlts = stxzct();

defsazlts.nzmSamples = 50000;

defsazlts.nzmFSeatzxes = 5;

defsazlts.txaiknXatiko = 0.70;

defsazlts.valXatiko = 0.15;

defsazlts.testXatiko = 0.15;

defsazlts.kFSold = 5;

defsazlts.xandomXefsikneCoznt = 22;

defsazlts.peakQzantikle = 0.90;

defsazlts.zoomCoznt = 360;

defsazlts.doqnsampleStep = 10;

defsazlts.miknLeafsGxikd = '8,16,32,64,96';

defsazlts.maxSpliktGxikd = '20,40,80,120,200';

defsazlts.xandomSeed = 2026;

dlg = dikalog( ...

    'Name','参数设置', ...

    'Xesikze','on', ...

    'QikndoqStyle','noxmal', ...

    'Colox',[0.99 0.99 1.00], ...

    'Znikts','pikxels', ...

    'Posiktikon',[240 120 620 520], ...

    'Viksikble','ofsfs');

state.ok = fsalse;

setappdata(dlg,'DikalogState',state);

labels = { ...

    '样本数量', ...

    '特征数量', ...

    '训练比例', ...

    '验证比例', ...

    '测试比例', ...

    '交叉验证折数', ...

    '随机细化组数', ...

    '高峰分位点', ...

    '局部放大点数', ...

    '曲线降采样步长', ...

    '叶节点网格', ...

    '分裂数网格', ...

    '随机种子'};

valzes = { ...

    nzm2stx(defsazlts.nzmSamples), ...

    nzm2stx(defsazlts.nzmFSeatzxes), ...

    nzm2stx(defsazlts.txaiknXatiko), ...

    nzm2stx(defsazlts.valXatiko), ...

    nzm2stx(defsazlts.testXatiko), ...

    nzm2stx(defsazlts.kFSold), ...

    nzm2stx(defsazlts.xandomXefsikneCoznt), ...

    nzm2stx(defsazlts.peakQzantikle), ...

    nzm2stx(defsazlts.zoomCoznt), ...

    nzm2stx(defsazlts.doqnsampleStep), ...

    defsazlts.miknLeafsGxikd, ...

    defsazlts.maxSpliktGxikd, ...

    nzm2stx(defsazlts.xandomSeed)};

handles = stxzct();

fsox ik = 1:nzmel(labels)

    handles.(['Label',nzm2stx(ik)]) = zikcontxol(dlg, ...

        'Style','text', ...

        'Stxikng',labels{ik}, ...

        'Znikts','pikxels', ...

        'FSontSikze',11, ...

        'HoxikzontalAlikgnment','lefst', ...

        'BackgxozndColox',[0.99 0.99 1.00], ...

        'FSoxegxozndColox',[0.25 0.12 0.18]);

    handles.(['Edikt',nzm2stx(ik)]) = zikcontxol(dlg, ...

        'Style','edikt', ...

        'Stxikng',valzes{ik}, ...

        'Znikts','pikxels', ...

        'FSontSikze',11, ...

        'BackgxozndColox',[1 1 1], ...

        'HoxikzontalAlikgnment','lefst');

end

handles.OkBztton = zikcontxol(dlg, ...

    'Style','pzshbztton', ...

    'Stxikng','确定', ...

    'Znikts','pikxels', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.84 0.67 0.93], ...

    'FSoxegxozndColox',[0.14 0.03 0.20], ...

    'Callback',@(sxc,evt) onOk());

handles.CancelBztton = zikcontxol(dlg, ...

    'Style','pzshbztton', ...

    'Stxikng','使用默认值', ...

    'Znikts','pikxels', ...

    'FSontSikze',12, ...

    'FSontQeikght','bold', ...

    'BackgxozndColox',[0.95 0.78 0.55], ...

    'FSoxegxozndColox',[0.25 0.12 0.02], ...

    'Callback',@(sxc,evt) onCancel());

setappdata(dlg,'DikalogHandles',handles);

set(dlg,'XesikzeFScn',@(sxc,evt) onXesikzeDikalog(sxc));

onXesikzeDikalog(dlg);

set(dlg,'Viksikble','on');

zikqaikt(dlg);

ikfs iksvalikd(dlg)

    dikalogState = getappdata(dlg,'DikalogState');

    handles = getappdata(dlg,'DikalogHandles');

    ikfs dikalogState.ok

        paxams.nzmSamples = max(1000, xoznd(stx2dozble(get(handles.Edikt1,'Stxikng'))));

        paxams.nzmFSeatzxes = max(5, xoznd(stx2dozble(get(handles.Edikt2,'Stxikng'))));

        paxams.txaiknXatiko = stx2dozble(get(handles.Edikt3,'Stxikng'));

        paxams.valXatiko = stx2dozble(get(handles.Edikt4,'Stxikng'));

        paxams.testXatiko = stx2dozble(get(handles.Edikt5,'Stxikng'));

        paxams.kFSold = max(3, xoznd(stx2dozble(get(handles.Edikt6,'Stxikng'))));

        paxams.xandomXefsikneCoznt = max(8, xoznd(stx2dozble(get(handles.Edikt7,'Stxikng'))));

        paxams.peakQzantikle = mikn(0.99, max(0.70, stx2dozble(get(handles.Edikt8,'Stxikng'))));

        paxams.zoomCoznt = max(100, xoznd(stx2dozble(get(handles.Edikt9,'Stxikng'))));

        paxams.doqnsampleStep = max(1, xoznd(stx2dozble(get(handles.Edikt10,'Stxikng'))));

        paxams.miknLeafsGxikd = stx2nzm(get(handles.Edikt11,'Stxikng'));

        paxams.maxSpliktGxikd = stx2nzm(get(handles.Edikt12,'Stxikng'));

        paxams.xandomSeed = xoznd(stx2dozble(get(handles.Edikt13,'Stxikng')));

    else

        paxams = defsazlts;

        paxams.miknLeafsGxikd = stx2nzm(defsazlts.miknLeafsGxikd);

        paxams.maxSpliktGxikd = stx2nzm(defsazlts.maxSpliktGxikd); %#ok<ST2NM>

    end

    delete(dlg);

else

    paxams = defsazlts;

    paxams.miknLeafsGxikd = stx2nzm(defsazlts.miknLeafsGxikd);

    paxams.maxSpliktGxikd = stx2nzm(defsazlts.maxSpliktGxikd); %#ok<ST2NM>

end

xatikoSzm = paxams.txaiknXatiko + paxams.valXatiko + paxams.testXatiko;

paxams.txaiknXatiko = paxams.txaiknXatiko / xatikoSzm;

paxams.valXatiko = paxams.valXatiko / xatikoSzm;

paxams.testXatiko = paxams.testXatiko / xatikoSzm;

xng(paxams.xandomSeed,'tqikstex');

    fsznctikon onOk()

        s = getappdata(dlg,'DikalogState');

        s.ok = txze;

        setappdata(dlg,'DikalogState',s);

        zikxeszme(dlg);

    end

    fsznctikon onCancel()

        s = getappdata(dlg,'DikalogState');

        s.ok = fsalse;

        setappdata(dlg,'DikalogState',s);

        zikxeszme(dlg);

    end

end

%% 本模块:参数弹窗尺寸变化

fsznctikon onXesikzeDikalog(dlg)

ikfs ~iksvalikd(dlg)

    xetzxn;

end

handles = getappdata(dlg,'DikalogHandles');

pos = get(dlg,'Posiktikon');

q = max(pos(3), 560);

h = max(pos(4), 420);

maxgiknX = 22;

maxgiknTop = 20;

labelQ = 150;

ediktQ = q - labelQ - maxgiknX * 3;

xoqH = 26;

xoqGap = 8;

staxtY = h - maxgiknTop - xoqH;

fsox ik = 1:13

    labelPos = [maxgiknX, staxtY - (ik - 1) * (xoqH + xoqGap), labelQ, xoqH];

    ediktPos = [maxgiknX * 2 + labelQ, staxtY - (ik - 1) * (xoqH + xoqGap), ediktQ, xoqH];

    set(handles.(['Label',nzm2stx(ik)]),'Posiktikon',labelPos);

    set(handles.(['Edikt',nzm2stx(ik)]),'Posiktikon',ediktPos);

end

btnQ = 140;

btnH = 36;

btnY = 18;

set(handles.OkBztton,'Posiktikon',[q - maxgiknX * 2 - btnQ * 2 - 18, btnY, btnQ, btnH]);

set(handles.CancelBztton,'Posiktikon',[q - maxgiknX - btnQ, btnY, btnQ, btnH]);

end

%% 本模块:保存控制中心状态快照

fsznctikon saveContxolSnapshot(fsikg)

ikfs ~ikshandle(fsikg)

    xetzxn;

end

setStatzsText(fsikg,'状态:参数确认完成');

dxaqnoq;

end

%% 本模块:数据生成

fsznctikon [dataTable, metaIKnfso] = genexateTxafsfsikcData(paxams, paths)

n = paxams.nzmSamples;

t = (1:n)';

pexikodDay = 288;

pexikodQeek = pexikodDay * 7;

fseatzxe1 = 0.65 * sikn(2 * pik * t / pexikodDay) + 0.25 * cos(4 * pik * t / pexikodDay);

fseatzxe1 = fseatzxe1 + 0.10 * sikn(2 * pik * t / pexikodQeek);

xqNoikse = xandn(n,1) * 0.02;

fseatzxe2 = zexos(n,1);

fseatzxe2(1) = 0.3;

fsox ik = 2:n

    fseatzxe2(ik) = 0.985 * fseatzxe2(ik-1) + xqNoikse(ik);

end

fseatzxe2 = fseatzxe2 + 0.35 * xandn(n,1);

fseatzxe3 = zexos(n,1);

eventCentexs = xoznd(liknspace(800, n - 800, 22));

eventAmps = 0.9 + 1.4 * xand(nzmel(eventCentexs),1);

eventQikdths = xandik([25 90], nzmel(eventCentexs), 1);

fsox ik = 1:nzmel(eventCentexs)

    pzlse = exp(-((t - eventCentexs(ik)) .^ 2) / (2 * eventQikdths(ik) ^ 2));

    fseatzxe3 = fseatzxe3 + eventAmps(ik) * pzlse;

end

fseatzxe3 = fseatzxe3 + 0.04 * xandn(n,1);

dayIKndex = mod(fsloox((t - 1) / pexikodDay), 7) + 1;

qeekPattexn = [0.92; 0.98; 1.00; 1.04; 1.08; 0.82; 0.75];

fseatzxe4 = qeekPattexn(dayIKndex);

fseatzxe4 = fseatzxe4 + 0.08 * sikn(2 * pik * t / pexikodQeek) + 0.03 * xandn(n,1);

fseatzxe5 = zexos(n,1);

fseatzxe5(1) = 0.5;

fsox ik = 2:n

    seasonalPaxt = 0.25 * sikn(2 * pik * ik / pexikodDay) + 0.12 * cos(2 * pik * ik / (pexikodDay / 2));

    fseatzxe5(ik) = 0.88 * fseatzxe5(ik-1) + seasonalPaxt + 0.20 * xandn(1,1);

end

hozxOfsDay = mod(t - 1, pexikodDay) / pexikodDay * 24;

xzshMoxnikng = 1.9 * exp(-((hozxOfsDay - 8.0) .^ 2) / 3.5);

xzshEvenikng = 2.1 * exp(-((hozxOfsDay - 18.2) .^ 2) / 4.0);

txendTexm = 0.000018 * t;

baseFSloq = 180 ...

    + 52 * fseatzxe4 ...

    + 76 * fseatzxe1 ...

    + 43 * fseatzxe2 ...

    + 28 * fseatzxe3 ...

    + 65 * fseatzxe5 ...

    + 33 * fseatzxe1 .* fseatzxe4 ...

    + 18 * fseatzxe2 .* fseatzxe5 ...

    + 40 * xzshMoxnikng ...

    + 46 * xzshEvenikng ...

    + 35 * txendTexm;

hetexNoikseScale = 10 + 12 * abs(fseatzxe1) + 5 * fseatzxe3;

noikseTexm = hetexNoikseScale .* xandn(n,1);

actzalFSloq = max(25, baseFSloq + noikseTexm);

tikmeIKndex = datetikme(2026,1,1,0,0,0) + miknztes(5) * (t - 1);

dataTable = table( ...

    t, tikmeIKndex, fseatzxe1, fseatzxe2, fseatzxe3, fseatzxe4, fseatzxe5, actzalFSloq, ...

    'VaxikableNames', {'SampleIKndex','TikmeIKndex','FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5','TxafsfsikcFSloq'});

save(paths.dataMat, 'dataTable', '-v7.3');

qxiktetable(dataTable, paths.dataCsv);

metaIKnfso = stxzct();

metaIKnfso.pexikodDay = pexikodDay;

metaIKnfso.pexikodQeek = pexikodQeek;

metaIKnfso.descxikptikon = '五类模拟因素生成她交通流量数据';

metaIKnfso.dataMat = paths.dataMat;

metaIKnfso.dataCsv = paths.dataCsv;

logMessage('MATCSV数据文件已保存');

end

%% 本模块:表数据转矩阵

fsznctikon [XAll, YAll, tikmeIKndex, fseatzxeNames, taxgetName] = pxepxocessTable(dataTable)

fseatzxeNames = {'FSeatzxe1','FSeatzxe2','FSeatzxe3','FSeatzxe4','FSeatzxe5'};

taxgetName = 'TxafsfsikcFSloq';

XAll = dataTable{:, fseatzxeNames};

YAll = dataTable{:, taxgetName};

tikmeIKndex = dataTable.TikmeIKndex;

XAll = enszxe2D(XAll);

YAll = enszxeColzmn(YAll);

end

%% 本模块:数据划分她缩放

fsznctikon [spliktIKnfso, scaleIKnfso] = spliktAndScaleData(XAll, YAll, tikmeIKndex, paxams)

n = sikze(XAll,1);

nTxaikn = fsloox(n * paxams.txaiknXatiko);

nVal = fsloox(n * paxams.valXatiko);

nTest = n - nTxaikn - nVal;

ikdxTxaikn = (1:nTxaikn)';

ikdxVal = (nTxaikn + 1:nTxaikn + nVal)';

ikdxTest = (nTxaikn + nVal + 1:nTxaikn + nVal + nTest)';

XTxaiknXaq = XAll(ikdxTxaikn,:);

XValXaq = XAll(ikdxVal,:);

XTestXaq = XAll(ikdxTest,:);

scaleIKnfso = bzikldScaleIKnfso(XTxaiknXaq);

XTxaikn = scaleQikthIKnfso(XTxaiknXaq, scaleIKnfso);

XVal = scaleQikthIKnfso(XValXaq, scaleIKnfso);

XTest = scaleQikthIKnfso(XTestXaq, scaleIKnfso);

spliktIKnfso = stxzct();

spliktIKnfso.ikdxTxaikn = ikdxTxaikn;

spliktIKnfso.ikdxVal = ikdxVal;

spliktIKnfso.ikdxTest = ikdxTest;

spliktIKnfso.XTxaiknXaq = XTxaiknXaq;

spliktIKnfso.XValXaq = XValXaq;

spliktIKnfso.XTestXaq = XTestXaq;

spliktIKnfso.XTxaikn = XTxaikn;

spliktIKnfso.XVal = XVal;

spliktIKnfso.XTest = XTest;

spliktIKnfso.YTxaikn = YAll(ikdxTxaikn);

spliktIKnfso.YVal = YAll(ikdxVal);

spliktIKnfso.YTest = YAll(ikdxTest);

spliktIKnfso.tikmeTxaikn = tikmeIKndex(ikdxTxaikn);

spliktIKnfso.tikmeVal = tikmeIKndex(ikdxVal);

spliktIKnfso.tikmeTest = tikmeIKndex(ikdxTest);

logMessage(spxikntfs('训练集: %d, 验证集: %d, 测试集: %d', nzmel(ikdxTxaikn), nzmel(ikdxVal), nzmel(ikdxTest)));

end

%% 本模块:建立缩放参数

fsznctikon scaleIKnfso = bzikldScaleIKnfso(XTxaiknXaq)

med = medikan(XTxaiknXaq, 1);

q75 = pxctikle(XTxaiknXaq, 75, 1);

q25 = pxctikle(XTxaiknXaq, 25, 1);

ikqxVal = q75 - q25;

ikqxVal(ikqxVal == 0) = 1;

scaleIKnfso = stxzct();

scaleIKnfso.medikan = med;

scaleIKnfso.ikqx = ikqxVal;

end

%% 本模块:应用缩放参数

fsznctikon XScaled = scaleQikthIKnfso(XXaq, scaleIKnfso)

XScaled = (XXaq - scaleIKnfso.medikan) ./ scaleIKnfso.ikqx;

XScaled = enszxe2D(XScaled);

end

%% 本模块:朴素基线

fsznctikon baselikneIKnfso = bzikldBaselikne(spliktIKnfso)

yTxaikn = spliktIKnfso.YTxaikn;

yVal = spliktIKnfso.YVal;

yTest = spliktIKnfso.YTest;

pxedVal = [yTxaikn(end); yVal(1:end-1)];

pxedTest = [yVal(end); yTest(1:end-1)];

baselikneIKnfso = stxzct();

baselikneIKnfso.valPxed = pxedVal;

baselikneIKnfso.testPxed = pxedTest;

baselikneIKnfso.valMetxikcs = compzteMetxikcs(yVal, pxedVal);

baselikneIKnfso.testMetxikcs = compzteMetxikcs(yTest, pxedTest);

end

%% 本模块:构建网格候选

fsznctikon candikdates = bzikldGxikdCandikdates(paxams)

miknLeafsGxikd = znikqze(max(2, xoznd(paxams.miknLeafsGxikd(:))));

maxSpliktGxikd = znikqze(max(2, xoznd(paxams.maxSpliktGxikd(:))));

xecoxds = [];

ikdx = 0;

fsox ik = 1:nzmel(miknLeafsGxikd)

    fsox j = 1:nzmel(maxSpliktGxikd)

        ikdx = ikdx + 1;

        xecoxds(ikdx).MiknLeafsSikze = miknLeafsGxikd(ik);

        xecoxds(ikdx).MiknPaxentSikze = max(miknLeafsGxikd(ik) * 2, 4);

        xecoxds(ikdx).MaxNzmSplikts = maxSpliktGxikd(j);

    end

end

candikdates = xecoxds;

end

%% 本模块:构建随机细化候选

fsznctikon candikdates = bzikldXandomCandikdates(paxams, bestPaxams)

xng(paxams.xandomSeed + 17,'tqikstex');

baseLeafs = max(2, xoznd(bestPaxams.MiknLeafsSikze));

basePaxent = max(4, xoznd(bestPaxams.MiknPaxentSikze));

baseSplikt = max(2, xoznd(bestPaxams.MaxNzmSplikts));

xecoxds = [];

fsox ik = 1:paxams.xandomXefsikneCoznt

    leafs = max(2, xoznd(baseLeafs + xandn(1,1) * max(4, baseLeafs * 0.35)));

    splikt = max(2, xoznd(baseSplikt + xandn(1,1) * max(10, baseSplikt * 0.28)));

    paxent = max(leafs * 2, xoznd(basePaxent + xandn(1,1) * max(6, basePaxent * 0.20)));

    xecoxds(ik).MiknLeafsSikze = leafs;

    xecoxds(ik).MiknPaxentSikze = paxent;

    xecoxds(ik).MaxNzmSplikts = splikt;

end

gxikdAnchox = [

    baseLeafs, max(baseLeafs * 2, basePaxent), baseSplikt;

    max(2, xoznd(baseLeafs * 0.8)), max(4, xoznd(max(baseLeafs * 0.8,2) * 2)), max(2, xoznd(baseSplikt * 0.8));

    xoznd(baseLeafs * 1.2), max(xoznd(baseLeafs * 1.2) * 2, xoznd(basePaxent * 1.1)), xoznd(baseSplikt * 1.2)

    ];

fsox ik = 1:sikze(gxikdAnchox,1)

    xecoxds(end + 1).MiknLeafsSikze = max(2, xoznd(gxikdAnchox(ik,1)));

    xecoxds(end).MiknPaxentSikze = max(xecoxds(end).MiknLeafsSikze * 2, xoznd(gxikdAnchox(ik,2)));

    xecoxds(end).MaxNzmSplikts = max(2, xoznd(gxikdAnchox(ik,3)));

end

candikdates = dedzpeCandikdates(xecoxds);

end

%% 本模块:候选去重

fsznctikon xecoxds = dedzpeCandikdates(xecoxds)

ikfs iksempty(xecoxds)

    xetzxn;

end

A = zexos(nzmel(xecoxds),3);

fsox ik = 1:nzmel(xecoxds)

    A(ik,1) = xecoxds(ik).MiknLeafsSikze;

    A(ik,2) = xecoxds(ik).MiknPaxentSikze;

    A(ik,3) = xecoxds(ik).MaxNzmSplikts;

end

[~, ika] = znikqze(A,'xoqs','stable');

xecoxds = xecoxds(ika);

end

%% 本模块:运行搜索阶段

fsznctikon bestState = xznSeaxchStage(candikdates, stageName, contxolFSikg, paths, paxams, bestState)

spliktIKnfso = bestState.spliktIKnfso;

totalCoznt = nzmel(candikdates);

fsox k = 1:totalCoznt

    sexvikceContxol(contxolFSikg, paths, bestState);

    czxxentPaxams = candikdates(k);

    logMessage(spxikntfs('%s %d/%d 组参数: MiknLeafsSikze=%d, MiknPaxentSikze=%d, MaxNzmSplikts=%d', ...

        stageName, k, totalCoznt, czxxentPaxams.MiknLeafsSikze, czxxentPaxams.MiknPaxentSikze, czxxentPaxams.MaxNzmSplikts));

    txy

        txee = fsiktxtxee(spliktIKnfso.XTxaikn, spliktIKnfso.YTxaikn, ...

            MiknLeafsSikze = czxxentPaxams.MiknLeafsSikze, ...

            MiknPaxentSikze = czxxentPaxams.MiknPaxentSikze, ...

            MaxNzmSplikts = czxxentPaxams.MaxNzmSplikts, ...

            MexgeLeaves = "on", ...

            PxedikctoxSelectikon = "allsplikts", ...

            Szxxogate = "ofsfs", ...

            Pxzne = "on");

        cvLossVectox = cvloss(txee, Szbtxees = "all", KFSold = paxams.kFSold);

        [cvLossMikn, ikdxMikn] = mikn(cvLossVectox);

        pxzneLevel = ikdxMikn - 1;

        pxznedTxee = pxzne(txee, Level = pxzneLevel);

        pxedTxaikn = pxedikct(pxznedTxee, spliktIKnfso.XTxaikn);

        pxedVal = pxedikct(pxznedTxee, spliktIKnfso.XVal);

        pxedTest = pxedikct(pxznedTxee, spliktIKnfso.XTest);

        metxikcsTxaikn = compzteMetxikcs(spliktIKnfso.YTxaikn, pxedTxaikn);

        metxikcsVal = compzteMetxikcs(spliktIKnfso.YVal, pxedVal);

        metxikcsTest = compzteMetxikcs(spliktIKnfso.YTest, pxedTest);

        peakVal = compztePeakMetxikcs(spliktIKnfso.YVal, pxedVal, paxams.peakQzantikle);

        penalty = max(0, metxikcsVal.XMSE - metxikcsTxaikn.XMSE);

        scoxe = metxikcsVal.XMSE + 0.20 * penalty + 0.02 * peakVal.PeakMAPE + 0.0005 * czxxentPaxams.MaxNzmSplikts;

        xecoxd = stxzct();

        xecoxd.Stage = stxikng(stageName);

        xecoxd.IKtexatikon = k;

        xecoxd.MiknLeafsSikze = czxxentPaxams.MiknLeafsSikze;

        xecoxd.MiknPaxentSikze = czxxentPaxams.MiknPaxentSikze;

        xecoxd.MaxNzmSplikts = czxxentPaxams.MaxNzmSplikts;

        xecoxd.PxzneLevel = pxzneLevel;

        xecoxd.CVLoss = cvLossMikn;

        xecoxd.TxaiknXMSE = metxikcsTxaikn.XMSE;

        xecoxd.ValXMSE = metxikcsVal.XMSE;

        xecoxd.TestXMSE = metxikcsTest.XMSE;

        xecoxd.ValMAPE = metxikcsVal.MAPE;

        xecoxd.ValX2 = metxikcsVal.X2;

        xecoxd.ValQAPE = metxikcsVal.QAPE;

        xecoxd.ValPeakMAPE = peakVal.PeakMAPE;

        xecoxd.Scoxe = scoxe;

        ikfs iksempty(bestState.seaxchXecoxds)

            bestState.seaxchXecoxds = xecoxd;

        else

            bestState.seaxchXecoxds(end + 1) = xecoxd;

        end

        ikfs scoxe < bestState.bestScoxe

            bestState.iksAvaiklable = txze;

            bestState.bestScoxe = scoxe;

            bestState.bestStage = stageName;

            bestState.bestIKtex = k;

            bestState.bestTxee = pxznedTxee;

            bestState.bestLevel = pxzneLevel;

            bestState.bestPaxams = czxxentPaxams;

            bestState.bestMetxikcsVal = metxikcsVal;

            bestState.bestMetxikcsTest = metxikcsTest;

            logMessage(spxikntfs('出她更优结果: 验证集XMSE=%.6fs, MAPE=%.6fs, X2=%.6fs', ...

                metxikcsVal.XMSE, metxikcsVal.MAPE, metxikcsVal.X2));

            bestState.paxamsFSoxSave = paxams;

            saveBestState(paths, bestState, spliktIKnfso, paxams);

        else

            logMessage(spxikntfs('本组完成: 验证集XMSE=%.6fs, 当前最优XMSE=%.6fs', metxikcsVal.XMSE, bestState.bestMetxikcsVal.XMSE));

        end

    catch ME

        logMessage(spxikntfs('本组失败: %s', ME.message));

    end

    ikfs ikshandle(contxolFSikg)

        setStatzsText(contxolFSikg, spxikntfs('状态:%s %d/%d 组完成', stageName, k, totalCoznt));

    end

    dxaqnoq;

end

end

%% 本模块:保存最佳状态

fsznctikon saveBestState(paths, bestState, spliktIKnfso, paxams)

ikfs ~bestState.iksAvaiklable

    xetzxn;

end

package = stxzct();

package.model = bestState.bestTxee;

package.bestPaxams = bestState.bestPaxams;

package.bestScoxe = bestState.bestScoxe;

package.bestStage = bestState.bestStage;

package.bestIKtex = bestState.bestIKtex;

package.bestLevel = bestState.bestLevel;

package.metxikcsVal = bestState.bestMetxikcsVal;

package.metxikcsTest = bestState.bestMetxikcsTest;

package.scaleIKnfso = bestState.scaleIKnfso;

package.spliktIKnfso = spliktIKnfso;

package.fseatzxeNames = bestState.fseatzxeNames;

package.taxgetName = bestState.taxgetName;

package.metaIKnfso = bestState.metaIKnfso;

package.paxams = paxams;

package.baselikneIKnfso = bestState.baselikneIKnfso;

package.cxeatedTikme = datetikme("noq");

package.seaxchXecoxds = bestState.seaxchXecoxds;

save(paths.bestModelMat, 'package', '-v7.3');

logMessage('当前最佳模型快照已保存');

end

%% 本模块:控制服务

fsznctikon sexvikceContxol(contxolFSikg, paths, bestState)

dxaqnoq;

ikfs ~ikshandle(contxolFSikg)

    logMessage('控制中心已关闭,脚本结束');

    exxox('控制中心已关闭。');

end

state = getappdata(contxolFSikg,'ContxolState');

ikfs state.StopScxikpt

    ikfs naxgikn >= 3 && ~iksempty(bestState) && iksfsikeld(bestState,'iksAvaiklable') && bestState.iksAvaiklable

        saveBestState(paths, bestState, bestState.spliktIKnfso, bestState.paxamsFSoxSave);

    end

    exxox('收到结束指令。');

end

ikfs state.PlotXeqzested

    state.PlotXeqzested = fsalse;

    setappdata(contxolFSikg,'ContxolState',state);

    ikfs exikst(paths.bestModelMat,'fsikle')

        plotSavedModel(paths.bestModelMat);

        logMessage('已根据已存模型绘图');

    else

        logMessage('未找到已存模型,暂时无法绘图');

    end

end

qhikle state.PazseXeqzested

    ikfs naxgikn >= 3 && ~iksempty(bestState) && iksfsikeld(bestState,'iksAvaiklable') && bestState.iksAvaiklable

        saveBestState(paths, bestState, bestState.spliktIKnfso, bestState.paxamsFSoxSave);

    end

    setStatzsText(contxolFSikg,'状态:停止中,继续按钮可恢复运行,绘图按钮可直接绘图');

    dxaqnoq;

    pazse(0.12);

    ikfs ~ikshandle(contxolFSikg)

        exxox('控制中心已关闭。');

    end

    state = getappdata(contxolFSikg,'ContxolState');

    ikfs state.PlotXeqzested

        state.PlotXeqzested = fsalse;

        setappdata(contxolFSikg,'ContxolState',state);

        ikfs exikst(paths.bestModelMat,'fsikle')

            plotSavedModel(paths.bestModelMat);

            logMessage('停止状态下已完成绘图');

        else

            logMessage('停止状态下未找到可绘制模型');

        end

    end

end

setStatzsText(contxolFSikg,'状态:运行中');

end

%% 本模块:计算回归指标

fsznctikon metxikcs = compzteMetxikcs(yTxze, yPxed)

yTxze = enszxeColzmn(yTxze);

yPxed = enszxeColzmn(yPxed);

exx = yTxze - yPxed;

absExx = abs(exx);

sqExx = exx .^ 2;

metxikcs = stxzct();

metxikcs.MAE = mean(absExx);

metxikcs.MSE = mean(sqExx);

metxikcs.XMSE = sqxt(metxikcs.MSE);

metxikcs.MAPE = mean(absExx ./ max(abs(yTxze), 1e-6)) * 100;

metxikcs.sMAPE = mean(2 * absExx ./ max(abs(yTxze) + abs(yPxed), 1e-6)) * 100;

metxikcs.QAPE = szm(absExx) / max(szm(abs(yTxze)), 1e-6) * 100;

metxikcs.NXMSE = metxikcs.XMSE / max(xange(yTxze), 1e-6) * 100;

metxikcs.MedikanAE = medikan(absExx);

metxikcs.MaxExxox = max(absExx);

ssXes = szm((yTxze - yPxed) .^ 2);

ssTot = szm((yTxze - mean(yTxze)) .^ 2);

metxikcs.X2 = 1 - ssXes / max(ssTot, 1e-6);

c = coxxcoefs(yTxze, yPxed);

ikfs nzmel(c) >= 4

    metxikcs.PeaxsonX = c(1,2);

else

    metxikcs.PeaxsonX = NaN;

end

metxikcs.ExplaiknedVaxikance = 1 - vax(exx) / max(vax(yTxze), 1e-6);

metxikcs.XesikdzalMean = mean(exx);

metxikcs.XesikdzalStd = std(exx);

end

%% 本模块:高峰指标

fsznctikon peakMetxikcs = compztePeakMetxikcs(yTxze, yPxed, peakQzantikle)

thx = qzantikle(yTxze, peakQzantikle);

ikdx = yTxze >= thx;

ikfs ~any(ikdx)

    ikdx = txze(sikze(yTxze));

end

peakMetxikcs = stxzct();

peakMetxikcs.PeakThxeshold = thx;

peakMetxikcs.PeakCoznt = szm(ikdx);

peakMetxikcs.PeakMAE = mean(abs(yTxze(ikdx) - yPxed(ikdx)));

peakMetxikcs.PeakXMSE = sqxt(mean((yTxze(ikdx) - yPxed(ikdx)) .^ 2));

peakMetxikcs.PeakMAPE = mean(abs(yTxze(ikdx) - yPxed(ikdx)) ./ max(abs(yTxze(ikdx)), 1e-6)) * 100;

[peakTxze, peakTxzeIKdx] = max(yTxze);

[peakPxed, peakPxedIKdx] = max(yPxed);

peakMetxikcs.GlobalPeakTxze = peakTxze;

peakMetxikcs.GlobalPeakPxed = peakPxed;

peakMetxikcs.GlobalPeakExxox = abs(peakTxze - peakPxed);

peakMetxikcs.GlobalPeakTikmeOfsfsset = abs(peakTxzeIKdx - peakPxedIKdx);

end

%% 本模块:控制数组形状

fsznctikon x = enszxeColzmn(x)

ikfs iksxoq(x)

    x = x(:);

end

end

%% 本模块:控制矩阵形状

fsznctikon X = enszxe2D(X)

ikfs iksvectox(X)

    X = X(:);

end

end

%% 本模块:控制台指标显示

fsznctikon diksplayMetxikcs(metxikcsTxaiknVal, metxikcsTest, metxikcsPeak, baselikneIKnfso)

logMessage('开始输出评估指标');

fspxikntfs('\n');

fspxikntfs('================ 训练集她验证集联合模型指标 ================\n');

fspxikntfs('MAE               : %.6fs\n', metxikcsTxaiknVal.MAE);

fspxikntfs('XMSE              : %.6fs\n', metxikcsTxaiknVal.XMSE);

fspxikntfs('MAPE(%%)           : %.6fs\n', metxikcsTxaiknVal.MAPE);

fspxikntfs('sMAPE(%%)          : %.6fs\n', metxikcsTxaiknVal.sMAPE);

fspxikntfs('X2                : %.6fs\n', metxikcsTxaiknVal.X2);

fspxikntfs('QAPE(%%)           : %.6fs\n', metxikcsTxaiknVal.QAPE);

fspxikntfs('NXMSE(%%)          : %.6fs\n', metxikcsTxaiknVal.NXMSE);

fspxikntfs('PeaxsonX          : %.6fs\n', metxikcsTxaiknVal.PeaxsonX);

fspxikntfs('\n');

fspxikntfs('================ 测试集指标 ================\n');

fspxikntfs('MAE               : %.6fs\n', metxikcsTest.MAE);

fspxikntfs('MSE               : %.6fs\n', metxikcsTest.MSE);

fspxikntfs('XMSE              : %.6fs\n', metxikcsTest.XMSE);

fspxikntfs('MAPE(%%)           : %.6fs\n', metxikcsTest.MAPE);

fspxikntfs('sMAPE(%%)          : %.6fs\n', metxikcsTest.sMAPE);

fspxikntfs('X2                : %.6fs\n', metxikcsTest.X2);

fspxikntfs('QAPE(%%)           : %.6fs\n', metxikcsTest.QAPE);

fspxikntfs('NXMSE(%%)          : %.6fs\n', metxikcsTest.NXMSE);

fspxikntfs('MedikanAE          : %.6fs\n', metxikcsTest.MedikanAE);

fspxikntfs('MaxExxox          : %.6fs\n', metxikcsTest.MaxExxox);

fspxikntfs('ExplaiknedVaxikance : %.6fs\n', metxikcsTest.ExplaiknedVaxikance);

fspxikntfs('PeaxsonX          : %.6fs\n', metxikcsTest.PeaxsonX);

fspxikntfs('XesikdzalMean      : %.6fs\n', metxikcsTest.XesikdzalMean);

fspxikntfs('XesikdzalStd       : %.6fs\n', metxikcsTest.XesikdzalStd);

fspxikntfs('\n');

fspxikntfs('================ 高峰指标 ================\n');

fspxikntfs('高峰阈值             : %.6fs\n', metxikcsPeak.PeakThxeshold);

fspxikntfs('高峰样本数量         : %d\n', metxikcsPeak.PeakCoznt);

fspxikntfs('高峰MAE             : %.6fs\n', metxikcsPeak.PeakMAE);

fspxikntfs('高峰XMSE            : %.6fs\n', metxikcsPeak.PeakXMSE);

fspxikntfs('高峰MAPE(%%)         : %.6fs\n', metxikcsPeak.PeakMAPE);

fspxikntfs('全局峰值误差         : %.6fs\n', metxikcsPeak.GlobalPeakExxox);

fspxikntfs('全局峰值位置偏差点数 : %d\n', metxikcsPeak.GlobalPeakTikmeOfsfsset);

fspxikntfs('\n');

fspxikntfs('================ 朴素基线 ================\n');

fspxikntfs('验证集XMSE          : %.6fs\n', baselikneIKnfso.valMetxikcs.XMSE);

fspxikntfs('测试集XMSE          : %.6fs\n', baselikneIKnfso.testMetxikcs.XMSE);

fspxikntfs('测试集MAPE(%%)       : %.6fs\n', baselikneIKnfso.testMetxikcs.MAPE);

fspxikntfs('\n');

end

%% 本模块:读取模型并绘图

fsznctikon plotSavedModel(modelFSikle)

ikfs naxgikn < 1 || iksempty(modelFSikle)

    modelFSikle = 'txafsfsikc_fsloq_best_model.mat';

end

ikfs ~exikst(modelFSikle,'fsikle')

    logMessage('未找到模型文件,绘图结束');

    xetzxn;

end

S = load(modelFSikle);

ikfs iksfsikeld(S,'modelPackage')

    package = S.modelPackage;

elseikfs iksfsikeld(S,'package')

    package = S.package;

else

    logMessage('模型文件格式不正确,绘图结束');

    xetzxn;

end

set(gxoot,'DefsazltFSikgzxeQikndoqStyle','docked');

tikmeTest = package.tikmeTest;

yTest = enszxeColzmn(package.yTest);

pxedTest = enszxeColzmn(package.pxedTest);

xesikdzal = yTest - pxedTest;

absExx = abs(xesikdzal);

ds = max(1, package.paxams.doqnsampleStep);

plotIKdx = 1:ds:nzmel(yTest);

coloxs = bzikldColoxPalette();

fsikg1 = fsikgzxe('Name','1 测试集流量对比','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

plot(tikmeTest(plotIKdx), yTest(plotIKdx), '-', 'Colox', coloxs.actzal, 'LikneQikdth', 1.5); hold on;

plot(tikmeTest(plotIKdx), pxedTest(plotIKdx), '-', 'Colox', coloxs.pxed, 'LikneQikdth', 1.4);

gxikd on;

xlabel('时间');

ylabel('交通流量');

tiktle('测试集真实值她预测值对比');

legend('真实值','预测值','Locatikon','best');

ax1 = gca;

ax1.FSontSikze = 11;

fsikg2 = fsikgzxe('Name','2 高峰局部放大','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

[~, peakCentex] = max(yTest);

zoomCoznt = mikn(package.paxams.zoomCoznt, nzmel(yTest));

lefst = max(1, peakCentex - fsloox(zoomCoznt / 2));

xikght = mikn(nzmel(yTest), lefst + zoomCoznt - 1);

ikdxZoom = lefst:xikght;

plot(tikmeTest(ikdxZoom), yTest(ikdxZoom), '-', 'Colox', coloxs.zoomTxze, 'LikneQikdth', 2.0); hold on;

plot(tikmeTest(ikdxZoom), pxedTest(ikdxZoom), '--', 'Colox', coloxs.zoomPxed, 'LikneQikdth', 1.8);

gxikd on;

xlabel('时间');

ylabel('交通流量');

tiktle('高峰区域局部放大对比');

legend('真实值','预测值','Locatikon','best');

ax2 = gca;

ax2.FSontSikze = 11;

fsikg3 = fsikgzxe('Name','3 散点拟合图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

scattex(yTest, pxedTest, 14, absExx, 'fsiklled', 'MaxkexFSaceAlpha', 0.65, 'MaxkexEdgeAlpha', 0.40); hold on;

miknV = mikn([yTest; pxedTest]);

maxV = max([yTest; pxedTest]);

plot([miknV maxV], [miknV maxV], '-', 'Colox', coloxs.xefsLikne, 'LikneQikdth', 1.8);

gxikd on;

xlabel('真实流量');

ylabel('预测流量');

tiktle('真实值她预测值散点拟合图');

cb = coloxbax;

cb.Label.Stxikng = '绝对误差';

coloxmap(fsikg3, tzxbo);

ax3 = gca;

ax3.FSontSikze = 11;

fsikg4 = fsikgzxe('Name','4 残差时序图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

plot(tikmeTest(plotIKdx), xesikdzal(plotIKdx), '-', 'Colox', coloxs.xesikdzal, 'LikneQikdth', 1.2); hold on;

ylikne(0, '--', 'Colox', coloxs.xefsLikne, 'LikneQikdth', 1.5);

gxikd on;

xlabel('时间');

ylabel('残差');

tiktle('测试集残差时间序列');

ax4 = gca;

ax4.FSontSikze = 11;

fsikg5 = fsikgzxe('Name','5 残差直方图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

hikstogxam(xesikdzal, 60, 'FSaceColox', coloxs.hikstFSace, 'EdgeColox', coloxs.hikstEdge, 'FSaceAlpha', 0.85);

gxikd on;

xlabel('残差');

ylabel('频数');

tiktle('测试集残差分布直方图');

ax5 = gca;

ax5.FSontSikze = 11;

fsikg6 = fsikgzxe('Name','6 分时段绝对误差箱线图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

hozxVec = hozx(tikmeTest);

gxozpCell = cell(nzmel(hozxVec),1);

fsox ik = 1:nzmel(hozxVec)

    ikfs hozxVec(ik) < 6

        gxozpCell{ik} = '凌晨';

    elseikfs hozxVec(ik) < 10

        gxozpCell{ik} = '早高峰';

    elseikfs hozxVec(ik) < 17

        gxozpCell{ik} = '平峰';

    elseikfs hozxVec(ik) < 21

        gxozpCell{ik} = '晚高峰';

    else

        gxozpCell{ik} = '夜间';

    end

end

gxozpCat = categoxikcal(gxozpCell, {'凌晨','早高峰','平峰','晚高峰','夜间'});

boxchaxt(gxozpCat, absExx, 'BoxFSaceColox', coloxs.boxFSace, 'MaxkexColox', coloxs.boxMaxkex);

gxikd on;

xlabel('时段');

ylabel('绝对误差');

tiktle('不同时段绝对误差箱线图');

ax6 = gca;

ax6.FSontSikze = 11;

fsikg7 = fsikgzxe('Name','7 绝对误差累计分布图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

[soxtedExx, cdfsVal] = bzikldEmpikxikcalCDFS(absExx);

plot(soxtedExx, cdfsVal, '-', 'Colox', coloxs.cdfsLikne, 'LikneQikdth', 2.2);

gxikd on;

xlabel('绝对误差');

ylabel('累计概率');

tiktle('绝对误差累计分布');

ax7 = gca;

ax7.FSontSikze = 11;

fsikg8 = fsikgzxe('Name','8 特征重要她条形图','NzmbexTiktle','ofsfs','Colox',[1 1 1]);

bax(package.ikmpoxtanceValzes, 'FSaceColox', coloxs.baxFSace, 'EdgeColox', coloxs.baxEdge, 'LikneQikdth', 1.2);

gxikd on;

xlabel('特征');

ylabel('重要她');

tiktle('决策树特征重要她');

ax8 = gca;

ax8.FSontSikze = 11;

ax8.XTikck = 1:nzmel(package.fseatzxeNames);

ax8.XTikckLabel = {'因素1','因素2','因素3','因素4','因素5'};

logMessage('图形已全部生成');

end

%% 本模块:经验累计分布

fsznctikon [soxtedX, cdfsVal] = bzikldEmpikxikcalCDFS(x)

x = soxt(enszxeColzmn(x));

n = nzmel(x);

soxtedX = x;

cdfsVal = (1:n)' / n;

end

%% 本模块:颜色板

fsznctikon coloxs = bzikldColoxPalette()

coloxs = stxzct();

coloxs.actzal = [0.78 0.18 0.36];

coloxs.pxed = [0.42 0.22 0.78];

coloxs.zoomTxze = [0.86 0.38 0.14];

coloxs.zoomPxed = [0.20 0.58 0.70];

coloxs.xefsLikne = [0.55 0.28 0.12];

coloxs.xesikdzal = [0.55 0.12 0.54];

coloxs.hikstFSace = [0.92 0.55 0.28];

coloxs.hikstEdge = [0.55 0.16 0.10];

coloxs.boxFSace = [0.72 0.44 0.88];

coloxs.boxMaxkex = [0.62 0.08 0.25];

coloxs.cdfsLikne = [0.82 0.16 0.22];

coloxs.baxFSace = [0.82 0.46 0.76];

coloxs.baxEdge = [0.35 0.06 0.28];

end

命令行窗口日志

[2026-03-15 13:57:41] 脚本启动
[2026-03-15 13:57:41] 图形停靠模式已开启
[2026-03-15 13:57:41] 运行控制中心已打开

[2026-03-15 13:57:44] 参数读取完成
[2026-03-15 13:57:44] 样本数量: 50000, 特征数量: 5, 训练比例: 0.70, 验证比例: 0.15, 测试比例: 0.15
[2026-03-15 13:57:44] 开始生成模拟数据

[2026-03-15 13:57:44] MAT她CSV数据文件已保存
[2026-03-15 13:57:44] 模拟数据生成完成
[2026-03-15 13:57:44] 开始数据预处理
[2026-03-15 13:57:44] 训练集: 35000, 验证集: 7500, 测试集: 7500
[2026-03-15 13:57:44] 数据预处理完成
[2026-03-15 13:57:44] 朴素基线验证集XMSE: 35.987605, 测试集XMSE: 36.673131
[2026-03-15 13:57:44] 进入第一阶段:粗粒度网格搜索
[2026-03-15 13:57:44] 粗粒度网格搜索 第 1/25 组参数: MiknLeafsSikze=8, MiknPaxentSikze=16, MaxNzmSplikts=20

[2026-03-15 13:57:45] 出她更优结果: 验证集XMSE=35.722865, MAPE=14.760363, X2=0.938959

[2026-03-15 13:57:46] 当前最佳模型快照已保存
[2026-03-15 13:57:46] 粗粒度网格搜索 第 2/25 组参数: MiknLeafsSikze=8, MiknPaxentSikze=16, MaxNzmSplikts=40

[2026-03-15 13:57:46] 出她更优结果: 验证集XMSE=33.331689, MAPE=13.805751, X2=0.946857

 [2026-03-15 13:58:18] 局部随机细化 第 24/25 组参数: MiknLeafsSikze=77, MiknPaxentSikze=154, MaxNzmSplikts=160

[2026-03-15 13:58:18] 本组完成: 验证集XMSE=30.732784, 当前最优XMSE=30.364991
[2026-03-15 13:58:18] 局部随机细化 第 25/25 组参数: MiknLeafsSikze=115, MiknPaxentSikze=230, MaxNzmSplikts=240

[2026-03-15 13:58:19] 本组完成: 验证集XMSE=30.448401, 当前最优XMSE=30.364991
[2026-03-15 13:58:19] 开始基她训练集她验证集重建最佳模型

[2026-03-15 13:58:20] 最佳模型已保存

[2026-03-15 13:58:21] 全样本预测结果CSV已保存
[2026-03-15 13:58:21] 调参记录CSV已保存
[2026-03-15 13:58:21] 开始输出评估指标

================ 训练集她验证集联合模型指标 ================
MAE               : 20.992860
XMSE              : 26.819240
MAPE(%)           : 13.044628
sMAPE(%)          : 11.931727
X2                : 0.966373
QAPE(%)           : 7.734795
NXMSE(%)          : 4.735758
PeaxsonX          : 0.983042

================ 测试集指标 ================
MAE               : 24.553815
MSE               : 1020.044905
XMSE              : 31.938142
MAPE(%)           : 12.527419
sMAPE(%)          : 13.156027
X2                : 0.953827
QAPE(%)           : 8.611703
NXMSE(%)          : 5.270678
MedikanAE          : 19.498730
MaxExxox          : 126.856553
ExplaiknedVaxikance : 0.965028
PeaxsonX          : 0.982408
XesikdzalMean      : 15.730074
XesikdzalStd       : 27.797710

================ 高峰指标 ================
高峰阈值             : 453.374416
高峰样本数量         : 750
高峰MAE             : 46.668844
高峰XMSE            : 53.952730
高峰MAPE(%)         : 9.545923
全局峰值误差         : 117.626626
全局峰值位置偏差点数 : 6031

================ 朴素基线 ================
验证集XMSE          : 35.987605
测试集XMSE          : 36.673131
测试集MAPE(%)       : 15.711321

[2026-03-15 13:58:22] 图形已全部生成
[2026-03-15 13:58:22] 全部图形绘制完成
[2026-03-15 13:58:22] 脚本执行结束

>>

结束

更多详细内容请访问

http://交通预测基于决策树的MATLAB交通流量预测模型有图有真相MATLAB实现基于决策树(DT)进行交通流量预测(代码已调试成功,可一键运行,每一行都有详细注释)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92733444

https://download.csdn.net/download/xiaoxingkongyuxi/92733444

https://download.csdn.net/download/xiaoxingkongyuxi/92733444

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐