ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SVM-LSTM回归预测实战:小样本时序数据建模与MATLAB GUI实现

SVM-LSTM回归预测实战:小样本时序数据建模与MATLAB GUI实现 简介一套基于MATLAB实现的支持向量机SVM与长短期记忆网络LSTM融合的回归预测完整项目面向具备一定编程基础、熟悉机器学习与深度学习原理的研究人员、工程师及高年级学生适用于电力负荷、新能源功率、设备状态等强时序非线性预测场景。项目从数据生成、预处理、滑窗构造到LSTM特征提取、SVM回归训练及评估可视化形成闭环重点解决时序依赖与非线性关系难以同时建模的问题。压缩包仅含1个docx文档大小128KB文档内含完整程序、GUI设计与代码详解结构覆盖项目背景、模型架构、代码示例等可作为可复用建模模板。已有70人学习下载。相比零散代码这份整理能帮助读者快速理解SVM-LSTM串联机制与GUI回调逻辑降低复现门槛适合作为课程设计或工程预研的基础参考。1. 为什么回归预测要绕一大圈用SVM-LSTM一个缝合模型的实用边界SVM-LSTM回归预测光看名字像个强行缝合的模型组合实际上在工程仿真和小样本时序数据上它比单独用SVM或LSTM要稳得多。我在做设备剩余寿命预测时遇到过一种典型困境数据只有几百条LSTM还没训练到位就过拟合而SVM完全吃不到时间依赖信息。把LSTM当特征提取器、把SVM当回归头之后两者短板刚好互补。这个方案适合谁手头有仿真数据、传感器时序、容量衰减曲线这类“数据量不大但时间顺序非常重要”的回归任务也适合想用MATLAB快速做出一个能演示、能点按钮、能把训练过程和预测结果展示出来的项目。你需要理解一点组合模型不是玄学它更接近流水线——LSTM负责从窗口序列里压缩出特征SVM负责在小样本下把特征映射到目标值。下面从原理到代码再到GUI一步步说清楚。2. 先立住理论SVR的管道、LSTM的隐状态以及三种组合结构的选型2.1 SVR的回归逻辑间隔、不敏感损失和核函数SVM做回归时我们通常称它为SVR全称是Support Vector Regression。它的思想不是“让预测线穿过所有点”而是找一条“管道”管道内部允许误差管道外部的点才被当作真正的问题样本。这个管道的半宽就是参数Epsilon也叫不敏感损失。误差小于Epsilon的样本不贡献损失大于Epsilon的样本才参与优化这样模型天然对小噪声不敏感。对回归任务来说SVM的关键参数有三个核函数、BoxConstraint也叫C和Epsilon。BoxConstraint控制对管道外样本的惩罚力度越大越“认真”越小越容许偏差Epsilon控制管道的宽容度越大越“糊”。这两个参数是互相牵制的如果你把C设很大、Epsilon设很小结果就是每个样本都想拉成支持向量模型文件大、预测时抖动剧烈。在MATLAB里回归SVM对应的函数是fitrsvm。默认核函数是高斯核rbf可以换成linear、polynomial。我一般建议先用linear跑一个baseline因为LSTM提取出来的特征通常已经比较紧凑线性核在很多情况下够用只有当线性核离线评估不好时再换rbf并配合KernelScale调节。对于小样本仿真数据高斯核上限高但翻车率也高这是后面避坑部分要重点提的。2.2 LSTM的时序特征提取细胞状态与三个门在回归任务中起什么作用LSTM在组合模型里的角色不是“最终输出”而是“特征压缩器”。它从头到尾读入一个时间窗口通过遗忘门、输入门、输出门维护一条细胞状态。这条细胞状态可以理解为模型在整个窗口内积累的“记忆”而我们真正要拿来做回归的是最后一个时间步的隐状态h_t。它把窗口里的时间依赖关系压缩成一个向量这个向量就是SVM的输入。很多人问LSTM不是已经有了输出层吗为什么还要接SVM原因是MATLAB中典型的LSTM回归网络在最后接的是全连接层全连接层本质上是一个线性回归头。当样本量只有几百时线性头拟合非线性目标很吃力换成SVM作为回归头可以借核函数做非线性映射又不容易像深层的全连接那样过拟合。在代码层面关键是lstmLayer的OutputMode参数。如果设成lastLSTM只返回最后一个时刻的隐状态设成sequence则返回每一个时刻的输出。我们后续用activations提取特征时需要给这一层起个明确的名字否则默认名称容易在多层结构里混淆。还有一个直觉判断窗口越长h_t要压缩的信息越多特征提取难度越大窗口太短又可能丢长周期趋势。所以窗口长度是第一个要调的超参数。2.3 组合方式选型串联特征输入、并联加权、残差修正三种结构的区别SVM-LSTM这个名头下实际工程里有三种常见接法差别很大别听到组合就随便拼。结构数据流适用场景主要翻车点串联特征输入原始窗口 → LSTM提取特征 → SVM输出小样本、强非线性、需要解释中间特征LSTM特征质量决定上限并联加权输出LSTM预测一个值SVM用原始特征预测一个值再加权融合对稳定性要求高需要多个模型互相纠错权重需要额外调工作量翻倍残差修正LSTM先预测SVM预测LSTM残差最终结果相加目标波动大LSTM能抓住趋势但丢细节残差归一化后太小时SVM学不到信号我在实际项目中用得最多的是第一种也就是“LSTM提取特征 → SVM回归输出”。原因很简单它最容易复现参数量最少而且后续封装GUI时传递模型最直接。并联和残差修正在生产环境有价值但如果你只是想把一个完整的SVM-LSTM回归项目跑通并展示串联结构已经能把大部分收益拿到手。如果你面对的是“小样本仿真数据预测”还经常有人拿高斯过程回归GPR来对比。我的看法是如果数据几乎是静态、没有时间依赖关系高斯过程回归确实省事但一旦你决定用滑动窗口引入时间信息LSTM在压缩时序特征上比手动构造滞后特征要省力得多。SVM-LSTM算是一个折中不吃大样本又能吃到时序结构。3. 搭一个可复现的SVM-LSTM回归程序从造数据到训练SVM回归头的完整代码3.1 数据准备与归一化单变量时序数据如何转成监督学习样本先把问题收敛到单变量时序回归输入是过去winSize个时间点输出是下一个时间点的值。我们生成的演示数据是趋势项加周期项加噪声共300个点。实际项目中你直接把data替换成自己的仿真或采集数据即可。% 生成演示用仿真时序数据趋势 周期 噪声 rng(42); n 300; t (1:n); data 10 0.05*t 2*sin(2*pi*t/50) 0.3*randn(n,1); % 按时间顺序划分训练/验证/测试 trainLen 180; valLen 40; trainData data(1:trainLen); valData data(trainLen1:trainLenvalLen); testData data(trainLenvalLen1:end); % 归一化参数只用训练段估计防止数据泄漏 [xtrainN, ps] mapminmax(trainData); xvalN mapminmax(apply, valData, ps); xtestN mapminmax(apply, testData, ps);这段代码里最需要注意的是mapminmax它按行处理所以传入列向量时要先转置成行向量。ps结构体里保存了训练段的min和range验证段和测试段都用mapminmax(apply, ...)套用同一套参数而不是各自重新归一化。很多人在这翻车后面避坑章节会专门展开。接下来把归一化后的序列切成窗口样本。窗口函数是组合模型的骨架我一般单独写成一个函数文件方便GUI里复用。function [X, Y] createSlidingWindow(data, winSize) % data: 归一化后的行向量或列向量 % X{i}: 第i个样本对应的 1 x winSize 窗口 % Y(i): 第i个样本的目标值 data data(:); % 强制转成列避免行列方向出错 n length(data) - winSize; X cell(n, 1); Y zeros(n, 1); for i 1:n X{i} data(i:iwinSize-1); Y(i) data(iwinSize); end end这段代码的逻辑落在“窗口末尾不能包含目标值”这个边界上。第i个样本取data(i)~data(iwinSize-1)目标是data(iwinSize)两者之间错开一个时刻。如果写成了data(i:iwinSize)并取data(iwinSize)为目标窗口末尾正好偷看了目标点训练时R2能到0.99预测时必然崩盘。这是时序监督学习最常见的低级错误。3.2 训练LSTM并在训练中把时序特征提取出来窗口化之后训练样本数是原始点数 - winSize。以300点数据、winSize20为例训练段180点能产出160个样本对LSTM来说已经是一个可以勉强学习的小数据集。注意这些样本有重叠所以验证集不能和训练集有重叠最好的做法是先把原始序列切成几段再在各段内部滑动。下面是LSTM部分的完整代码重点在层名和OutputMode。winSize 20; hiddenUnits 15; [XTr, YTr] createSlidingWindow(xtrainN, winSize); [XVal, YVal] createSlidingWindow(xvalN, winSize); [XTe, YTe] createSlidingWindow(xtestN, winSize); layers [ sequenceInputLayer(1, Name, input) lstmLayer(hiddenUnits, OutputMode, last, Name, lstm_feat) fullyConnectedLayer(1, Name, fc) regressionLayer ]; options trainingOptions(adam, ... MaxEpochs, 150, ... MiniBatchSize, 16, ... InitialLearnRate, 0.005, ... GradientThreshold, 1, ... ValidationData, {XVal, YVal}, ... ValidationFrequency, 20, ... Verbose, false); net trainNetwork(XTr, YTr, layers, options);lstm_feat这一层是后续SVM的特征来源。OutputMode设为last后activations返回的每一列就是一条样本在最后时间步的隐状态。hiddenUnits决定特征维度15个隐藏单元意味着SVM输入是15维。如果特征维度太大、样本太少SVM会非常容易过拟合但如果特征维度太小LSTM又压缩不够我一般从10到30之间试。MaxEpochs在数据量小的时候不能太小150轮足够让损失收敛但要配合GradientThreshold防止梯度爆炸。MiniBatchSize设成16是因为训练样本只有百来条太大的batch会在这类数据上产生明显波动。如果你的数据量超过几千这个值可以提到64。训练完成后用activations提取特征fTr activations(net, XTr, lstm_feat); fTe activations(net, XTe, lstm_feat); % 修正维度activations返回的矩阵通常是 hiddenUnits x 样本数 fTr squeeze(fTr); if size(fTr, 1) ~ numel(YTr) fTr fTr; end fTe squeeze(fTe); if size(fTe, 1) ~ numel(YTe) fTe fTe; end这里size(fTr, 1)检查的是“样本数”是否在前。不同MATLAB版本、不同层类型下activations的输出维度方向略有差异加入这层防御性判断能省掉很多排查时间。特征矩阵准备好后每一行是一个样本每一列是一个隐藏单元对应的特征。3.3 用SVM回归器学习特征到目标值的映射LSTM在训练过程中全连接层已经被优化过但我们不用它来预测而是把它当成一个辅助训练头。真正做最终预测的是SVM。SVM输入是刚刚提取的特征输出是归一化后的目标值。svmMdl fitrsvm(fTr, YTr, ... KernelFunction, rbf, ... KernelScale, auto, ... BoxConstraint, 20, ... Epsilon, 0.05, ... Standardize, true); predTrN predict(svmMdl, fTr); predTeN predict(svmMdl, fTe);KernelScale设成auto会让MATLAB自动估计尺度省去首次跑通时的手调。BoxConstraint20和Epsilon0.05是我在小样本回归里的常用起点。注意目标是归一化后的值所以预测结果也是归一化的。反归一化时必须用训练阶段保存的ps参数predTe mapminmax(reverse, predTeN, ps); YTeOrig testData(winSize1:end); rmse sqrt(mean((YTeOrig - predTe).^2)); mae mean(abs(YTeOrig - predTe)); r2 1 - sum((YTeOrig - predTe).^2) / sum((YTeOrig - mean(YTeOrig)).^2); fprintf(RMSE%.4f MAE%.4f R2%.4f\n, rmse, mae, r2);反归一化时predTeN是列向量需要转成行向量再用mapminmax(reverse, ...)最后转回列向量。YTeOrig取的是原始测试段里从winSize1到末尾的部分因为前面winSize个点没有足够历史窗口不是模型的预测对象。3.4 模型评估误差指标和反向传播不可用的SVM怎么调参SVM和LSTM的调参节奏完全不同。LSTM用反向传播优化内部权重SVM则是一个凸优化问题它的超参数必须靠外循环搜索。我一般把调参分成两层第一层固定LSTM的网络结构和训练参数只调winSize和hiddenUnits把特征提取这层定下来第二层再对SVM做参数搜索重点看BoxConstraint、Epsilon、KernelScale。如果特征维度不高可以在fitrsvm里直接打开超参数优化svmMdl fitrsvm(fTr, YTr, ... KernelFunction, rbf, ... OptimizeHyperparameters, {BoxConstraint, Epsilon, KernelScale}, ... HyperparameterOptimizationOptions, struct(ShowPlots, false, ... AcquisitionFunctionName, expected-improvement-plus, MaxObjectiveEvaluations, 30));这个优化会额外花几分钟但对小样本数据来说值得。可以提前把特征矩阵保存成mat文件避免每次重跑LSTM。注意特征提取必须来自同一个训练好的LSTM不能换了LSTM参数后再拿旧特征去做SVM搜索。4. 把模型写进GUIApp Designer控件、回调函数与模型传递4.1 App Designer还是GUIDE新版MATLAB的现实选择GUIDE在较新版本MATLAB里已经停止更新新项目不建议再用。App Designer是当前最稳的选择原因有三个一是界面和回调函数在同一个.mlapp文件里管理不会像GUIDE那样生成一对分离的.fig和.m二是控件回调能直接访问app对象模型数据可以很自然地存放在properties里三是它自带uiprogressdlg这类现代进度控件训练LSTM时至少能提示用户“没死机”。如果你的MATLAB版本偏老也可以用GUIDE但接下来的代码风格是针对App Designer的。核心思路是把模型对象放在app的私有属性里按钮回调之间通过app来传递数据。4.2 界面控件一次最小可用回归预测GUI需要哪些组件我不建议做一个塞满高级控件的界面回归预测项目的演示GUI只要六个组件就能讲清楚流程。控件类型作用载入数据按钮Button从工作区或文件读取原始序列窗口长度输入Numeric Edit Field设置滑动窗口长度隐藏单元输入Numeric Edit Field设置LSTM隐藏单元数量训练按钮Button执行SVM-LSTM训练流程预测按钮Button对最后一个窗口做下一步预测日志/绘图区TextArea UIAxes显示训练状态和预测点把超参数直接暴露成输入框比在代码里改参数更符合“项目实例”的表达方式。训练阶段会消耗时间所以再加一个“保存模型”按钮会更好。在App Designer的代码视图中先在私有属性里预留模型容器properties (Access private) RawData [] % 原始未归一化序列 Net % 训练好的LSTM网络 SvmMdl % 训练好的SVM回归模型 NormPs % 数据归一化参数 endNormPs必须存下来否则预测时无法把新窗口的归一化做到和训练时一致。4.3 回调函数中如何复用训练好的模型代码与参数传递训练按钮的回调可以这样写。这里把训练过程抽到一个外部函数trainSvmLstmModel里不把一大堆代码堆进回调否则GUI代码会变得很难维护。function TrainButtonPushed(app, event) % 读取界面上的超参数 winSize app.WindowSizeEditField.Value; hiddenUnits app.HiddenUnitsEditField.Value; boxC app.BoxConstraintEditField.Value; if isempty(app.RawData) app.LogTextArea.Value 请先点击“载入数据”按钮; return; end % 不定进度对话框训练中强制刷新界面 dlg uiprogressdlg(app.UIFigure, ... Title, SVM-LSTM Training, ... Message, 正在训练 LSTM请稍候, ... Indeterminate, on); drawnow; try [app.Net, app.SvmMdl, app.NormPs] ... trainSvmLstmModel(app.RawData, winSize, hiddenUnits, boxC); app.LogTextArea.Value 训练完成可以执行预测; catch ME app.LogTextArea.Value sprintf(训练失败%s, ME.message); end close(dlg); enddrawnow很重要。在MATLAB GUI中如果回调执行了一个长时间任务界面事件循环会被阻塞Windows上经常显示“未响应”。虽然uiprogressdlg也不能真异步但至少配合drawnow能刷新一次界面让用户知道程序还在跑。外部训练函数trainSvmLstmModel把第3章的代码组织成一个可复用版本function [net, svmMdl, ps] trainSvmLstmModel(data, winSize, hiddenUnits, boxC) % 划分训练/验证/测试 n numel(data); trainLen round(n*0.7); valLen round(n*0.15); trainData data(1:trainLen); valData data(trainLen1:trainLenvalLen); testData data(trainLenvalLen1:end); % 归一化 [xtrainN, ps] mapminmax(trainData); xvalN mapminmax(apply, valData, ps); xtestN mapminmax(apply, testData, ps); % 窗口化 [XTr, YTr] createSlidingWindow(xtrainN, winSize); [XVal, YVal] createSlidingWindow(xvalN, winSize); % LSTM layers [ sequenceInputLayer(1) lstmLayer(hiddenUnits, OutputMode, last, Name, feat) fullyConnectedLayer(1) regressionLayer]; opts trainingOptions(adam, ... MaxEpochs, 150, ... MiniBatchSize, 16, ... InitialLearnRate, 0.005, ... GradientThreshold, 1, ... ValidationData, {XVal, YVal}, ... Verbose, false); net trainNetwork(XTr, YTr, layers, opts); % 提取特征 fTr squeeze(activations(net, XTr, feat)); if size(fTr, 1) ~ numel(YTr) fTr fTr; end % 训练SVM svmMdl fitrsvm(fTr, YTr, ... KernelFunction, rbf, ... BoxConstraint, boxC, ... Epsilon, 0.05, ... Standardize, true); end注意这里训练函数为了控制代码长度只用了训练集特征训练SVM。如果希望更严谨可以用验证集做早期停止或SVM参数搜索但对GUI演示来说已经够了。预测按钮的回调是另一个关键点。我们预测的是原始序列最后winSize个点之后的下一个值function PredictButtonPushed(app, event) if isempty(app.Net) || isempty(app.SvmMdl) app.LogTextArea.Value 请先训练模型; return; end winSize app.WindowSizeEditField.Value; lastRaw app.RawData(end-winSize1:end, 1); % 归一化新窗口 lastNorm mapminmax(apply, lastRaw, app.NormPs); % LSTM特征提取 fNew activations(app.Net, {lastNorm}, feat); fNew squeeze(fNew); if size(fNew, 1) ~ 1 fNew fNew; end % SVM预测并反归一化 predNewN predict(app.SvmMdl, fNew); predNewN predNewN(:); predNew mapminmax(reverse, predNewN, app.NormPs); % 显示结果 app.PredValueLabel.Text sprintf(%.3f, predNew); plot(app.UIAxes, app.RawData, b-, LineWidth, 1); hold(app.UIAxes, on); plot(app.UIAxes, numel(app.RawData) 1, predNew, ro, ... MarkerFaceColor, r); hold(app.UIAxes, off); end这里给人提个醒activations接收的输入是cell数组cell的每个元素是一个1 x winSize矩阵和训练数据XTr的格式完全一致。很多人直接用向量调用activations会报维度错误就是这个细节。4.4 模型保存与重新加载不用每次打开GUI都重新训练LSTM训练在CPU上可能要等几分钟封装成GUI后如果每次打开都重新训练体验会很差。所以加一个保存模型的回调把网络、SVM、归一化参数、窗口长度一起存进.mat文件。function SaveModelButtonPushed(app, event) [file, path] uiputfile(svm_lstm_model.mat); if isequal(file, 0) return; end net app.Net; svmMdl app.SvmMdl; ps app.NormPs; winSize app.WindowSizeEditField.Value; matlabVersion version; save(fullfile(path, file), net, svmMdl, ps, winSize, matlabVersion); app.LogTextArea.Value sprintf(模型已保存到 %s, fullfile(path, file)); end注意这里把version也存了进去。原因很简单LSTM网络对象在不同MATLAB版本之间不保证兼容保存版本号至少能在半年后打开模型时提醒自己“这个模型是用哪个版本训出来的”。加载模型时在界面上加一个“载入模型”按钮用load把变量恢复到app属性中即可。5. SVM-LSTM避坑最容易翻车的五个细节与排查顺序5.1 训练集预测曲线像透视表测试集乱成一团归一化参数混入了全样本现象训练集R2超过0.95测试集R2直接变成负数预测曲线严重偏移。原因在划分训练/验证/测试之前先对整个300点序列调用了一次mapminmax。此时测试集的统计量已经参与了归一化参数的计算等于模型在训练阶段偷看了测试集的分布。时序数据里这种泄漏比随机划分的数据更难发现因为曲线走势仍然很平滑。解决严格按照“先切段、再归一化”的顺序。归一的min和range只从训练段获得测试段用mapminmax(apply, testData, ps)套用训练参数而不是重新调用mapminmax(testData)。我在第3章的代码里是这么做的但如果从别处抄代码第一件事就是检查有没有这一行[xtrainN, ps] mapminmax(trainData);如果看到对完整数据做归一化立刻改掉。5.2 模型几乎把上一个时刻的值直接抄过来滑动窗口偷看目标现象预测值比真实值滞后一个时间步看起来像把上一步真实值平移了一下但R2居然很高。原因窗口构造时把目标点也放进了输入。比如X取data(i:iwinSize)Y取data(iwinSize)这样输入的最后一位就是目标本身。模型根本不需要学规律直接把输入最后一位搬出来就行。另一种可能是窗口末尾紧挨目标点对于平滑曲线来说模型学会了“输出等于窗口最后一刻的值”本质上还是偷看。解决用一段最简单的数据自检。构造一个线性递增序列1:20窗口长度取3打印第一个样本的X和Y。正确的X应该是[1,2,3]Y是4如果出现[1,2,3,4]同时Y4说明窗口滑过头了。我在createSlidingWindow里用data(i:iwinSize-1)作为输入data(iwinSize)作为目标就是为了在代码层面杜绝这个问题。5.3 SVM的rbf核造成特征维度爆炸或支持向量太多现象训练完成后svmMdl对象占内存数百MB预测单条样本也明显卡顿画出曲线高频抖动。原因BoxConstraint设得过大Epsilon设得过小再加上KernelScale不匹配导致SVM把几乎所有样本都当成了支持向量。LSTM特征本身有15维或更高径向基核在这个维度上计算核矩阵组合起来会让优化问题非常笨重。解决先降维再训SVM。可以在提取特征后加一步PCA保留90%方差的主成分。SVM参数上先试BoxConstraint在1到50之间的值Epsilon从0.1开始往上调别一上来就是0.001。如果还是爆量换成linear核跑一版对比线性核在特征已经不错的场景下往往损失很小但模型体积小很多。[coeff, score] pca(fTr); fTrPca score(:, 1:min(size(score,2), 8));这一步不是必须的但当SVM模型文件大到不正常时它就是最直接的后悔药。5.4 GUI里点训练界面一直转圈且显示“未响应”现象点击“训练”按钮后整个App Designer窗口无法拖拽Windows标题栏出现“未响应”过几分钟后恢复。原因训练回调是同步执行的LSTM训练过程不会主动交还控制权给界面事件循环。你在回调里没有调用drawnow也没有弹进度框系统就认为程序卡死。解决训练前调用drawnow并显示一个不定进度对话框。这个方案并不能真正异步但至少让用户看到反馈。更彻底的做法是把LSTM训练放到外部脚本预先训练好并保存模型GUI里只做“载入模型”和“预测”避开长时间训练。对演示型GUI来说这个妥协非常有效。5.5 保存模型后在另一台电脑上加载失败现象load(svm_lstm_model.mat)能执行但predict时报错提示网络层级信息不兼容或者直接连load都失败。原因LSTM网络对象内部带有编译过的计算图和版本相关信息不同MATLAB版本之间不能保证无缝加载。相比之下SVM模型是内置分类器对象兼容性反而好一些。解决保存模型时把version一起写入mat文件。换机器之前先确认两边MATLAB版本一致如果不一致就不要试图直接迁移训练好的网络而是迁移数据、脚本和SVM参数重新训练LSTM。如果是为了部署可以把LSTM导出为ONNX格式但SVM没有官方的ONNX导出通道所以这类组合模型最省事的部署方式仍然是“同一版本MATLAB环境”。6. 验证模型有没有学漏残差自相关、多步预测与我的固定复现习惯6.1 用残差自相关判断模型有没有学漏规律训练完成之后不要只看RMSE和R2。时序回归里一个高R2可能只是因为你预测的是平滑趋势而真正的时序细节全都在残差里。我会把测试集残差做一次自相关分析residual YTeOrig - predTe; figure; autocorr(residual, 20);如果残差在滞后1或滞后2处自相关显著超过置信区间说明LSTM窗口里的时间依赖没有被完全提取这时候优先加大winSize或者增加LSTM隐藏单元数量。如果残差自相关总体落在置信区间内说明模型已经把该学的时序信息吃干净了。6.2 从单步预测到多步预测滚动还是不滚动这个方案默认是做一步预测。如果你需要未来10步常见做法是滚动预测把预测值拼到窗口末尾形成新窗口再预测下一步。滚动预测的优点是代码改动小缺点是误差会累积多步之后预测曲线会向训练数据的均值回归。如果只是项目展示滚动预测够用。如果要做严肃的多步预测我会建议换一个输出头让LSTM直接输出未来多个时刻而不是再接SVM做单步。SVM-LSTM组合擅长的是“单步回归 特征诊断”这是它的舒适区别硬拿着它做长程多步预测。6.3 我固定的复现流程现在每次拿到新数据集我都会按同一套节奏推进先用200个点训练一个winSize10、hiddenUnits10的小模型看残差自相关确认没有数据泄漏然后做一轮窗口长度和隐藏单元的简单网格搜索固定LSTM后再调SVM的BoxConstraint和Epsilon最后才封装GUI。多花一小时在前两步上后面能省一整天的调试时间。有一次我跳过残差自相关直接做GUI结果界面点起来很漂亮现场展示时才发现模型把滞后一个时刻的噪声当成了信号。这个教训让我养成了先验证残差、再碰界面的习惯希望帮到你。本文还有配套的精品资源点击获取
返回列表