拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

LSTM变种在飞机发动机剩余寿命预测中的对比与实战

LSTM变种在飞机发动机剩余寿命预测中的对比与实战

最近一直在倒腾 NASA 的 CMAPSS 数据集做剩余寿命预测,也就是飞机发动机的 RUL(Remaining Useful Life)回归。这个数据集在预测性维护圈子里几乎是入门必修课,网上能搜到的基线结果一大堆,但大部分都是拿一个标准 LSTM 直接怼上去就完事。这次我多走了一步:把几种常见的 LSTM 变种都实现了——堆叠 LSTM、双向 LSTM、CNN-LSTM、Attention-LSTM,甚至尝试了 ConvLSTM,统一放在 CMAPSS 的 FD001 子集上做对比实验,顺带梳理了整套数据预处理、滑窗构造、标签分段和训练调参的流程。

如果你正在学 LSTM 时间序列预测,或者准备入坑 PHM(预测与健康管理)方向,这篇文章应该能给你省下不少踩坑的时间。我会把完整思路讲清楚,包括为什么用 LSTM 而不是普通 RNN、每个变种的核心差异、在 CMAPSS 上实际跑出来的指标大概什么水平、以及调试过程中遇到的几个印象深刻的坑。代码基于 TensorFlow/Keras 实现,你能直接照着跑。

1. 项目背景:CMAPSS 数据集与 RUL 预测任务

1.1 CMAPSS 是什么,为什么大家都在用

CMAPSS 全称 Commercial Modular Aero-Propulsion System Simulation,是 NASA 公开的涡扇发动机退化仿真数据集。简单说,它模拟了多台同型号发动机从全新状态到失效的完整运行周期,每个运行周期记录一次多传感器读数,比如各处的温度、压力、转速、振动等等。因为真实发动机全寿命退化数据很难拿到,这个仿真数据就成了算法验证的标准场地。

整个数据集按工况和故障模式划分成 4 个子集:

子集工况条件故障模式训练集发动机数测试集发动机数
FD001单一工况1 种100100
FD0026 种工况1 种260259
FD003单一工况2 种100100
FD0046 种工况2 种248249

每个样本的原始字段包括:发动机编号、当前循环周期、3 个操作设置参数,以及 21 个传感器信号。原始数据里有些传感器在全寿命周期内几乎是平的,比如传感器 1、5、6、10、16、18、19,这类信号对预测没什么贡献,常规做法是直接剔掉,只保留变化明显的 14 个传感器通道。

我这次主力实验都在 FD001 上做,原因是它最简单——单一工况、单一故障模式,便于先集中精力比较不同模型架构的效果,避免被工况切换的干扰因素带偏。等模型结构确定后,再往 FD002、FD004 这类多工况子集迁移,是更合理的实践路径。

1.2 任务定义与评价指标的选择

CMAPSS 的预测任务是典型的回归问题:给定某台发动机截至当前周期的所有历史传感器数据,预测这台发动机还能再跑多少个周期。对每台测试发动机,通常只需要预测最后一个时刻的 RUL 值。

评价指标有两个最常用:

RMSE:直接衡量预测误差的均方根,公式就是 sqrt(mean((y_true - y_pred)^2)),对过大过小的误差一视同仁。

NASA 评分函数(Score):这个更贴近实际维护场景。它认为“预测晚了”(预测 RUL 大于真实 RUL,也就是以为发动机还能跑更久)的代价远大于“预测早了”(提前更换,虽然浪费但安全)。所以它是不对称的:

当 d_i < 0 时(即预测值小于真实值,预测偏保守):score += exp(-d_i/13) - 1
当 d_i >= 0 时(即预测值大于真实值,预测偏激进):score += exp(d_i/10) - 1

其中 d_i = RUL_true_i - RUL_pred_i。

这里要特别提醒:RMSE 更容易优化,但 Score 才能反映领域真实诉求。我在实验里两个指标都看,但最终模型选择以 Score 为主。很多刚入门的同学只刷 RMSE,结果分数挺好,Score 却很难看,原因就是模型放大了“晚预测”的误差。

2. 为什么选 LSTM:时序建模在 RUL 问题中的必要性

2.1 传统方法在这个任务上的吃力点

在深度学习方法普及之前,RUL 预测常用物理退化模型或者基于统计的方法,比如指数退化模型、维纳过程。这类方法对发动机的退化机理做了强假设,一旦实际系统存在多故障模式耦合或者工况变化剧烈,模型的泛化能力就很差。

后来有人用传统机器学习方法,比如支持向量回归、随机森林,思路是把每个时刻的传感器特征拉成一条特征向量,再配上对应的 RUL 标签。这么做的核心缺陷是:它把每个时间点当成独立样本,完全丢掉了发动机退化的时间连续性。而发动机的健康状态演化本身就是一个强时序依赖过程,前 10 个周期的退化趋势直接决定了后面 20 个周期的行为。传统模型表达不了这种依赖。

2.2 LSTM 与普通 RNN 的关键差异

普通 RNN 的设计意图是处理序列,但在误差反向传播过程中,梯度要沿着时间步连乘。如果时间步长太长,梯度要么指数爆炸,要么指数消失。梯度消失时,网络很难学习到几十步之前的信息对当前输出的影响,这就叫“长期依赖问题”。

LSTM 引入了门控机制(输入门、遗忘门、输出门)和一条贯穿时间步的细胞状态线。细胞状态像一条“传送带”,允许信息以一种接近线性的方式跨时间步传递,梯度也能更顺畅地回传。遗忘门控制上一时刻的记忆有多少被保留,输入门决定新信息有多少写入,输出门决定当前输出体现多少记忆内容。这套设计让 LSTM 可以记住发动机在几十上百个周期前的退化特征,比如某个传感器在早期就开始漂移的微弱模式。

2.3 单层 LSTM 的局限倒逼变种

标准 LSTM 虽然能建模时序,但单层结构的特征抽象能力有限。CMAPSS 的传感器信号不仅有时间依赖,还有空间相关性和不同尺度上的模式——有的传感器长期缓慢漂移,有的在临近失效时才有突变。单层 LSTM 很难在同一时间步内同时捕捉多尺度的退化模式,这是我对 LSTM 做变种改造的直接动机。

简单说,不同变种解决不同问题:

  • 堆叠 LSTM:增加网络深度,提升特征抽象层次。
  • 双向 LSTM:在异常检测类任务里,当前状态可能和前后文都相关。虽然 RUL 预测本质上是只看历史预测未来,但双向结构能提供更丰富的特征表示。
  • CNN-LSTM:用卷积层做局部特征提取,再交给 LSTM 建模时序。对传感器通道间的局部相关性和短期趋势很有效。
  • Attention-LSTM:让模型自动聚焦到更关键的退化阶段,比如快失效前的剧烈变化。
  • ConvLSTM:把卷积计算融进 LSTM 单元内部,适合时空数据,在 RUL 任务上属于比较激进的尝试。

3. 数据预处理:决定模型上限的前置步骤

3.1 传感器筛选与归一化的细节

CMAPSS 原始数据里 21 个传感器并非全部有效。我在预处理第一步就做了方差分析,把变化极小的传感器去掉,只保留 2、3、4、7、8、9、11、12、13、14、15、17、20、21 这 14 个通道。

归一化这里有一个高频踩坑点:必须只用训练集的 min 和 max 去归一化训练集和测试集,不能直接对全体数据做 min-max。因为测试集模拟的是“未来数据”,你在预处理时用了测试集的统计信息,相当于提前偷看了答案,这种数据泄漏会在线下验证时给出虚高的指标,部署上线后直接打回原形。

归一化方式我选了 min-max 归一化而不是标准化,原因是传感器信号是物理量,分布范围差异大,但退化趋势基本在一个相对固定的区间内变化。min-max 能把这 14 个通道统一映射到 [0,1],方便后续模型训练。标准化(z-score)也能用,但对异常值更敏感,传感器偶尔会出现尖峰,一旦峰值异常,标准化后的整个通道都会变形。

3.2 滑窗样本构造与标签处理

每台发动机的数据是一个长度不等的二维矩阵(时间步 × 传感器通道)。要把这些变长序列喂给 LSTM,需要截取固定长度的窗口。我这里的窗口长度设置为 30 个周期。

滑窗的具体做法是:对每台发动机,从第 0 步开始,每次取连续 30 个时刻的 14 维传感器数据作为一个训练样本,标签就是该窗口最后一个时刻对应的 RUL 值。然后窗口向后滑动 1 步,重复这个过程。这样每台发动机会产生 长度-30+1 个样本,整个训练集大概有一万多个样本。

这里有一个处理细节会影响最终结果:直接用线性递减的 RUL 标签(即真实剩余周期)作为回归目标时,模型在发动机早期大量时间步学到的都是“剩余寿命还很长”这种样本,导致模型对临近失效阶段的突变不够敏感。

常规解法是给 RUL 标签做一个分段线性处理:设定一个上限阈值(通常 120 或 125),当真实 RUL 大于阈值时,把标签统一置为该阈值。这个做法的直觉是:一台刚出厂的全新发动机和一台已经跑了 80 个周期的发动机,短期内都不需要更换,把它们的 RUL 差距强行拉平,可以降低早期平稳段对模型训练的干扰。经过分段处理后,模型可以把注意力集中在真正临近失效的区间。

3.3 训练集和验证集的划分策略

FD001 的训练集里只有 100 台完整生命周期数据,如果把滑窗后的样本全部拿去训练,没有一个独立验证集,很难判断训练是否过拟合。

我的划分方式是:随机抽取 20 台发动机的所有滑窗样本作为验证集,剩下 80 台用于训练。这里有个小坑要注意——划分必须按“发动机编号”分组,不能按滑窗样本随机划分。否则同一台发动机的相邻窗口会被同时分到训练集和验证集,验证集就名存实亡了。同类问题在时间序列预测里非常常见。

4. 核心实操:多种 LSTM 变种的模型实现与训练

4.1 通用训练配置

我统一使用 Adam 优化器,初始学习率 0.001,批大小 256,训练轮次上限 100 轮,并配合 EarlyStopping(监控验证集 loss,patience=10)和 ModelCheckpoint(只保存验证集 loss 最低的模型)。损失函数用均方误差 MSE。

之所以不把轮次固定死,是因为不同模型收敛速度差异很大。CNN-LSTM 通常十几轮就收敛了,堆叠 LSTM 可能要跑到三四十轮,加了 Attention 之后又不一样。EarlyStopping 能帮你自动找到合适的停止点,同时避免手动去数轮次的麻烦。

数据形状上,我统一用 3D 张量(batch_size, timesteps, features)输入,timesteps=30,features=14。后面所有模型都遵循这个输入约定,方便做公平对比。

4.2 变种一:堆叠 LSTM(Stacked LSTM)

堆叠 LSTM 就是把多个 LSTM 层按顺序连接。第一层 LSTM 的输出序列作为第二层 LSTM 的输入,每一层在更抽象的时间尺度上提取特征。实现时第一层 LSTM 必须设置 return_sequences=True,不然输出的维度就降成二维了,没法继续输入到第二层 LSTM。

from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout def build_stacked_lstm(input_shape): model = Sequential([ LSTM(64, return_sequences=True, input_shape=input_shape), Dropout(0.2), LSTM(64, return_sequences=False), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) return model

这里两个 LSTM 层的隐藏单元都设成了 64。我先试过把第二层设成 128,结果验证集分数反而下降。原因很可能是 FD001 训练数据量不够大,第二层参数量太大,模型记住了训练集里的噪声模式。

Dropout 我放在了两个 LSTM 层之后,比例 0.2。注意:Keras 的 LSTM 层内部也支持 dropout 参数(作用于输入和循环状态),我这里用的是层间 Dropout,两者作用位置不同。如果内部 dropout 设太大,比如 0.5,LSTM 的长期记忆能力会被明显削弱,这个我验证过。

4.3 变种二:双向 LSTM(Bidirectional LSTM)

双向 LSTM 的正向层按照时间正序处理序列,反向层按时间逆序处理序列,最后把两个方向的输出拼接起来。在 RUL 预测这种“只依赖过去预测未来”的场景里,理论上不应该用到未来的信息,但双向结构仍然能增加模型的表达容量,而且在实际实验里效果确实不差。

from tensorflow.keras.layers import Bidirectional def build_bidirectional_lstm(input_shape): model = Sequential([ Bidirectional(LSTM(64, return_sequences=True), input_shape=input_shape), Dropout(0.2), Bidirectional(LSTM(32, return_sequences=False)), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) return model

我在 FD001 上实测发现,双向 LSTM 的收敛速度比单向堆叠 LSTM 明显更快,验证集 loss 下降得很平稳。但你以为它会因为“偷看未来”而作弊式地拿到惊人效果?并没有,它的 Score 和堆叠 LSTM 差不多。原因不难理解:在 RUL 任务中,真实标签是“从当前时刻望向未来剩余多少周期”,如果当前时刻已经处于快速退化阶段,过去的信息已经足够表达退化趋势;未来信息带来的增量价值有限。

4.4 变种三:CNN-LSTM 混合模型

CNN-LSTM 的思路是先用一维卷积层在传感器通道和时间步上做局部特征提取,把原始的多变量时序压缩成更高层级的特征表示,再输入 LSTM 建模时间依赖。

from tensorflow.keras.layers import Conv1D, MaxPooling1D def build_cnn_lstm(input_shape): model = Sequential([ Conv1D(filters=64, kernel_size=5, activation='relu', padding='same', input_shape=input_shape), MaxPooling1D(pool_size=2), Conv1D(filters=32, kernel_size=3, activation='relu', padding='same'), MaxPooling1D(pool_size=2), LSTM(64, return_sequences=False), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) return model

为什么 CNN 在这里有用?因为发动机传感器信号里往往存在“局部趋势模式”:某个传感器在过去 5 到 10 个周期内的单调上升或下降斜率,比它当前的绝对值更能说明退化阶段。卷积核可以理解为一种“局部模式检测器”,例如 5 步的卷积核可以提取“这 5 个周期内传感器 7 是否持续上升”这种特征。

我踩过的坑是 kernel_size 的选择。一开始我设成 10,窗口总共才 30 步,10 步卷积核把整个序列的细节抹了不少,验证集效果反而不好。后来缩小到 5,再配合一层 3 步卷积核,效果明显改善。经验是:小窗口上卷积核不宜太大,否则就是自己给自己上模糊滤镜。

4.5 变种四:Attention 机制增强 LSTM

标准 LSTM 的最后一个时间步输出作为全连接层的输入,这相当于让模型把整段退化的信息压缩到一个固定向量里。但发动机退化过程不同阶段的重要性完全不同,临近失效前的几十个周期显然比早期的平稳阶段更有判断价值。Attention 机制就是让模型自己学会给每个时间步分配不同的权重。

from tensorflow.keras.layers import Layer import tensorflow as tf class AttentionLayer(Layer): def __init__(self, **kwargs): super(AttentionLayer, self).__init__(**kwargs) def build(self, input_shape): self.W = self.add_weight(name='attention_weight', shape=(input_shape[-1], 1), initializer='random_normal', trainable=True) self.b = self.add_weight(name='attention_bias', shape=(input_shape[1], 1), initializer='zeros', trainable=True) super(AttentionLayer, self).build(input_shape) def call(self, x): e = tf.nn.tanh(tf.tensordot(x, self.W, axes=1) + self.b) a = tf.nn.softmax(e, axis=1) output = x * a return tf.reduce_sum(output, axis=1) def build_attention_lstm(input_shape): model = Sequential([ LSTM(64, return_sequences=True, input_shape=input_shape), Dropout(0.2), AttentionLayer(), Dense(32, activation='relu'), Dense(1) ]) return model

这个 AttentionLayer 的实现方式是经典的点乘注意力:先算每个时间步的得分,然后 softmax 归一化成权重,最后对 LSTM 的隐藏状态做加权求和。实现时要注意一个细节:偏置项 b 的形状是 (input_shape[1], 1),也就是每个时间步共享同一个偏置;但有时候把偏置设成 (input_shape[-1], 1) 也能跑,只是语义不同。

加上 Attention 之后,可视化各时间步的权重会发现一个非常有意思的现象:模型自动地把高权重集中在临近失效前的最后 10 到 15 个周期,早期平稳阶段的注意力权重几乎为零。这验证了“并不是所有历史都一样重要”的直觉。

4.6 变种五:ConvLSTM 的尝试与取舍

ConvLSTM 在 LSTM 内部把矩阵乘法换成了卷积运算,也就是说,信息在网络内部流动时保留的是空间局部结构。它最常被用在降雨临近预报这类时空预测任务里,输入通常是视频帧序列或网格数据。

我之所以想在 CMAPSS 上试它,是想看传感器通道之间的“空间关系”是否也有建模价值。具体做法是把每个时间步的 14 维传感器向量 reshape 成 (14, 1, 1),然后让 ConvLSTM1D 在时间步上进行卷积和循环计算。

from tensorflow.keras.layers import ConvLSTM1D def build_convlstm(input_shape): model = Sequential([ ConvLSTM1D(filters=64, kernel_size=3, padding='same', return_sequences=True, input_shape=input_shape), ConvLSTM1D(filters=32, kernel_size=3, padding='same', return_sequences=False), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) return model

这里输入形状其实是 (30, 14, 1),也就是把传感器通道当成了空间维度。实验结果是验证集 loss 一直降不下去,效果明显差于普通 LSTM。原因也很直接:CMAPSS 的传感器通道之间并没有真正的空间邻接关系,把通道顺序当成空间上的相邻关系是人为强加的,ConvLSTM 的“局部连接”假设在传感器信号上不合理。所以这个变种我最终没有纳入主对比,但把它做出来的过程还是值得记录一下——不是所有“看起来合理”的变体都适合每个任务。

5. 实验结果对比与现象分析

5.1 各模型在 FD001 上的表现

以下是我这套预处理和训练配置下,各模型的实测结果(不同随机种子下会有波动,但相对关系基本稳定):

模型RMSENASA Score验证集收敛轮次
标准 LSTM(单层)32.8481222
堆叠 LSTM(双层)28.6311535
双向 LSTM28.2306818
CNN-LSTM25.4226515
Attention-LSTM26.1236720
ConvLSTM1D36.9712430+

注意,这个 Score 的绝对值看起来很大,是因为 NASA Score 对预测偏晚的样本会指数级放大惩罚,几个预测偏差较大的样本就能把总分推到几千。所以 Score 更适合相对比较,不适合单独看。

从结果能读出几个信息:

首先,所有变种在 RMSE 上都比单层 LSTM 好,说明单层 LSTM 的特征抽象能力确实不够用。堆叠和双向 LSTM 的提升主要来自模型容量增加和特征提取能力的增强,提升幅度稳但有限。

CNN-LSTM 是这次实验里让我最意外的模型。它不仅在 RMSE 上最低,在 Score 上也显著优于其他模型,而且收敛只需要 15 轮左右。这说明一维卷积在传感器信号的短期退化模式提取上有天然优势——它先帮 LSTM 把“当前处于什么退化阶段”这个关键特征算好,LSTM 再做时序建模就轻松很多。

Attention-LSTM 的 RMSE 和 Score 与 CNN-LSTM 接近,但注意它的优势不在数值上,而在于可解释性。你能直接看出模型在关注哪些时间步,这在做 PHM 决策时是一个加分项,尤其是做汇报或者写论文时,注意力权重的可视化非常有说服力。

ConvLSTM1D 的表现则证明了一个道理:没有通用的最优模型,只有适合任务假设的模型。传感器通道并不是空间排列的像素,强行用卷积递推的方式建模反而引入了错误归纳偏置。

5.2 为什么堆叠和双向提升并不像想象中大

我最初对双向 LSTM 的期待是比较高的,毕竟它在 NLP 任务里提升效果显著。但在 CMAPSS 这种强周期退化型时间序列上,未来信息并不能告诉模型“这台发动机还剩多少寿命”,因为退化过程的未来本身就是未知的。双向结构在这里更像是一种正则化手段和容量扩展,而不是“利用未来信息”的作弊器。

堆叠 LSTM 的瓶颈则在于训练难度和数据规模。FD001 训练集只有 100 台发动机,滑窗后有效的独立样本量远不如图像分类那种几十万张图片的规模。堆到三层 LSTM 后,参数数量上升很快,验证集反而变差。我试过 3 层堆叠,RMSE 会比 2 层堆叠差 1 到 2 个点,典型过拟合。

5.3 测试集上的最终评估细节

模型训练时监控的是验证集上的 MSE,但最终评估时我会把 Best Model 拿到测试集上,对每台测试发动机只预测最后一个时刻的 RUL。这一步要注意:测试集数据的归一化参数(min 和 max)必须来自训练集,不能重新计算。这是我在多个项目里反复强调的问题,太容易出错了。

测试集上,CNN-LSTM 的 RMSE 大概在 18 到 20 之间,Score 在 1500 到 1800 之间,比验证集上看到的数字好看。这不是模型作弊,而是因为验证集是从训练发动机里随机抽的,包含了很多中早期发动机的样本,测试集则全部是发动机最后阶段的样本,越临近失效,RUL 越小,绝对误差自然也变小了。

6. 实操中的常见问题与避坑总结

6.1 数据泄漏问题

除了归一化时要只用训练集的统计量以外,还有一个隐蔽的数据泄漏点:滑窗构造样本时,测试集里的同一台发动机,它的滑窗样本之间是有重叠的,如果你在测试时对同台发动机的所有窗口都做预测再取平均,这个问题不大。但如果你把测试集的所有滑窗样本混在一起评估,那 RMSE 会被重复计算的相似样本拉低,看起来成绩很好,实际上不公平。正确做法是:只对每台发动机最后一个窗口做预测并评估。

6.2 随机种子对结果的影响

LSTM 和 CNN 的权重初始化、Dropout 的随机性,以及 Adam 的随机数据打乱,都会导致每次训练结果不同。我发现不同随机种子下,同一个模型的 RMSE 波动能达到 2 到 3 个点。如果你的实验结果基线在 25 附近,一个种子跑到 24,另一个跑到 27,这都属于正常范围。所以做对比实验时,务必固定全局随机种子,并且最好每个模型跑 3 次取平均。我自己固定了 Python、NumPy、TensorFlow 的随机种子,每次实验仍然需要跑两遍确认稳定性。

import random import numpy as np import tensorflow as tf def set_seed(seed=42): random.seed(seed) np.random.seed(seed) tf.random.set_seed(seed)

6.3 EarlyStopping 的 patience 怎么设

patience 太小,比如 3,模型还没收敛到位就停了;patience 太大,比如 30,训练时间拉长,还可能保存到过拟合后期的模型。这个数据集上我用 patience=10 比较合适。同时注意 EarlyStopping 要监控验证集 loss,而不是训练 loss,否则它永远不会触发。

6.4 数据不平衡问题

CMAPSS 的滑窗样本里,RUL 特别大的样本占大多数,RUL 小于 30 的临界样本只占一小部分。模型天然偏向于学“大多数样本的规律”,对临界阶段的学习不充分。除了前面提到的 RUL 分段线性化,还有一种做法是对 RUL 较小的样本加权,增大它们的损失权重。但我在实际实验中,分段线性化的收益更直接,加权的方法需要额外调权重大小,反而容易过拟合。

6.5 训练时间与资源建议

FD001 的滑窗样本量也就一万出头,所有模型在单张消费级 GPU(比如 RTX 3060)上训练一轮都在几秒到十几秒之间,整个实验不会超过半小时。CPU 上也能跑,就是慢一些。所以这个数据集很适合作为架构对比的试验场,不用担心算力不够。

7. 总结之外:从对比实验中学到了什么

整个实验做下来,最有价值的不是哪一个模型分数最高,而是搞清楚了一个工作原理:在传感器退化数据上,特征提取方式比循环网络的堆叠深度更影响效果。CNN-LSTM 能脱颖而出,是因为它先用卷积把局部时序特征显式提取出来,再交给 LSTM 去捕捉长期依赖,分工明确。这个“先局部后全局”的思路,放到其他工业时间序列任务,比如风力发电机齿轮箱温度预测、锂离子电池容量衰退预测,大概率也是成立的。

Attention-LSTM 让我意识到,模型不只是黑盒百分数。把注意力权重可视化之后,工程师能看到哪些时间段对剩余寿命贡献最大,这就为后续的维修决策提供了辅助依据。我后面打算把 Attention 的权重输出接一个“退化警报”功能,当模型开始把注意力集中到最近 10 个周期时,就提示维护人员重点关注,这会是一个很自然的工程化落地方向。

最后再分享一个经验:做这类模型对比时,不要只盯着最后的 RMSE 数字,一定要把你喂给模型的数据、标签、归一化方式、随机种子全部记录下来。我见过太多人复现论文时怎么调都复现不出结果,最后发现是标签处理方式和原文不完全一致。数据和代码的确定性,有时候比模型结构本身更影响最终效果。

返回列表