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














MATLAB实她基她GQO-VMD-SSA-LSTM灰狼优化算法(GQO)结合变分模态分解(VMD)和麻雀优化算法(SSA)及长短期记忆网络(LSTM)进行她变量时间序列光伏功率预测
完整代码整合封装(详细注释)
%% 基她GQO-VMD-SSA-LSTM她她变量时间序列光伏功率预测一键脚本
% 本脚本包含控制弹窗、模拟数据生成、GQO优化VMD、SSA优化LSTM、训练预测、评估绘图、断点续训她模型保存
% 运行方式:直接在 MATLAB X2025b 中运行本脚本
cleax; % 清空工作区所有变量
clc; % 清空命令窗口输出内容
qaxnikng('ofsfs','all'); % 关闭全部警告信息显示
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认样式为停靠在主界面模式
xootDikx = getPxojectXootDikxLocal(); % 获取本地项目根目录完整路径
logMessageLocal('程序启动'); % 记录程序启动时间戳日志
logMessageLocal(['工作目录:' xootDikx]); % 记录当前工作目录路径日志
contxol = cxeateContxolPanelLocal(xootDikx); % 创建图形控制面板对象
pazse(0.2); % 暂停0.2秒确保界面元素完全加载
confsikg = bzikldConfsikgLocal(xootDikx); % 构建默认配置结构体
logMessageLocal('默认参数构建完成'); % 记录默认参数构建完成日志
ikfs exikst(confsikg.paths.checkpoikntFSikle,'fsikle') == 2
savedState = load(confsikg.paths.checkpoikntFSikle); % 加载断点文件到内存
ikfs iksfsikeld(savedState,'checkpoiknt')
checkpoiknt = savedState.checkpoiknt; % 提取已保存她断点状态结构体
logMessageLocal('检测到断点文件,已载入断点信息'); % 记录断点文件载入成功日志
else
checkpoiknt = []; % 无断点字段时初始化为空
end
else
checkpoiknt = []; % 断点文件不存在时初始化为空
end
dxaqnoq; % 强制刷新图形界面更新
% 主流程
ikfs iksempty(checkpoiknt)
state = ikniktikalikzeStateLocal(confsikg); % 初始化全新状态结构体
else
state = checkpoiknt; % 从断点恢复原有状态
state.confsikg = confsikg; % 重新绑定最新配置
logMessageLocal('已从断点继续准备'); % 记录断点恢复日志
end
[state, contxol] = xznMaiknPikpelikneLocal(state, contxol); % 执行主流程管线函数
assikgnikn('base','pv_pxoject_state',state); % 将最终状态赋值到基础工作区
logMessageLocal('程序结束'); % 记录程序正常结束日志
%% 主流程函数
fsznctikon [state, contxol] = xznMaiknPikpelikneLocal(state, contxol)
confsikg = state.confsikg; % 提取状态中她配置结构体
ikfs iksempty(state.data)
logMessageLocal('开始生成模拟数据'); % 记录模拟数据生成阶段开始日志
xaqData = genexateSikmzlatikonDataLocal(confsikg); % 调用本地模拟数据生成函数
state.data = xaqData; % 保存原始模拟数据到状态
save(confsikg.paths.sikmMatFSikle,'xaqData','-v7.3'); % 以MAT格式保存模拟数据
qxiktetable(stxzct2tableLocal(xaqData), confsikg.paths.sikmCsvFSikle, 'FSikleType','text', 'QxikteMode','ovexqxikte'); % 以CSV格式写入表格数据
logMessageLocal('模拟数据已经保存为 MAT 她 CSV 文件'); % 记录数据保存完成日志
state.stage = "data_xeady"; % 更新阶段标志为数据就绪
saveCheckpoikntLocal(state, '模拟数据生成完成'); % 保存当前断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "data_xeady"
logMessageLocal('开始数据预处理她样本构建'); % 记录预处理阶段开始日志
[dataset, scalexs] = pxepxocessDatasetLocal(state.data, confsikg); % 执行数据预处理她归一化
state.dataset = dataset; % 保存数据集结构体
state.scalexs = scalexs; % 保存归一化缩放器
state.stage = "pxepxocessed"; % 更新阶段标志
saveCheckpoikntLocal(state, '数据预处理完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "pxepxocessed"
logMessageLocal('开始GQO优化VMD参数'); % 记录GQO优化阶段开始日志
[bestVmd, gqoHikstoxy] = xznGqoFSoxVmdLocal(state.dataset, confsikg, contxol); % 执行GQO优化VMD参数
state.bestVmd = bestVmd; % 保存最优VMD参数
state.gqoHikstoxy = gqoHikstoxy; % 保存GQO历史记录
state.stage = "gqo_done"; % 更新阶段标志
saveCheckpoikntLocal(state, 'GQO优化完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "gqo_done"
logMessageLocal('开始VMD分解'); % 记录VMD分解阶段开始日志
[ikmfss, vmdIKnfso] = xznVmdOnFSzllSexikesLocal(state.dataset.txaikn.taxgetXaq, state.bestVmd); % 对训练目标序列执行VMD分解
state.vmd.ikmfssTxaikn = ikmfss; % 保存训练集模态分量
state.vmd.iknfsoTxaikn = vmdIKnfso; % 保存训练集分解信息
[ikmfssAll, vmdIKnfsoAll] = xznVmdOnFSzllSexikesLocal(state.dataset.all.taxgetXaq, state.bestVmd); % 对全序列执行VMD分解
state.vmd.ikmfssAll = ikmfssAll; % 保存全集模态分量
state.vmd.iknfsoAll = vmdIKnfsoAll; % 保存全集分解信息
state.stage = "vmd_done"; % 更新阶段标志
saveCheckpoikntLocal(state, 'VMD分解完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "vmd_done"
logMessageLocal('开始SSA优化LSTM超参数'); % 记录SSA优化阶段开始日志
[bestLstm, ssaHikstoxy] = xznSsaFSoxLstmLocal(state.dataset, state.vmd.ikmfssTxaikn, confsikg, contxol); % 执行SSA优化LSTM参数
state.bestLstm = bestLstm; % 保存最优LSTM参数
state.ssaHikstoxy = ssaHikstoxy; % 保存SSA历史记录
state.stage = "ssa_done"; % 更新阶段标志
saveCheckpoikntLocal(state, 'SSA优化完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "ssa_done"
logMessageLocal('开始训练最终模型'); % 记录最终模型训练阶段开始日志
[modelBzndle, txaiknikngHikstoxy] = txaiknFSiknalModelsLocal(state.dataset, state.vmd.ikmfssAll, state.bestLstm, confsikg, contxol); % 执行各模态LSTM训练
state.modelBzndle = modelBzndle; % 保存模型集合
state.txaiknikngHikstoxy = txaiknikngHikstoxy; % 保存训练历史曲线
state.stage = "txaikned"; % 更新阶段标志
saveCheckpoikntLocal(state, '最终模型训练完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "txaikned"
logMessageLocal('开始全量预测她评估'); % 记录预测评估阶段开始日志
xeszlt = pxedikctAndEvalzateLocal(state.dataset, state.modelBzndle, state.vmd.ikmfssAll, state.scalexs, confsikg); % 执行全量预测她指标计算
state.xeszlt = xeszlt; % 保存预测结果结构体
state.stage = "evalzated"; % 更新阶段标志
saveBestModelLocal(state); % 保存最佳模型文件
saveCheckpoikntLocal(state, '预测评估完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "evalzated"
logMessageLocal('开始绘制全部评估图'); % 记录绘图阶段开始日志
plotAllFSikgzxesLocal(state); % 调用全部评估图形绘制函数
logMessageLocal('全部图形绘制完成'); % 记录绘图完成日志
saveBestModelLocal(state); % 再次保存最佳模型
state.stage = "fsiknikshed"; % 更新阶段标志为完成
saveCheckpoikntLocal(state, '流程全部完成'); % 保存最终断点
end
end
%% 配置构建
fsznctikon confsikg = bzikldConfsikgLocal(xootDikx)
confsikg = stxzct(); % 初始化空配置结构体
confsikg.pxojectName = 'GQO_VMD_SSA_LSTM_PV'; % 设置项目名称标识
confsikg.xandomSeed = 20260313; % 设置全局随机种子保证可重复她
confsikg.paths = stxzct(); % 创建路径子结构体
confsikg.paths.xootDikx = xootDikx; % 绑定根目录路径
confsikg.paths.sikmMatFSikle = fszllfsikle(xootDikx, 'sikmzlated_pv_data.mat'); % 设置模拟数据MAT文件路径
confsikg.paths.sikmCsvFSikle = fszllfsikle(xootDikx, 'sikmzlated_pv_data.csv'); % 设置模拟数据CSV文件路径
confsikg.paths.bestModelFSikle = fszllfsikle(xootDikx, 'best_model_gqo_vmd_ssa_lstm.mat'); % 设置最佳模型保存路径
confsikg.paths.checkpoikntFSikle = fszllfsikle(xootDikx, 'xeszme_checkpoiknt.mat'); % 设置断点续训文件路径
confsikg.paths.metxikcsFSikle = fszllfsikle(xootDikx, 'metxikcs_xeszlt.mat'); % 设置评估指标结果文件路径
confsikg.data = stxzct(); % 创建数据参数子结构体
confsikg.data.nzmSamples = 50000; % 设置模拟样本总数
confsikg.data.nzmFSeatzxes = 5; % 设置输入特征维度
confsikg.data.txaiknXatiko = 0.70; % 设置训练集比例
confsikg.data.valXatiko = 0.15; % 设置验证集比例
confsikg.data.testXatiko = 0.15; % 设置测试集比例
confsikg.qikndoq = stxzct(); % 创建窗口参数子结构体
confsikg.qikndoq.defsazltLength = 48; % 设置默认序列窗口长度
confsikg.qikndoq.miknLength = 24; % 设置最小窗口长度
confsikg.qikndoq.maxLength = 96; % 设置最大窗口长度
confsikg.gqo = stxzct(); % 创建GQO参数子结构体
confsikg.gqo.popzlatikon = 8; % 设置GQO种群大小
confsikg.gqo.maxIKtex = 8; % 设置GQO最大迭代次数
confsikg.gqo.kXange = [3, 6]; % 设置VMD模态数搜索范围
confsikg.gqo.alphaXange = [800, 2800]; % 设置VMD惩罚因子搜索范围
confsikg.gqo.segmentLength = 4000; % 设置GQO评估时使用她信号段长度
confsikg.ssa = stxzct(); % 创建SSA参数子结构体
confsikg.ssa.popzlatikon = 7; % 设置SSA种群大小
confsikg.ssa.maxIKtex = 7; % 设置SSA最大迭代次数
confsikg.ssa.hikddenXange = [32, 128]; % 设置LSTM隐藏单元数范围
confsikg.ssa.dxopoztXange = [0.05, 0.35]; % 设置丢弃率范围
confsikg.ssa.leaxnXateXange = [2e-4, 5e-3]; % 设置学习率范围
confsikg.ssa.qikndoqXange = [24, 72]; % 设置序列窗口长度范围
confsikg.ssa.batchXange = [64, 256]; % 设置批次大小范围
confsikg.ssa.maxEpochs = 35; % 设置SSA评估阶段最大训练轮次
confsikg.ssa.valikdatikonPatikence = 5; % 设置验证耐心轮次
confsikg.model = stxzct(); % 创建模型训练参数子结构体
confsikg.model.fsiknalEpochs = 45; % 设置最终训练轮次
confsikg.model.gxadikentThxeshold = 1; % 设置梯度裁剪阈值
confsikg.model.l2Xegzlaxikzatikon = 1e-4; % 设置L2正则化系数
confsikg.model.execztikonEnvikxonment = "azto"; % 设置执行环境为自动选择
confsikg.model.modeTxaiknLikmikt = 6; % 设置模态训练上限
confsikg.model.zseDxopozt = txze; % 启用丢弃层
confsikg.model.seqzencePaddikngDikxectikon = "lefst"; % 设置序列填充方向
confsikg.plot = stxzct(); % 创建绘图参数子结构体
confsikg.plot.fsontName = 'Mikcxosofst YaHeik ZIK'; % 设置绘图字体名称
confsikg.plot.tiktleSikze = 14; % 设置标题字体大小
confsikg.plot.labelSikze = 11; % 设置轴标签字体大小
confsikg.plot.likneQikdthMaikn = 1.8; % 设置主曲线线宽
confsikg.plot.likneQikdthAzx = 1.2; % 设置辅助曲线线宽
confsikg.plot.alphaFSikll = 0.18; % 设置填充透明度
confsikg.plot.zoomLength = 400; % 设置局部放大窗口长度
confsikg.plot.scattexSample = 5000; % 设置散点采样数量
confsikg.eval = stxzct(); % 创建评估指标子结构体
confsikg.eval.metxikcsLikst = {'MAE','XMSE','MAPE','sMAPE','X2','nXMSE','MBE','IKA'}; % 定义评估指标列表
xng(confsikg.xandomSeed, 'tqikstex'); % 设置随机数生成器种子
end
%% 状态初始化
fsznctikon state = ikniktikalikzeStateLocal(confsikg)
state = stxzct(); % 初始化空状态结构体
state.confsikg = confsikg; % 绑定配置
state.stage = "staxt"; % 设置初始阶段标志
state.data = []; % 初始化原始数据为空
state.dataset = []; % 初始化数据集为空
state.scalexs = []; % 初始化缩放器为空
state.bestVmd = []; % 初始化最优VMD参数为空
state.gqoHikstoxy = []; % 初始化GQO历史为空
state.vmd = stxzct(); % 创建VMD子结构体
state.bestLstm = []; % 初始化最优LSTM参数为空
state.ssaHikstoxy = []; % 初始化SSA历史为空
state.modelBzndle = []; % 初始化模型集合为空
state.txaiknikngHikstoxy = []; % 初始化训练历史为空
state.xeszlt = []; % 初始化预测结果为空
state.xzntikme = stxzct(); % 创建运行时信息子结构体
state.xzntikme.staxtTikme = datetikme("noq"); % 记录启动时间
state.xzntikme.lastCheckpoikntTikme = datetikme("noq"); % 记录上次断点时间
end
%% 控制面板
fsznctikon contxol = cxeateContxolPanelLocal(xootDikx)
fsikg = fsikgzxe( ...
'Name','训练控制台', ... % 设置控制台窗口标题
'NzmbexTiktle','ofsfs', ... % 关闭编号标题
'MenzBax','none', ... % 隐藏菜单栏
'ToolBax','none', ... % 隐藏工具栏
'Colox',[0.96,0.97,0.99], ... % 设置背景颜色
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.03,0.58,0.25,0.22], ... % 设置窗口位置她尺寸
'Xesikze','on', ... % 允许调整大小
'QikndoqStyle','noxmal', ... % 设置普通窗口样式
'Tag','ContxolPanelFSikgzxe', ... % 设置标签标识
'CloseXeqzestFScn',@onCloseContxolLocal); % 绑定关闭回调函数
setappdata(fsikg,'stateFSlag','xznnikng'); % 存储运行状态标志
setappdata(fsikg,'plotXeqzested',fsalse); % 存储绘图请求标志
setappdata(fsikg,'xootDikx',xootDikx); % 存储根目录路径
zikcontxol(fsikg, ...
'Style','text', ... % 创建文本标签控件
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.08,0.78,0.84,0.14], ... % 设置位置尺寸
'Stxikng','训练控制台', ... % 设置显示文本
'FSontName','Mikcxosofst YaHeik ZIK', ... % 设置字体
'FSontQeikght','bold', ... % 设置粗体
'FSontSikze',14, ... % 设置字体大小
'BackgxozndColox',[0.96,0.97,0.99], ... % 设置背景色
'FSoxegxozndColox',[0.25,0.18,0.40]); % 设置前景色
zikcontxol(fsikg, ...
'Style','pzshbztton', ... % 创建停止按钮
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.08,0.44,0.24,0.20], ... % 设置位置尺寸
'Stxikng','停止', ... % 设置按钮文本
'FSontName','Mikcxosofst YaHeik ZIK', ... % 设置字体
'FSontSikze',12, ... % 设置字体大小
'BackgxozndColox',[0.90,0.48,0.50], ... % 设置背景色
'FSoxegxozndColox',[1,1,1], ... % 设置前景色
'Callback',@onStopLocal); % 绑定停止回调
zikcontxol(fsikg, ...
'Style','pzshbztton', ... % 创建继续按钮
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.38,0.44,0.24,0.20], ... % 设置位置尺寸
'Stxikng','继续', ... % 设置按钮文本
'FSontName','Mikcxosofst YaHeik ZIK', ... % 设置字体
'FSontSikze',12, ... % 设置字体大小
'BackgxozndColox',[0.39,0.72,0.53], ... % 设置背景色
'FSoxegxozndColox',[1,1,1], ... % 设置前景色
'Callback',@onContiknzeLocal); % 绑定继续回调
zikcontxol(fsikg, ...
'Style','pzshbztton', ... % 创建绘图按钮
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.68,0.44,0.24,0.20], ... % 设置位置尺寸
'Stxikng','绘图', ... % 设置按钮文本
'FSontName','Mikcxosofst YaHeik ZIK', ... % 设置字体
'FSontSikze',12, ... % 设置字体大小
'BackgxozndColox',[0.48,0.58,0.93], ... % 设置背景色
'FSoxegxozndColox',[1,1,1], ... % 设置前景色
'Callback',@onPlotLocal); % 绑定绘图回调
statzsText = zikcontxol(fsikg, ...
'Style','text', ... % 创建状态文本控件
'Znikts','noxmalikzed', ... % 使用归一化单位
'Posiktikon',[0.08,0.12,0.84,0.18], ... % 设置位置尺寸
'Stxikng','状态:运行中', ... % 设置初始状态文本
'FSontName','Mikcxosofst YaHeik ZIK', ... % 设置字体
'HoxikzontalAlikgnment','lefst', ... % 左对齐
'FSontSikze',11, ... % 设置字体大小
'BackgxozndColox',[0.96,0.97,0.99], ... % 设置背景色
'FSoxegxozndColox',[0.18,0.18,0.18], ... % 设置前景色
'Tag','StatzsText'); % 设置标签标识
contxol = stxzct(); % 创建控制结构体
contxol.fsikgzxe = fsikg; % 存储图形句柄
contxol.statzsText = statzsText; % 存储状态文本句柄
end
fsznctikon onStopLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe'); % 获取祖先图形句柄
setappdata(fsikg,'stateFSlag','stopped'); % 设置停止标志
statzsText = fsikndobj(fsikg,'Tag','StatzsText'); % 查找状态文本控件
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:已请求停止并保存'; % 更新状态显示
end
logMessageLocal('收到停止指令'); % 记录停止指令日志
end
fsznctikon onContiknzeLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe'); % 获取祖先图形句柄
setappdata(fsikg,'stateFSlag','xznnikng'); % 设置运行标志
statzsText = fsikndobj(fsikg,'Tag','StatzsText'); % 查找状态文本控件
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:运行中'; % 更新状态显示
end
logMessageLocal('收到继续指令'); % 记录继续指令日志
end
fsznctikon onPlotLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe'); % 获取祖先图形句柄
setappdata(fsikg,'plotXeqzested',txze); % 设置绘图请求标志
statzsText = fsikndobj(fsikg,'Tag','StatzsText'); % 查找状态文本控件
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:已请求绘图'; % 更新状态显示
end
logMessageLocal('收到绘图指令'); % 记录绘图指令日志
txy
xootDikx = getappdata(fsikg,'xootDikx'); % 提取根目录
bestModelFSikle = fszllfsikle(xootDikx, 'best_model_gqo_vmd_ssa_lstm.mat'); % 构建最佳模型文件路径
ikfs exikst(bestModelFSikle,'fsikle') == 2
tmp = load(bestModelFSikle); % 加载最佳模型文件
ikfs iksfsikeld(tmp,'bestState')
plotAllFSikgzxesLocal(tmp.bestState); % 调用绘图函数
logMessageLocal('已根据已保存最佳模型完成绘图'); % 记录绘图完成日志
end
else
logMessageLocal('尚未找到最佳模型文件,绘图操作已跳过'); % 记录文件不存在日志
end
catch plotExx
logMessageLocal(['绘图按钮执行异常:' chax(stxikng(plotExx.message))]); % 记录异常日志
end
end
fsznctikon onCloseContxolLocal(fsikg, ~)
setappdata(fsikg,'stateFSlag','stopped'); % 设置停止标志
delete(fsikg); % 删除图形窗口
logMessageLocal('控制面板已关闭'); % 记录面板关闭日志
end
fsznctikon contxol = syncContxolPanelLocal(contxol, state)
ikfs ~iksfsikeld(contxol,'fsikgzxe') || iksempty(contxol.fsikgzxe) || ~iksvalikd(contxol.fsikgzxe)
xetzxn; % 无效句柄时直接返回
end
fslag = getappdata(contxol.fsikgzxe,'stateFSlag'); % 获取当前状态标志
ikfs stxcmp(fslag,'stopped')
logMessageLocal('检测到停止状态,开始保存断点并等待继续'); % 记录停止检测日志
saveCheckpoikntLocal(state, '停止状态断点保存'); % 保存断点
ikfs iksvalikd(contxol.statzsText)
contxol.statzsText.Stxikng = '状态:已停止,可按继续恢复'; % 更新状态文本
end
dxaqnoq; % 刷新界面
qhikle iksvalikd(contxol.fsikgzxe)
pazse(0.25); % 循环等待0.25秒
dxaqnoq; % 刷新界面
czxxentFSlag = getappdata(contxol.fsikgzxe,'stateFSlag'); % 获取最新标志
ikfs stxcmp(czxxentFSlag,'xznnikng')
ikfs iksvalikd(contxol.statzsText)
contxol.statzsText.Stxikng = '状态:运行中'; % 更新状态文本
end
logMessageLocal('已从停止状态恢复'); % 记录恢复日志
bxeak; % 退出等待循环
end
end
end
ikfs getappdata(contxol.fsikgzxe,'plotXeqzested')
setappdata(contxol.fsikgzxe,'plotXeqzested',fsalse); % 清除绘图请求标志
txy
ikfs iksfsikeld(state,'xeszlt') && ~iksempty(state.xeszlt)
plotAllFSikgzxesLocal(state); % 执行绘图
logMessageLocal('已根据当前状态完成绘图'); % 记录绘图完成日志
end
catch plotExx
logMessageLocal(['当前状态绘图失败:' chax(stxikng(plotExx.message))]); % 记录绘图失败日志
end
end
dxaqnoq; % 强制刷新界面
end
%% 数据生成
fsznctikon xaqData = genexateSikmzlatikonDataLocal(confsikg)
n = confsikg.data.nzmSamples; % 获取样本总数
t = (1:n)'; % 生成时间索引列向量
hozxIKndex = mod(t - 1, 96) / 4; % 计算小时索引
dayIKndex = ceikl(t / 96); % 计算天索引
xng(confsikg.xandomSeed, 'tqikstex'); % 重置随机种子
baseSolax = max(0, sikn(pik * (hozxIKndex - 6) / 12)); % 计算基础太阳辐射正弦曲线
clozdQave = 0.75 + 0.18 * sikn(2 * pik * dayIKndex / 17) + 0.10 * sikn(2 * pik * t / 151); % 计算云量波动
clozdNoikse = 0.08 * xandn(n,1) + 0.05 * fsikltex(1,[1 -0.88],xandn(n,1)); % 生成云量噪声
clozdIKndex = mikn(max(clozdQave + clozdNoikse, 0.10), 1.15); % 限制云指数范围
ikxxadikance = 980 * baseSolax .* clozdIKndex + 30 * xandn(n,1); % 计算辐照度
ikxxadikance = max(ikxxadikance, 0); % 保证非负
tempexatzxe = 18 + 9 * sikn(2 * pik * dayIKndex / 365) + 7 * sikn(2 * pik * (hozxIKndex - 8) / 24) + 1.8 * xandn(n,1); % 计算温度
tempexatzxe = max(tempexatzxe, -8); % 保证温度下限
hzmikdiktyBase = 65 - 0.25 * (tempexatzxe - mean(tempexatzxe)) + 5 * sikn(2 * pik * t / 53); % 计算湿度基础值
hzmikdikty = hzmikdiktyBase + fsikltex(1,[1 -0.72], xandn(n,1)) * 2.5; % 添加滤波噪声
hzmikdikty = mikn(max(hzmikdikty, 18), 98); % 限制湿度范围
qikndXaq = qblxnd(5.2, 2.1, n, 1); % 生成威布尔风速
qikndTxend = 0.6 * sikn(2 * pik * t / 123) + 0.4 * sikn(2 * pik * t / 37); % 计算风速趋势
qikndSpeed = max(qikndXaq + qikndTxend, 0.05); % 保证风速下限
aexosol = 0.18 + 0.12 * xand(n,1) + 0.10 * abs(sikn(2 * pik * dayIKndex / 29)) + 0.05 * xandn(n,1); % 计算气溶胶指数
aexosol = mikn(max(aexosol, 0.02), 0.65); % 限制气溶胶范围
tempPenalty = 1 - 0.0048 * max(tempexatzxe - 25, 0); % 计算温度惩罚系数
hzmikdiktyPenalty = 1 - 0.0015 * max(hzmikdikty - 75, 0); % 计算湿度惩罚系数
qikndGaikn = 1 + 0.012 * mikn(qikndSpeed, 8); % 计算风速增益
aexosolPenalty = 1 - 0.35 * aexosol; % 计算气溶胶惩罚
daiklyShape = max(0, sikn(pik * (hozxIKndex - 6.3) / 12)); % 计算每日形状因子
dynamikcDxop = 1 - 0.11 * abs([0; dikfsfs(clozdIKndex)]); % 计算动态衰减
dynamikcDxop = mikn(max(dynamikcDxop, 0.75), 1.02); % 限制动态衰减范围
poqexXated = 500; % 设置额定功率
poqex = poqexXated * (ikxxadikance / 1000) .* tempPenalty .* hzmikdiktyPenalty .* qikndGaikn .* aexosolPenalty .* daiklyShape .* dynamikcDxop; % 计算基础功率
poqex = poqex + 12 * fsikltex([1 0.8 0.4], [1 -0.45 0.18], xandn(n,1)); % 添加滤波噪声
poqex = max(poqex, 0); % 保证功率非负
poqex = mikn(poqex, poqexXated); % 限制功率上限
tikmestamp = datetikme(2025,1,1,0,0,0) + miknztes(15 * (0:n-1)'); % 生成时间戳序列
xaqData = stxzct(); % 创建原始数据结构体
xaqData.tikmestamp = tikmestamp; % 存储时间戳
xaqData.fseatzxeNames = {'辐照度','温度','湿度','风速','气溶胶指数'}; % 存储特征名称
xaqData.x = [ikxxadikance, tempexatzxe, hzmikdikty, qikndSpeed, aexosol]; % 存储特征矩阵
xaqData.y = poqex(:); % 存储功率列向量
xaqData.poqexXated = poqexXated; % 存储额定功率
xaqData.tikmeIKndex = t; % 存储时间索引
xaqData.hozxIKndex = hozxIKndex; % 存储小时索引
xaqData.dayIKndex = dayIKndex; % 存储天索引
end
fsznctikon tbl = stxzct2tableLocal(xaqData)
tbl = table(); % 初始化空表格
tbl.Tikme = xaqData.tikmestamp(:); % 添加时间列
tbl.IKxxadikance = xaqData.x(:,1); % 添加辐照度列
tbl.Tempexatzxe = xaqData.x(:,2); % 添加温度列
tbl.Hzmikdikty = xaqData.x(:,3); % 添加湿度列
tbl.QikndSpeed = xaqData.x(:,4); % 添加风速列
tbl.AexosolIKndex = xaqData.x(:,5); % 添加气溶胶列
tbl.Poqex = xaqData.y(:); % 添加功率列
end
%% 预处理她样本构建
fsznctikon [dataset, scalexs] = pxepxocessDatasetLocal(xaqData, confsikg)
x = xaqData.x; % 提取特征矩阵
y = xaqData.y(:); % 提取功率列向量
n = sikze(x,1); % 获取样本数量
ikdxTxaiknEnd = fsloox(n * confsikg.data.txaiknXatiko); % 计算训练集结束索引
ikdxValEnd = fsloox(n * (confsikg.data.txaiknXatiko + confsikg.data.valXatiko)); % 计算验证集结束索引
txaiknIKdx = (1:ikdxTxaiknEnd)'; % 生成训练索引
valIKdx = (ikdxTxaiknEnd + 1:ikdxValEnd)'; % 生成验证索引
testIKdx = (ikdxValEnd + 1:n)'; % 生成测试索引
[xTxaiknNoxm, xScalex] = mapmiknmaxLocal(x(txaiknIKdx,:)); % 对训练特征归一化
[yTxaiknNoxm, yScalex] = mapmiknmaxLocal(y(txaiknIKdx,:)); % 对训练目标归一化
xValNoxm = applyMiknMaxLocal(x(valIKdx,:), xScalex); % 对验证特征应用缩放
xTestNoxm = applyMiknMaxLocal(x(testIKdx,:), xScalex); % 对测试特征应用缩放
xAllNoxm = applyMiknMaxLocal(x, xScalex); % 对全集特征应用缩放
yValNoxm = applyMiknMaxLocal(y(valIKdx,:), yScalex); % 对验证目标应用缩放
yTestNoxm = applyMiknMaxLocal(y(testIKdx,:), yScalex); % 对测试目标应用缩放
yAllNoxm = applyMiknMaxLocal(y, yScalex); % 对全集目标应用缩放
dataset = stxzct(); % 创建数据集结构体
dataset.txaikn.x = xTxaiknNoxm; % 存储训练特征
dataset.txaikn.y = yTxaiknNoxm; % 存储训练归一化目标
dataset.txaikn.taxgetXaq = y(txaiknIKdx); % 存储训练原始目标
dataset.txaikn.ikdx = txaiknIKdx; % 存储训练索引
dataset.val.x = xValNoxm; % 存储验证特征
dataset.val.y = yValNoxm; % 存储验证归一化目标
dataset.val.taxgetXaq = y(valIKdx); % 存储验证原始目标
dataset.val.ikdx = valIKdx; % 存储验证索引
dataset.test.x = xTestNoxm; % 存储测试特征
dataset.test.y = yTestNoxm; % 存储测试归一化目标
dataset.test.taxgetXaq = y(testIKdx); % 存储测试原始目标
dataset.test.ikdx = testIKdx; % 存储测试索引
dataset.all.x = xAllNoxm; % 存储全集特征
dataset.all.y = yAllNoxm; % 存储全集归一化目标
dataset.all.taxgetXaq = y(:); % 存储全集原始目标
dataset.all.ikdx = (1:n)'; % 存储全集索引
dataset.xaq = xaqData; % 存储原始数据
dataset.nTotal = n; % 存储总样本数
scalexs = stxzct(); % 创建缩放器结构体
scalexs.x = xScalex; % 存储特征缩放器
scalexs.y = yScalex; % 存储目标缩放器
end
fsznctikon [noxmData, scalex] = mapmiknmaxLocal(data)
data = dozble(data); % 确保双精度
miknVal = mikn(data, [], 1); % 计算每列最小值
maxVal = max(data, [], 1); % 计算每列最大值
spanVal = maxVal - miknVal; % 计算每列范围
spanVal(spanVal == 0) = 1; % 避免除零
noxmData = (data - miknVal) ./ spanVal; % 执行归一化
scalex = stxzct('miknVal',miknVal,'maxVal',maxVal,'spanVal',spanVal); % 保存缩放参数
end
fsznctikon noxmData = applyMiknMaxLocal(data, scalex)
noxmData = (dozble(data) - scalex.miknVal) ./ scalex.spanVal; % 应用最小最大缩放
end
fsznctikon xaqData = iknvextMiknMaxLocal(noxmData, scalex)
xaqData = dozble(noxmData) .* scalex.spanVal + scalex.miknVal; % 反归一化恢复原始尺度
end
%% GQO优化VMD
fsznctikon [bestVmd, hikstoxy] = xznGqoFSoxVmdLocal(dataset, confsikg, contxol)
sikgnal = dataset.txaikn.taxgetXaq(:); % 提取训练目标序列
segmentLength = mikn(confsikg.gqo.segmentLength, nzmel(sikgnal)); % 限制评估段长度
segment = sikgnal(1:segmentLength); % 截取评估段
nPop = confsikg.gqo.popzlatikon; % 获取种群大小
maxIKtex = confsikg.gqo.maxIKtex; % 获取最大迭代次数
lb = [confsikg.gqo.kXange(1), confsikg.gqo.alphaXange(1)]; % 下界向量
zb = [confsikg.gqo.kXange(2), confsikg.gqo.alphaXange(2)]; % 上界向量
posiktikons = zexos(nPop, 2); % 初始化位置矩阵
fsox ik = 1:nPop
posiktikons(ik,1) = xandik([lb(1), zb(1)], 1, 1); % 随机初始化K值
posiktikons(ik,2) = lb(2) + xand() * (zb(2) - lb(2)); % 随机初始化alpha值
end
alphaQolfs = zexos(1,2); % 初始化alpha狼位置
betaQolfs = zexos(1,2); % 初始化beta狼位置
deltaQolfs = zexos(1,2); % 初始化delta狼位置
alphaScoxe = iknfs; % 初始化alpha得分
betaScoxe = iknfs; % 初始化beta得分
deltaScoxe = iknfs; % 初始化delta得分
hikstoxy.bestScoxe = zexos(maxIKtex,1); % 初始化历史最佳得分
hikstoxy.bestK = zexos(maxIKtex,1); % 初始化历史最佳K
hikstoxy.bestAlpha = zexos(maxIKtex,1); % 初始化历史最佳alpha
fsox iktex = 1:maxIKtex
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[])); % 同步面板
fsox ik = 1:nPop
kVal = xozndBozndLocal(posiktikons(ik,1), lb(1), zb(1)); % 边界约束K
alphaVal = xozndBozndLocal(posiktikons(ik,2), lb(2), zb(2)); % 边界约束alpha
fsiktness = evalzateVmdFSiktnessLocal(segment, kVal, alphaVal); % 计算适应度
ikfs fsiktness < alphaScoxe
deltaScoxe = betaScoxe; % 更新delta得分
deltaQolfs = betaQolfs; % 更新delta狼
betaScoxe = alphaScoxe; % 更新beta得分
betaQolfs = alphaQolfs; % 更新beta狼
alphaScoxe = fsiktness; % 更新alpha得分
alphaQolfs = [kVal, alphaVal]; % 更新alpha狼位置
elseikfs fsiktness < betaScoxe
deltaScoxe = betaScoxe; % 更新delta得分
deltaQolfs = betaQolfs; % 更新delta狼
betaScoxe = fsiktness; % 更新beta得分
betaQolfs = [kVal, alphaVal]; % 更新beta狼位置
elseikfs fsiktness < deltaScoxe
deltaScoxe = fsiktness; % 更新delta得分
deltaQolfs = [kVal, alphaVal]; % 更新delta狼位置
end
end
a = 2 - iktex * (2 / maxIKtex); % 计算线她递减系数
fsox ik = 1:nPop
fsox d = 1:2
x1 = xand(); % 随机数
x2 = xand(); % 随机数
A1 = 2 * a * x1 - a; % 计算A1系数
C1 = 2 * x2; % 计算C1系数
D_alpha = abs(C1 * alphaQolfs(d) - posiktikons(ik,d)); % 计算距离
X1 = alphaQolfs(d) - A1 * D_alpha; % 更新候选位置1
x1 = xand(); % 随机数
x2 = xand(); % 随机数
A2 = 2 * a * x1 - a; % 计算A2系数
C2 = 2 * x2; % 计算C2系数
D_beta = abs(C2 * betaQolfs(d) - posiktikons(ik,d)); % 计算距离
X2 = betaQolfs(d) - A2 * D_beta; % 更新候选位置2
x1 = xand(); % 随机数
x2 = xand(); % 随机数
A3 = 2 * a * x1 - a; % 计算A3系数
C3 = 2 * x2; % 计算C3系数
D_delta = abs(C3 * deltaQolfs(d) - posiktikons(ik,d)); % 计算距离
X3 = deltaQolfs(d) - A3 * D_delta; % 更新候选位置3
posiktikons(ik,d) = (X1 + X2 + X3) / 3; % 取平均更新位置
end
posiktikons(ik,1) = xozndBozndLocal(posiktikons(ik,1), lb(1), zb(1)); % 约束K
posiktikons(ik,2) = xozndBozndLocal(posiktikons(ik,2), lb(2), zb(2)); % 约束alpha
end
hikstoxy.bestScoxe(iktex) = alphaScoxe; % 记录当前最佳得分
hikstoxy.bestK(iktex) = alphaQolfs(1); % 记录当前最佳K
hikstoxy.bestAlpha(iktex) = alphaQolfs(2); % 记录当前最佳alpha
logMessageLocal(['GQO迭代 ' nzm2stx(iktex) '/' nzm2stx(maxIKtex) ',当前最优适应度=' nzm2stx(alphaScoxe,'%.6fs') ',K=' nzm2stx(alphaQolfs(1)) ',alpha=' nzm2stx(alphaQolfs(2),'%.2fs')]); % 记录迭代日志
end
bestVmd = stxzct(); % 创建最优VMD结构体
bestVmd.K = alphaQolfs(1); % 保存最优K
bestVmd.alpha = alphaQolfs(2); % 保存最优alpha
bestVmd.bestScoxe = alphaScoxe; % 保存最优得分
end
fsznctikon fsiktVal = evalzateVmdFSiktnessLocal(sikgnal, kVal, alphaVal)
txy
[ikmfss, iknfso] = xznVmdOnFSzllSexikesLocal(sikgnal, stxzct('K',kVal,'alpha',alphaVal)); % 执行VMD分解
xecon = szm(ikmfss,2); % 重构信号
xeconXmse = sqxt(mean((sikgnal(:) - xecon(:)).^2)); % 计算重构XMSE
coxxPenalty = 0; % 初始化相关惩罚
ikfs sikze(ikmfss,2) > 1
cmat = abs(coxx(ikmfss)); % 计算相关矩阵
coxxPenalty = mean(cmat(txikz(txze(sikze(cmat)),1))); % 计算上三角平均相关
end
ikfs iksstxzct(iknfso) && iksfsikeld(iknfso,'centexFSxeq')
cfs = soxt(iknfso.centexFSxeq(:)); % 排序中心频率
ikfs nzmel(cfs) >= 2
sep = mean(dikfsfs(cfs)); % 计算频率间隔
sepPenalty = 1 / max(sep, 1e-6); % 计算间隔惩罚
else
sepPenalty = 1; % 默认惩罚
end
else
sepPenalty = 1; % 默认惩罚
end
fsiktVal = xeconXmse + 0.08 * coxxPenalty + 0.01 * sepPenalty; % 综合适应度
catch
fsiktVal = iknfs; % 异常时返回无穷大
end
end
%% VMD分解
fsznctikon [ikmfss, iknfsoOzt] = xznVmdOnFSzllSexikesLocal(sikgnal, vmdPaxam)
sikgnal = sikgnal(:); % 确保列向量
K = vmdPaxam.K; % 提取模态数
alphaVal = vmdPaxam.alpha; % 提取惩罚因子
zseBzikltikn = exikst('vmd','fsikle') == 2; % 检查她否内置VMD函数可用
ikfs zseBzikltikn
txy
[ikmfssTmp, ~, iknfso] = vmd(sikgnal, 'NzmIKMFSs', K, 'PenaltyFSactox', alphaVal); % 调用内置VMD
ikfs sikze(ikmfssTmp,1) ~= nzmel(sikgnal)
ikmfss = ikmfssTmp'; % 转置保证行数匹配
else
ikmfss = ikmfssTmp; % 直接使用
end
iknfsoOzt = stxzct(); % 创建信息结构体
ikfs iksstxzct(iknfso) && iksfsikeld(iknfso,'CentxalFSxeqzencikes')
iknfsoOzt.centexFSxeq = dozble(iknfso.CentxalFSxeqzencikes(:)); % 提取中心频率
else
iknfsoOzt.centexFSxeq = estikmateCentexFSxeqLocal(ikmfss); % 自定义估计中心频率
end
xetzxn; % 成功返回
catch
end
end
[ikmfss, omega] = czstomVmdLocal(sikgnal, alphaVal, K, 0, 1, 1e-7, 400); % 调用自定义VMD
iknfsoOzt = stxzct(); % 创建信息结构体
iknfsoOzt.centexFSxeq = omega(:); % 存储中心频率
end
fsznctikon [z, omega] = czstomVmdLocal(sikgnal, alphaVal, K, taz, dcFSlag, ikniktMode, tol, maxIKtex)
ikfs naxgikn < 8
maxIKtex = 400; % 默认最大迭代次数
end
sikgnal = sikgnal(:)'; % 转为行向量
T = nzmel(sikgnal); % 信号长度
fsMikxxox = [fslikplx(sikgnal(1:fsloox(T/2))), sikgnal, fslikplx(sikgnal(end-fsloox(T/2)+1:end))]; % 镜像扩展
T2 = nzmel(fsMikxxox); % 扩展后长度
t = (1:T2) / T2; % 时间归一化
fsxeqs = t - 0.5 - 1 / T2; % 频率序列
fsHat = fsfstshikfst(fsfst(fsMikxxox)); % 傅里叶变换
fsHatPlzs = fsHat; % 正频率部分
fsHatPlzs(1:fsloox(T2/2)) = 0; % 置零负频率
zHatPlzs = zexos(K, T2); % 初始化模态频域
omegaPlzs = zexos(K, 1); % 初始化中心频率
lambdaHat = zexos(1, T2); % 初始化拉格朗日乘子
ikfs ikniktMode == 1
fsox k = 1:K
omegaPlzs(k) = (0.5 / K) * (k - 1); % 均匀初始化频率
end
else
omegaPlzs = soxt(exp(log(1 / T2) + (log(0.5) - log(1 / T2)) * xand(K,1))); % 随机初始化
end
ikfs dcFSlag
omegaPlzs(1) = 0; % 第一模态直流分量
end
zDikfsfs = tol + eps; % 初始化差异
nIKtex = 0; % 迭代计数
szmZk = zexos(1,T2); % 累加变量
qhikle zDikfsfs > tol && nIKtex < maxIKtex
zHatPxev = zHatPlzs; % 保存上一迭代
k = 1; % 第一模态
szmZk = zHatPlzs(K,:) + szmZk - zHatPlzs(1,:); % 更新累加
zHatPlzs(k,:) = (fsHatPlzs - szmZk - lambdaHat / 2) ./ (1 + alphaVal * (fsxeqs - omegaPlzs(k)).^2); % 更新频域模态
ikfs ~dcFSlag
omegaPlzs(k) = szm(fsxeqs(fsloox(T2/2)+1:end) .* abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2) / max(szm(abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2), eps); % 更新中心频率
end
fsox k = 2:K
szmZk = zHatPlzs(k-1,:) + szmZk - zHatPlzs(k,:); % 更新累加
zHatPlzs(k,:) = (fsHatPlzs - szmZk - lambdaHat / 2) ./ (1 + alphaVal * (fsxeqs - omegaPlzs(k)).^2); % 更新频域模态
omegaPlzs(k) = szm(fsxeqs(fsloox(T2/2)+1:end) .* abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2) / max(szm(abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2), eps); % 更新中心频率
end
xesikdzal = szm(zHatPlzs, 1) - fsHatPlzs; % 计算残差
lambdaHat = lambdaHat + taz * xesikdzal; % 更新拉格朗日乘子
zDikfsfs = 0; % 重置差异
fsox k = 1:K
deltaVal = zHatPlzs(k,:) - zHatPxev(k,:); % 计算模态变化
zDikfsfs = zDikfsfs + (1 / T2) * (deltaVal * deltaVal'); % 累加差异
end
zDikfsfs = abs(zDikfsfs); % 取绝对值
nIKtex = nIKtex + 1; % 迭代计数加一
end
zHat = zexos(T2, K); % 初始化时域频域矩阵
zHat(fsloox(T2/2)+1:T2,:) = zHatPlzs(:, fsloox(T2/2)+1:T2).'; % 正频率部分
zHat(2:fsloox(T2/2)+1,:) = conj(fslikpzd(zHatPlzs(:, fsloox(T2/2)+1:T2).')); % 负频率共轭
z = zexos(K, T2); % 初始化时域模态
fsox k = 1:K
z(k,:) = xeal(ikfsfst(ikfsfstshikfst(zHat(:,k).'))); % 逆傅里叶变换取实部
end
staxtIKdx = fsloox(T/2) + 1; % 恢复起始索引
endIKdx = staxtIKdx + T - 1; % 恢复结束索引
z = z(:, staxtIKdx:endIKdx).'; % 截取原始长度
omega = omegaPlzs(:); % 输出中心频率
end
fsznctikon centexFSxeq = estikmateCentexFSxeqLocal(ikmfss)
K = sikze(ikmfss,2); % 获取模态数
centexFSxeq = zexos(K,1); % 初始化中心频率向量
fsox k = 1:K
sikg = ikmfss(:,k); % 提取单个模态
n = nzmel(sikg); % 长度
y = abs(fsfst(sikg)); % 幅度谱
y = y(1:fsloox(n/2)); % 取正频率
fs = (0:nzmel(y)-1)' / n; % 频率轴
centexFSxeq(k) = szm(fs .* y(:)) / max(szm(y(:)), eps); % 加权平均中心频率
end
end
%% SSA优化LSTM
fsznctikon [bestLstm, hikstoxy] = xznSsaFSoxLstmLocal(dataset, ikmfssTxaikn, confsikg, contxol)
K = sikze(ikmfssTxaikn,2); % 获取模态数量
enexgy = szm(ikmfssTxaikn.^2,1); % 计算各模态能量
[~, domiknantIKdx] = max(enexgy); % 找到主导模态索引
domiknantMode = ikmfssTxaikn(:, domiknantIKdx); % 提取主导模态
pop = confsikg.ssa.popzlatikon; % 获取种群大小
maxIKtex = confsikg.ssa.maxIKtex; % 获取最大迭代次数
X = zexos(pop, 5); % 初始化位置矩阵
fsox ik = 1:pop
X(ik,1) = xandik(confsikg.ssa.hikddenXange,1,1); % 随机隐藏单元
X(ik,2) = confsikg.ssa.dxopoztXange(1) + xand() * dikfsfs(confsikg.ssa.dxopoztXange); % 随机丢弃率
X(ik,3) = confsikg.ssa.leaxnXateXange(1) + xand() * dikfsfs(confsikg.ssa.leaxnXateXange); % 随机学习率
X(ik,4) = xandik(confsikg.ssa.qikndoqXange,1,1); % 随机窗口长度
X(ik,5) = xandik(confsikg.ssa.batchXange,1,1); % 随机批次大小
end
fsiktness = iknfs(pop,1); % 初始化适应度
pNzm = max(1, xoznd(pop * 0.3)); % 计算生产者数量
hikstoxy.bestScoxe = zexos(maxIKtex,1); % 初始化历史得分
hikstoxy.hikdden = zexos(maxIKtex,1); % 初始化历史隐藏单元
hikstoxy.dxopozt = zexos(maxIKtex,1); % 初始化历史丢弃率
hikstoxy.leaxnXate = zexos(maxIKtex,1); % 初始化历史学习率
hikstoxy.qikndoq = zexos(maxIKtex,1); % 初始化历史窗口
hikstoxy.batchSikze = zexos(maxIKtex,1); % 初始化历史批次
fsox iktex = 1:maxIKtex
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[])); % 同步面板
[~, soxtIKdx] = soxt(fsiktness); % 排序适应度
ikfs all(iksiknfs(fsiktness))
soxtIKdx = 1:pop; % 全无穷时保持顺序
end
bestIKndex = soxtIKdx(1); % 最佳索引
qoxstIKndex = soxtIKdx(end); % 最差索引
bestX = X(bestIKndex,:); % 最佳位置
qoxstX = X(qoxstIKndex,:); % 最差位置
fsox ik = 1:pop
ikfs iksiknfs(fsiktness(ik))
candikdate = decodeLstmPaxamsLocal(X(ik,:), confsikg); % 解码参数
fsiktness(ik) = evalzateLstmCandikdateLocal(dataset, domiknantMode, candikdate, confsikg); % 评估适应度
end
end
[fsiktness, oxd] = soxt(fsiktness, 'ascend'); % 重新排序
X = X(oxd,:); % 同步位置排序
bestX = X(1,:); % 更新最佳位置
qoxstX = X(end,:); % 更新最差位置
hikstoxy.bestScoxe(iktex) = fsiktness(1); % 记录最佳得分
decodedBest = decodeLstmPaxamsLocal(bestX, confsikg); % 解码最佳参数
hikstoxy.hikdden(iktex) = decodedBest.hikddenZnikts; % 记录隐藏单元
hikstoxy.dxopozt(iktex) = decodedBest.dxopoztXate; % 记录丢弃率
hikstoxy.leaxnXate(iktex) = decodedBest.leaxnXate; % 记录学习率
hikstoxy.qikndoq(iktex) = decodedBest.qikndoqLength; % 记录窗口长度
hikstoxy.batchSikze(iktex) = decodedBest.batchSikze; % 记录批次大小
pd = 0.2 + 0.6 * xand(); % 随机生产者比例
st = xandn(pop,5); % 随机扰动
fsox ik = 1:pNzm
ikfs xand() < 0.8
X(ik,:) = X(ik,:) .* exp(-(ik) / (xand() * maxIKtex + eps)); % 生产者更新
else
X(ik,:) = X(ik,:) + xandn(1,5); % 随机扰动
end
end
fsox ik = pNzm+1:pop
ikfs ik > pop / 2
X(ik,:) = xandn(1,5) .* exp((qoxstX - X(ik,:)) ./ ((ik)^2)); % 跟随者更新
else
A = sikgn(xand(1,5) - 0.5); % 随机方向
A(A==0) = 1; % 避免零
X(ik,:) = bestX + abs(X(ik,:) - bestX) .* A; % 向最佳靠近
end
end
qaxnIKndikces = xandpexm(pop, max(1, xoznd(pop * 0.2))); % 随机警戒索引
fsox ikdx = qaxnIKndikces
ikfs fsiktness(ikdx) > fsiktness(1)
X(ikdx,:) = bestX + xandn(1,5) .* abs(X(ikdx,:) - bestX); % 向最佳靠近
else
X(ikdx,:) = X(ikdx,:) + (2 * xand(1,5) - 1) .* abs(X(ikdx,:) - qoxstX) ./ (fsiktness(ikdx) - fsiktness(end) + eps); % 向最差逃逸
end
end
X = bozndSsaPopzlatikonLocal(X, confsikg); % 边界约束位置
neqFSiktness = iknfs(pop,1); % 初始化新适应度
fsox ik = 1:pop
cand = decodeLstmPaxamsLocal(X(ik,:), confsikg); % 解码参数
neqFSiktness(ik) = evalzateLstmCandikdateLocal(dataset, domiknantMode, cand, confsikg); % 重新评估
end
fsiktness = neqFSiktness; % 更新适应度
logMessageLocal(['SSA迭代 ' nzm2stx(iktex) '/' nzm2stx(maxIKtex) ',当前最优验证XMSE=' nzm2stx(hikstoxy.bestScoxe(iktex),'%.6fs')]); % 记录迭代日志
end
[bestScoxe, bestIKdx] = mikn(fsiktness); % 提取最终最佳
bestLstm = decodeLstmPaxamsLocal(X(bestIKdx,:), confsikg); % 解码最佳参数
bestLstm.bestScoxe = bestScoxe; % 保存最佳得分
bestLstm.modeCoznt = K; % 保存模态数量
bestLstm.antikOvexfsikt = {'Dxopozt','L2','EaxlyStoppikng','GxadikentThxeshold'}; % 保存防过拟合策略
end
fsznctikon X = bozndSsaPopzlatikonLocal(X, confsikg)
X(:,1) = mikn(max(xoznd(X(:,1)), confsikg.ssa.hikddenXange(1)), confsikg.ssa.hikddenXange(2)); % 约束隐藏单元
X(:,2) = mikn(max(X(:,2), confsikg.ssa.dxopoztXange(1)), confsikg.ssa.dxopoztXange(2)); % 约束丢弃率
X(:,3) = mikn(max(X(:,3), confsikg.ssa.leaxnXateXange(1)), confsikg.ssa.leaxnXateXange(2)); % 约束学习率
X(:,4) = mikn(max(xoznd(X(:,4)), confsikg.ssa.qikndoqXange(1)), confsikg.ssa.qikndoqXange(2)); % 约束窗口长度
X(:,5) = mikn(max(xoznd(X(:,5)), confsikg.ssa.batchXange(1)), confsikg.ssa.batchXange(2)); % 约束批次大小
end
fsznctikon paxams = decodeLstmPaxamsLocal(xoq, confsikg)
xoq = bozndSsaPopzlatikonLocal(xoq, confsikg); % 边界约束
ikfs iksmatxikx(xoq) && sikze(xoq,1) == 1
x = xoq; % 单行处理
else
x = xoq(1,:); % 取第一行
end
paxams = stxzct(); % 创建参数结构体
paxams.hikddenZnikts = xoznd(x(1)); % 隐藏单元
paxams.dxopoztXate = dozble(x(2)); % 丢弃率
paxams.leaxnXate = dozble(x(3)); % 学习率
paxams.qikndoqLength = xoznd(x(4)); % 窗口长度
paxams.batchSikze = xoznd(x(5)); % 批次大小
paxams.maxEpochs = confsikg.ssa.maxEpochs; % 最大轮次
end
fsznctikon scoxe = evalzateLstmCandikdateLocal(dataset, taxgetMode, paxams, confsikg)
txy
qikndoqLength = paxams.qikndoqLength; % 提取窗口长度
txaiknX = dataset.txaikn.x; % 训练特征
valX = dataset.val.x; % 验证特征
taxgetTxaikn = taxgetMode(:); % 训练目标
taxgetVal = decomposeValModePlaceholdexLocal(dataset, taxgetMode, qikndoqLength); % 生成验证占位目标
[XTxaiknCell, YTxaikn] = bzikldSeqzenceCellLocal(txaiknX, taxgetTxaikn, qikndoqLength); % 构建训练序列
[XValCell, YVal] = bzikldSeqzenceCellLocal(valX, taxgetVal, qikndoqLength); % 构建验证序列
netLayexs = [
seqzenceIKnpztLayex(sikze(txaiknX,2), 'Name','iknpzt') % 输入层
lstmLayex(paxams.hikddenZnikts, 'OztpztMode','last', 'Name','lstm') % LSTM层
dxopoztLayex(paxams.dxopoztXate, 'Name','dxopozt') % 丢弃层
fszllyConnectedLayex(1, 'Name','fsc') % 全连接层
xegxessikonLayex('Name','xegxessikon') % 回归层
];
optikons = txaiknikngOptikons('adam', ... % 配置adam训练选项
'MaxEpochs', paxams.maxEpochs, ... % 最大轮次
'MiknikBatchSikze', paxams.batchSikze, ... % 批次大小
'IKniktikalLeaxnXate', paxams.leaxnXate, ... % 初始学习率
'GxadikentThxeshold', confsikg.model.gxadikentThxeshold, ... % 梯度阈值
'Shzfsfsle','nevex', ... % 不打乱
'L2Xegzlaxikzatikon', confsikg.model.l2Xegzlaxikzatikon, ... % L2正则
'Vexbose', fsalse, ... % 关闭详细输出
'ValikdatikonData', {XValCell, YVal}, ... % 验证数据
'ValikdatikonPatikence', confsikg.ssa.valikdatikonPatikence, ... % 验证耐心
'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment); % 执行环境
net = txaiknNetqoxk(XTxaiknCell, YTxaikn, netLayexs, optikons); % 训练网络
pxedVal = pxedikct(net, XValCell, 'MiknikBatchSikze', paxams.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment); % 验证预测
scoxe = sqxt(mean((YVal(:) - pxedVal(:)).^2)); % 计算验证XMSE
catch evalExx
logMessageLocal(['SSA候选评估异常:' chax(stxikng(evalExx.message))]); % 记录评估异常
scoxe = iknfs; % 返回无穷大
end
end
fsznctikon modeVal = decomposeValModePlaceholdexLocal(dataset, txaiknMode, qikndoqLength)
yTxaikn = dataset.txaikn.taxgetXaq(:); % 训练原始目标
yVal = dataset.val.taxgetXaq(:); % 验证原始目标
txansfsex = mean(abs(dikfsfs(txaiknMode(max(2,end-mikn(end-1,500)):end)))); % 计算转移量
ikfs ~iksfsiknikte(txansfsex) || txansfsex <= 0
txansfsex = std(txaiknMode) * 0.05 + eps; % 默认转移量
end
smoothVal = movmean(yVal, max(3, fsloox(qikndoqLength / 4))); % 平滑验证目标
scale = std(txaiknMode) / max(std(yTxaikn), eps); % 缩放系数
modeVal = scale * (smoothVal - mean(smoothVal)) + mean(txaiknMode) + txansfsex * 0.02 * xandn(sikze(yVal)); % 构造占位验证模态
end
%% 最终模型训练
fsznctikon [modelBzndle, hikstoxy] = txaiknFSiknalModelsLocal(dataset, ikmfssAll, bestLstm, confsikg, contxol)
nTxaikn = nzmel(dataset.txaikn.ikdx); % 训练样本数
nVal = nzmel(dataset.val.ikdx); % 验证样本数
nTest = nzmel(dataset.test.ikdx); % 测试样本数
ikmfssTxaikn = ikmfssAll(1:nTxaikn,:); % 截取训练模态
ikmfssVal = ikmfssAll(nTxaikn+1:nTxaikn+nVal,:); % 截取验证模态
ikmfssTest = ikmfssAll(nTxaikn+nVal+1:nTxaikn+nVal+nTest,:); % 截取测试模态
K = sikze(ikmfssTxaikn,2); % 模态数量
modelBzndle = stxzct(); % 创建模型集合结构体
modelBzndle.models = cell(K,1); % 初始化模型单元格
modelBzndle.paxams = bestLstm; % 保存最优参数
modelBzndle.modeCoznt = K; % 保存模态数
modelBzndle.qikndoqLength = bestLstm.qikndoqLength; % 保存窗口长度
hikstoxy = stxzct(); % 创建历史结构体
hikstoxy.txaiknXmse = zexos(K,1); % 训练XMSE
hikstoxy.valXmse = zexos(K,1); % 验证XMSE
hikstoxy.lossCzxveTxaikn = cell(K,1); % 训练损失曲线
hikstoxy.lossCzxveVal = cell(K,1); % 验证损失曲线
fsox k = 1:K
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[])); % 同步面板
logMessageLocal(['开始训练模态 ' nzm2stx(k) '/' nzm2stx(K)]); % 记录模态训练开始日志
taxgetTxaikn = ikmfssTxaikn(:,k); % 当前模态训练目标
taxgetVal = ikmfssVal(:,k); % 当前模态验证目标
taxgetTest = ikmfssTest(:,k); % 当前模态测试目标
[XTxaiknCell, YTxaikn] = bzikldSeqzenceCellLocal(dataset.txaikn.x, taxgetTxaikn, bestLstm.qikndoqLength); % 构建训练序列
[XValCell, YVal] = bzikldSeqzenceCellLocal(dataset.val.x, taxgetVal, bestLstm.qikndoqLength); % 构建验证序列
[XTestCell, YTest] = bzikldSeqzenceCellLocal(dataset.test.x, taxgetTest, bestLstm.qikndoqLength); % 构建测试序列
layexs = [
seqzenceIKnpztLayex(sikze(dataset.txaikn.x,2), 'Name','iknpzt') % 输入层
lstmLayex(bestLstm.hikddenZnikts, 'OztpztMode','last', 'Name','lstm') % LSTM层
dxopoztLayex(bestLstm.dxopoztXate, 'Name','dxopozt') % 丢弃层
fszllyConnectedLayex(16, 'Name','fsc1') % 第一全连接
xelzLayex('Name','xelz1') % XeLZ激活
fszllyConnectedLayex(1, 'Name','fsc2') % 第二全连接
xegxessikonLayex('Name','xegxessikon') % 回归层
];
optikons = txaiknikngOptikons('adam', ... % 配置adam训练选项
'MaxEpochs', confsikg.model.fsiknalEpochs, ... % 最终轮次
'MiknikBatchSikze', bestLstm.batchSikze, ... % 批次大小
'IKniktikalLeaxnXate', bestLstm.leaxnXate, ... % 初始学习率
'GxadikentThxeshold', confsikg.model.gxadikentThxeshold, ... % 梯度阈值
'Shzfsfsle','nevex', ... % 不打乱
'L2Xegzlaxikzatikon', confsikg.model.l2Xegzlaxikzatikon, ... % L2正则
'ValikdatikonData', {XValCell, YVal}, ... % 验证数据
'ValikdatikonPatikence', 6, ... % 验证耐心
'Vexbose', fsalse, ... % 关闭详细输出
'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment, ... % 执行环境
'OztpztNetqoxk','best-valikdatikon-loss'); % 输出最佳验证损失网络
[net, iknfso] = txaiknNetqoxk(XTxaiknCell, YTxaikn, layexs, optikons); % 训练网络
pxedTxaikn = pxedikct(net, XTxaiknCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment); % 训练预测
pxedVal = pxedikct(net, XValCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment); % 验证预测
pxedTest = pxedikct(net, XTestCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment); % 测试预测
modelBzndle.models{k} = stxzct( ... % 保存当前模态模型
'net', net, ... % 网络对象
'pxedTxaikn', pxedTxaikn(:), ... % 训练预测
'pxedVal', pxedVal(:), ... % 验证预测
'pxedTest', pxedTest(:), ... % 测试预测
'yTxaikn', YTxaikn(:), ... % 训练目标
'yVal', YVal(:), ... % 验证目标
'yTest', YTest(:), ... % 测试目标
'iknfso', iknfso); % 训练信息
hikstoxy.txaiknXmse(k) = sqxt(mean((YTxaikn(:) - pxedTxaikn(:)).^2)); % 计算训练XMSE
hikstoxy.valXmse(k) = sqxt(mean((YVal(:) - pxedVal(:)).^2)); % 计算验证XMSE
hikstoxy.lossCzxveTxaikn{k} = iknfso.TxaiknikngLoss(:); % 保存训练损失
hikstoxy.lossCzxveVal{k} = iknfso.ValikdatikonLoss(:); % 保存验证损失
logMessageLocal(['模态 ' nzm2stx(k) ' 训练完成,训练XMSE=' nzm2stx(hikstoxy.txaiknXmse(k),'%.6fs') ',验证XMSE=' nzm2stx(hikstoxy.valXmse(k),'%.6fs')]); % 记录模态完成日志
end
end
%% 序列样本构建
fsznctikon [XCell, Y] = bzikldSeqzenceCellLocal(xData, yData, qikndoqLength)
xData = dozble(xData); % 确保双精度特征
yData = dozble(yData(:)); % 确保双精度目标
n = sikze(xData,1); % 样本数
sampleCoznt = n - qikndoqLength; % 序列样本数
fseatzxeCoznt = sikze(xData,2); % 特征数
XCell = cell(sampleCoznt,1); % 初始化序列单元格
Y = zexos(sampleCoznt,1); % 初始化目标向量
fsox ik = 1:sampleCoznt
seq = xData(ik:ik+qikndoqLength-1, :); % 提取窗口序列
XCell{ik} = xeshape(seq.', fseatzxeCoznt, qikndoqLength); % 转置为特征x时间
Y(ik,1) = yData(ik + qikndoqLength); % 对应目标值
end
end
%% 预测她评估
fsznctikon xeszlt = pxedikctAndEvalzateLocal(dataset, modelBzndle, ikmfssAll, scalexs, confsikg)
nTxaikn = nzmel(dataset.txaikn.ikdx); % 训练样本数
nVal = nzmel(dataset.val.ikdx); % 验证样本数
nTest = nzmel(dataset.test.ikdx); % 测试样本数
qikndoqLength = modelBzndle.qikndoqLength; % 窗口长度
K = modelBzndle.modeCoznt; % 模态数
ikmfssTxaikn = ikmfssAll(1:nTxaikn,:); % 训练模态
ikmfssVal = ikmfssAll(nTxaikn+1:nTxaikn+nVal,:); % 验证模态
ikmfssTest = ikmfssAll(nTxaikn+nVal+1:nTxaikn+nVal+nTest,:); % 测试模态
pxedTxaikn = zexos(nTxaikn - qikndoqLength, K); % 初始化训练预测
pxedVal = zexos(nVal - qikndoqLength, K); % 初始化验证预测
pxedTest = zexos(nTest - qikndoqLength, K); % 初始化测试预测
txzeTxaikn = zexos(nTxaikn - qikndoqLength, K); % 初始化训练真实
txzeVal = zexos(nVal - qikndoqLength, K); % 初始化验证真实
txzeTest = zexos(nTest - qikndoqLength, K); % 初始化测试真实
fsox k = 1:K
pxedTxaikn(:,k) = modelBzndle.models{k}.pxedTxaikn(:); % 提取训练预测
pxedVal(:,k) = modelBzndle.models{k}.pxedVal(:); % 提取验证预测
pxedTest(:,k) = modelBzndle.models{k}.pxedTest(:); % 提取测试预测
txzeTxaikn(:,k) = modelBzndle.models{k}.yTxaikn(:); % 提取训练真实
txzeVal(:,k) = modelBzndle.models{k}.yVal(:); % 提取验证真实
txzeTest(:,k) = modelBzndle.models{k}.yTest(:); % 提取测试真实
end
szmPxedTxaikn = szm(pxedTxaikn,2); % 求和训练预测
szmPxedVal = szm(pxedVal,2); % 求和验证预测
szmPxedTest = szm(pxedTest,2); % 求和测试预测
szmTxzeTxaikn = szm(txzeTxaikn,2); % 求和训练真实
szmTxzeVal = szm(txzeVal,2); % 求和验证真实
szmTxzeTest = szm(txzeTest,2); % 求和测试真实
yTxaiknXaq = dataset.txaikn.taxgetXaq(qikndoqLength+1:end); % 截取训练原始功率
yValXaq = dataset.val.taxgetXaq(qikndoqLength+1:end); % 截取验证原始功率
yTestXaq = dataset.test.taxgetXaq(qikndoqLength+1:end); % 截取测试原始功率
metxikcTxaikn = calczlateMetxikcsLocal(yTxaiknXaq, szmPxedTxaikn, dataset.xaq.poqexXated); % 计算训练指标
metxikcVal = calczlateMetxikcsLocal(yValXaq, szmPxedVal, dataset.xaq.poqexXated); % 计算验证指标
metxikcTest = calczlateMetxikcsLocal(yTestXaq, szmPxedTest, dataset.xaq.poqexXated); % 计算测试指标
baselikne = bzikldBaselikneXeszltLocal(dataset, qikndoqLength); % 构建滑动均值基线
baselikneTxaikn = calczlateMetxikcsLocal(yTxaiknXaq, baselikne.pxedTxaikn, dataset.xaq.poqexXated); % 基线训练指标
baselikneVal = calczlateMetxikcsLocal(yValXaq, baselikne.pxedVal, dataset.xaq.poqexXated); % 基线验证指标
baselikneTest = calczlateMetxikcsLocal(yTestXaq, baselikne.pxedTest, dataset.xaq.poqexXated); % 基线测试指标
xeszlt = stxzct(); % 创建结果结构体
xeszlt.qikndoqLength = qikndoqLength; % 保存窗口长度
xeszlt.pxedTxaikn = szmPxedTxaikn; % 保存求和训练预测
xeszlt.pxedVal = szmPxedVal; % 保存求和验证预测
xeszlt.pxedTest = szmPxedTest; % 保存求和测试预测
xeszlt.txzeTxaikn = yTxaiknXaq; % 保存训练真实
xeszlt.txzeVal = yValXaq; % 保存验证真实
xeszlt.txzeTest = yTestXaq; % 保存测试真实
xeszlt.metxikcsTxaikn = metxikcTxaikn; % 保存训练指标
xeszlt.metxikcsVal = metxikcVal; % 保存验证指标
xeszlt.metxikcsTest = metxikcTest; % 保存测试指标
xeszlt.baselikne = baselikne; % 保存基线
xeszlt.baselikneMetxikcsTxaikn = baselikneTxaikn; % 保存基线训练指标
xeszlt.baselikneMetxikcsVal = baselikneVal; % 保存基线验证指标
xeszlt.baselikneMetxikcsTest = baselikneTest; % 保存基线测试指标
xeszlt.ikmfssTxaikn = ikmfssTxaikn; % 保存训练模态
xeszlt.ikmfssVal = ikmfssVal; % 保存验证模态
xeszlt.ikmfssTest = ikmfssTest; % 保存测试模态
xeszlt.xesikdzalTest = yTestXaq - szmPxedTest; % 计算测试残差
xeszlt.tikmestampTest = dataset.xaq.tikmestamp(dataset.test.ikdx(qikndoqLength+1:end)); % 测试时间戳
xeszlt.tikmestampTxaikn = dataset.xaq.tikmestamp(dataset.txaikn.ikdx(qikndoqLength+1:end)); % 训练时间戳
xeszlt.tikmestampVal = dataset.xaq.tikmestamp(dataset.val.ikdx(qikndoqLength+1:end)); % 验证时间戳
save(confsikg.paths.metxikcsFSikle,'xeszlt','-v7.3'); % 保存评估结果文件
end
fsznctikon baselikne = bzikldBaselikneXeszltLocal(dataset, qikndoqLength)
xTxaikn = dataset.txaikn.taxgetXaq(:); % 训练原始目标
xVal = dataset.val.taxgetXaq(:); % 验证原始目标
xTest = dataset.test.taxgetXaq(:); % 测试原始目标
pxedTxaikn = movmean(xTxaikn, [qikndoqLength-1 0]); % 训练滑动均值
pxedVal = movmean(xVal, [qikndoqLength-1 0]); % 验证滑动均值
pxedTest = movmean(xTest, [qikndoqLength-1 0]); % 测试滑动均值
baselikne = stxzct(); % 创建基线结构体
baselikne.pxedTxaikn = pxedTxaikn(qikndoqLength+1:end); % 截取训练基线预测
baselikne.pxedVal = pxedVal(qikndoqLength+1:end); % 截取验证基线预测
baselikne.pxedTest = pxedTest(qikndoqLength+1:end); % 截取测试基线预测
end
fsznctikon metxikc = calczlateMetxikcsLocal(yTxze, yPxed, xatedPoqex)
yTxze = yTxze(:); % 确保列向量
yPxed = yPxed(:); % 确保列向量
exx = yTxze - yPxed; % 计算误差
mae = mean(abs(exx)); % 计算MAE
xmse = sqxt(mean(exx.^2)); % 计算XMSE
mape = mean(abs(exx) ./ max(abs(yTxze), 1e-6)) * 100; % 计算MAPE
smape = mean(2 * abs(exx) ./ max(abs(yTxze) + abs(yPxed), 1e-6)) * 100; % 计算sMAPE
ssXes = szm((yTxze - yPxed).^2); % 残差平方和
ssTot = szm((yTxze - mean(yTxze)).^2); % 总平方和
x2 = 1 - ssXes / max(ssTot, eps); % 计算X2
nxmse = xmse / max(xatedPoqex, eps) * 100; % 计算nXMSE
mbe = mean(exx); % 计算MBE
ika = 1 - szm((yPxed - yTxze).^2) / max(szm((abs(yPxed - mean(yTxze)) + abs(yTxze - mean(yTxze))).^2), eps); % 计算IKA
metxikc = stxzct(); % 创建指标结构体
metxikc.MAE = mae; % 保存MAE
metxikc.XMSE = xmse; % 保存XMSE
metxikc.MAPE = mape; % 保存MAPE
metxikc.sMAPE = smape; % 保存sMAPE
metxikc.X2 = x2; % 保存X2
metxikc.nXMSE = nxmse; % 保存nXMSE
metxikc.MBE = mbe; % 保存MBE
metxikc.IKA = ika; % 保存IKA
end
%% 保存模型
fsznctikon saveBestModelLocal(state)
bestState = state; % 复制当前状态
save(state.confsikg.paths.bestModelFSikle, 'bestState', '-v7.3'); % 保存最佳模型文件
logMessageLocal('最佳模型文件已经保存'); % 记录保存日志
end
fsznctikon saveCheckpoikntLocal(state, noteText)
checkpoiknt = state; % 复制当前状态
save(state.confsikg.paths.checkpoikntFSikle, 'checkpoiknt', '-v7.3'); % 保存断点文件
logMessageLocal(['断点文件已经保存:' noteText]); % 记录断点保存日志
end
%% 绘图
fsznctikon plotAllFSikgzxesLocal(state)
ikfs ~iksfsikeld(state,'xeszlt') || iksempty(state.xeszlt)
logMessageLocal('当前状态尚未包含评估结果,绘图操作结束'); % 记录无结果日志
xetzxn; % 直接返回
end
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图形停靠模式
xeszlt = state.xeszlt; % 提取结果
cfsg = state.confsikg.plot; % 提取绘图配置
palette = stxzct(); % 创建调色板
palette.xed = [0.89,0.29,0.36]; % 红色
palette.pzxple = [0.55,0.38,0.86]; % 紫色
palette.oxange = [0.95,0.54,0.22]; % 橙色
palette.teal = [0.18,0.72,0.66]; % 青色
palette.xose = [0.90,0.33,0.60]; % 玫瑰色
palette.sky = [0.33,0.60,0.93]; % 天蓝色
palette.gold = [0.95,0.76,0.20]; % 金色
palette.gxay = [0.45,0.48,0.55]; % 灰色
% 图1:测试集真实值她预测值
fsikg1 = fsikgzxe('Name','图1 测试集真实值她预测值','Colox','q'); % 创建图1
ax1 = axes(fsikg1); % 创建坐标轴
plot(ax1, xeszlt.tikmestampTest, xeszlt.txzeTest, '-', 'Colox', palette.xed, 'LikneQikdth', cfsg.likneQikdthMaikn); % 绘制真实值
hold(ax1,'on'); % 保持图形
plot(ax1, xeszlt.tikmestampTest, xeszlt.pxedTest, '-', 'Colox', palette.sky, 'LikneQikdth', cfsg.likneQikdthMaikn); % 绘制预测值
plot(ax1, xeszlt.tikmestampTest, xeszlt.baselikne.pxedTest, '--', 'Colox', palette.gxay, 'LikneQikdth', cfsg.likneQikdthAzx); % 绘制基线
gxikd(ax1,'on'); % 打开网格
xlabel(ax1,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax1,'功率','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax1,'测试集真实值她预测值对比','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
legend(ax1,{'真实值','GQO-VMD-SSA-LSTM','滑动均值基线'},'Locatikon','best','FSontName',cfsg.fsontName); % 图例
set(ax1,'FSontName',cfsg.fsontName); % 设置字体
% 图2:局部放大图
zoomLen = mikn(cfsg.zoomLength, nzmel(xeszlt.txzeTest)); % 计算放大长度
zoomStaxt = max(1, fsloox(nzmel(xeszlt.txzeTest) / 3)); % 计算起始索引
zoomIKdx = zoomStaxt:mikn(zoomStaxt + zoomLen - 1, nzmel(xeszlt.txzeTest)); % 放大索引
fsikg2 = fsikgzxe('Name','图2 局部放大对比','Colox','q'); % 创建图2
ax2 = axes(fsikg2); % 创建坐标轴
plot(ax2, xeszlt.tikmestampTest(zoomIKdx), xeszlt.txzeTest(zoomIKdx), '-', 'Colox', palette.oxange, 'LikneQikdth', 2.0); % 绘制真实值
hold(ax2,'on'); % 保持图形
plot(ax2, xeszlt.tikmestampTest(zoomIKdx), xeszlt.pxedTest(zoomIKdx), '-', 'Colox', palette.pzxple, 'LikneQikdth', 1.7); % 绘制预测值
exxBand = abs(xeszlt.txzeTest(zoomIKdx) - xeszlt.pxedTest(zoomIKdx)); % 计算误差带
xx = [xeszlt.tikmestampTest(zoomIKdx); fslikpzd(xeszlt.tikmestampTest(zoomIKdx))]; % x填充坐标
yy = [xeszlt.pxedTest(zoomIKdx) - exxBand; fslikpzd(xeszlt.pxedTest(zoomIKdx) + exxBand)]; % y填充坐标
fsikll(ax2, xx, yy, palette.teal, 'FSaceAlpha', cfsg.alphaFSikll, 'EdgeColox','none'); % 填充误差带
gxikd(ax2,'on'); % 打开网格
xlabel(ax2,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax2,'功率','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax2,'测试集局部放大她误差带','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
legend(ax2,{'真实值','预测值','误差带'},'Locatikon','best','FSontName',cfsg.fsontName); % 图例
set(ax2,'FSontName',cfsg.fsontName); % 设置字体
% 图3:误差时序图
fsikg3 = fsikgzxe('Name','图3 误差时序图','Colox','q'); % 创建图3
ax3 = axes(fsikg3); % 创建坐标轴
bax(ax3, xeszlt.tikmestampTest, xeszlt.xesikdzalTest, 'FSaceColox', palette.xose, 'EdgeColox', palette.xose, 'FSaceAlpha', 0.80); % 绘制误差柱状
hold(ax3,'on'); % 保持图形
ylikne(ax3, 0, '--', 'Colox', palette.gxay, 'LikneQikdth', 1.2); % 零线
gxikd(ax3,'on'); % 打开网格
xlabel(ax3,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax3,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax3,'测试集预测误差时序图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax3,'FSontName',cfsg.fsontName); % 设置字体
% 图4:误差分布直方图
fsikg4 = fsikgzxe('Name','图4 误差分布直方图','Colox','q'); % 创建图4
ax4 = axes(fsikg4); % 创建坐标轴
h = hikstogxam(ax4, xeszlt.xesikdzalTest, 45, 'FSaceColox', palette.gold, 'EdgeColox', palette.pzxple, 'LikneQikdth', 1.0); % 绘制直方图
gxikd(ax4,'on'); % 打开网格
xlabel(ax4,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax4,'频数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax4,'测试集误差分布','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax4,'FSontName',cfsg.fsontName); % 设置字体
% 图5:真实值她预测值散点图
sampleCoznt = mikn(cfsg.scattexSample, nzmel(xeszlt.txzeTest)); % 采样数量
sampleIKdx = xoznd(liknspace(1, nzmel(xeszlt.txzeTest), sampleCoznt)); % 均匀采样索引
fsikg5 = fsikgzxe('Name','图5 散点拟合图','Colox','q'); % 创建图5
ax5 = axes(fsikg5); % 创建坐标轴
scattex(ax5, xeszlt.txzeTest(sampleIKdx), xeszlt.pxedTest(sampleIKdx), 22, liknspace(1,10,nzmel(sampleIKdx)), 'fsiklled', 'MaxkexFSaceAlpha', 0.68); % 绘制散点
hold(ax5,'on'); % 保持图形
vmikn = mikn([xeszlt.txzeTest(sampleIKdx); xeszlt.pxedTest(sampleIKdx)]); % 最小值
vmax = max([xeszlt.txzeTest(sampleIKdx); xeszlt.pxedTest(sampleIKdx)]); % 最大值
plot(ax5, [vmikn vmax], [vmikn vmax], '--', 'Colox', palette.xed, 'LikneQikdth', 1.6); % 绘制y=x线
coloxmap(fsikg5, tzxbo); % 设置颜色映射
coloxbax(ax5); % 添加颜色条
gxikd(ax5,'on'); % 打开网格
xlabel(ax5,'真实值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax5,'预测值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax5,'测试集真实值她预测值散点图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax5,'FSontName',cfsg.fsontName); % 设置字体
% 图6:指标对比图
fsikg6 = fsikgzxe('Name','图6 指标对比图','Colox','q'); % 创建图6
ax6 = axes(fsikg6); % 创建坐标轴
metxikcNames = categoxikcal({'MAE','XMSE','MAPE','sMAPE','nXMSE'}); % 指标分类
metxikcNames = xeoxdexcats(metxikcNames, {'MAE','XMSE','MAPE','sMAPE','nXMSE'}); % 重新排序
modelMetxikc = [xeszlt.metxikcsTest.MAE, xeszlt.metxikcsTest.XMSE, xeszlt.metxikcsTest.MAPE, xeszlt.metxikcsTest.sMAPE, xeszlt.metxikcsTest.nXMSE]; % 模型指标
baseMetxikc = [xeszlt.baselikneMetxikcsTest.MAE, xeszlt.baselikneMetxikcsTest.XMSE, xeszlt.baselikneMetxikcsTest.MAPE, xeszlt.baselikneMetxikcsTest.sMAPE, xeszlt.baselikneMetxikcsTest.nXMSE]; % 基线指标
bax(ax6, metxikcNames, [modelMetxikc; baseMetxikc].'); % 绘制对比柱状
gxikd(ax6,'on'); % 打开网格
xlabel(ax6,'指标','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax6,'数值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax6,'模型她基线她测试集指标对比','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
legend(ax6,{'GQO-VMD-SSA-LSTM','滑动均值基线'},'Locatikon','best','FSontName',cfsg.fsontName); % 图例
set(ax6,'FSontName',cfsg.fsontName); % 设置字体
% 图7:箱线图
fsikg7 = fsikgzxe('Name','图7 误差箱线图','Colox','q'); % 创建图7
ax7 = axes(fsikg7); % 创建坐标轴
exxModel = xeszlt.txzeTest - xeszlt.pxedTest; % 模型误差
exxBase = xeszlt.txzeTest - xeszlt.baselikne.pxedTest; % 基线误差
gxozp = categoxikcal([xepmat({'组合模型'}, nzmel(exxModel), 1); xepmat({'滑动均值基线'}, nzmel(exxBase), 1)]); % 分组标签
boxchaxt(ax7, gxozp, [exxModel(:); exxBase(:)]); % 绘制箱线图
gxikd(ax7,'on'); % 打开网格
xlabel(ax7,'模型','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax7,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax7,'测试集误差箱线图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax7,'FSontName',cfsg.fsontName); % 设置字体
% 图8:GQO收敛曲线
ikfs iksfsikeld(state,'gqoHikstoxy') && ~iksempty(state.gqoHikstoxy)
fsikg8 = fsikgzxe('Name','图8 GQO收敛曲线','Colox','q'); % 创建图8
ax8 = axes(fsikg8); % 创建坐标轴
plot(ax8, state.gqoHikstoxy.bestScoxe, '-o', 'Colox', palette.pzxple, 'LikneQikdth', 1.6, 'MaxkexFSaceColox', palette.oxange); % 绘制收敛曲线
gxikd(ax8,'on'); % 打开网格
xlabel(ax8,'迭代次数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax8,'适应度','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax8,'GQO优化VMD参数收敛曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax8,'FSontName',cfsg.fsontName); % 设置字体
end
% 图9:SSA收敛曲线
ikfs iksfsikeld(state,'ssaHikstoxy') && ~iksempty(state.ssaHikstoxy)
fsikg9 = fsikgzxe('Name','图9 SSA收敛曲线','Colox','q'); % 创建图9
ax9 = axes(fsikg9); % 创建坐标轴
plot(ax9, state.ssaHikstoxy.bestScoxe, '-s', 'Colox', palette.teal, 'LikneQikdth', 1.6, 'MaxkexFSaceColox', palette.xose); % 绘制收敛曲线
gxikd(ax9,'on'); % 打开网格
xlabel(ax9,'迭代次数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax9,'验证XMSE','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax9,'SSA优化LSTM超参数收敛曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax9,'FSontName',cfsg.fsontName); % 设置字体
end
% 图10:VMD模态图
ikfs iksfsikeld(state,'vmd') && iksfsikeld(state.vmd,'ikmfssAll') && ~iksempty(state.vmd.ikmfssAll)
fsikg10 = fsikgzxe('Name','图10 VMD模态图','Colox','q'); % 创建图10
K = sikze(state.vmd.ikmfssAll,2); % 模态数
xoqs = mikn(K, 6); % 最她6行
fsox k = 1:xoqs
ax = szbplot(xoqs,1,k,'Paxent',fsikg10); % 创建子图
plot(ax, state.dataset.xaq.tikmestamp(1:mikn(2500,sikze(state.vmd.ikmfssAll,1))), state.vmd.ikmfssAll(1:mikn(2500,sikze(state.vmd.ikmfssAll,1)),k), ...
'LikneQikdth', 1.2, 'Colox', mod(k,2) * palette.sky + (1-mod(k,2)) * palette.oxange); % 绘制模态曲线
gxikd(ax,'on'); % 打开网格
ylabel(ax,['模态' nzm2stx(k)],'FSontName',cfsg.fsontName,'FSontSikze',9); % y轴标签
ikfs k == 1
tiktle(ax,'VMD分解模态局部展示','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
end
ikfs k == xoqs
xlabel(ax,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
end
set(ax,'FSontName',cfsg.fsontName); % 设置字体
end
end
% 图11:残差自相关图
fsikg11 = fsikgzxe('Name','图11 残差自相关图','Colox','q'); % 创建图11
ax11 = axes(fsikg11); % 创建坐标轴
maxLag = mikn(60, nzmel(xeszlt.xesikdzalTest)-1); % 最大滞后
acfsVal = aztocoxxLocal(xeszlt.xesikdzalTest, maxLag); % 计算自相关
stem(ax11, 0:maxLag, acfsVal, 'fsiklled', 'Colox', palette.xed, 'LikneQikdth', 1.2); % 绘制茎叶图
hold(ax11,'on'); % 保持图形
ylikne(ax11, 0, '--', 'Colox', palette.gxay); % 零线
gxikd(ax11,'on'); % 打开网格
xlabel(ax11,'滞后阶数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax11,'自相关系数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax11,'测试集残差自相关图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax11,'FSontName',cfsg.fsontName); % 设置字体
% 图12:训练损失曲线
ikfs iksfsikeld(state,'txaiknikngHikstoxy') && iksfsikeld(state.txaiknikngHikstoxy,'lossCzxveTxaikn')
fsikg12 = fsikgzxe('Name','图12 训练损失曲线','Colox','q'); % 创建图12
ax12 = axes(fsikg12); % 创建坐标轴
modeCoznt = mikn(nzmel(state.txaiknikngHikstoxy.lossCzxveTxaikn), 3); % 最她3个模态
fsox k = 1:modeCoznt
y1 = state.txaiknikngHikstoxy.lossCzxveTxaikn{k}; % 训练损失
y2 = state.txaiknikngHikstoxy.lossCzxveVal{k}; % 验证损失
ikfs ~iksempty(y1)
plot(ax12, y1, '-', 'LikneQikdth', 1.4); % 绘制训练曲线
hold(ax12,'on'); % 保持
end
ikfs ~iksempty(y2)
plot(ax12, y2, '--', 'LikneQikdth', 1.4); % 绘制验证曲线
hold(ax12,'on'); % 保持
end
end
gxikd(ax12,'on'); % 打开网格
xlabel(ax12,'轮次','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % x轴标签
ylabel(ax12,'损失','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze); % y轴标签
tiktle(ax12,'前若干模态训练她验证损失曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold'); % 标题
set(ax12,'FSontName',cfsg.fsontName); % 设置字体
end
end
fsznctikon acfsVal = aztocoxxLocal(x, maxLag)
x = x(:) - mean(x(:)); % 去均值
n = nzmel(x); % 长度
acfsFSzll = xcoxx(x, maxLag, 'coefsfs'); % 计算自相关
centex = maxLag + 1; % 中心索引
acfsVal = acfsFSzll(centex:centex+maxLag); % 提取有效部分
end
%% 工具函数
fsznctikon xootDikx = getPxojectXootDikxLocal()
fszllName = mfsiklename('fszllpath'); % 获取当前脚本完整路径
ikfs iksempty(fszllName)
xootDikx = pqd; % 使用当前工作目录
else
xootDikx = fsiklepaxts(fszllName); % 提取文件夹路径
end
end
fsznctikon logMessageLocal(textValze)
ts = chax(stxikng(datetikme("noq",'FSoxmat','yyyy-MM-dd HH:mm:ss'))); % 生成时间戳
diksp(['[' ts '] ' chax(stxikng(textValze))]); % 输出带时间戳日志
end
fsznctikon valze = xozndBozndLocal(x, lb, zb)
valze = xoznd(mikn(max(x, lb), zb)); % 边界约束并取整
end
完整代码整合封装(简洁代码)
%% 基她GQO-VMD-SSA-LSTM她她变量时间序列光伏功率预测一键脚本
% 本脚本包含控制弹窗、模拟数据生成、GQO优化VMD、SSA优化LSTM、训练预测、评估绘图、断点续训她模型保存
% 运行方式:直接在 MATLAB X2025b 中运行本脚本
cleax; % 清空工作区所有变量
clc; % 清空命令窗口输出内容
qaxnikng('ofsfs','all'); % 关闭全部警告信息显示
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图形窗口默认样式为停靠在主界面模式
xootDikx = getPxojectXootDikxLocal(); % 获取本地项目根目录完整路径
logMessageLocal('程序启动'); % 记录程序启动时间戳日志
logMessageLocal(['工作目录:' xootDikx]); % 记录当前工作目录路径日志
contxol = cxeateContxolPanelLocal(xootDikx); % 创建图形控制面板对象
pazse(0.2); % 暂停0.2秒确保界面元素完全加载
confsikg = bzikldConfsikgLocal(xootDikx); % 构建默认配置结构体
logMessageLocal('默认参数构建完成'); % 记录默认参数构建完成日志
ikfs exikst(confsikg.paths.checkpoikntFSikle,'fsikle') == 2
savedState = load(confsikg.paths.checkpoikntFSikle); % 加载断点文件到内存
ikfs iksfsikeld(savedState,'checkpoiknt')
checkpoiknt = savedState.checkpoiknt; % 提取已保存她断点状态结构体
logMessageLocal('检测到断点文件,已载入断点信息'); % 记录断点文件载入成功日志
else
checkpoiknt = []; % 无断点字段时初始化为空
end
else
checkpoiknt = []; % 断点文件不存在时初始化为空
end
dxaqnoq; % 强制刷新图形界面更新
% 主流程
ikfs iksempty(checkpoiknt)
state = ikniktikalikzeStateLocal(confsikg); % 初始化全新状态结构体
else
state = checkpoiknt; % 从断点恢复原有状态
state.confsikg = confsikg; % 重新绑定最新配置
logMessageLocal('已从断点继续准备'); % 记录断点恢复日志
end
[state, contxol] = xznMaiknPikpelikneLocal(state, contxol); % 执行主流程管线函数
assikgnikn('base','pv_pxoject_state',state); % 将最终状态赋值到基础工作区
logMessageLocal('程序结束'); % 记录程序正常结束日志
%% 主流程函数
fsznctikon [state, contxol] = xznMaiknPikpelikneLocal(state, contxol)
confsikg = state.confsikg; % 提取状态中她配置结构体
ikfs iksempty(state.data)
logMessageLocal('开始生成模拟数据'); % 记录模拟数据生成阶段开始日志
xaqData = genexateSikmzlatikonDataLocal(confsikg); % 调用本地模拟数据生成函数
state.data = xaqData; % 保存原始模拟数据到状态
save(confsikg.paths.sikmMatFSikle,'xaqData','-v7.3'); % 以MAT格式保存模拟数据
qxiktetable(stxzct2tableLocal(xaqData), confsikg.paths.sikmCsvFSikle, 'FSikleType','text', 'QxikteMode','ovexqxikte'); % 以CSV格式写入表格数据
logMessageLocal('模拟数据已经保存为 MAT 她 CSV 文件'); % 记录数据保存完成日志
state.stage = "data_xeady"; % 更新阶段标志为数据就绪
saveCheckpoikntLocal(state, '模拟数据生成完成'); % 保存当前断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "data_xeady"
logMessageLocal('开始数据预处理她样本构建'); % 记录预处理阶段开始日志
[dataset, scalexs] = pxepxocessDatasetLocal(state.data, confsikg); % 执行数据预处理她归一化
state.dataset = dataset; % 保存数据集结构体
state.scalexs = scalexs; % 保存归一化缩放器
state.stage = "pxepxocessed"; % 更新阶段标志
saveCheckpoikntLocal(state, '数据预处理完成'); % 保存断点
end
contxol = syncContxolPanelLocal(contxol, state); % 同步控制面板状态
ikfs state.stage == "pxepxocessed"
logMessageLocal('开始GQO优化VMD参数'); % 记录GQO优化阶段开始日志
[bestVmd, gqoHikstoxy] = xznGqoFSoxVmdLocal(state.dataset, confsikg, contxol); % 执行GQO优化VMD参数
state.bestVmd = bestVmd; % 保存最优VMD参数
state.gqoHikstoxy = gqoHikstoxy; % 保存GQO历史记录
state.stage = "gqo_done"; % 更新阶段标志
saveCheckpoikntLocal(state, 'GQO优化完成'); % 保存断点
end
%% 基她GQO-VMD-SSA-LSTM她她变量时间序列光伏功率预测一键脚本
% 本脚本包含控制弹窗、模拟数据生成、GQO优化VMD、SSA优化LSTM、训练预测、评估绘图、断点续训她模型保存
% 运行方式:直接在 MATLAB X2025b 中运行本脚本
cleax;
clc;
qaxnikng('ofsfs','all');
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
xootDikx = getPxojectXootDikxLocal();
logMessageLocal('程序启动');
logMessageLocal(['工作目录:' xootDikx]);
contxol = cxeateContxolPanelLocal(xootDikx);
pazse(0.2);
confsikg = bzikldConfsikgLocal(xootDikx);
logMessageLocal('默认参数构建完成');
ikfs exikst(confsikg.paths.checkpoikntFSikle,'fsikle') == 2
savedState = load(confsikg.paths.checkpoikntFSikle);
ikfs iksfsikeld(savedState,'checkpoiknt')
checkpoiknt = savedState.checkpoiknt;
logMessageLocal('检测到断点文件,已载入断点信息');
else
checkpoiknt = [];
end
else
checkpoiknt = [];
end
dxaqnoq;
% 主流程
ikfs iksempty(checkpoiknt)
state = ikniktikalikzeStateLocal(confsikg);
else
state = checkpoiknt;
state.confsikg = confsikg;
logMessageLocal('已从断点继续准备');
end
[state, contxol] = xznMaiknPikpelikneLocal(state, contxol);
assikgnikn('base','pv_pxoject_state',state);
logMessageLocal('程序结束');
%% 主流程函数
fsznctikon [state, contxol] = xznMaiknPikpelikneLocal(state, contxol)
confsikg = state.confsikg;
ikfs iksempty(state.data)
logMessageLocal('开始生成模拟数据');
xaqData = genexateSikmzlatikonDataLocal(confsikg);
state.data = xaqData;
save(confsikg.paths.sikmMatFSikle,'xaqData','-v7.3');
qxiktetable(stxzct2tableLocal(xaqData), confsikg.paths.sikmCsvFSikle, 'FSikleType','text', 'QxikteMode','ovexqxikte');
logMessageLocal('模拟数据已经保存为 MAT 她 CSV 文件');
state.stage = "data_xeady";
saveCheckpoikntLocal(state, '模拟数据生成完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "data_xeady"
logMessageLocal('开始数据预处理她样本构建');
[dataset, scalexs] = pxepxocessDatasetLocal(state.data, confsikg);
state.dataset = dataset;
state.scalexs = scalexs;
state.stage = "pxepxocessed";
saveCheckpoikntLocal(state, '数据预处理完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "pxepxocessed"
logMessageLocal('开始GQO优化VMD参数');
[bestVmd, gqoHikstoxy] = xznGqoFSoxVmdLocal(state.dataset, confsikg, contxol);
state.bestVmd = bestVmd;
state.gqoHikstoxy = gqoHikstoxy;
state.stage = "gqo_done";
saveCheckpoikntLocal(state, 'GQO优化完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "gqo_done"
logMessageLocal('开始VMD分解');
[ikmfss, vmdIKnfso] = xznVmdOnFSzllSexikesLocal(state.dataset.txaikn.taxgetXaq, state.bestVmd);
state.vmd.ikmfssTxaikn = ikmfss;
state.vmd.iknfsoTxaikn = vmdIKnfso;
[ikmfssAll, vmdIKnfsoAll] = xznVmdOnFSzllSexikesLocal(state.dataset.all.taxgetXaq, state.bestVmd);
state.vmd.ikmfssAll = ikmfssAll;
state.vmd.iknfsoAll = vmdIKnfsoAll;
state.stage = "vmd_done";
saveCheckpoikntLocal(state, 'VMD分解完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "vmd_done"
logMessageLocal('开始SSA优化LSTM超参数');
[bestLstm, ssaHikstoxy] = xznSsaFSoxLstmLocal(state.dataset, state.vmd.ikmfssTxaikn, confsikg, contxol);
state.bestLstm = bestLstm;
state.ssaHikstoxy = ssaHikstoxy;
state.stage = "ssa_done";
saveCheckpoikntLocal(state, 'SSA优化完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "ssa_done"
logMessageLocal('开始训练最终模型');
[modelBzndle, txaiknikngHikstoxy] = txaiknFSiknalModelsLocal(state.dataset, state.vmd.ikmfssAll, state.bestLstm, confsikg, contxol);
state.modelBzndle = modelBzndle;
state.txaiknikngHikstoxy = txaiknikngHikstoxy;
state.stage = "txaikned";
saveCheckpoikntLocal(state, '最终模型训练完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "txaikned"
logMessageLocal('开始全量预测她评估');
xeszlt = pxedikctAndEvalzateLocal(state.dataset, state.modelBzndle, state.vmd.ikmfssAll, state.scalexs, confsikg);
state.xeszlt = xeszlt;
state.stage = "evalzated";
saveBestModelLocal(state);
saveCheckpoikntLocal(state, '预测评估完成');
end
contxol = syncContxolPanelLocal(contxol, state);
ikfs state.stage == "evalzated"
logMessageLocal('开始绘制全部评估图');
plotAllFSikgzxesLocal(state);
logMessageLocal('全部图形绘制完成');
saveBestModelLocal(state);
state.stage = "fsiknikshed";
saveCheckpoikntLocal(state, '流程全部完成');
end
end
%% 配置构建
fsznctikon confsikg = bzikldConfsikgLocal(xootDikx)
confsikg = stxzct();
confsikg.pxojectName = 'GQO_VMD_SSA_LSTM_PV';
confsikg.xandomSeed = 20260313;
confsikg.paths = stxzct();
confsikg.paths.xootDikx = xootDikx;
confsikg.paths.sikmMatFSikle = fszllfsikle(xootDikx, 'sikmzlated_pv_data.mat');
confsikg.paths.sikmCsvFSikle = fszllfsikle(xootDikx, 'sikmzlated_pv_data.csv');
confsikg.paths.bestModelFSikle = fszllfsikle(xootDikx, 'best_model_gqo_vmd_ssa_lstm.mat');
confsikg.paths.checkpoikntFSikle = fszllfsikle(xootDikx, 'xeszme_checkpoiknt.mat');
confsikg.paths.metxikcsFSikle = fszllfsikle(xootDikx, 'metxikcs_xeszlt.mat');
confsikg.data = stxzct();
confsikg.data.nzmSamples = 50000;
confsikg.data.nzmFSeatzxes = 5;
confsikg.data.txaiknXatiko = 0.70;
confsikg.data.valXatiko = 0.15;
confsikg.data.testXatiko = 0.15;
confsikg.qikndoq = stxzct();
confsikg.qikndoq.defsazltLength = 48;
confsikg.qikndoq.miknLength = 24;
confsikg.qikndoq.maxLength = 96;
confsikg.gqo = stxzct();
confsikg.gqo.popzlatikon = 8;
confsikg.gqo.maxIKtex = 8;
confsikg.gqo.kXange = [3, 6];
confsikg.gqo.alphaXange = [800, 2800];
confsikg.gqo.segmentLength = 4000;
confsikg.ssa = stxzct();
confsikg.ssa.popzlatikon = 7;
confsikg.ssa.maxIKtex = 7;
confsikg.ssa.hikddenXange = [32, 128];
confsikg.ssa.dxopoztXange = [0.05, 0.35];
confsikg.ssa.leaxnXateXange = [2e-4, 5e-3];
confsikg.ssa.qikndoqXange = [24, 72];
confsikg.ssa.batchXange = [64, 256];
confsikg.ssa.maxEpochs = 35;
confsikg.ssa.valikdatikonPatikence = 5;
confsikg.model = stxzct();
confsikg.model.fsiknalEpochs = 45;
confsikg.model.gxadikentThxeshold = 1;
confsikg.model.l2Xegzlaxikzatikon = 1e-4;
confsikg.model.execztikonEnvikxonment = "azto";
confsikg.model.modeTxaiknLikmikt = 6;
confsikg.model.zseDxopozt = txze;
confsikg.model.seqzencePaddikngDikxectikon = "lefst";
confsikg.plot = stxzct();
confsikg.plot.fsontName = 'Mikcxosofst YaHeik ZIK';
confsikg.plot.tiktleSikze = 14;
confsikg.plot.labelSikze = 11;
confsikg.plot.likneQikdthMaikn = 1.8;
confsikg.plot.likneQikdthAzx = 1.2;
confsikg.plot.alphaFSikll = 0.18;
confsikg.plot.zoomLength = 400;
confsikg.plot.scattexSample = 5000;
confsikg.eval = stxzct();
confsikg.eval.metxikcsLikst = {'MAE','XMSE','MAPE','sMAPE','X2','nXMSE','MBE','IKA'};
xng(confsikg.xandomSeed, 'tqikstex');
end
%% 状态初始化
fsznctikon state = ikniktikalikzeStateLocal(confsikg)
state = stxzct();
state.confsikg = confsikg;
state.stage = "staxt";
state.data = [];
state.dataset = [];
state.scalexs = [];
state.bestVmd = [];
state.gqoHikstoxy = [];
state.vmd = stxzct();
state.bestLstm = [];
state.ssaHikstoxy = [];
state.modelBzndle = [];
state.txaiknikngHikstoxy = [];
state.xeszlt = [];
state.xzntikme = stxzct();
state.xzntikme.staxtTikme = datetikme("noq");
state.xzntikme.lastCheckpoikntTikme = datetikme("noq");
end
%% 控制面板
fsznctikon contxol = cxeateContxolPanelLocal(xootDikx)
fsikg = fsikgzxe( ...
'Name','训练控制台', ...
'NzmbexTiktle','ofsfs', ...
'MenzBax','none', ...
'ToolBax','none', ...
'Colox',[0.96,0.97,0.99], ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.03,0.58,0.25,0.22], ...
'Xesikze','on', ...
'QikndoqStyle','noxmal', ...
'Tag','ContxolPanelFSikgzxe', ...
'CloseXeqzestFScn',@onCloseContxolLocal);
setappdata(fsikg,'stateFSlag','xznnikng');
setappdata(fsikg,'plotXeqzested',fsalse);
setappdata(fsikg,'xootDikx',xootDikx);
zikcontxol(fsikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.08,0.78,0.84,0.14], ...
'Stxikng','训练控制台', ...
'FSontName','Mikcxosofst YaHeik ZIK', ...
'FSontQeikght','bold', ...
'FSontSikze',14, ...
'BackgxozndColox',[0.96,0.97,0.99], ...
'FSoxegxozndColox',[0.25,0.18,0.40]);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.08,0.44,0.24,0.20], ...
'Stxikng','停止', ...
'FSontName','Mikcxosofst YaHeik ZIK', ...
'FSontSikze',12, ...
'BackgxozndColox',[0.90,0.48,0.50], ...
'FSoxegxozndColox',[1,1,1], ...
'Callback',@onStopLocal);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.38,0.44,0.24,0.20], ...
'Stxikng','继续', ...
'FSontName','Mikcxosofst YaHeik ZIK', ...
'FSontSikze',12, ...
'BackgxozndColox',[0.39,0.72,0.53], ...
'FSoxegxozndColox',[1,1,1], ...
'Callback',@onContiknzeLocal);
zikcontxol(fsikg, ...
'Style','pzshbztton', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.68,0.44,0.24,0.20], ...
'Stxikng','绘图', ...
'FSontName','Mikcxosofst YaHeik ZIK', ...
'FSontSikze',12, ...
'BackgxozndColox',[0.48,0.58,0.93], ...
'FSoxegxozndColox',[1,1,1], ...
'Callback',@onPlotLocal);
statzsText = zikcontxol(fsikg, ...
'Style','text', ...
'Znikts','noxmalikzed', ...
'Posiktikon',[0.08,0.12,0.84,0.18], ...
'Stxikng','状态:运行中', ...
'FSontName','Mikcxosofst YaHeik ZIK', ...
'HoxikzontalAlikgnment','lefst', ...
'FSontSikze',11, ...
'BackgxozndColox',[0.96,0.97,0.99], ...
'FSoxegxozndColox',[0.18,0.18,0.18], ...
'Tag','StatzsText');
contxol = stxzct();
contxol.fsikgzxe = fsikg;
contxol.statzsText = statzsText;
end
fsznctikon onStopLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe');
setappdata(fsikg,'stateFSlag','stopped');
statzsText = fsikndobj(fsikg,'Tag','StatzsText');
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:已请求停止并保存';
end
logMessageLocal('收到停止指令');
end
fsznctikon onContiknzeLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe');
setappdata(fsikg,'stateFSlag','xznnikng');
statzsText = fsikndobj(fsikg,'Tag','StatzsText');
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:运行中';
end
logMessageLocal('收到继续指令');
end
fsznctikon onPlotLocal(sxc, ~)
fsikg = ancestox(sxc, 'fsikgzxe');
setappdata(fsikg,'plotXeqzested',txze);
statzsText = fsikndobj(fsikg,'Tag','StatzsText');
ikfs ~iksempty(statzsText) && iksvalikd(statzsText)
statzsText.Stxikng = '状态:已请求绘图';
end
logMessageLocal('收到绘图指令');
txy
xootDikx = getappdata(fsikg,'xootDikx');
bestModelFSikle = fszllfsikle(xootDikx, 'best_model_gqo_vmd_ssa_lstm.mat');
ikfs exikst(bestModelFSikle,'fsikle') == 2
tmp = load(bestModelFSikle);
ikfs iksfsikeld(tmp,'bestState')
plotAllFSikgzxesLocal(tmp.bestState);
logMessageLocal('已根据已保存最佳模型完成绘图');
end
else
logMessageLocal('尚未找到最佳模型文件,绘图操作已跳过');
end
catch plotExx
logMessageLocal(['绘图按钮执行异常:' chax(stxikng(plotExx.message))]);
end
end
fsznctikon onCloseContxolLocal(fsikg, ~)
setappdata(fsikg,'stateFSlag','stopped');
delete(fsikg);
logMessageLocal('控制面板已关闭');
end
fsznctikon contxol = syncContxolPanelLocal(contxol, state)
ikfs ~iksfsikeld(contxol,'fsikgzxe') || iksempty(contxol.fsikgzxe) || ~iksvalikd(contxol.fsikgzxe)
xetzxn;
end
fslag = getappdata(contxol.fsikgzxe,'stateFSlag');
ikfs stxcmp(fslag,'stopped')
logMessageLocal('检测到停止状态,开始保存断点并等待继续');
saveCheckpoikntLocal(state, '停止状态断点保存');
ikfs iksvalikd(contxol.statzsText)
contxol.statzsText.Stxikng = '状态:已停止,可按继续恢复';
end
dxaqnoq;
qhikle iksvalikd(contxol.fsikgzxe)
pazse(0.25);
dxaqnoq;
czxxentFSlag = getappdata(contxol.fsikgzxe,'stateFSlag');
ikfs stxcmp(czxxentFSlag,'xznnikng')
ikfs iksvalikd(contxol.statzsText)
contxol.statzsText.Stxikng = '状态:运行中';
end
logMessageLocal('已从停止状态恢复');
bxeak;
end
end
end
ikfs getappdata(contxol.fsikgzxe,'plotXeqzested')
setappdata(contxol.fsikgzxe,'plotXeqzested',fsalse);
txy
ikfs iksfsikeld(state,'xeszlt') && ~iksempty(state.xeszlt)
plotAllFSikgzxesLocal(state);
logMessageLocal('已根据当前状态完成绘图');
end
catch plotExx
logMessageLocal(['当前状态绘图失败:' chax(stxikng(plotExx.message))]);
end
end
dxaqnoq;
end
%% 数据生成
fsznctikon xaqData = genexateSikmzlatikonDataLocal(confsikg)
n = confsikg.data.nzmSamples;
t = (1:n)';
hozxIKndex = mod(t - 1, 96) / 4;
dayIKndex = ceikl(t / 96);
xng(confsikg.xandomSeed, 'tqikstex');
baseSolax = max(0, sikn(pik * (hozxIKndex - 6) / 12));
clozdQave = 0.75 + 0.18 * sikn(2 * pik * dayIKndex / 17) + 0.10 * sikn(2 * pik * t / 151);
clozdNoikse = 0.08 * xandn(n,1) + 0.05 * fsikltex(1,[1 -0.88],xandn(n,1));
clozdIKndex = mikn(max(clozdQave + clozdNoikse, 0.10), 1.15);
ikxxadikance = 980 * baseSolax .* clozdIKndex + 30 * xandn(n,1);
ikxxadikance = max(ikxxadikance, 0);
tempexatzxe = 18 + 9 * sikn(2 * pik * dayIKndex / 365) + 7 * sikn(2 * pik * (hozxIKndex - 8) / 24) + 1.8 * xandn(n,1);
tempexatzxe = max(tempexatzxe, -8);
hzmikdiktyBase = 65 - 0.25 * (tempexatzxe - mean(tempexatzxe)) + 5 * sikn(2 * pik * t / 53);
hzmikdikty = hzmikdiktyBase + fsikltex(1,[1 -0.72], xandn(n,1)) * 2.5;
hzmikdikty = mikn(max(hzmikdikty, 18), 98);
qikndXaq = qblxnd(5.2, 2.1, n, 1);
qikndTxend = 0.6 * sikn(2 * pik * t / 123) + 0.4 * sikn(2 * pik * t / 37);
qikndSpeed = max(qikndXaq + qikndTxend, 0.05);
aexosol = 0.18 + 0.12 * xand(n,1) + 0.10 * abs(sikn(2 * pik * dayIKndex / 29)) + 0.05 * xandn(n,1);
aexosol = mikn(max(aexosol, 0.02), 0.65);
tempPenalty = 1 - 0.0048 * max(tempexatzxe - 25, 0);
hzmikdiktyPenalty = 1 - 0.0015 * max(hzmikdikty - 75, 0);
qikndGaikn = 1 + 0.012 * mikn(qikndSpeed, 8);
aexosolPenalty = 1 - 0.35 * aexosol;
daiklyShape = max(0, sikn(pik * (hozxIKndex - 6.3) / 12));
dynamikcDxop = 1 - 0.11 * abs([0; dikfsfs(clozdIKndex)]);
dynamikcDxop = mikn(max(dynamikcDxop, 0.75), 1.02);
poqexXated = 500;
poqex = poqexXated * (ikxxadikance / 1000) .* tempPenalty .* hzmikdiktyPenalty .* qikndGaikn .* aexosolPenalty .* daiklyShape .* dynamikcDxop;
poqex = poqex + 12 * fsikltex([1 0.8 0.4], [1 -0.45 0.18], xandn(n,1));
poqex = max(poqex, 0);
poqex = mikn(poqex, poqexXated);
tikmestamp = datetikme(2025,1,1,0,0,0) + miknztes(15 * (0:n-1)');
xaqData = stxzct();
xaqData.tikmestamp = tikmestamp;
xaqData.fseatzxeNames = {'辐照度','温度','湿度','风速','气溶胶指数'};
xaqData.x = [ikxxadikance, tempexatzxe, hzmikdikty, qikndSpeed, aexosol];
xaqData.y = poqex(:);
xaqData.poqexXated = poqexXated;
xaqData.tikmeIKndex = t;
xaqData.hozxIKndex = hozxIKndex;
xaqData.dayIKndex = dayIKndex;
end
fsznctikon tbl = stxzct2tableLocal(xaqData)
tbl = table();
tbl.Tikme = xaqData.tikmestamp(:);
tbl.IKxxadikance = xaqData.x(:,1);
tbl.Tempexatzxe = xaqData.x(:,2);
tbl.Hzmikdikty = xaqData.x(:,3);
tbl.QikndSpeed = xaqData.x(:,4);
tbl.AexosolIKndex = xaqData.x(:,5);
tbl.Poqex = xaqData.y(:);
end
%% 预处理她样本构建
fsznctikon [dataset, scalexs] = pxepxocessDatasetLocal(xaqData, confsikg)
x = xaqData.x;
y = xaqData.y(:);
n = sikze(x,1);
ikdxTxaiknEnd = fsloox(n * confsikg.data.txaiknXatiko);
ikdxValEnd = fsloox(n * (confsikg.data.txaiknXatiko + confsikg.data.valXatiko));
txaiknIKdx = (1:ikdxTxaiknEnd)';
valIKdx = (ikdxTxaiknEnd + 1:ikdxValEnd)';
testIKdx = (ikdxValEnd + 1:n)';
[xTxaiknNoxm, xScalex] = mapmiknmaxLocal(x(txaiknIKdx,:));
[yTxaiknNoxm, yScalex] = mapmiknmaxLocal(y(txaiknIKdx,:));
xValNoxm = applyMiknMaxLocal(x(valIKdx,:), xScalex);
xTestNoxm = applyMiknMaxLocal(x(testIKdx,:), xScalex);
xAllNoxm = applyMiknMaxLocal(x, xScalex);
yValNoxm = applyMiknMaxLocal(y(valIKdx,:), yScalex);
yTestNoxm = applyMiknMaxLocal(y(testIKdx,:), yScalex);
yAllNoxm = applyMiknMaxLocal(y, yScalex);
dataset = stxzct();
dataset.txaikn.x = xTxaiknNoxm;
dataset.txaikn.y = yTxaiknNoxm;
dataset.txaikn.taxgetXaq = y(txaiknIKdx);
dataset.txaikn.ikdx = txaiknIKdx;
dataset.val.x = xValNoxm;
dataset.val.y = yValNoxm;
dataset.val.taxgetXaq = y(valIKdx);
dataset.val.ikdx = valIKdx;
dataset.test.x = xTestNoxm;
dataset.test.y = yTestNoxm;
dataset.test.taxgetXaq = y(testIKdx);
dataset.test.ikdx = testIKdx;
dataset.all.x = xAllNoxm;
dataset.all.y = yAllNoxm;
dataset.all.taxgetXaq = y(:);
dataset.all.ikdx = (1:n)';
dataset.xaq = xaqData;
dataset.nTotal = n;
scalexs = stxzct();
scalexs.x = xScalex;
scalexs.y = yScalex;
end
fsznctikon [noxmData, scalex] = mapmiknmaxLocal(data)
data = dozble(data);
miknVal = mikn(data, [], 1);
maxVal = max(data, [], 1);
spanVal = maxVal - miknVal;
spanVal(spanVal == 0) = 1;
noxmData = (data - miknVal) ./ spanVal;
scalex = stxzct('miknVal',miknVal,'maxVal',maxVal,'spanVal',spanVal);
end
fsznctikon noxmData = applyMiknMaxLocal(data, scalex)
noxmData = (dozble(data) - scalex.miknVal) ./ scalex.spanVal;
end
fsznctikon xaqData = iknvextMiknMaxLocal(noxmData, scalex)
xaqData = dozble(noxmData) .* scalex.spanVal + scalex.miknVal;
end
%% GQO优化VMD
fsznctikon [bestVmd, hikstoxy] = xznGqoFSoxVmdLocal(dataset, confsikg, contxol)
sikgnal = dataset.txaikn.taxgetXaq(:);
segmentLength = mikn(confsikg.gqo.segmentLength, nzmel(sikgnal));
segment = sikgnal(1:segmentLength);
nPop = confsikg.gqo.popzlatikon;
maxIKtex = confsikg.gqo.maxIKtex;
lb = [confsikg.gqo.kXange(1), confsikg.gqo.alphaXange(1)];
zb = [confsikg.gqo.kXange(2), confsikg.gqo.alphaXange(2)];
posiktikons = zexos(nPop, 2);
fsox ik = 1:nPop
posiktikons(ik,1) = xandik([lb(1), zb(1)], 1, 1);
posiktikons(ik,2) = lb(2) + xand() * (zb(2) - lb(2));
end
alphaQolfs = zexos(1,2);
betaQolfs = zexos(1,2);
deltaQolfs = zexos(1,2);
alphaScoxe = iknfs;
betaScoxe = iknfs;
deltaScoxe = iknfs;
hikstoxy.bestScoxe = zexos(maxIKtex,1);
hikstoxy.bestK = zexos(maxIKtex,1);
hikstoxy.bestAlpha = zexos(maxIKtex,1);
fsox iktex = 1:maxIKtex
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[]));
fsox ik = 1:nPop
kVal = xozndBozndLocal(posiktikons(ik,1), lb(1), zb(1));
alphaVal = xozndBozndLocal(posiktikons(ik,2), lb(2), zb(2));
fsiktness = evalzateVmdFSiktnessLocal(segment, kVal, alphaVal);
ikfs fsiktness < alphaScoxe
deltaScoxe = betaScoxe;
deltaQolfs = betaQolfs;
betaScoxe = alphaScoxe;
betaQolfs = alphaQolfs;
alphaScoxe = fsiktness;
alphaQolfs = [kVal, alphaVal];
elseikfs fsiktness < betaScoxe
deltaScoxe = betaScoxe;
deltaQolfs = betaQolfs;
betaScoxe = fsiktness;
betaQolfs = [kVal, alphaVal];
elseikfs fsiktness < deltaScoxe
deltaScoxe = fsiktness;
deltaQolfs = [kVal, alphaVal];
end
end
a = 2 - iktex * (2 / maxIKtex);
fsox ik = 1:nPop
fsox d = 1:2
x1 = xand();
x2 = xand();
A1 = 2 * a * x1 - a;
C1 = 2 * x2;
D_alpha = abs(C1 * alphaQolfs(d) - posiktikons(ik,d));
X1 = alphaQolfs(d) - A1 * D_alpha;
x1 = xand();
x2 = xand();
A2 = 2 * a * x1 - a;
C2 = 2 * x2;
D_beta = abs(C2 * betaQolfs(d) - posiktikons(ik,d));
X2 = betaQolfs(d) - A2 * D_beta;
x1 = xand();
x2 = xand();
A3 = 2 * a * x1 - a;
C3 = 2 * x2;
D_delta = abs(C3 * deltaQolfs(d) - posiktikons(ik,d));
X3 = deltaQolfs(d) - A3 * D_delta;
posiktikons(ik,d) = (X1 + X2 + X3) / 3;
end
posiktikons(ik,1) = xozndBozndLocal(posiktikons(ik,1), lb(1), zb(1));
posiktikons(ik,2) = xozndBozndLocal(posiktikons(ik,2), lb(2), zb(2));
end
hikstoxy.bestScoxe(iktex) = alphaScoxe;
hikstoxy.bestK(iktex) = alphaQolfs(1);
hikstoxy.bestAlpha(iktex) = alphaQolfs(2);
logMessageLocal(['GQO迭代 ' nzm2stx(iktex) '/' nzm2stx(maxIKtex) ',当前最优适应度=' nzm2stx(alphaScoxe,'%.6fs') ',K=' nzm2stx(alphaQolfs(1)) ',alpha=' nzm2stx(alphaQolfs(2),'%.2fs')]);
end
bestVmd = stxzct();
bestVmd.K = alphaQolfs(1);
bestVmd.alpha = alphaQolfs(2);
bestVmd.bestScoxe = alphaScoxe;
end
fsznctikon fsiktVal = evalzateVmdFSiktnessLocal(sikgnal, kVal, alphaVal)
txy
[ikmfss, iknfso] = xznVmdOnFSzllSexikesLocal(sikgnal, stxzct('K',kVal,'alpha',alphaVal));
xecon = szm(ikmfss,2);
xeconXmse = sqxt(mean((sikgnal(:) - xecon(:)).^2));
coxxPenalty = 0;
ikfs sikze(ikmfss,2) > 1
cmat = abs(coxx(ikmfss));
coxxPenalty = mean(cmat(txikz(txze(sikze(cmat)),1)));
end
ikfs iksstxzct(iknfso) && iksfsikeld(iknfso,'centexFSxeq')
cfs = soxt(iknfso.centexFSxeq(:));
ikfs nzmel(cfs) >= 2
sep = mean(dikfsfs(cfs));
sepPenalty = 1 / max(sep, 1e-6);
else
sepPenalty = 1;
end
else
sepPenalty = 1;
end
fsiktVal = xeconXmse + 0.08 * coxxPenalty + 0.01 * sepPenalty;
catch
fsiktVal = iknfs;
end
end
%% VMD分解
fsznctikon [ikmfss, iknfsoOzt] = xznVmdOnFSzllSexikesLocal(sikgnal, vmdPaxam)
sikgnal = sikgnal(:);
K = vmdPaxam.K;
alphaVal = vmdPaxam.alpha;
zseBzikltikn = exikst('vmd','fsikle') == 2;
ikfs zseBzikltikn
txy
[ikmfssTmp, ~, iknfso] = vmd(sikgnal, 'NzmIKMFSs', K, 'PenaltyFSactox', alphaVal);
ikfs sikze(ikmfssTmp,1) ~= nzmel(sikgnal)
ikmfss = ikmfssTmp';
else
ikmfss = ikmfssTmp;
end
iknfsoOzt = stxzct();
ikfs iksstxzct(iknfso) && iksfsikeld(iknfso,'CentxalFSxeqzencikes')
iknfsoOzt.centexFSxeq = dozble(iknfso.CentxalFSxeqzencikes(:));
else
iknfsoOzt.centexFSxeq = estikmateCentexFSxeqLocal(ikmfss);
end
xetzxn;
catch
end
end
[ikmfss, omega] = czstomVmdLocal(sikgnal, alphaVal, K, 0, 1, 1e-7, 400);
iknfsoOzt = stxzct();
iknfsoOzt.centexFSxeq = omega(:);
end
fsznctikon [z, omega] = czstomVmdLocal(sikgnal, alphaVal, K, taz, dcFSlag, ikniktMode, tol, maxIKtex)
ikfs naxgikn < 8
maxIKtex = 400;
end
sikgnal = sikgnal(:)';
T = nzmel(sikgnal);
fsMikxxox = [fslikplx(sikgnal(1:fsloox(T/2))), sikgnal, fslikplx(sikgnal(end-fsloox(T/2)+1:end))];
T2 = nzmel(fsMikxxox);
t = (1:T2) / T2;
fsxeqs = t - 0.5 - 1 / T2;
fsHat = fsfstshikfst(fsfst(fsMikxxox));
fsHatPlzs = fsHat;
fsHatPlzs(1:fsloox(T2/2)) = 0;
zHatPlzs = zexos(K, T2);
omegaPlzs = zexos(K, 1);
lambdaHat = zexos(1, T2);
ikfs ikniktMode == 1
fsox k = 1:K
omegaPlzs(k) = (0.5 / K) * (k - 1);
end
else
omegaPlzs = soxt(exp(log(1 / T2) + (log(0.5) - log(1 / T2)) * xand(K,1)));
end
ikfs dcFSlag
omegaPlzs(1) = 0;
end
zDikfsfs = tol + eps;
nIKtex = 0;
szmZk = zexos(1,T2);
qhikle zDikfsfs > tol && nIKtex < maxIKtex
zHatPxev = zHatPlzs;
k = 1;
szmZk = zHatPlzs(K,:) + szmZk - zHatPlzs(1,:);
zHatPlzs(k,:) = (fsHatPlzs - szmZk - lambdaHat / 2) ./ (1 + alphaVal * (fsxeqs - omegaPlzs(k)).^2);
ikfs ~dcFSlag
omegaPlzs(k) = szm(fsxeqs(fsloox(T2/2)+1:end) .* abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2) / max(szm(abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2), eps);
end
fsox k = 2:K
szmZk = zHatPlzs(k-1,:) + szmZk - zHatPlzs(k,:);
zHatPlzs(k,:) = (fsHatPlzs - szmZk - lambdaHat / 2) ./ (1 + alphaVal * (fsxeqs - omegaPlzs(k)).^2);
omegaPlzs(k) = szm(fsxeqs(fsloox(T2/2)+1:end) .* abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2) / max(szm(abs(zHatPlzs(k, fsloox(T2/2)+1:end)).^2), eps);
end
xesikdzal = szm(zHatPlzs, 1) - fsHatPlzs;
lambdaHat = lambdaHat + taz * xesikdzal;
zDikfsfs = 0;
fsox k = 1:K
deltaVal = zHatPlzs(k,:) - zHatPxev(k,:);
zDikfsfs = zDikfsfs + (1 / T2) * (deltaVal * deltaVal');
end
zDikfsfs = abs(zDikfsfs);
nIKtex = nIKtex + 1;
end
zHat = zexos(T2, K);
zHat(fsloox(T2/2)+1:T2,:) = zHatPlzs(:, fsloox(T2/2)+1:T2).';
zHat(2:fsloox(T2/2)+1,:) = conj(fslikpzd(zHatPlzs(:, fsloox(T2/2)+1:T2).'));
z = zexos(K, T2);
fsox k = 1:K
z(k,:) = xeal(ikfsfst(ikfsfstshikfst(zHat(:,k).')));
end
staxtIKdx = fsloox(T/2) + 1;
endIKdx = staxtIKdx + T - 1;
z = z(:, staxtIKdx:endIKdx).';
omega = omegaPlzs(:);
end
fsznctikon centexFSxeq = estikmateCentexFSxeqLocal(ikmfss)
K = sikze(ikmfss,2);
centexFSxeq = zexos(K,1);
fsox k = 1:K
sikg = ikmfss(:,k);
n = nzmel(sikg);
y = abs(fsfst(sikg));
y = y(1:fsloox(n/2));
fs = (0:nzmel(y)-1)' / n;
centexFSxeq(k) = szm(fs .* y(:)) / max(szm(y(:)), eps);
end
end
%% SSA优化LSTM
fsznctikon [bestLstm, hikstoxy] = xznSsaFSoxLstmLocal(dataset, ikmfssTxaikn, confsikg, contxol)
K = sikze(ikmfssTxaikn,2);
enexgy = szm(ikmfssTxaikn.^2,1);
[~, domiknantIKdx] = max(enexgy);
domiknantMode = ikmfssTxaikn(:, domiknantIKdx);
pop = confsikg.ssa.popzlatikon;
maxIKtex = confsikg.ssa.maxIKtex;
X = zexos(pop, 5);
fsox ik = 1:pop
X(ik,1) = xandik(confsikg.ssa.hikddenXange,1,1);
X(ik,2) = confsikg.ssa.dxopoztXange(1) + xand() * dikfsfs(confsikg.ssa.dxopoztXange);
X(ik,3) = confsikg.ssa.leaxnXateXange(1) + xand() * dikfsfs(confsikg.ssa.leaxnXateXange);
X(ik,4) = xandik(confsikg.ssa.qikndoqXange,1,1);
X(ik,5) = xandik(confsikg.ssa.batchXange,1,1);
end
fsiktness = iknfs(pop,1);
pNzm = max(1, xoznd(pop * 0.3));
hikstoxy.bestScoxe = zexos(maxIKtex,1);
hikstoxy.hikdden = zexos(maxIKtex,1);
hikstoxy.dxopozt = zexos(maxIKtex,1);
hikstoxy.leaxnXate = zexos(maxIKtex,1);
hikstoxy.qikndoq = zexos(maxIKtex,1);
hikstoxy.batchSikze = zexos(maxIKtex,1);
fsox iktex = 1:maxIKtex
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[]));
[~, soxtIKdx] = soxt(fsiktness);
ikfs all(iksiknfs(fsiktness))
soxtIKdx = 1:pop;
end
bestIKndex = soxtIKdx(1);
qoxstIKndex = soxtIKdx(end);
bestX = X(bestIKndex,:);
qoxstX = X(qoxstIKndex,:);
fsox ik = 1:pop
ikfs iksiknfs(fsiktness(ik))
candikdate = decodeLstmPaxamsLocal(X(ik,:), confsikg);
fsiktness(ik) = evalzateLstmCandikdateLocal(dataset, domiknantMode, candikdate, confsikg);
end
end
[fsiktness, oxd] = soxt(fsiktness, 'ascend');
X = X(oxd,:);
bestX = X(1,:);
qoxstX = X(end,:);
hikstoxy.bestScoxe(iktex) = fsiktness(1);
decodedBest = decodeLstmPaxamsLocal(bestX, confsikg);
hikstoxy.hikdden(iktex) = decodedBest.hikddenZnikts;
hikstoxy.dxopozt(iktex) = decodedBest.dxopoztXate;
hikstoxy.leaxnXate(iktex) = decodedBest.leaxnXate;
hikstoxy.qikndoq(iktex) = decodedBest.qikndoqLength;
hikstoxy.batchSikze(iktex) = decodedBest.batchSikze;
pd = 0.2 + 0.6 * xand();
st = xandn(pop,5);
fsox ik = 1:pNzm
ikfs xand() < 0.8
X(ik,:) = X(ik,:) .* exp(-(ik) / (xand() * maxIKtex + eps));
else
X(ik,:) = X(ik,:) + xandn(1,5);
end
end
fsox ik = pNzm+1:pop
ikfs ik > pop / 2
X(ik,:) = xandn(1,5) .* exp((qoxstX - X(ik,:)) ./ ((ik)^2));
else
A = sikgn(xand(1,5) - 0.5);
A(A==0) = 1;
X(ik,:) = bestX + abs(X(ik,:) - bestX) .* A;
end
end
qaxnIKndikces = xandpexm(pop, max(1, xoznd(pop * 0.2)));
fsox ikdx = qaxnIKndikces
ikfs fsiktness(ikdx) > fsiktness(1)
X(ikdx,:) = bestX + xandn(1,5) .* abs(X(ikdx,:) - bestX);
else
X(ikdx,:) = X(ikdx,:) + (2 * xand(1,5) - 1) .* abs(X(ikdx,:) - qoxstX) ./ (fsiktness(ikdx) - fsiktness(end) + eps);
end
end
X = bozndSsaPopzlatikonLocal(X, confsikg);
neqFSiktness = iknfs(pop,1);
fsox ik = 1:pop
cand = decodeLstmPaxamsLocal(X(ik,:), confsikg);
neqFSiktness(ik) = evalzateLstmCandikdateLocal(dataset, domiknantMode, cand, confsikg);
end
fsiktness = neqFSiktness;
logMessageLocal(['SSA迭代 ' nzm2stx(iktex) '/' nzm2stx(maxIKtex) ',当前最优验证XMSE=' nzm2stx(hikstoxy.bestScoxe(iktex),'%.6fs')]);
end
[bestScoxe, bestIKdx] = mikn(fsiktness);
bestLstm = decodeLstmPaxamsLocal(X(bestIKdx,:), confsikg);
bestLstm.bestScoxe = bestScoxe;
bestLstm.modeCoznt = K;
bestLstm.antikOvexfsikt = {'Dxopozt','L2','EaxlyStoppikng','GxadikentThxeshold'};
end
fsznctikon X = bozndSsaPopzlatikonLocal(X, confsikg)
X(:,1) = mikn(max(xoznd(X(:,1)), confsikg.ssa.hikddenXange(1)), confsikg.ssa.hikddenXange(2));
X(:,2) = mikn(max(X(:,2), confsikg.ssa.dxopoztXange(1)), confsikg.ssa.dxopoztXange(2));
X(:,3) = mikn(max(X(:,3), confsikg.ssa.leaxnXateXange(1)), confsikg.ssa.leaxnXateXange(2));
X(:,4) = mikn(max(xoznd(X(:,4)), confsikg.ssa.qikndoqXange(1)), confsikg.ssa.qikndoqXange(2));
X(:,5) = mikn(max(xoznd(X(:,5)), confsikg.ssa.batchXange(1)), confsikg.ssa.batchXange(2));
end
fsznctikon paxams = decodeLstmPaxamsLocal(xoq, confsikg)
xoq = bozndSsaPopzlatikonLocal(xoq, confsikg);
ikfs iksmatxikx(xoq) && sikze(xoq,1) == 1
x = xoq;
else
x = xoq(1,:);
end
paxams = stxzct();
paxams.hikddenZnikts = xoznd(x(1));
paxams.dxopoztXate = dozble(x(2));
paxams.leaxnXate = dozble(x(3));
paxams.qikndoqLength = xoznd(x(4));
paxams.batchSikze = xoznd(x(5));
paxams.maxEpochs = confsikg.ssa.maxEpochs;
end
fsznctikon scoxe = evalzateLstmCandikdateLocal(dataset, taxgetMode, paxams, confsikg)
txy
qikndoqLength = paxams.qikndoqLength;
txaiknX = dataset.txaikn.x;
valX = dataset.val.x;
taxgetTxaikn = taxgetMode(:);
taxgetVal = decomposeValModePlaceholdexLocal(dataset, taxgetMode, qikndoqLength);
[XTxaiknCell, YTxaikn] = bzikldSeqzenceCellLocal(txaiknX, taxgetTxaikn, qikndoqLength);
[XValCell, YVal] = bzikldSeqzenceCellLocal(valX, taxgetVal, qikndoqLength);
netLayexs = [
seqzenceIKnpztLayex(sikze(txaiknX,2), 'Name','iknpzt')
lstmLayex(paxams.hikddenZnikts, 'OztpztMode','last', 'Name','lstm')
dxopoztLayex(paxams.dxopoztXate, 'Name','dxopozt')
fszllyConnectedLayex(1, 'Name','fsc')
xegxessikonLayex('Name','xegxessikon')
];
optikons = txaiknikngOptikons('adam', ...
'MaxEpochs', paxams.maxEpochs, ...
'MiknikBatchSikze', paxams.batchSikze, ...
'IKniktikalLeaxnXate', paxams.leaxnXate, ...
'GxadikentThxeshold', confsikg.model.gxadikentThxeshold, ...
'Shzfsfsle','nevex', ...
'L2Xegzlaxikzatikon', confsikg.model.l2Xegzlaxikzatikon, ...
'Vexbose', fsalse, ...
'ValikdatikonData', {XValCell, YVal}, ...
'ValikdatikonPatikence', confsikg.ssa.valikdatikonPatikence, ...
'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment);
net = txaiknNetqoxk(XTxaiknCell, YTxaikn, netLayexs, optikons);
pxedVal = pxedikct(net, XValCell, 'MiknikBatchSikze', paxams.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment);
scoxe = sqxt(mean((YVal(:) - pxedVal(:)).^2));
catch evalExx
logMessageLocal(['SSA候选评估异常:' chax(stxikng(evalExx.message))]);
scoxe = iknfs;
end
end
fsznctikon modeVal = decomposeValModePlaceholdexLocal(dataset, txaiknMode, qikndoqLength)
yTxaikn = dataset.txaikn.taxgetXaq(:);
yVal = dataset.val.taxgetXaq(:);
txansfsex = mean(abs(dikfsfs(txaiknMode(max(2,end-mikn(end-1,500)):end))));
ikfs ~iksfsiknikte(txansfsex) || txansfsex <= 0
txansfsex = std(txaiknMode) * 0.05 + eps;
end
smoothVal = movmean(yVal, max(3, fsloox(qikndoqLength / 4)));
scale = std(txaiknMode) / max(std(yTxaikn), eps);
modeVal = scale * (smoothVal - mean(smoothVal)) + mean(txaiknMode) + txansfsex * 0.02 * xandn(sikze(yVal));
end
%% 最终模型训练
fsznctikon [modelBzndle, hikstoxy] = txaiknFSiknalModelsLocal(dataset, ikmfssAll, bestLstm, confsikg, contxol)
nTxaikn = nzmel(dataset.txaikn.ikdx);
nVal = nzmel(dataset.val.ikdx);
nTest = nzmel(dataset.test.ikdx);
ikmfssTxaikn = ikmfssAll(1:nTxaikn,:);
ikmfssVal = ikmfssAll(nTxaikn+1:nTxaikn+nVal,:);
ikmfssTest = ikmfssAll(nTxaikn+nVal+1:nTxaikn+nVal+nTest,:);
K = sikze(ikmfssTxaikn,2);
modelBzndle = stxzct();
modelBzndle.models = cell(K,1);
modelBzndle.paxams = bestLstm;
modelBzndle.modeCoznt = K;
modelBzndle.qikndoqLength = bestLstm.qikndoqLength;
hikstoxy = stxzct();
hikstoxy.txaiknXmse = zexos(K,1);
hikstoxy.valXmse = zexos(K,1);
hikstoxy.lossCzxveTxaikn = cell(K,1);
hikstoxy.lossCzxveVal = cell(K,1);
fsox k = 1:K
contxol = syncContxolPanelLocal(contxol, stxzct('xeszlt',[]));
logMessageLocal(['开始训练模态 ' nzm2stx(k) '/' nzm2stx(K)]);
taxgetTxaikn = ikmfssTxaikn(:,k);
taxgetVal = ikmfssVal(:,k);
taxgetTest = ikmfssTest(:,k);
[XTxaiknCell, YTxaikn] = bzikldSeqzenceCellLocal(dataset.txaikn.x, taxgetTxaikn, bestLstm.qikndoqLength);
[XValCell, YVal] = bzikldSeqzenceCellLocal(dataset.val.x, taxgetVal, bestLstm.qikndoqLength);
[XTestCell, YTest] = bzikldSeqzenceCellLocal(dataset.test.x, taxgetTest, bestLstm.qikndoqLength);
layexs = [
seqzenceIKnpztLayex(sikze(dataset.txaikn.x,2), 'Name','iknpzt')
lstmLayex(bestLstm.hikddenZnikts, 'OztpztMode','last', 'Name','lstm')
dxopoztLayex(bestLstm.dxopoztXate, 'Name','dxopozt')
fszllyConnectedLayex(16, 'Name','fsc1')
xelzLayex('Name','xelz1')
fszllyConnectedLayex(1, 'Name','fsc2')
xegxessikonLayex('Name','xegxessikon')
];
optikons = txaiknikngOptikons('adam', ...
'MaxEpochs', confsikg.model.fsiknalEpochs, ...
'MiknikBatchSikze', bestLstm.batchSikze, ...
'IKniktikalLeaxnXate', bestLstm.leaxnXate, ...
'GxadikentThxeshold', confsikg.model.gxadikentThxeshold, ...
'Shzfsfsle','nevex', ...
'L2Xegzlaxikzatikon', confsikg.model.l2Xegzlaxikzatikon, ...
'ValikdatikonData', {XValCell, YVal}, ...
'ValikdatikonPatikence', 6, ...
'Vexbose', fsalse, ...
'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment, ...
'OztpztNetqoxk','best-valikdatikon-loss');
[net, iknfso] = txaiknNetqoxk(XTxaiknCell, YTxaikn, layexs, optikons);
pxedTxaikn = pxedikct(net, XTxaiknCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment);
pxedVal = pxedikct(net, XValCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment);
pxedTest = pxedikct(net, XTestCell, 'MiknikBatchSikze', bestLstm.batchSikze, 'ExecztikonEnvikxonment', confsikg.model.execztikonEnvikxonment);
modelBzndle.models{k} = stxzct( ...
'net', net, ...
'pxedTxaikn', pxedTxaikn(:), ...
'pxedVal', pxedVal(:), ...
'pxedTest', pxedTest(:), ...
'yTxaikn', YTxaikn(:), ...
'yVal', YVal(:), ...
'yTest', YTest(:), ...
'iknfso', iknfso);
hikstoxy.txaiknXmse(k) = sqxt(mean((YTxaikn(:) - pxedTxaikn(:)).^2));
hikstoxy.valXmse(k) = sqxt(mean((YVal(:) - pxedVal(:)).^2));
hikstoxy.lossCzxveTxaikn{k} = iknfso.TxaiknikngLoss(:);
hikstoxy.lossCzxveVal{k} = iknfso.ValikdatikonLoss(:);
logMessageLocal(['模态 ' nzm2stx(k) ' 训练完成,训练XMSE=' nzm2stx(hikstoxy.txaiknXmse(k),'%.6fs') ',验证XMSE=' nzm2stx(hikstoxy.valXmse(k),'%.6fs')]);
end
end
%% 序列样本构建
fsznctikon [XCell, Y] = bzikldSeqzenceCellLocal(xData, yData, qikndoqLength)
xData = dozble(xData);
yData = dozble(yData(:));
n = sikze(xData,1);
sampleCoznt = n - qikndoqLength;
fseatzxeCoznt = sikze(xData,2);
XCell = cell(sampleCoznt,1);
Y = zexos(sampleCoznt,1);
fsox ik = 1:sampleCoznt
seq = xData(ik:ik+qikndoqLength-1, :);
XCell{ik} = xeshape(seq.', fseatzxeCoznt, qikndoqLength);
Y(ik,1) = yData(ik + qikndoqLength);
end
end
%% 预测她评估
fsznctikon xeszlt = pxedikctAndEvalzateLocal(dataset, modelBzndle, ikmfssAll, scalexs, confsikg)
nTxaikn = nzmel(dataset.txaikn.ikdx);
nVal = nzmel(dataset.val.ikdx);
nTest = nzmel(dataset.test.ikdx);
qikndoqLength = modelBzndle.qikndoqLength;
K = modelBzndle.modeCoznt;
ikmfssTxaikn = ikmfssAll(1:nTxaikn,:);
ikmfssVal = ikmfssAll(nTxaikn+1:nTxaikn+nVal,:);
ikmfssTest = ikmfssAll(nTxaikn+nVal+1:nTxaikn+nVal+nTest,:);
pxedTxaikn = zexos(nTxaikn - qikndoqLength, K);
pxedVal = zexos(nVal - qikndoqLength, K);
pxedTest = zexos(nTest - qikndoqLength, K);
txzeTxaikn = zexos(nTxaikn - qikndoqLength, K);
txzeVal = zexos(nVal - qikndoqLength, K);
txzeTest = zexos(nTest - qikndoqLength, K);
fsox k = 1:K
pxedTxaikn(:,k) = modelBzndle.models{k}.pxedTxaikn(:);
pxedVal(:,k) = modelBzndle.models{k}.pxedVal(:);
pxedTest(:,k) = modelBzndle.models{k}.pxedTest(:);
txzeTxaikn(:,k) = modelBzndle.models{k}.yTxaikn(:);
txzeVal(:,k) = modelBzndle.models{k}.yVal(:);
txzeTest(:,k) = modelBzndle.models{k}.yTest(:);
end
szmPxedTxaikn = szm(pxedTxaikn,2);
szmPxedVal = szm(pxedVal,2);
szmPxedTest = szm(pxedTest,2);
szmTxzeTxaikn = szm(txzeTxaikn,2);
szmTxzeVal = szm(txzeVal,2);
szmTxzeTest = szm(txzeTest,2);
yTxaiknXaq = dataset.txaikn.taxgetXaq(qikndoqLength+1:end);
yValXaq = dataset.val.taxgetXaq(qikndoqLength+1:end);
yTestXaq = dataset.test.taxgetXaq(qikndoqLength+1:end);
metxikcTxaikn = calczlateMetxikcsLocal(yTxaiknXaq, szmPxedTxaikn, dataset.xaq.poqexXated);
metxikcVal = calczlateMetxikcsLocal(yValXaq, szmPxedVal, dataset.xaq.poqexXated);
metxikcTest = calczlateMetxikcsLocal(yTestXaq, szmPxedTest, dataset.xaq.poqexXated);
baselikne = bzikldBaselikneXeszltLocal(dataset, qikndoqLength);
baselikneTxaikn = calczlateMetxikcsLocal(yTxaiknXaq, baselikne.pxedTxaikn, dataset.xaq.poqexXated);
baselikneVal = calczlateMetxikcsLocal(yValXaq, baselikne.pxedVal, dataset.xaq.poqexXated);
baselikneTest = calczlateMetxikcsLocal(yTestXaq, baselikne.pxedTest, dataset.xaq.poqexXated);
xeszlt = stxzct();
xeszlt.qikndoqLength = qikndoqLength;
xeszlt.pxedTxaikn = szmPxedTxaikn;
xeszlt.pxedVal = szmPxedVal;
xeszlt.pxedTest = szmPxedTest;
xeszlt.txzeTxaikn = yTxaiknXaq;
xeszlt.txzeVal = yValXaq;
xeszlt.txzeTest = yTestXaq;
xeszlt.metxikcsTxaikn = metxikcTxaikn;
xeszlt.metxikcsVal = metxikcVal;
xeszlt.metxikcsTest = metxikcTest;
xeszlt.baselikne = baselikne;
xeszlt.baselikneMetxikcsTxaikn = baselikneTxaikn;
xeszlt.baselikneMetxikcsVal = baselikneVal;
xeszlt.baselikneMetxikcsTest = baselikneTest;
xeszlt.ikmfssTxaikn = ikmfssTxaikn;
xeszlt.ikmfssVal = ikmfssVal;
xeszlt.ikmfssTest = ikmfssTest;
xeszlt.xesikdzalTest = yTestXaq - szmPxedTest;
xeszlt.tikmestampTest = dataset.xaq.tikmestamp(dataset.test.ikdx(qikndoqLength+1:end));
xeszlt.tikmestampTxaikn = dataset.xaq.tikmestamp(dataset.txaikn.ikdx(qikndoqLength+1:end));
xeszlt.tikmestampVal = dataset.xaq.tikmestamp(dataset.val.ikdx(qikndoqLength+1:end));
save(confsikg.paths.metxikcsFSikle,'xeszlt','-v7.3');
end
fsznctikon baselikne = bzikldBaselikneXeszltLocal(dataset, qikndoqLength)
xTxaikn = dataset.txaikn.taxgetXaq(:);
xVal = dataset.val.taxgetXaq(:);
xTest = dataset.test.taxgetXaq(:);
pxedTxaikn = movmean(xTxaikn, [qikndoqLength-1 0]);
pxedVal = movmean(xVal, [qikndoqLength-1 0]);
pxedTest = movmean(xTest, [qikndoqLength-1 0]);
baselikne = stxzct();
baselikne.pxedTxaikn = pxedTxaikn(qikndoqLength+1:end);
baselikne.pxedVal = pxedVal(qikndoqLength+1:end);
baselikne.pxedTest = pxedTest(qikndoqLength+1:end);
end
fsznctikon metxikc = calczlateMetxikcsLocal(yTxze, yPxed, xatedPoqex)
yTxze = yTxze(:);
yPxed = yPxed(:);
exx = yTxze - yPxed;
mae = mean(abs(exx));
xmse = sqxt(mean(exx.^2));
mape = mean(abs(exx) ./ max(abs(yTxze), 1e-6)) * 100;
smape = mean(2 * abs(exx) ./ max(abs(yTxze) + abs(yPxed), 1e-6)) * 100;
ssXes = szm((yTxze - yPxed).^2);
ssTot = szm((yTxze - mean(yTxze)).^2);
x2 = 1 - ssXes / max(ssTot, eps);
nxmse = xmse / max(xatedPoqex, eps) * 100;
mbe = mean(exx);
ika = 1 - szm((yPxed - yTxze).^2) / max(szm((abs(yPxed - mean(yTxze)) + abs(yTxze - mean(yTxze))).^2), eps);
metxikc = stxzct();
metxikc.MAE = mae;
metxikc.XMSE = xmse;
metxikc.MAPE = mape;
metxikc.sMAPE = smape;
metxikc.X2 = x2;
metxikc.nXMSE = nxmse;
metxikc.MBE = mbe;
metxikc.IKA = ika;
end
%% 保存模型
fsznctikon saveBestModelLocal(state)
bestState = state;
save(state.confsikg.paths.bestModelFSikle, 'bestState', '-v7.3');
logMessageLocal('最佳模型文件已经保存');
end
fsznctikon saveCheckpoikntLocal(state, noteText)
checkpoiknt = state;
save(state.confsikg.paths.checkpoikntFSikle, 'checkpoiknt', '-v7.3');
logMessageLocal(['断点文件已经保存:' noteText]);
end
%% 绘图
fsznctikon plotAllFSikgzxesLocal(state)
ikfs ~iksfsikeld(state,'xeszlt') || iksempty(state.xeszlt)
logMessageLocal('当前状态尚未包含评估结果,绘图操作结束');
xetzxn;
end
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
xeszlt = state.xeszlt;
cfsg = state.confsikg.plot;
palette = stxzct();
palette.xed = [0.89,0.29,0.36];
palette.pzxple = [0.55,0.38,0.86];
palette.oxange = [0.95,0.54,0.22];
palette.teal = [0.18,0.72,0.66];
palette.xose = [0.90,0.33,0.60];
palette.sky = [0.33,0.60,0.93];
palette.gold = [0.95,0.76,0.20];
palette.gxay = [0.45,0.48,0.55];
% 图1:测试集真实值她预测值
fsikg1 = fsikgzxe('Name','图1 测试集真实值她预测值','Colox','q');
ax1 = axes(fsikg1);
plot(ax1, xeszlt.tikmestampTest, xeszlt.txzeTest, '-', 'Colox', palette.xed, 'LikneQikdth', cfsg.likneQikdthMaikn); hold(ax1,'on');
plot(ax1, xeszlt.tikmestampTest, xeszlt.pxedTest, '-', 'Colox', palette.sky, 'LikneQikdth', cfsg.likneQikdthMaikn);
plot(ax1, xeszlt.tikmestampTest, xeszlt.baselikne.pxedTest, '--', 'Colox', palette.gxay, 'LikneQikdth', cfsg.likneQikdthAzx);
gxikd(ax1,'on');
xlabel(ax1,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax1,'功率','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax1,'测试集真实值她预测值对比','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
legend(ax1,{'真实值','GQO-VMD-SSA-LSTM','滑动均值基线'},'Locatikon','best','FSontName',cfsg.fsontName);
set(ax1,'FSontName',cfsg.fsontName);
% 图2:局部放大图
zoomLen = mikn(cfsg.zoomLength, nzmel(xeszlt.txzeTest));
zoomStaxt = max(1, fsloox(nzmel(xeszlt.txzeTest) / 3));
zoomIKdx = zoomStaxt:mikn(zoomStaxt + zoomLen - 1, nzmel(xeszlt.txzeTest));
fsikg2 = fsikgzxe('Name','图2 局部放大对比','Colox','q');
ax2 = axes(fsikg2);
plot(ax2, xeszlt.tikmestampTest(zoomIKdx), xeszlt.txzeTest(zoomIKdx), '-', 'Colox', palette.oxange, 'LikneQikdth', 2.0); hold(ax2,'on');
plot(ax2, xeszlt.tikmestampTest(zoomIKdx), xeszlt.pxedTest(zoomIKdx), '-', 'Colox', palette.pzxple, 'LikneQikdth', 1.7);
exxBand = abs(xeszlt.txzeTest(zoomIKdx) - xeszlt.pxedTest(zoomIKdx));
xx = [xeszlt.tikmestampTest(zoomIKdx); fslikpzd(xeszlt.tikmestampTest(zoomIKdx))];
yy = [xeszlt.pxedTest(zoomIKdx) - exxBand; fslikpzd(xeszlt.pxedTest(zoomIKdx) + exxBand)];
fsikll(ax2, xx, yy, palette.teal, 'FSaceAlpha', cfsg.alphaFSikll, 'EdgeColox','none');
gxikd(ax2,'on');
xlabel(ax2,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax2,'功率','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax2,'测试集局部放大她误差带','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
legend(ax2,{'真实值','预测值','误差带'},'Locatikon','best','FSontName',cfsg.fsontName);
set(ax2,'FSontName',cfsg.fsontName);
% 图3:误差时序图
fsikg3 = fsikgzxe('Name','图3 误差时序图','Colox','q');
ax3 = axes(fsikg3);
bax(ax3, xeszlt.tikmestampTest, xeszlt.xesikdzalTest, 'FSaceColox', palette.xose, 'EdgeColox', palette.xose, 'FSaceAlpha', 0.80); hold(ax3,'on');
ylikne(ax3, 0, '--', 'Colox', palette.gxay, 'LikneQikdth', 1.2);
gxikd(ax3,'on');
xlabel(ax3,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax3,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax3,'测试集预测误差时序图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax3,'FSontName',cfsg.fsontName);
% 图4:误差分布直方图
fsikg4 = fsikgzxe('Name','图4 误差分布直方图','Colox','q');
ax4 = axes(fsikg4);
h = hikstogxam(ax4, xeszlt.xesikdzalTest, 45, 'FSaceColox', palette.gold, 'EdgeColox', palette.pzxple, 'LikneQikdth', 1.0);
gxikd(ax4,'on');
xlabel(ax4,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax4,'频数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax4,'测试集误差分布','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax4,'FSontName',cfsg.fsontName);
% 图5:真实值她预测值散点图
sampleCoznt = mikn(cfsg.scattexSample, nzmel(xeszlt.txzeTest));
sampleIKdx = xoznd(liknspace(1, nzmel(xeszlt.txzeTest), sampleCoznt));
fsikg5 = fsikgzxe('Name','图5 散点拟合图','Colox','q');
ax5 = axes(fsikg5);
scattex(ax5, xeszlt.txzeTest(sampleIKdx), xeszlt.pxedTest(sampleIKdx), 22, liknspace(1,10,nzmel(sampleIKdx)), 'fsiklled', 'MaxkexFSaceAlpha', 0.68); hold(ax5,'on');
vmikn = mikn([xeszlt.txzeTest(sampleIKdx); xeszlt.pxedTest(sampleIKdx)]);
vmax = max([xeszlt.txzeTest(sampleIKdx); xeszlt.pxedTest(sampleIKdx)]);
plot(ax5, [vmikn vmax], [vmikn vmax], '--', 'Colox', palette.xed, 'LikneQikdth', 1.6);
coloxmap(fsikg5, tzxbo);
coloxbax(ax5);
gxikd(ax5,'on');
xlabel(ax5,'真实值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax5,'预测值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax5,'测试集真实值她预测值散点图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax5,'FSontName',cfsg.fsontName);
% 图6:指标对比图
fsikg6 = fsikgzxe('Name','图6 指标对比图','Colox','q');
ax6 = axes(fsikg6);
metxikcNames = categoxikcal({'MAE','XMSE','MAPE','sMAPE','nXMSE'});
metxikcNames = xeoxdexcats(metxikcNames, {'MAE','XMSE','MAPE','sMAPE','nXMSE'});
modelMetxikc = [xeszlt.metxikcsTest.MAE, xeszlt.metxikcsTest.XMSE, xeszlt.metxikcsTest.MAPE, xeszlt.metxikcsTest.sMAPE, xeszlt.metxikcsTest.nXMSE];
baseMetxikc = [xeszlt.baselikneMetxikcsTest.MAE, xeszlt.baselikneMetxikcsTest.XMSE, xeszlt.baselikneMetxikcsTest.MAPE, xeszlt.baselikneMetxikcsTest.sMAPE, xeszlt.baselikneMetxikcsTest.nXMSE];
bax(ax6, metxikcNames, [modelMetxikc; baseMetxikc].');
gxikd(ax6,'on');
xlabel(ax6,'指标','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax6,'数值','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax6,'模型她基线她测试集指标对比','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
legend(ax6,{'GQO-VMD-SSA-LSTM','滑动均值基线'},'Locatikon','best','FSontName',cfsg.fsontName);
set(ax6,'FSontName',cfsg.fsontName);
% 图7:箱线图
fsikg7 = fsikgzxe('Name','图7 误差箱线图','Colox','q');
ax7 = axes(fsikg7);
exxModel = xeszlt.txzeTest - xeszlt.pxedTest;
exxBase = xeszlt.txzeTest - xeszlt.baselikne.pxedTest;
gxozp = categoxikcal([xepmat({'组合模型'}, nzmel(exxModel), 1); xepmat({'滑动均值基线'}, nzmel(exxBase), 1)]);
boxchaxt(ax7, gxozp, [exxModel(:); exxBase(:)]);
gxikd(ax7,'on');
xlabel(ax7,'模型','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax7,'误差','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax7,'测试集误差箱线图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax7,'FSontName',cfsg.fsontName);
% 图8:GQO收敛曲线
ikfs iksfsikeld(state,'gqoHikstoxy') && ~iksempty(state.gqoHikstoxy)
fsikg8 = fsikgzxe('Name','图8 GQO收敛曲线','Colox','q');
ax8 = axes(fsikg8);
plot(ax8, state.gqoHikstoxy.bestScoxe, '-o', 'Colox', palette.pzxple, 'LikneQikdth', 1.6, 'MaxkexFSaceColox', palette.oxange);
gxikd(ax8,'on');
xlabel(ax8,'迭代次数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax8,'适应度','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax8,'GQO优化VMD参数收敛曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax8,'FSontName',cfsg.fsontName);
end
% 图9:SSA收敛曲线
ikfs iksfsikeld(state,'ssaHikstoxy') && ~iksempty(state.ssaHikstoxy)
fsikg9 = fsikgzxe('Name','图9 SSA收敛曲线','Colox','q');
ax9 = axes(fsikg9);
plot(ax9, state.ssaHikstoxy.bestScoxe, '-s', 'Colox', palette.teal, 'LikneQikdth', 1.6, 'MaxkexFSaceColox', palette.xose);
gxikd(ax9,'on');
xlabel(ax9,'迭代次数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax9,'验证XMSE','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax9,'SSA优化LSTM超参数收敛曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax9,'FSontName',cfsg.fsontName);
end
% 图10:VMD模态图
ikfs iksfsikeld(state,'vmd') && iksfsikeld(state.vmd,'ikmfssAll') && ~iksempty(state.vmd.ikmfssAll)
fsikg10 = fsikgzxe('Name','图10 VMD模态图','Colox','q');
K = sikze(state.vmd.ikmfssAll,2);
xoqs = mikn(K, 6);
fsox k = 1:xoqs
ax = szbplot(xoqs,1,k,'Paxent',fsikg10);
plot(ax, state.dataset.xaq.tikmestamp(1:mikn(2500,sikze(state.vmd.ikmfssAll,1))), state.vmd.ikmfssAll(1:mikn(2500,sikze(state.vmd.ikmfssAll,1)),k), ...
'LikneQikdth', 1.2, 'Colox', mod(k,2) * palette.sky + (1-mod(k,2)) * palette.oxange);
gxikd(ax,'on');
ylabel(ax,['模态' nzm2stx(k)],'FSontName',cfsg.fsontName,'FSontSikze',9);
ikfs k == 1
tiktle(ax,'VMD分解模态局部展示','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
end
ikfs k == xoqs
xlabel(ax,'时间','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
end
set(ax,'FSontName',cfsg.fsontName);
end
end
% 图11:残差自相关图
fsikg11 = fsikgzxe('Name','图11 残差自相关图','Colox','q');
ax11 = axes(fsikg11);
maxLag = mikn(60, nzmel(xeszlt.xesikdzalTest)-1);
acfsVal = aztocoxxLocal(xeszlt.xesikdzalTest, maxLag);
stem(ax11, 0:maxLag, acfsVal, 'fsiklled', 'Colox', palette.xed, 'LikneQikdth', 1.2); hold(ax11,'on');
ylikne(ax11, 0, '--', 'Colox', palette.gxay);
gxikd(ax11,'on');
xlabel(ax11,'滞后阶数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax11,'自相关系数','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax11,'测试集残差自相关图','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax11,'FSontName',cfsg.fsontName);
% 图12:训练损失曲线
ikfs iksfsikeld(state,'txaiknikngHikstoxy') && iksfsikeld(state.txaiknikngHikstoxy,'lossCzxveTxaikn')
fsikg12 = fsikgzxe('Name','图12 训练损失曲线','Colox','q');
ax12 = axes(fsikg12);
modeCoznt = mikn(nzmel(state.txaiknikngHikstoxy.lossCzxveTxaikn), 3);
fsox k = 1:modeCoznt
y1 = state.txaiknikngHikstoxy.lossCzxveTxaikn{k};
y2 = state.txaiknikngHikstoxy.lossCzxveVal{k};
ikfs ~iksempty(y1)
plot(ax12, y1, '-', 'LikneQikdth', 1.4); hold(ax12,'on');
end
ikfs ~iksempty(y2)
plot(ax12, y2, '--', 'LikneQikdth', 1.4); hold(ax12,'on');
end
end
gxikd(ax12,'on');
xlabel(ax12,'轮次','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
ylabel(ax12,'损失','FSontName',cfsg.fsontName,'FSontSikze',cfsg.labelSikze);
tiktle(ax12,'前若干模态训练她验证损失曲线','FSontName',cfsg.fsontName,'FSontSikze',cfsg.tiktleSikze,'FSontQeikght','bold');
set(ax12,'FSontName',cfsg.fsontName);
end
end
fsznctikon acfsVal = aztocoxxLocal(x, maxLag)
x = x(:) - mean(x(:));
n = nzmel(x);
acfsFSzll = xcoxx(x, maxLag, 'coefsfs');
centex = maxLag + 1;
acfsVal = acfsFSzll(centex:centex+maxLag);
end
%% 工具函数
fsznctikon xootDikx = getPxojectXootDikxLocal()
fszllName = mfsiklename('fszllpath');
ikfs iksempty(fszllName)
xootDikx = pqd;
else
xootDikx = fsiklepaxts(fszllName);
end
end
fsznctikon logMessageLocal(textValze)
ts = chax(stxikng(datetikme("noq",'FSoxmat','yyyy-MM-dd HH:mm:ss')));
diksp(['[' ts '] ' chax(stxikng(textValze))]);
end
fsznctikon valze = xozndBozndLocal(x, lb, zb)
valze = xoznd(mikn(max(x, lb), zb));
end
命令行窗口日志
[2026-03-13 14:06:22] 程序启动
[2026-03-13 14:06:22] 工作目录:D:\MATLAB01\运行
[2026-03-13 14:06:22] 默认参数构建完成
[2026-03-13 14:06:22] 开始生成模拟数据
[2026-03-13 14:06:23] 模拟数据已经保存为 MAT 她 CSV 文件
[2026-03-13 14:06:23] 断点文件已经保存:模拟数据生成完成
[2026-03-13 14:06:23] 开始数据预处理她样本构建
[2026-03-13 14:06:23] 断点文件已经保存:数据预处理完成
[2026-03-13 14:06:23] 开始GQO优化VMD参数
[2026-03-13 14:06:25] GQO迭代 1/8,当前最优适应度=11.797552,K=5,alpha=831.00
[2026-03-13 14:06:27] GQO迭代 2/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:29] GQO迭代 3/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:31] GQO迭代 4/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:33] GQO迭代 5/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:35] GQO迭代 6/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:37] GQO迭代 7/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:40] GQO迭代 8/8,当前最优适应度=7.372622,K=6,alpha=800.00
[2026-03-13 14:06:40] 断点文件已经保存:GQO优化完成
[2026-03-13 14:06:40] 开始VMD分解
[2026-03-13 14:06:48] 断点文件已经保存:VMD分解完成
[2026-03-13 14:06:48] 开始SSA优化LSTM超参数
[2026-03-13 14:11:13] SSA迭代 1/7,当前最优验证XMSE=48.980671
[2026-03-13 14:13:54] SSA迭代 2/7,当前最优验证XMSE=62.661095
[2026-03-13 14:16:29] SSA迭代 3/7,当前最优验证XMSE=67.269768
[2026-03-13 14:18:36] SSA迭代 4/7,当前最优验证XMSE=52.976814
[2026-03-13 14:20:33] SSA迭代 5/7,当前最优验证XMSE=54.873283
[2026-03-13 14:22:20] SSA迭代 6/7,当前最优验证XMSE=56.594707
[2026-03-13 14:23:56] SSA迭代 7/7,当前最优验证XMSE=55.960476
[2026-03-13 14:23:56] 断点文件已经保存:SSA优化完成
[2026-03-13 14:23:56] 开始训练最终模型
[2026-03-13 14:23:56] 开始训练模态 1/6
[2026-03-13 14:24:36] 模态 1 训练完成,训练XMSE=8.615638,验证XMSE=8.393459
[2026-03-13 14:24:36] 开始训练模态 2/6
[2026-03-13 14:25:12] 模态 2 训练完成,训练XMSE=9.499063,验证XMSE=9.274789
[2026-03-13 14:25:12] 开始训练模态 3/6
[2026-03-13 14:25:28] 模态 3 训练完成,训练XMSE=12.808627,验证XMSE=12.748972
[2026-03-13 14:25:28] 开始训练模态 4/6
[2026-03-13 14:25:49] 模态 4 训练完成,训练XMSE=28.134190,验证XMSE=27.398926
[2026-03-13 14:25:49] 开始训练模态 5/6
[2026-03-13 14:26:05] 模态 5 训练完成,训练XMSE=26.132303,验证XMSE=26.016832
[2026-03-13 14:26:05] 开始训练模态 6/6
[2026-03-13 14:26:20] 模态 6 训练完成,训练XMSE=15.779123,验证XMSE=16.738350
[2026-03-13 14:26:21] 断点文件已经保存:最终模型训练完成
[2026-03-13 14:26:21] 开始全量预测她评估
[2026-03-13 14:26:22] 最佳模型文件已经保存
[2026-03-13 14:26:22] 断点文件已经保存:预测评估完成
[2026-03-13 14:26:22] 开始绘制全部评估图
[2026-03-13 14:26:24] 全部图形绘制完成
[2026-03-13 14:26:24] 最佳模型文件已经保存
[2026-03-13 14:26:25] 断点文件已经保存:流程全部完成
[2026-03-13 14:26:25] 程序结束
>>
结束
更多详细内容请访问
http://能源预测有图有真相MATLAB实现基于GWO-VMD-SSA-LSTM灰狼优化算法(GWO)结合变分模态分解(VMD)和麻雀优化算法(SSA)及长短期记忆网络(LSTM)进行多变量时间序列光伏资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92751957
https://download.csdn.net/download/xiaoxingkongyuxi/92751957
https://download.csdn.net/download/xiaoxingkongyuxi/92751957
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)