我们先从实际开发里最常见的困惑说起拿到一批时间序列数据到底该用深度学习模型还是经典滤波算法网上资料往往把 LSTM 和卡尔曼滤波分开讲一个讲“神经网络拟合非线性”一个讲“状态估计最优”真正把两者放在一起做对比、做代码复现的内容并不算多。这篇文章就围绕这两个热度很高的模型展开不讲抽象数学推导而是从原理、适用场景、Python 代码、参数调优、常见坑点几个维度完整过一遍。无论你是做预测、做量化、做传感器数据处理还是正在准备相关论文复现这篇文章都能给你一条比较清晰的落地路径。1. 为什么 LSTM 和卡尔曼滤波经常被放在一起讨论1.1 两种模型分别解决什么问题卡尔曼滤波Kalman Filter是一种基于状态空间模型的最优递归估计算法最早由 Rudolf Kalman 在 1960 年提出。它解决的问题是系统状态无法直接观测只能通过带噪声的观测值来估计真实状态。最经典的例子是航天器导航、雷达目标跟踪、传感器数据融合。LSTMLong Short-Term Memory长短期记忆网络是一种循环神经网络RNN的改进结构专门用来处理序列数据中的长期依赖问题。它解决的问题是普通 RNN 在反向传播过程中容易出现梯度消失或梯度爆炸导致模型很难学到距离当前时刻较远的有效信息。LSTM 通过引入“门控机制”和“记忆单元”让信息可以选择性保留或遗忘。1.2 为什么两种思路可以互相补充从时间序列预测的角度看两者解决的是不同层面的问题卡尔曼滤波适合线性高斯系统计算量小实时性强能给出带置信区间的最优估计。LSTM 适合非线性、复杂模式的序列数据不需要人为指定状态方程只要有足够数据就能学习到隐含规律。在实际项目中有人直接二选一也有人把两者结合起来比如用 LSTM 预测“过程噪声”或“状态转移”再用卡尔曼滤波做最终的平滑输出。这种结合方式在自动驾驶轨迹预测、金融波动率建模、工业传感器异常检测里都有研究。所以“2026 年最火的两个模型”并不是说它们取代了 Transformer 或其他模型而是因为它们分别代表了“经典信号处理方法”和“深度学习方法”在时间序列预测上的两条典型技术路线。理解它们的核心思想和代码实现对后续学习更复杂的模型非常有帮助。2. 核心原理先把模型框架搞懂2.1 卡尔曼滤波的状态空间描述卡尔曼滤波不是凭空出现的黑盒它建立在一组数学模型假设上。我们需要定义两个方程状态转移方程x_k A * x_{k-1} B * u_k w_k其中x_k 是 k 时刻的系统状态向量A 是状态转移矩阵B 是控制输入矩阵u_k 是外部控制量w_k 是过程噪声通常假设服从均值为 0、协方差为 Q 的正态分布观测方程z_k H * x_k v_k其中z_k 是 k 时刻的观测值H 是观测矩阵v_k 是观测噪声通常假设服从均值为 0、协方差为 R 的正态分布为了方便理解我们可以举一个一维例子用温度计测量室温。房间的真实温度变化过程比较缓慢我们可以假设温度基本不变也就是 A1没有外部控制输入温度计读数会有噪声所以观测方程就是 z_k x_k v_k。这时候卡尔曼滤波就可以用来从一系列带噪声的温度读数中估计真实温度。2.2 卡尔曼滤波的两大步骤预测与更新卡尔曼滤波是一个递归过程每来一个新观测值就会执行两个阶段。第一阶段是预测Predict根据上一时刻的状态估计当前时刻状态计算当前时刻的状态协方差第二阶段是更新Update计算卡尔曼增益 K结合观测值修正状态估计更新状态协方差卡尔曼增益可以理解为一个“信任权重”它决定我们更相信模型的预测结果还是更相信传感器观测结果。如果观测噪声很小卡尔曼增益会变大算法就更“相信”观测如果过程噪声很小模型预测更可靠卡尔曼增益会变小。整个递推过程只需要保存上一时刻的状态和协方差不需要保存历史数据所以计算效率非常高非常适合实时系统。2.3 LSTM 的门控机制与记忆单元LSTM 的核心创新是引入了一个贯穿时间步的“细胞状态”cell state。这个细胞状态可以理解为一条信息高速公路梯度可以在较长的序列中顺畅流动。具体来说LSTM 有三个门遗忘门forget gate决定上一时刻的细胞状态有多少信息要被丢弃输入门input gate决定当前输入有多少信息要写入细胞状态输出门output gate决定当前细胞状态有多少信息要输出到隐状态每一时刻的更新过程可以概括为f_t sigmoid(W_f * [h_{t-1}, x_t] b_f) i_t sigmoid(W_i * [h_{t-1}, x_t] b_i) o_t sigmoid(W_o * [h_{t-1}, x_t] b_o) c_t f_t * c_{t-1} i_t * tanh(W_c * [h_{t-1}, x_t] b_c) h_t o_t * tanh(c_t)其中 h_t 是隐状态c_t 是细胞状态。这些公式看起来复杂但在代码层面我们只需要调用深度学习框架里的 LSTM 层就好不必手动实现反向传播。2.4 LSTM 的输入输出形状使用 TensorFlow 或 PyTorch 时新手最容易出错的是输入数据的 shape。LSTM 层期望的输入通常是三维张量(batch_size, time_steps, input_dim)batch_size每批样本数time_steps每个样本包含多少个历史时间点input_dim每个时间点上特征数量例如我们用过去 24 小时的温度数据预测下一小时温度如果每个小时只有一个温度值那么 time_steps24input_dim1。如果有温度和湿度两个特征input_dim2。3. 环境准备与数据说明3.1 运行环境本文代码以 Python 3.8 为例建议准备以下库pip install numpy pandas matplotlib scikit-learn tensorflow版本不需要完全固定TensorFlow 使用 2.x 即可。如果只想跑卡尔曼滤波部分不安装 TensorFlow 也可以因为卡尔曼滤波我们手动实现不依赖专用库。3.2 数据集选择思路为了便于复现本文使用模拟数据和真实开放数据结合的方式讲解卡尔曼滤波部分使用正弦波叠加高斯噪声的模拟数据方便观察滤波平滑效果。LSTM 部分使用带趋势和噪声的信号数据同时也可以替换成你自己的 CSV 文件。如果你有真实业务数据只需要把数据读取部分替换成 pd.read_csv 即可后续的滑动窗口构造和模型训练流程可以复用。3.3 项目结构建议按照下面的目录组织文件time_series_forecast/ ├── data/ │ └── series.csv ├── lstm_forecast.py ├── kalman_filter.py └── requirements.txt这样代码、数据、依赖分离后续扩展也比较方便。4. 实战一LSTM 时间序列预测完整代码4.1 数据读取与预处理我们先生成一份模拟的时间序列数据。为了让实验更有意义数据由趋势项、周期性成分和随机噪声组成。import numpy as np import pandas as pd import matplotlib.pyplot as plt # 生成模拟数据趋势 正弦周期 噪声 np.random.seed(42) t np.arange(0, 1000, 1) trend 0.02 * t seasonal 5 * np.sin(2 * np.pi * t / 50) noise np.random.normal(0, 0.5, sizet.shape) data trend seasonal noise df pd.DataFrame({time: t, value: data}) df.to_csv(data/series.csv, indexFalse) plt.figure(figsize(12, 4)) plt.plot(t, data) plt.title(Simulated Time Series) plt.xlabel(time) plt.ylabel(value) plt.show()数据生成后我们需要做归一化。LSTM 使用 tanh 和 sigmoid 激活函数对输入数值范围比较敏感。如果不做归一化数值过大可能导致训练不稳定。这里使用 MinMaxScaler 把数据缩放到 0 到 1 之间。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler() scaled_data scaler.fit_transform(df[[value]])4.2 构造滑动窗口样本LSTM 不能直接吃一维序列我们需要把数据切成“过去若干步预测未来一步”的样本。def create_sequences(data, lookback24, forecast_horizon1): X, y [], [] for i in range(len(data) - lookback - forecast_horizon 1): X.append(data[i:i lookback, 0]) y.append(data[i lookback forecast_horizon - 1, 0]) return np.array(X), np.array(y) lookback 24 X, y create_sequences(scaled_data, lookback) # 划分训练集和测试集 split int(0.8 * len(X)) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] # 调整为 LSTM 输入形状 (batch_size, time_steps, input_dim) X_train X_train.reshape((X_train.shape[0], X_train.shape[1], 1)) X_test X_test.reshape((X_test.shape[0], X_test.shape[1], 1))这里需要注意slide window 构造完之后训练集和测试集要严格按照时间顺序划分不能随机打乱否则会造成数据泄露测试结果会比真实情况好很多但在线上使用时模型效果会暴跌。4.3 构建 LSTM 模型我们搭建一个包含两层 LSTM 的模型最后接一个全连接层输出预测值。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout model Sequential([ LSTM(64, return_sequencesTrue, input_shape(lookback, 1)), Dropout(0.2), LSTM(32, return_sequencesFalse), Dropout(0.2), Dense(1) ]) model.compile(optimizeradam, lossmse, metrics[mae]) model.summary()参数说明第一个 LSTM 层设置 return_sequencesTrue表示要返回每个时间步的隐状态方便后一层继续处理序列。第二个 LSTM 层只需要最后一个时间步的输出因此 return_sequencesFalse。Dropout 用于缓解过拟合一般设置在 0.1 到 0.3 之间。损失函数使用均方误差 MSE适合回归任务。4.4 训练与预测训练轮数不宜太少也不宜太多。我们可以使用 EarlyStopping 自动停止训练。from tensorflow.keras.callbacks import EarlyStopping early_stop EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue) history model.fit( X_train, y_train, validation_split0.2, epochs50, batch_size32, callbacks[early_stop], verbose1 )训练完成后对测试集进行预测并还原到原始数值范围。y_pred_scaled model.predict(X_test) y_test_inv scaler.inverse_transform(y_test.reshape(-1, 1)) y_pred_inv scaler.inverse_transform(y_pred_scaled)4.5 结果评估与绘图我们使用 RMSE 和 MAE 两个指标评估预测效果。from sklearn.metrics import mean_squared_error, mean_absolute_error rmse np.sqrt(mean_squared_error(y_test_inv, y_pred_inv)) mae mean_absolute_error(y_test_inv, y_pred_inv) print(fRMSE: {rmse:.4f}) print(fMAE: {mae:.4f}) plt.figure(figsize(12, 5)) plt.plot(y_test_inv, labelTrue) plt.plot(y_pred_inv, labelLSTM Pred) plt.legend() plt.title(LSTM Forecast Result) plt.show()如果数据有明显的周期性LSTM 通常能学到不错的效果。如果发现训练损失下降很慢首先要检查学习率其次检查数据是否归一化再检查滑动窗口长度是否合适。5. 实战二卡尔曼滤波时间序列预测完整代码5.1 一维卡尔曼滤波的状态方程设计对于一维时间序列我们假设状态 x 是“真实值”状态转移使用恒速模型或恒值模型。这里用恒值模型作为例子也就是假设目标值在短时间内基本不变变化由过程噪声描述x_k x_{k-1} w_k z_k x_k v_k对应的矩阵参数都是 1 维A 1H 1Q 是过程噪声方差R 是观测噪声方差5.2 手动实现卡尔曼滤波不依赖 filterpy 等第三方库手动实现反而能帮助理解每一步的含义。import numpy as np import matplotlib.pyplot as plt def kalman_filter_1d(zs, A1.0, H1.0, Q1e-3, R0.5, x00.0, P01.0): 一维卡尔曼滤波 zs: 观测序列 A: 状态转移系数 H: 观测系数 Q: 过程噪声方差 R: 观测噪声方差 x0: 初始状态 P0: 初始协方差 n len(zs) x_hat np.zeros(n) # 滤波后的状态估计 P np.zeros(n) # 状态协方差 K_list np.zeros(n) # 卡尔曼增益 x x0 P_prev P0 for k in range(n): # 1. 预测 x_pred A * x P_pred A * P_prev * A Q # 2. 更新 K P_pred * H / (H * P_pred * H R) x x_pred K * (zs[k] - H * x_pred) P (1 - K * H) * P_pred x_hat[k] x P[k] P K_list[k] K P_prev P return x_hat, P, K_list代码逻辑很清晰每一步都和前面讲的预测-更新流程对应。这里有一个很容易忽略的点P 的初始值 P0 如果设置得比较大表示初始状态很不确定滤波器会更快地“相信”观测数据。5.3 在模拟数据上运行卡尔曼滤波我们生成带有噪声的正弦波数据然后使用卡尔曼滤波做平滑。np.random.seed(0) n 500 true_signal np.sin(np.linspace(0, 10 * np.pi, n)) measurements true_signal np.random.normal(0, 0.3, n) filtered, P, K kalman_filter_1d( measurements, Q1e-3, R0.3, x00.0, P01.0 ) plt.figure(figsize(12, 5)) plt.plot(true_signal, labelTrue Signal, linewidth2) plt.plot(measurements, labelMeasurements, alpha0.6) plt.plot(filtered, labelKalman Filtered, linewidth2) plt.legend() plt.title(1D Kalman Filter Smoothing) plt.show()运行结果中滤波后的曲线会比原始观测数据平滑很多同时能保持一定的跟随性。如果 Q 参数设置得过大滤波结果会非常“信任观测”平滑效果变差如果 R 设置得过大滤波结果会非常“信任模型”导致曲线过于迟钝真实变化可能被抹平。5.4 使用卡尔曼滤波做多步预测卡尔曼滤波做单步滤波很容易但如果要预测未来多步需要根据最后的状态和协方差向前递推。因为是恒值模型未来任意时刻的状态预测值都等于最后一步的滤波值但协方差会随着时间增加表示不确定性增大。def kalman_forecast(last_x, last_P, A, Q, steps): forecasts [] x last_x P last_P for _ in range(steps): x A * x P A * P * A Q forecasts.append(x) return np.array(forecasts), P future_steps 20 forecasts, _ kalman_forecast(filtered[-1], P[-1], 1.0, 1e-3, future_steps) plt.figure(figsize(12, 5)) plt.plot(range(n), filtered, labelFiltered) future_index np.arange(n, n future_steps) plt.plot(future_index, forecasts, labelKalman Forecast, linestyle--) plt.legend() plt.title(Kalman Filter Multi-step Forecast) plt.show()多步预测中你会看到预测线基本保持水平因为恒值模型假设状态不变化。如果时间序列有明显的上升趋势需要引入速度分量也就是使用二阶卡尔曼滤波状态向量变成 [位置, 速度]状态转移矩阵也要相应调整。6. 两种模型的对比与选择建议6.1 适用场景对比维度LSTM卡尔曼滤波数据量要求需要较多历史数据少量数据也能工作非线性建模强弱依赖线性高斯假设实时性推理快但训练慢非常快适合嵌入式可解释性较弱黑盒强状态和噪声有物理含义参数调优网络结构、学习率、窗口长度需要调 Q、R、P0多变量扩展容易直接加 feature需要构造状态空间模型不确定性量化需要额外方法协方差天然给出置信区间6.2 如何选择如果数据规律比较复杂、非线性强、样本量充足优先考虑 LSTM。如果系统模型相对清晰有物理方程支持或者对实时性和可解释性要求高优先考虑卡尔曼滤波。实际项目中还有一种比较流行的做法先用 LSTM 学习残差或趋势再用卡尔曼滤波做状态估计。例如在目标跟踪任务中LSTM 负责根据历史轨迹预测目标可能的运动模式卡尔曼滤波负责把 LSTM 输出与传感器观测融合得到更稳定的轨迹。这种“深度学习 经典方法”的组合在论文里很常见也值得自己动手实验。不过要注意两种方法结合不是简单拼接每一部分的输入输出必须理清楚。7. 常见问题与排查思路7.1 LSTM 训练损失不下降可能原因有很多按概率从高到低排列问题现象常见原因解决思路损失一直不降学习率过大尝试 0.001、0.0001 等更小的学习率损失震荡学习率过大或 batch_size 太小调低学习率增大 batch_size训练集 loss 很低测试集很高过拟合增加 Dropout、增加数据量、减小模型容量结果全部接近均值滑动窗口不够长增大 lookback或检查数据是否存在强随机性7.2 卡尔曼滤波结果太滞后滤波结果比真实信号慢半拍通常是过程噪声 Q 设置太小导致滤波器过度相信模型预测对观测响应太慢。可以尝试调大 Q让滤波器更“敏感”地跟随观测数据。反过来如果滤波结果仍然有明显噪声说明观测噪声方差 R 被设置得偏低滤波器对观测过于信任。可以考虑适当增大 R。7.3 数据泄露导致预测结果虚高用 LSTM 做时间序列预测时最常见的错误是在数据预处理阶段使用了全部数据的统计量。比如对整体数据做 MinMaxScaler再划分训练集和测试集这就是一种数据泄露。正确做法是scaler MinMaxScaler() scaled_train scaler.fit_transform(train_data) scaled_test scaler.transform(test_data)也就是说训练集先 fit测试集只用 transform使用训练集的统计量进行缩放。7.4 卡尔曼滤波矩阵维度不匹配做多维状态估计时经常会遇到矩阵乘法维度不匹配的问题。建议每一步打印矩阵的 shapeprint(A shape:, A.shape) print(P shape:, P.shape) print(H shape:, H.shape)维度错误通常是因为 A 和 H 的定义与状态向量维度不一致。8. 最佳实践与工程建议8.1 数据预处理规范时间序列模型落地时数据质量往往比模型结构更重要。检查缺失值如果缺失比例较低可以使用前向填充或线性插值如果较高需要仔细分析缺失原因。检查异常值可以用滑动窗口计算 z-score超过阈值的数据点单独处理。时序划分训练集、验证集、测试集必须按时间顺序划分不能用 KFold 之类的随机划分方式。归一化LSTM 需要归一化卡尔曼滤波中的数值最好也保持在合理范围内。8.2 模型融合不是堆叠很多初学者可能会觉得“两个模型都跑一遍然后取平均”就是融合。这种简单做法在部分场景下确实能降低方差但不是最优方案。更合理的思路是用卡尔曼滤波处理高频噪声得到一条平滑的观测序列。用 LSTM 学习平滑序列中的长期趋势和周期性。最终的预测结果可以是 LSTM 输出经过卡尔曼滤波修正后的值。这种方式有点类似“信号分解 深度预测”的思想在实际工程中和论文中都有很强的实用性。8.3 生产环境注意事项模型上线前先在离线测试集上评估不能只盯着训练集指标。如果使用 LSTM线上推理时需要自己维护一个长度为 lookback 的队列每来一个新数据就更新队列。卡尔曼滤波部署非常简单不依赖外部深度学习框架可以很方便地移植到 C、Java、嵌入式设备。定期重新训练 LSTM 模型因为数据分布可能发生变化卡尔曼滤波则要监控 Q 和 R 是否仍然合理。所有涉及模型变更、参数调优的操作建议先在测试环境验证并保留回滚机制。9. 总结与下一步学习建议这篇文章从概念、原理、Python 代码和工程实践四个层面梳理了 LSTM 和卡尔曼滤波在时间序列预测中的应用。读完你应该能回答这几个问题卡尔曼滤波为什么能做平滑和预测它的预测和更新两个阶段分别做了什么。LSTM 如何构造滑动窗口样本为什么输入 shape 是三维的。什么时候选 LSTM什么时候选卡尔曼滤波。两类模型如何结合起来使用。常见坑点有哪些如何避免数据泄露。下一步建议按顺序做三件事第一把文章里的代码自己敲一遍不要直接复制粘贴。特别是手工实现卡尔曼滤波的部分每一步对照公式理解印象会深很多。第二找一份真实数据比如股票日线数据、电力负荷数据、气象观测数据分别用 LSTM 和卡尔曼滤波跑一遍对比效果。建议先画图观察数据的趋势和噪声特点再决定用什么模型。第三如果你对论文复现感兴趣可以搜索带有“Kalman Filter LSTM”关键词的时间序列预测论文重点关注作者如何设计状态空间模型、如何把 LSTM 输出映射到状态转移矩阵或观测噪声中。理解了这两类方法的思想再去读这一类文章会轻松得多。时间序列预测没有万能模型LSTM 和卡尔曼滤波只是两条比较经典的技术路线。先把基础打牢后续去学 Transformer、Informer、状态空间模型时会发现很多思想都是相通的。