资讯详情

基于QRLSTM的区间回归预测:Matlab 2018实现分位数LSTM模型

📅 2026/10/12 10:02:00 | 华诺云谱 👁 阅读
基于QRLSTM的区间回归预测:Matlab 2018实现分位数LSTM模型
1. 从点预测到区间预测为什么我盯上了QRLSTM做数据回归预测的人多半都经历过这种尴尬模型跑完精度指标再漂亮业务方一句话就把你问住了——你说明天发电量是500度那上下能差多少500度是稳妥值还是乐观值传统的神经网络回归输出层就是一个神经元MSE一算预测结果是一条细线。可现实世界的数据尤其是风电功率、光伏出力、电价、交通流量这类时序数据天生就是波动的。均值预测解决的是平均情况会怎样但我要知道的是大概率落在哪个区间。这个痛点我琢磨了很久。先说结论我最终在Matlab 2018版里实现了基于分位数长短期记忆网络QRLSTM的区间回归预测效果比单纯的LSTM残差误差估计靠谱得多。QRLSTM的思想并不复杂——把LSTM的时序特征提取能力和分位数回归的区间表达能力拼在一起让模型不只输出一个预测点而是同时输出多个分位点的条件预测值。比如同时预测10%、50%、90%三个分位点那么这组预测天然就构成一个区间10%到90%之间的范围约等于80%置信区间。算法不再是猜一个点而是描述整个分布的形状。这篇博客就来完整拆解这套方法在Matlab 2018环境下的代码实现。适合的人群正在做时序回归预测对精度不太满意的被业务方追问预测区间的以及想在老版本Matlab上跑通LSTM变体算法、但又不想被新版深度学习工具箱折腾的朋友。我会从原理、损失函数构造、数据组织、Matlab代码实现、结果校验五个维度讲透所有代码基于Matlab 2018b亲测可跑涉及的操作我会说明为什么这样做而不是只丢一段能跑的代码。2. 分位数回归与LSTM结合的底层逻辑2.1 分位数回归到底解决了什么常规回归拟合的是条件均值E[y|x]也就是给定输入特征x预测y的期望。但均值的表达力有限尤其是数据分布呈现偏态、厚尾、异方差特征时用一条均值曲线代表所有情况会丢失大量信息。分位数回归的思路完全不同它拟合的是条件分位数函数Q_y(τ|x)其中τ是0到1之间的分位点。当τ0.9时模型预测的是在给定x的条件下y的取值有90%概率小于等于这个值。多个分位点组合起来就能恢复出预测条件分布的完整形态。这个方法最早在计量经济学里用得比较多Koenker和Bassett在1978年就奠定了理论基础后来被引入机器学习领域和神经网络结合的尝试也一直没断过。这里有个关键点容易被新手忽略分位数回归不是把数据集按分位数切几份然后分别训练几个模型。它是在一个模型内部用特殊设计的非对称损失函数让网络在不同输出节点上各管一段。QRLSTM在输出层布置多个神经元每个神经元对应一个τ值所有节点共享同一个LSTM特征提取器通过损失函数的权重分配让每个输出节点学会预测对应的分位数。2.2 分位数损失函数为什么不能用MSE从MSE换到分位数损失是实现QRLSTM的第一个坎。分位数损失也叫pinball loss的数学形式长这样L_τ(y, ŷ) max(τ·(y - ŷ), (τ-1)·(y - ŷ))看起来有点绕拆开理解就好。假设我们预测的是τ0.9分位点也就是90%的情况都不会超过这个值。如果真实值y比预测值ŷ大说明模型低估了误差为y - ŷ是正数此时乘上τ0.9惩罚系数是0.9这个惩罚比较重——因为低估90%分位点意味着实际值大概率会超出预测区间后果严重。反过来如果预测值比真实值大误差为负数惩罚系数只有0.1即模型稍微高估是可以接受的。对比一下就清楚MSE为什么不行MSE对正负误差的惩罚是对称的模型会倾向于预测条件均值而分位数损失是非对称的它强迫模型在训练过程中不断调整权重让输出值稳定地偏向某一侧。τ越接近1模型越倾向于给出保守的高估τ越接近0模型越倾向于给出激进的低估。正是这种偏心的惩罚机制成就了分位数预测。拿快递送达时间做类比。平台说预计明天14点到16点之间送达这个最晚16点其实就是90%分位点平台在预估时宁可说得晚一点也不希望被投诉为什么没送到。平台内部使用的本质上就是带分位数思想的预测策略。2.3 LSTM在这里扮演什么角色数据回归预测中纯分位数回归需要人工构造特征处理不了高维时序数据内部的长期依赖关系。LSTM通过输入门、遗忘门、输出门三个门控单元能够决定历史信息中哪些保留、哪些丢弃、哪些输出。在QRLSTM结构里LSTM层负责从原始时间序列中提取隐状态序列最后一层的隐状态对接分位数回归输出层。还有个细节值得说QRLSTM里的LSTM层参数是多个分位点共享的只有输出层的全连接权重和偏置是各分位点独立的。这个设计既有理论依据也有工程考量——时序特征的提取规律对不同分位点来说是通用的共享参数可以大幅减少训练开销而各分位点最后的输出权重不同保证了每个分位数预测的个性。这种共享特征个性映射的结构和multi-task learning里硬参数共享的思路如出一辙。3. 数据准备与Matlab 2018环境的基本功3.1 Matlab 2018对深度学习的支持边界如果你的机器上装的是Matlab 2018b需要先确认几个关键工具箱。LSTM网络的训练依赖Deep Learning Toolbox2018b版本叫Neural Network Toolbox在2018b版本里lstmLayer、sequenceInputLayer、fullyConnectedLayer、regressionLayer这些API是齐备的。但有一个大坑Matlab 2018b对自定义训练循环dlnetwork的支持还很弱到R2019b之后才逐步成熟。这意味着我们没法像新版那样用自定义trainNetwork循环来写一个灵活的损失函数。解决方案有两个。方案A借用Symbolic Math Toolbox里的函数句柄把分位数损失封装成一个自定义回归层然后塞进trainNetwork里跑。方案B干脆不用trainNetwork直接用LSTM的前向计算公式手写反向传播——太硬核不推荐。实际操作中方案A是主流路子下面第4节我会放出完整代码。另一个环境注意点如果没有NVIDIA GPU训练LSTM会慢到你怀疑人生。2018b的trainNetwork用CPU训练是支持的但建议把MiniBatchSize调小一点比如16或32序列长度控制在几十步以内。我实测一个包含1000个样本、序列长度20、LSTM隐层32个神经元的小规模模型CPU训练大约需要3到5分钟一轮epoch还能接受。如果序列长度超过100建议租个带GPU的机器或者换用GRU层2018b也支持gruLayer降低计算量。3.2 时序数据如何组织成训练样本LSTM的输入数据标准格式是观测 × 时间步 × 特征的cell数组。Matlab的trainNetwork要求序列数据是N行1列的cell数组每个cell里是一个timesteps × features的矩阵。这里N是样本个数每个样本是一个独立的序列。举个例子。假设原始数据是一维风电功率序列x(1), x(2), ..., x(2000)我们要用过去5个时间步预测未来1个时间步。样本的构造方式先设定滑动步长从第6个点开始逐个滑动切出x(t-5)到x(t-1)作为输入序列x(t)作为标签。2000个点大概能产出1995个样本。切完之后输入是1995 × 1的cell数组每个cell是5 × 1的矩阵时间步5特征维度1输出是1995 × 1的向量。有两处非常容易踩坑提醒一下。第一Matlab的cell数组维度是 [样本数, 1]不是 [1, 样本数]很多人传反了报错。第二标签向量的行数必须等于cell数组里的样本数也就是说每个样本需要一个对应标签。如果你做的是多步预测输出就应该是cell数组每个标签cell里是horizon × 1的矩阵这一步细节我在第5节展开。还有一个实践技巧数据要不要归一化LSTM的激活函数是tanh和sigmoid族对输入尺度很敏感。我的做法是对输入和标签各做一次mapminmax到[0, 1]训练完之后把预测结果再还原回去。注意归一化的参数只能从训练集上计算验证集和测试集必须复用训练集同一套min和max否则会造成信息泄漏让测试指标虚高。这一点我在早期的项目里吃过亏测试集上看着误差很小一部署到新数据上就穿帮。3.3 训练集与测试集的划分原则时间序列和普通回归不一样不能直接随机打乱划分样本。原因很简单LSTM的记忆机制依赖时间顺序如果把未来的样本放进训练集模型会偷看到未来信息测试集上的表现就不是真实的泛化能力。正确的做法是前80%的时间段做训练集后20%做测试集。如果原始数据是2000个时间点的序列那么前1600个点切出的样本用于训练后400个点切出的样本用于测试。洗牌操作只对训练集内部做mini-batch洗牌整体样本顺序不能跨区间打乱。还有一点归一化参数在前一步已经说明只从训练集中计算。在代码实现时如果你不想让完整的滑动窗口样本一次性占满内存——2000个点还好但如果原始序列是几万条切出的样本数会呈线性膨胀——可以考虑用tall数组分批处理。Matlab 2018支持tall数组和trainNetwork配合不过配置起来有点繁琐小数据量的话建议直接一次性构建省心。4. QRLSTM的Matlab代码实现核心步骤详解4.1 自定义分位数损失层绕开Matlab内置损失的限制Matlab 2018b的trainNetwork默认只支持内置的regressionLayerMSE损失没有现成的分位数损失层。我们必须自定义一个regressionLayer子类。自定义回归层在Matlab里要写成一个类文件至少包含三个函数构造函数、predict前向计算、以及反向传播相关的backward。后者是难点因为trainNetwork在训练自定义层时会自动调用它来求梯度。其实在R2018b里自定义层的梯度如果由Deep Learning Toolbox自动计算你需要把自己的损失函数用支持自动微分的方式写出来。这里给出一个可以跑通的简化实现新建文件quantileLayer.m代码如下。classdef quantileLayer nnet.layer.RegressionLayer properties Tau 0.5 % 分位点可由外部传入 end methods function layer quantileLayer(tau) layer.Tau tau; layer.Name quantile_loss; layer.Description Quantile loss layer; end function loss forwardLoss(layer, Y, T) % Y: 预测值, T: 目标值 % 分位数损失: max(tau*(T-Y), (tau-1)*(T-Y)) err T - Y; loss mean(max(layer.Tau * err, (layer.Tau - 1) * err)); end end end注意这个简化版本只重写了forwardLoss没有写backward。在Matlab 2018b里如果你的自定义层继承了nnet.layer.RegressionLayer且只改forwardLoss系统会用数值微分近似梯度吗不会——它会报错要求你实现backward。要让2018b正常训练需要同时实现backward函数。但好消息是分位数损失的梯度推导非常容易不看公式也能推出来。损失L mean(max(tau·e, (tau-1)·e))其中e T - Y。当e 0时L tau·e对e求导是tau当e 0时L (tau-1)·e导数为tau-1。注意导数不存在的点e0几乎不会碰到可以忽略。再用链式法则loss对Y的导数就是 -tau当T Y或 -(tau-1)当T Y。因此backward可以写成function dLdY backwardLoss(layer, Y, T) e T - Y; dLdY -layer.Tau * (e 0) - (layer.Tau - 1) * (e 0); dLdY dLdY / numel(e); end这里我用逻辑索引对正的误差和负的误差各自赋予不同的梯度系数实现非对称惩罚。加上mean归一化系数1/numel(e)梯度尺度和内置回归层保持一致。4.2 共享LSTM层与多分位输出结构一个QRLSTM要同时预测多个分位点光靠一个自定义损失层是不够的。最直接的实现方案每个分位点单独建一个网络——也就是LSTM特征提取器不共享各自训练各自的模型。这样做代码最简单预测效果通常也不差但缺点是多个模型彼此独立训练成本高且模型之间缺乏一致性约束。共享特征提取器的方式在Matlab 2018b里也能实现方法是把多个分位输出头拼接在同一个LSTM层之后。具体做法LSTM层之后连接一个fullyConnectedLayer输出维度设为分位点数量K让这个全连接层同时产出K个节点的输出。然后在训练时损失函数需要同时计算K个分位点损失并求和。这要求自定义损失层能接收多列输出。我把这个问题拆细一点。假设分位点取[0.1, 0.5, 0.9]K3。网络上层的输出维度就是3。标签T的维度也应该设计成每个时间步3个值对应三个分位点的期望输出。但原始训练标签只有一个真实值怎么变成三列答案是复制三列每一列的真实值相同但训练时不同列使用不同τ的损失函数。这里有个不算技巧的技巧。Matlab的trainNetwork自定义层的forwardLoss接收到的Y和T都是按样本 × 输出维度组织的我们可以让同一批次里的每个样本对应一个特定的τ而不是让三个τ同时出现在同一个样本上。简单说把数据集复制三份第一份用τ0.1的分位损失层去训第二份用τ0.5第三份用τ0.9。三份数据输入同一个LSTM共享层但通过不同的输出分支。这个思路在代码里最清晰也最容易扩展。不过在2018b里trainNetwork不能像Keras的functional API那样随意拼接多输出分支。因为Matlab 2018b的layerGraph不支持多输出连接到一个共享层之后分别接不同的损失。最可行的兼容方案还是多模型分训也就是为每个τ单独建一个LSTM全连接分位损失层每个模型的结构完全一样差别只在τ值不同。训练完成之后预测时把K个模型的结果横向拼在一起就得到K个分位点的预测矩阵然后绘制预测区间。4.3 主训练代码逐行讲解下面给出一段完整的QRLSTM训练脚本适用于Matlab 2018b。为节省篇幅我略去了数据加载部分默认已有变量XTraincell数组N×1每个cell是timesteps×1矩阵和YTrainN×1向量。% 定义分位点集合 taus [0.1, 0.5, 0.9]; numTaus length(taus); models cell(1, numTaus); % 公共网络参数 numFeatures 1; % 输入特征维度输入序列每时间步的维度 numHiddenUnits 32; % LSTM隐层单元数 numResponses 1; % 输出维度 % 遍历每个分位点分别训练 for i 1:numTaus tau taus(i); % 构建网络结构 layers [ sequenceInputLayer(numFeatures, Normalization, none) lstmLayer(numHiddenUnits, OutputMode, last) fullyConnectedLayer(numResponses) quantileLayer(tau) % 自己定义的分位损失层 ]; % 训练参数 options trainingOptions(adam, ... MaxEpochs, 120, ... MiniBatchSize, 32, ... InitialLearnRate, 0.005, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.5, ... LearnRateDropPeriod, 30, ... Shuffle, every-epoch, ... Verbose, 1, ... Plots, training-progress); % 训练当前分位模型 models{i} trainNetwork(XTrain, YTrain, layers, options); end循环里最需要注意的是 layers 数组的末尾接的是 quantileLayer(tau)而不是内置的regressionLayer。请一定确认quantileLayer.m文件在当前工作目录下否则trainNetwork会直接报未定义类错误。有个细节lstmLayer的OutputMode参数这里用last意思是只返回最后一个时间步的隐状态适用于序列到序列的单步回归预测。如果你做的是序列到序列的多步预测需要改成sequence并调整标签格式。后面第5节会提到现在先保持简单。4.4 训练收敛与梯度问题排查实际训练中最常见的问题是loss不降或者直接NaN。我遇到过好几次最后发现是学习率没调好。分位数损失比MSE对学习率更敏感因为它本质上是分段线性函数在误差接近0的区域梯度是常数不会像MSE那样梯度随误差缩小而缩小。这导致训练后期可能会出现loss在一个小邻域内震荡无法进一步收敛。应对策略就是上面代码里设置的learnRateDropFactor和learnRateDropPeriod每30轮把学习率减半强制缩小震荡幅度。如果一开始就出现NaN大概率有两个原因输入数据包含NaN或Inf清洗一下学习率太大导致梯度爆炸把InitialLearnRate降到0.001甚至0.0005。LSTM对梯度爆炸格外敏感如果新手直接用默认的0.01学习率去训十有八九会飞。另外如果数据序列长度差异过大建议用sequencePaddingDirection参数统一补齐到相同长度否则MiniBatch里较长的序列会拖慢整体计算时间。我给的初始参数适合小规模数据几百到几千个样本。数据量越大隐层单元数和epoch数可以适当加大但学习率建议始终从0.005往下试。你可以对比一下同一份数据MSE损失和分位数损失训练出来的验证曲线形态差别很直观——分位数损失的loss曲线通常不是平滑下降的而是带着周期性震荡这是正常的。5. 预测流程与结果可视化不止要一条线5.1 多条分位数预测曲线的合成训练完三个模型τ0.10.50.9之后实测阶段把它们各自predict一遍就得到三列预测值。以某光伏出力预测为例时序数据是300个测试点预测结果大概是这样的形态τ0.9的曲线在大部分时段高于实测值τ0.1的曲线低于实测值τ0.5的曲线贴着实测值走。把这三条曲线画在同一个坐标系里中间的区域就是80%预测区间。% 对测试集进行预测 YPred_01 predict(models{1}, XTest); YPred_50 predict(models{2}, XTest); YPred_90 predict(models{3}, XTest); % 反归一化 YPred_01 YPred_01 * (ymax - ymin) ymin; YPred_50 YPred_50 * (ymax - ymin) ymin; YPred_90 YPred_90 * (ymax - ymin) ymin; % 绘制预测区间 figure; hold on; fill([1:numel(YPred_01), fliplr(1:numel(YPred_01))], ... [YPred_01, fliplr(YPred_90)], ... [0.8 0.9 0.95], EdgeColor, none, FaceAlpha, 0.4); plot(YPred_50, b-, LineWidth, 1.2); plot(YTest, k--, LineWidth, 1); legend(80%预测区间, 中位数预测, 实测值);这里的fill命令是画区间图的关键。原理是先把下界顺序排列然后拼接上界曲线翻转后的坐标形成一个闭合多边形再用FaceAlpha调透明度。如果你想把区间画得更收敛可以再加τ0.3和τ0.7的模型加密分位点采样。分位点越多区间形态的刻画越精细但训练成本线性上升。5.2 用pinball score检验预测质量画完图之后别只看区间包住了多少实测点那是覆盖率指标单看覆盖率不够。一个80%区间当然可以无脑把上下界拉到无穷远覆盖率直接100%但这样的区间没有任何信息量。正确的做法是用pinball score分位数损失值本身来评估每个分位点的预测质量。function score pinball_loss(tau, y_true, y_pred) e y_true - y_pred; score mean(max(tau * e, (tau - 1) * e)); end s1 pinball_loss(0.1, YTest, YPred_01); s2 pinball_loss(0.5, YTest, YPred_50); s3 pinball_loss(0.9, YTest, YPred_90); fprintf(pinball loss: tau0.1 - %.4f, tau0.5 - %.4f, tau0.9 - %.4f\n, s1, s2, s3);pinball score越低说明该分位点的预测越准。这里有个反直觉的地方值得强调测试集上τ0.1的损失值通常会显著小于τ0.9的损失值因为多数时间序列呈现右偏分布上尾更长在高分位点的预测天然更难。如果你发现某个分位点的pinball loss异常高可以检查一下是不是这个模型的训练没收敛或者是归一化参数出了问题。为了横向对比我建议你同时实现一个基准模型用MSE损失训一个普通LSTM然后用误差的标准差去构建区间。做法是算出测试集残差的标准差σ预测区间就是y_pred ± 1.28σ对应80%区间。对比一下QRLSTM和这个均值常数方差方法在pinball loss上的差异你会发现QRLSTM在分布前端的表现通常更好尤其在波动率随时间变化的时段。5.3 多步预测的扩展思路上面演示的是过去5步预测未来1步。但真实业务里比如提前24小时预测发电量需要的往往是多步预测。在LSTM架构里多步有两种思路。第一种是递归预测把当前预测值当作下一时间步的输入一步步滚下去——这个实现简单但误差会逐级累积预测区间会随步长拉大。第二种是直接多输出把lstmLayer的OutputMode改成sequence输出维度设为horizon一次输出未来多个时间步。后者更适合QRLSTM但标签组织方式不同每个样本的标签是horizon×1的矩阵放进cell数组。就我的经验而言递归预测适用于短期步长3步以内步长一旦超过5误差累积会导致分位区间过度膨胀上下界很快就脱离实际了。直接多输出则需要样本数量足够多否则最后几步的预测质量会明显下降。如果你要的是稳定可靠的结果可以先从单步预测起步把QRLSTM跑通再逐步扩展。6. 实测效果与调参经验踩坑之后的复盘6.1 三类数据上的表现对比我把QRLSTM分别跑在三个数据集上做了测试某风电场功率数据连续1个月采样间隔15分钟、某城市负荷数据连续一年采样间隔1小时、以及一组带明显趋势与周期的人工合成数据信噪比可调。测试集中在以下几点。风电场功率数据是最能体现QRLSTM价值的场景。风电功率分布有明显的右偏和大量接近0的值普通LSTM的MSE预测在低出力时段经常预测出负值而QRLSTM的τ0.1分位曲线天然贴近0下限物理上更合理。τ0.9分位曲线在高出力时段也明显比均值预测更保守这非常符合调度业务的需求——调度需要的是极端情况下的出力下限而不是均值。城市负荷数据上QRLSTM和普通LSTM的中位数预测精度τ0.5分支和MSE训练的模型差不多这说明分位数损失并没有牺牲中心位置的预测精度。但在工作日与节假日的切换点附近QRLSTM的区间宽度会明显变宽对突变时段的不确定性刻画更合理。人工合成数据测试更有意思。我让真实数据生成过程同时包含线性趋势、周期性、异方差噪声噪声方差随时间变化QRLSTM的区间宽度能够跟随噪声方差变化——噪声大的时段区间自动变宽噪声小的时段区间收窄。而均值常数方差的基准方法完全无法捕捉这种变化。6.2 隐层单元数与分位点数量的取舍隐层单元数numHiddenUnits不是越大越好。在1000个样本的小规模数据集上32个隐层单元非常稳妥16个也够用64个则明显过拟合区间在训练集上收得很窄测试集上覆盖率下降。样本量在5000以上时可以尝试64到128个隐层单元。一个经验法则隐层单元数不要超过样本数量的1/10否则LSTM的记忆容量太大反而学不到泛化特征。分位点数量方面最少取3个0.1、0.5、0.9可以满足80%区间的基本需求。如果想要更精细的分布形态取5个0.05、0.25、0.5、0.75、0.95可以画箱线图式的分布展示。再往上取9个每0.1一个分位点训练成本翻倍但分布刻画已经很平滑实际业务里很少需要超过5个分位点的分辨率。6.3 老版本Matlab的性能优化策略Matlab 2018b训练LSTM慢是普遍体验。我的优化策略有这几条亲测有效。第一数据类别的统一确保XTrain是cell数组每个cell是double矩阵。如果你的数据是单精度single某些内置层会报维度不匹配的错误最好统一转成double。第二关闭训练图Plots选项改成none训练进度图本身很耗资源尤其在远程桌面环境下绘制进度会显著拖慢迭代速度。第三用并行池在训练前运行parpool有时候trainNetwork会自动用上多核2018b在部分机器上需要手动开启并行池。第四预分配样本如果内存允许一次性预分配cell数组避免循环里反复扩容。说到plot功能的坑还有个小细节要提。Matlab 2018b的training-progress窗口在训练结束后如果直接关掉有时候会报错Figure is closed之类的提示原因和图形句柄残留有关。不影响训练结果但是挺烦人。解决方法是训练完后用close all清一下或者干脆不用Plots选项手动用waitbar自己画进度。7. 写在最后从跑通到落地还要想清楚三件事代码跑通、区间画出来这只是第一步。我实际把QRLSTM用于业务预测之后有三个体会想分享给同样在做数据回归预测的朋友。第一QRLSTM不能替代业务规则。区间预测给出的是概率意义上的范围但某些场景下物理约束是不可突破的比如功率不能为负、负荷不能超过变压器容量上限。模型输出之后一定要加一层后处理把越界的预测值修剪回物理可行域否则业务方看到负功率会直接质疑方法可信度。我在代码里会对τ0.1分支的输出做max(0, x)截断这个操作在真实项目里非常重要。第二模型更新频率比模型复杂度更重要。时序数据的分布特征会漂移今天训练好的QRLSTM三个月后在新数据上预测区间可能偏差很大。我通常设定每周或每两周重训一次模型并把滚动窗口加进训练数据生成流程。刚开始觉得频繁重训很麻烦后来发现训练时间其实很短小样本在CPU上也只需几分钟重训的收益远大于成本。第三分位点预测可以和业务决策直接挂钩。如果你的目标不是预测一个值而是决定一个行动方案那QRLSTM的分布信息可以帮你做阈值判断。比如在电力交易场景里用τ0.3分位点作为保守报价基准用τ0.7分位点作为激进报价上限可以更精细地把控风险。这种用法完全超出了普通LSTM的均值预测能力范围也是QRLSTM最值钱的地方。技术细节上如果你在跑代码时遇到Matlab报Layer ... is not supported这类错误优先检查两个地方自定义损失层的类定义是否继承正确以及Matlab版本是否为R2018b或以上。还有如果你用了trainNetwork里的Plots参数在无桌面环境的Linux服务器上跑需要先用matlab -nodisplay启动然后手动关闭绘图功能。这些Edge case我一开始没意识到折腾了不少时间写出来希望你能少走弯路。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑