LSTM与卡尔曼滤波:时间序列预测原理、对比与Python实战

LSTM与卡尔曼滤波:时间序列预测原理、对比与Python实战 如果你最近在看时间序列预测相关的内容一定绕不开两个名字LSTM 和卡尔曼滤波。一个来自深度学习是循环神经网络最经典的变体一个是控制与信号处理领域的老牌算法已经稳定服务了半个世纪。表面看一个偏神经网络、一个偏概率统计但在时间序列预测这件事上它们是两条完全不同的技术路线也是面试和实际项目里永远逃不掉的高频考点。这篇文章想先给一个明确判断不要因为“已经出现 Transformer 了”就跳过 LSTM也不要因为“深度学习时代”就忽视卡尔曼滤波。在绝大多数真实业务场景里LSTM 是复杂模式学习最稳妥的基线模型卡尔曼滤波是轻量级、可解释、能输出不确定性的最优解法。搞懂这两个模型比盲目追新模型更能解决实际问题。整篇文章会围绕“论文精读 代码复现”展开先讲清两个模型的底层思想和论文脉络再用 Python 从零到一复现卡尔曼滤波和 LSTM 的时序预测流程最后给出一个把 LSTM 输出交给卡尔曼滤波做平滑的融合示例。读完你会得到一套可直接改到自己数据上的预测流程也能在面试里把这两个模型讲得有条理。1. 这篇文章真正要解决的问题很多人在时间序列预测上的第一个困惑是模型太多了不知道该从哪个开始。这个问题背后还有一个更现实的矛盾——深度学习模型能拟合非常复杂的非线性关系但需要数据和调参传统滤波算法不需要训练但假设条件比较严格。两种方法各有各的适用范围完全不是替代关系。我见过不少项目组选了 LSTM训练出模型后却发现预测曲线抖动很厉害也有项目只用卡尔曼滤波处理带噪声的传感器数据但对某些非线性模式无能为力。这说明真正的问题不是“哪个模型更厉害”而是“哪个模型适合当前场景以及怎么组合使用”。另外这两个模型在 AI 面试里的出现频率极高。LSTM 考的是门控机制、梯度消失问题和序列建模能力卡尔曼滤波考的是状态空间模型、预测更新两步推导和 Q/R 参数含义。如果你只背结论不推公式很容易在追问环节露馅。本文针对的读者有三类正在入门时间序列预测想建立完整方法论的开发者需要用代码验证理论希望快速复现两个模型的工程人员准备面试想把 LSTM 和卡尔曼滤波讲清楚的技术候选人。读完这篇文章你会得到三个东西两个模型的原理认知、可运行的 Python 示例代码、一套模型选型和融合的实践方法。2. LSTM 核心概念与论文脉络LSTM 全称 Long Short-Term Memory中文叫长短期记忆网络是 Hochreiter 和 Schmidhuber 在 1997 年提出的。它出现的原因非常直接传统的循环神经网络RNN在序列较长时会出现梯度消失或梯度爆炸导致模型记不住早期信息。LSTM 的贡献就是通过门控机制解决“长期记忆”问题。2.1 RNN 到 LSTM从短期记忆到长短期记忆先看一个最简单的场景。假设你正在阅读文本“小明出生于北京他喜欢____”要预测空里的词你需要记住“北京”这个地点信息。普通 RNN 的隐藏状态会随序列长度逐渐衰减早期信息到后面基本被冲淡了。LSTM 的解决方案是增加一条“细胞状态”cell state通道让信息可以在序列中长距离传递并通过门控决定什么该记住、什么该忘记。LSTM 的核心结构包含三个门遗忘门决定上一时刻的细胞状态哪些信息需要丢弃输入门决定当前时刻的新信息有多少写入细胞状态输出门决定当前细胞状态有多少输出到隐藏状态。每个门本质上都是一个带 sigmoid 激活函数的全连接层。sigmoid 的输出在 0 到 1 之间0 表示完全过滤1 表示完全保留。这样网络就可以在训练中自动学习哪些历史信息重要、哪些当前信息值得更新。2.2 LSTM 的前向传播公式把结构翻译成公式状态更新如下f_t σ(W_f · [h_{t-1}, x_t] b_f) # 遗忘门 i_t σ(W_i · [h_{t-1}, x_t] b_i) # 输入门 C̃_t tanh(W_C · [h_{t-1}, x_t] b_C) # 候选细胞状态 C_t f_t * C_{t-1} i_t * C̃_t # 当前细胞状态 o_t σ(W_o · [h_{t-1}, x_t] b_o) # 输出门 h_t o_t * tanh(C_t) # 当前隐藏状态其中[h_{t-1}, x_t]表示上一时刻隐藏状态和当前输入拼接*表示逐元素相乘。从公式可以看清 LSTM 的设计逻辑细胞状态C_t通过遗忘门和输入门做线性更新梯度可以沿这条通路回传而不被反复压缩因此极大地缓解了梯度消失问题。2.3 论文精读的关键收获从论文角度看LSTM 最重要的贡献不是某个数学技巧而是“引入可学习的门控机制来控制信息流”这一建模思想。后来的 GRU 简化了门控结构Transformer 用注意力机制替换了循环结构但 LSTM 确立的“选择记忆”思路一直延续下来。在深度学习时代LSTM 的最大价值是给序列数据提供了一个强基线。你没有必要每次都用最复杂的模型很多业务数据用 LSTM 就能达到可用水平。3. 卡尔曼滤波核心概念与原理卡尔曼滤波Kalman Filter, KF由 Rudolf E. Kalman 在 1960 年提出。它解决的是一个看起来完全不同的问题在只有带噪声的观测数据时如何估计系统内部真实状态。它不依赖深度学习训练也不需要大量历史数据非常适合实时预测和传感器融合场景。3.1 用一个例子理解卡尔曼滤波想象你在室内用测距仪跟踪一架无人机。测距仪每次读数都有噪声但你知道无人机不可能瞬间瞬移到另一个位置它的运动基本符合动力学规律。卡尔曼滤波做的事就是把“观测值”和“物理规律预测值”按各自的不确定性加权融合得到一个比两者都更准的估计。这里有两个关键概念状态state无人机的位置、速度等真实但不可直接观测的量观测observation传感器读到的、包含噪声的数据。卡尔曼滤波假设系统是线性的噪声服从高斯分布。状态转移矩阵 A 描述物理规律观测矩阵 H 描述传感器如何读取状态过程噪声协方差 Q 表示模型的不确定性观测噪声协方差 R 表示传感器的噪声水平。3.2 预测与更新两个步骤卡尔曼滤波的运行可以拆成两步第一步是预测Predict用上一时刻的状态估计和运动模型推算当前时刻的先验状态x̂_k|k-1 A · x̂_{k-1|k-1} B · u_k P_k|k-1 A · P_{k-1|k-1} · A^T Q其中P是状态协方差矩阵表示当前估计的不确定度。u_k是外部控制量没有控制输入时可以忽略。第二步是更新Update用当前观测值修正先验估计K_k P_k|k-1 · H^T · (H · P_k|k-1 · H^T R)^(-1) x̂_k|k x̂_k|k-1 K_k · (z_k - H · x̂_k|k-1) P_k|k (I - K_k · H) · P_k|k-1这里的K_k就是卡尔曼增益它决定了在“相信模型预测”和“相信传感器观测”之间如何分配权重。如果观测噪声 R 很小卡尔曼增益会偏大滤波结果更贴近观测如果过程噪声 Q 很小说明模型很可靠滤波结果会更贴近模型预测。3.3 论文精读的关键收获卡尔曼滤波在工程界的地位极高因为它有清晰的概率解释、计算简单、占内存小、实时性极强。GPS 导航、自动驾驶状态估计、金融数据的波动率估计、传感器融合等场景中它都是标配算法。缺点也同样明显公式假定线性系统和高斯噪声。如果系统高度非线性就需要扩展卡尔曼滤波EKF或无迹卡尔曼滤波UKF原理仍然是预测加更新只是用不同方式处理非线性。4. 两个模型的对比什么时候用哪个把 LSTM 和卡尔曼滤波放在一起对比核心差异要看下表对比维度LSTM卡尔曼滤波核心技术路线数据驱动神经网络学习序列模式模型驱动状态空间模型 贝叶斯更新是否需要训练数据需要大量历史数据不需要训练但需要设定模型参数计算复杂度较高依赖 GPU/CPU 算力极低适合嵌入式实时系统对非线性的适应能力强可以拟合复杂非线性弱线性高斯假设下最优不确定性量化较弱通常只输出点预测自然输出协方差矩阵能给出置信区间可解释性较低黑盒模式较高物理模型与参数可解释适用数据规模大样本、复杂模式小样本、简单线性动态系统典型场景销量预测、股票走势、自然语言处理目标追踪、姿态解算、传感器滤波从这个对比可以看出两者不是竞争关系而是互补关系。LSTM 擅长从复杂历史数据中挖掘非线性模式卡尔曼滤波擅长在动态系统里做实时估计和噪声滤波。很多工程系统会把两个模型组合起来使用后面会给出示例。5. 环境准备与前置条件本文的代码复现以 Python 为主涉及 PyTorch、NumPy、Matplotlib。环境上不需要特别复杂的配置只要保证基本依赖可用。需要准备的环境如下Python 3.8 及以上版本PyTorch 2.x用于训练 LSTMNumPy 1.x用于数值计算和卡尔曼滤波实现Pandas 1.x非必须用于数据处理时可选Matplotlib用于绘制预测结果。安装依赖可以用以下命令pip install numpy pandas matplotlib torch如果你的机器没有 GPU本文的示例用 CPU 训练也完全没有问题因为 LSTM 示例使用的数据量很小几十个 epoch 即可完成。需要说明的是本文给出的版本范围是常见实践方案。如果你使用最新版本遇到接口差异可以参考官方文档调整重点在于理解整体流程。6. 卡尔曼滤波代码复现一维温度平滑先从最容易理解的卡尔曼滤波开始。我们构建一个场景用温度传感器测量环境温度传感器读数有噪声真实温度随时间缓慢变化。目标是用卡尔曼滤波把噪声滤掉估计出更接近真实的温度。6.1 生成模拟数据为了结果可复现先用固定随机种子生成带噪声的温度观测import numpy as np import matplotlib.pyplot as plt # 固定随机种子保证结果可复现 np.random.seed(42) # 生成 100 个时刻的真实温度带缓慢上升趋势 n 100 true_temp 25 0.05 * np.arange(n) # 观测噪声标准差设为 0.8 obs_noise 0.8 obs_temp true_temp np.random.normal(0, obs_noise, n) print(前 10 个观测值, obs_temp[:10])这段代码里true_temp是理想中的真实温度obs_temp是传感器带噪声的读数。在实际业务中obs_temp才是我们能拿到的数据。6.2 实现卡尔曼滤波对一维系统来说状态转移矩阵 A、观测矩阵 H 都是 1状态就是温度本身。我们把过程噪声方差 Q 设为 0.01观测噪声方差 R 设为 0.64即 0.8 的平方。# 卡尔曼滤波初始化 x 25.0 # 初始状态估计 P 1.0 # 初始状态协方差 A 1.0 # 状态转移矩阵 H 1.0 # 观测矩阵 Q 0.01 # 过程噪声方差 R 0.64 # 观测噪声方差 estimates [] for z in obs_temp: # 预测步骤 x_pred A * x P_pred A * P * A Q # 更新步骤 K P_pred * H / (H * P_pred * H R) x x_pred K * (z - H * x_pred) P (1 - K * H) * P_pred estimates.append(x) # 转换为数组方便绘图 estimates np.array(estimates)这里需要关注K的计算P_pred * H / (H * P_pred * H R)就是一维情况下的卡尔曼增益公式。当 R 越大分母越大K 越小说明传感器噪声大滤波结果更依赖模型预测当 Q 越大P 会变大K 跟着变大说明模型不可靠滤波结果更跟随观测。6.3 可视化验证把真实值、观测值和滤波结果画在一张图上能直观看出卡尔曼滤波的平滑效果plt.figure(figsize(10, 5)) plt.plot(true_temp, labelTrue Temperature, linewidth2) plt.plot(obs_temp, alpha0.6, linewidth0.8, labelObserved) plt.plot(estimates, linewidth2, linestyle--, labelKalman Estimate) plt.legend() plt.xlabel(Time Step) plt.ylabel(Temperature) plt.title(Kalman Filter for Temperature Smoothing) plt.grid(True, alpha0.3) plt.show()运行后可以看到观测曲线起伏很大而卡尔曼滤波输出明显更平滑同时能跟踪真实温度的变化趋势。因为Q设置得较小滤波结果不会因为单个噪声点剧烈波动。6.4 调参验证你可以修改Q和R观察效果。把R调大滤波曲线会更平滑但响应变慢把Q调大滤波会更敏感但噪声更多。理解这一对参数的取舍是卡尔曼滤波使用中最核心的能力。7. LSTM 时间序列预测代码复现卡尔曼滤波解决的是“有噪声的实时估计”问题LSTM 解决的是“从历史序列学习模式并预测未来”的问题。我们用一个带趋势的合成时间序列演示完整流程构造数据、切分样本、训练 LSTM、预测并可视化。7.1 构造训练数据用正弦波加线性趋势再加一点噪声模拟一个既有周期性又有趋势变化的时间序列import torch import torch.nn as nn np.random.seed(42) t np.arange(0, 20, 0.02) data np.sin(t) 0.02 * t np.random.normal(0, 0.05, sizet.shape)LSTM 需要监督学习形式的样本。给定一个长度为seq_len的历史窗口预测下一时刻的值。下面这个函数负责把原始序列切成样本def create_sequences(data, seq_len20): X, y [], [] for i in range(len(data) - seq_len): X.append(data[i:i seq_len]) y.append(data[i seq_len]) return np.array(X), np.array(y) seq_len 20 X, y create_sequences(data, seq_len) # 按 8:2 切分训练集和测试集 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] # 转换为 PyTorch 张量并增加特征维度 X_train torch.tensor(X_train, dtypetorch.float32).unsqueeze(-1) y_train torch.tensor(y_train, dtypetorch.float32).unsqueeze(-1) X_test torch.tensor(X_test, dtypetorch.float32).unsqueeze(-1) y_test torch.tensor(y_test, dtypetorch.float32).unsqueeze(-1) print(训练样本形状, X_train.shape, y_train.shape) print(测试样本形状, X_test.shape, y_test.shape)要注意unsqueeze(-1)的作用LSTM 期望输入形状是(batch, seq_len, input_size)这里的input_size是每个时刻的特征数我们用的是单变量序列所以特征数为 1。7.2 定义 LSTM 模型模型结构采用两层 LSTM 加一个全连接输出层。LSTM 处理序列后取最后一个时间步的隐藏状态作为特征再通过Linear映射到预测值class LSTMPredictor(nn.Module): def __init__(self, hidden_size32, num_layers2): super().__init__() self.lstm nn.LSTM( input_size1, hidden_sizehidden_size, num_layersnum_layers, batch_firstTrue ) self.fc nn.Linear(hidden_size, 1) def forward(self, x): # out 的形状(batch, seq_len, hidden_size) out, _ self.lstm(x) # 取最后一个时间步的输出 last_out out[:, -1, :] return self.fc(last_out) model LSTMPredictor(hidden_size32, num_layers2) print(model)这段代码里batch_firstTrue让输入和输出的 batch 维度放在第一维符合大多数人的使用习惯。out[:, -1, :]取出每个序列最后一个时刻的隐藏状态它已经聚合了序列的完整信息。7.3 训练循环使用 MSE 作为损失函数Adam 作为优化器。为了让模型不出现过拟合训练 50 个 epoch并用小批量数据训练criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr0.01) batch_size 64 dataset torch.utils.data.TensorDataset(X_train, y_train) loader torch.utils.data.DataLoader(dataset, batch_sizebatch_size, shuffleTrue) epochs 50 for epoch in range(epochs): for xb, yb in loader: optimizer.zero_grad() pred model(xb) loss criterion(pred, yb) loss.backward() optimizer.step() if (epoch 1) % 10 0: print(fEpoch {epoch 1:3d}, Loss: {loss.item():.6f})训练过程中loss 应该逐步下降。如果 loss 抖动明显可以调低学习率如果 loss 下降过慢可以适当增大学习率或增加 epoch 数。7.4 预测并绘制结果训练完成后用测试集进行预测。这里要注意一个新手容易犯的错测试集不能直接拿整个序列喂给模型因为 LSTM 模型内部没有记忆状态它只依赖输入窗口内的信息。因此测试集也要按窗口划分后逐样本预测。model.eval() with torch.no_grad(): y_pred model(X_test).numpy().flatten() y_true y_test.numpy().flatten() # 绘制结果 plt.figure(figsize(10, 5)) plt.plot(y_true, labelTrue) plt.plot(y_pred, labelLSTM Predict) plt.legend() plt.xlabel(Sample Index) plt.ylabel(Value) plt.title(LSTM Time Series Prediction on Test Set) plt.grid(True, alpha0.3) plt.show() # 输出 MSE mse np.mean((y_true - y_pred) ** 2) print(fTest MSE: {mse:.6f})如果预测曲线和真实曲线基本贴合说明模型已经学到了序列的周期和趋势。如果预测曲线出现明显滞后比如整体向右偏移常见原因是窗口长度不合适或数据未做差分处理。8. 融合示例LSTM 输出交给卡尔曼滤波做平滑在实际工程中LSTM 预测结果往往会带有随机抖动尤其是数据噪声较大的时候。一个非常实用的组合思路是先把 LSTM 当作“观测器”生成预测序列再用卡尔曼滤波对预测结果做后处理平滑。这样做的好处有三个预测曲线更平滑减少业务侧对“跳变”的投诉卡尔曼滤波会输出置信区间方便下游做风险判断实现成本低只需在 LSTM 后叠加几十行代码。把第 7 节的y_pred作为观测值再做一次卡尔曼滤波# 用卡尔曼滤波平滑 LSTM 预测结果 kf_smooth [] x_state float(y_pred[0]) P_state 1.0 A 1.0 H 1.0 Q 0.01 R 0.10 # 对预测结果滤波时R 可以设置得更小 for p in y_pred: x_pred_state A * x_state P_pred_state A * P_state * A Q K P_pred_state * H / (H * P_pred_state * H R) x_state x_pred_state K * (p - H * x_pred_state) P_state (1 - K * H) * P_pred_state kf_smooth.append(x_state) kf_smooth np.array(kf_smooth) # 绘制对比 plt.figure(figsize(12, 5)) plt.plot(y_true, labelTrue, linewidth2) plt.plot(y_pred, alpha0.7, linestyle--, labelLSTM Raw) plt.plot(kf_smooth, linewidth2, labelLSTM Kalman Smooth) plt.legend() plt.xlabel(Sample Index) plt.ylabel(Value) plt.title(LSTM Output Smoothed by Kalman Filter) plt.grid(True, alpha0.3) plt.show()运行后能看到叠加卡尔曼滤波后预测曲线的毛刺明显减少整体更接近真实趋势。注意这里的R设置比第 6 节小是因为 LSTM 预测虽然可能偏离真实值但短期内抖动幅度通常没有传感器噪声大所以滤波会更信任观测。需要说明的是这种融合方式是后处理并不改变 LSTM 的预测精度它只改善输出的平滑性和稳定性。如果你的目标本身就是降低 MSE应该把重心放在特征工程、窗口设计和模型调参上。9. 运行结果与效果验证完整跑通本文代码后你应该能看到两个明显结果。第一个是卡尔曼滤波的温度估计曲线。观测值围绕真实值上下波动滤波估计曲线既没有跟随每一个噪声点又没有严重滞后于真实趋势。这说明卡尔曼增益在“相信观测”和“相信模型”之间取得了平衡。第二个是 LSTM 的测试集预测曲线。在训练结束时loss 会稳定在一个较低水平测试集 MSE 也会体现模型在未见数据上的表现。叠加卡尔曼平滑后预测曲线的抖动减小但整体走势保持一致。判断一个时间序列预测系统是否成功建议按三个标准衡量数值准确性MSE、MAE 是否在业务可接受范围趋势跟随能力预测曲线是否在拐点处能及时转向稳定性连续预测结果是否抖动剧烈是否影响下游决策。如果失败第一步建议检查数据切分和归一化。很多 LSTM 预测效果差不是因为模型不够好而是因为训练集和测试集存在数据泄漏或者数据未做归一化导致 loss 不收敛。10. 常见问题与排查思路下面整理了 LSTM 和卡尔曼滤波代码复现过程中最常见的几类问题以及对应的排查思路问题现象可能原因排查方式解决方案LSTM 训练 loss 不下降学习率过大或过小数据未归一化打印 loss 曲线检查数据范围将数据归一化到 0~1调整学习率到 0.001~0.01预测曲线整体滞后窗口长度过短或数据未做趋势处理查看预测曲线与真实曲线的相位差增大 seq_len或对数据做一阶差分测试集效果好但线上效果差训练集和测试集分布不一致或存在数据泄漏检查数据切分是否打乱特征是否使用了未来信息按时间顺序切分严格避免用未来数据构造特征卡尔曼滤波估计发散Q、R 设置不合理或初始状态估计错误打印每个时刻的 P 和 K 值增大 Q 或减小 R重新设定初始状态卡尔曼滤波响应太慢Q 过小导致模型过于相信状态转移观察滤波曲线是否严重滞后于观测适当增大 Q让滤波结果更跟随观测LSTM 训练时显存不足batch_size 或 hidden_size 设置过大查看显存占用和日志减小 batch_size或降低 hidden_size预测结果出现 NaN学习率过高导致梯度爆炸检查 loss 是否为 NaN模型参数是否有异常值降低学习率添加梯度裁剪 clip_grad_norm_从实际项目来看LSTM 最容易踩的坑是数据泄漏。很多入门者会用全序列的均值做归一化这就把测试集信息泄漏到了训练过程。正确的做法是先切分数据再只基于训练集拟合归一化参数然后把同样的参数应用到测试集。卡尔曼滤波最常踩的坑是 Q 和 R 的取值没有物理依据。建议的做法是先根据传感器的标称精度确定 R例如传感器说明书标称误差为 0.8就把 R 设为 0.64Q 则根据系统运动模型的置信度确定先给一个较小值再用网格搜索微调。11. 最佳实践与工程建议把两个模型真正用到业务中需要关注的不仅是模型本身还有整个流程的工程细节。11.1 数据划分与归一化时间序列数据不能按随机方式划分训练集和测试集必须按时间顺序划分。否则模型会在测试阶段“偷看”未来数据得出的指标毫无参考价值。归一化也必须在划分之后进行并且只能使用训练集的统计量。推荐写法是把训练集 fit 后再 transform 训练集和测试集。11.2 窗口长度的选择LSTM 的窗口长度决定了模型能看到多长的历史信息。窗口太短模型学不到周期特征窗口太长训练开销增大且可能引入无关噪声。一个实用的方法是考察数据的自相关函数选择自相关系数较高的滞后阶数作为初始窗口长度。11.3 卡尔曼滤波参数调节卡尔曼滤波没有训练过程但参数设定本身就是模型设计。R 可以从传感器噪声的标准差推导Q 是过程噪声协方差表示模型对运动规律的信任程度。建议先用单位矩阵起步再根据验证集的估计误差手动调整。实际业务中如果滤波结果太光滑就先调大 Q如果噪声太明显就先调小 R。11.4 融合方案的工程落地在预测服务中集成 LSTM 和卡尔曼滤波推荐用独立的平滑模块。LSTM 负责预测输出卡尔曼滤波模块在上游组件中消费预测结果并输出平滑值和方差。这样设计的好处是如果某个环节出现问题可以单独回滚而不需要重新部署整个模型。11.5 监控与告警生产环境的模型会面临数据分布漂移。建议在预测模块中记录每天的输入分布、预测均值、方差和 MSE。当这些指标偏离训练期基准时触发告警并重新评估模型。卡尔曼滤波输出的协方差矩阵本身就是一个天然监控指标协方差意外增大往往意味着模型假设失效。12. 总结与后续学习方向本文从论文脉络讲到代码复现完整的走通了卡尔曼滤波和 LSTM 两条时间序列预测技术路线。你需要记住的核心判断是LSTM 适合从大量历史数据中学习复杂非线性模式卡尔曼滤波适合在线实时估计带噪声的动态系统两者融合能兼顾预测精度和输出稳定性。如果要把这套方法用到自己的数据上建议按这个顺序操作先用卡尔曼滤波做数据清洗和状态估计理解数据的噪声水平再用 LSTM 做序列预测重点调窗口长度、隐藏层大小和学习率最后把 LSTM 输出接入卡尔曼滤波做平滑观察业务指标是否改善。后续值得深入的方向包括LSTM 的变体 GRU、处理非线性系统的扩展卡尔曼滤波和无迹卡尔曼滤波、以及用 Transformer 做长序列预测。但无论技术怎么演进本文讲到的“数据驱动”和“模型驱动”两条路线的取舍始终是时间序列分析的核心议题。建议收藏本文在动手写代码时随时回来对照排查表和调参思路实践一次之后你对这两个模型的理解会比刷十篇文章更扎实。