今儿和大家聊聊 Transformer 结合卡尔曼滤波时序预测~
Transformer 和 卡尔曼滤波(Kalman Filter) 听起来好像是两个完全不相干的东西,一个用于 深度学习中的自然语言处理(NLP),一个是 经典控制和信号处理中的状态估计方法。
简单对比
概念 | Transformer | 卡尔曼滤波 |
---|---|---|
应用场景 | 机器翻译、文本生成、语音识别 | 目标跟踪、导航、信号处理 |
核心思想 | 通过注意力机制选择最相关的信息 | 通过贝叶斯估计融合新旧信息 |
数据处理方式 | 并行处理整个序列(注意力机制) | 逐步更新状态(递归计算) |
数学工具 | 线性代数、概率论 | 线性代数、概率论 |
从概念上讲,Transformer 和卡尔曼滤波都在处理“信息如何传播和更新”的问题,只是方式不同。
- Transformer 通过注意力(Attention)机制,从整个输入中找出最重要的信息。
- 卡尔曼滤波通过递归公式,利用当前观测值和过去的估计值,持续更新系统状态。
详细原理
Transformer 原理
Transformer 是 自然语言处理(NLP) 中的核心模型,它的主要特点是 不依赖循环结构,而是使用注意力机制并行处理整个序列。
1. Transformer 的核心组件
自注意力机制(Self-Attention)
-
计算输入序列内部的依赖关系,决定哪些词对当前词最重要。
-
公式:
-
- 分别是 查询(Query)、键(Key) 和 值(Value) 矩阵,来自输入数据的不同线性变换。
- 是维度缩放因子,防止梯度过大。
多头注意力(Multi-Head Attention)
- 通过多个不同的线性变换头(head),提取不同角度的信息,提高表达能力。
前馈神经网络(Feed-Forward Network, FFN)
- 在每个位置上独立应用一个小型的神经网络,提高模型复杂度。
残差连接(Residual Connection)和归一化(Layer Normalization)
- 让梯度稳定,优化收敛速度。
位置编码(Positional Encoding)
- 因为 Transformer 没有循环结构,所以需要额外的位置信息。通常使用正弦和余弦函数:
卡尔曼滤波原理
卡尔曼滤波是一种 递归最优估计 方法,它用于动态系统的状态估计,适用于系统受 高斯噪声干扰 的情况。
它的核心思想是:
- 结合 先验估计 和 当前观测数据,不断优化对真实状态的估计。
- 通过 最小均方误差(MMSE) 选择最佳状态。
1. 线性动态系统的状态方程
一个系统的状态 由 系统动态方程 和 观测方程 描述:
- :当前的真实状态(需要估计的量)
- :输入控制量
- :观测值(测量到的数据)
- 、、 是已知矩阵
- 、 分别是系统噪声和测量噪声,满足高斯分布:其中 和 是协方差矩阵,表示噪声大小。
2. 预测和更新两步
① 预测(Prediction)
使用上一时刻的状态,预测当前状态:
预测状态的不确定性:
② 更新(Update)
利用新观测数据修正预测:
更新状态:
更新不确定性:
其中:
- 是 卡尔曼增益(Kalman Gain),控制观测信息对估计值的影响。
- 是 协方差矩阵,表示估计的不确定性。
Transformer 与卡尔曼滤波的联系
虽然 Transformer 和卡尔曼滤波应用不同,但它们都基于 信息传播和更新 的核心思想:
- 信息流动方式:Transformer 通过 注意力机制 选择重要信息,并行计算所有时间步的状态。卡尔曼滤波通过 贝叶斯更新 逐步优化状态估计。
- 矩阵计算:Transformer 使用 矩阵乘法(QK^T) 来计算注意力权重。卡尔曼滤波使用 协方差矩阵 P 进行误差传播。
- 权重调整:Transformer 通过 注意力分数(softmax) 计算信息重要性。卡尔曼滤波通过 卡尔曼增益 K计算观测数据的权重。
完整案例
传统方法中,卡尔曼滤波(Kalman Filter)被广泛应用于动态系统状态估计,它通过递归贝叶斯估计的方式对数据进行去噪和状态估计;
近年来,Transformer 模型凭借其强大的自注意力机制,在自然语言处理和时序数据预测中取得了突破性的进展。
本案例整体思路:
- 生成虚拟数据集:构造正弦与余弦信号,并加入噪声;
- 卡尔曼滤波:对虚拟数据进行平滑处理;
- Transformer 模型构造与训练:利用卡尔曼滤波后的数据构造时序预测任务;
- 数据可视化:在一张图中绘制至少 4 个子图,分别展示原始数据、卡尔曼滤波结果、Transformer 预测结果以及真实信号与 Transformer 预测的对比~
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# 一、生成虚拟数据集
def generate_data(seq_length=150, noise_level=0.3, seed=42):
"""
生成虚拟的时序数据。数据由正弦函数和余弦函数叠加构成,同时加入高斯噪声。
参数:
seq_length - 数据点总数
noise_level - 噪声水平
seed - 随机种子,保证结果可重复性
返回:
t : 时间序列(numpy 数组)
y_true : 真实信号(无噪声)
y_noisy : 含噪声的观测数据
"""
np.random.seed(seed)
t = np.linspace(0, 10, seq_length)
# 构造真实信号:正弦函数与余弦函数叠加
y_true = np.sin(t) + 0.5 * np.cos(2 * t)
# 生成高斯噪声并加入真实信号
noise = noise_level * np.random.randn(seq_length)
y_noisy = y_true + noise
return t, y_true, y_noisy
# 调用数据生成函数,得到时间序列 t、真实信号 y_true 与带噪数据 y_noisy
t, y_true, y_noisy = generate_data()
# 二、卡尔曼滤波实现
def kalman_filter(y_noisy, Q=1e-3, R=0.1):
"""
对一维时序数据应用卡尔曼滤波进行平滑处理。
参数:
y_noisy - 带噪声的观测数据(numpy 数组)
Q - 过程噪声协方差(较小,反映状态变化的平稳性)
R - 观测噪声协方差(反映观测数据的不确定性)
返回:
x_est - 经过卡尔曼滤波的状态估计(平滑后信号)
"""
n = len(y_noisy)
x_est = np.zeros(n) # 存放滤波后的状态估计
P = np.zeros(n) # 存放估计协方差
# 初始状态估计:取第一个观测值;初始协方差设为 1
x_est[0] = y_noisy[0]
P[0] = 1.0
# 循环进行预测与更新
for k in range(1, n):
# 预测步骤:这里简单采用上一时刻状态作为预测值(状态转移矩阵 A=1)
x_pred = x_est[k - 1]
P_pred = P[k - 1] + Q # 预测协方差:上一协方差加上过程噪声
# 更新步骤:计算卡尔曼增益,修正预测值
K = P_pred / (P_pred + R)
x_est[k] = x_pred + K * (y_noisy[k] - x_pred)
P[k] = (1 - K) * P_pred
return x_est
# 对原始含噪数据应用卡尔曼滤波,获得平滑后的信号
y_kalman = kalman_filter(y_noisy)
# 三、Transformer 模型构造与原理解析
class TransformerTimeSeries(nn.Module):
"""
基于 Transformer 的时序预测模型。
模型结构包括:输入嵌入层 -> Transformer 模块(Encoder-Decoder 结构) -> 全连接输出层。
参数:
input_dim : 输入特征维度(本例为1)
model_dim : Transformer 模型的隐藏层维度
num_heads : 注意力头数
num_layers : Transformer 层数(Encoder 和 Decoder 均采用相同层数)
dropout : dropout 概率,用于防止过拟合
"""
def __init__(self, input_dim=1, model_dim=32, num_heads=4, num_layers=2, dropout=0.1):
super(TransformerTimeSeries, self).__init__()
# 输入嵌入层,将一维输入映射到 model_dim 维度
self.embedding = nn.Linear(input_dim, model_dim)
# 构造 Transformer 模块,采用 nn.Transformer 内置实现,Encoder 和 Decoder 均采用相同输入(自编码器方式)
self.transformer = nn.Transformer(d_model=model_dim,
nhead=num_heads,
num_encoder_layers=num_layers,
num_decoder_layers=num_layers,
dropout=dropout)
# 输出全连接层,将 Transformer 输出映射回一维预测值
self.fc_out = nn.Linear(model_dim, 1)
def forward(self, x):
"""
前向传播函数。
参数:
x: 输入张量,形状为 (batch_size, seq_length, input_dim)
返回:
输出张量,形状为 (batch_size, seq_length, 1)
"""
# 将输入数据经过嵌入层映射到高维空间
x = self.embedding(x)
# Transformer 模型要求的输入形状为 (seq_length, batch_size, model_dim),因此进行转置
x = x.permute(1, 0, 2)
# 这里使用自注意力机制,Encoder 和 Decoder 均输入相同数据
x = self.transformer(x, x)
# 将 Transformer 输出映射为目标维度
x = self.fc_out(x)
# 恢复原始形状 (batch_size, seq_length, 1)
x = x.permute(1, 0, 2)
return x
# 四、数据预处理与训练集构造
def prepare_data(y, seq_length=10):
"""
构造时序预测的训练数据集。将连续的时序数据分割成多个样本,每个样本包含 seq_length 个时间步的输入和下一个时刻的标签。
参数:
y : 一维时序数据(可以是原始数据或滤波后数据)
seq_length : 每个样本的输入序列长度
返回:
X - 特征数据,形状为 (样本数, seq_length, 1)
Y - 标签数据,形状为 (样本数)
"""
X, Y = [], []
for i in range(len(y) - seq_length):
X.append(y[i:i + seq_length])
Y.append(y[i + seq_length])
# 转换为 PyTorch 的 tensor,并增加一个特征维度
return torch.tensor(X).float().unsqueeze(-1), torch.tensor(Y).float()
# 采用卡尔曼滤波后的数据作为 Transformer 模型的输入数据,便于提升预测效果
X_train, Y_train = prepare_data(y_kalman, seq_length=10)
dataset = TensorDataset(X_train, Y_train)
dataloader = DataLoader(dataset, batch_size=8, shuffle=True)
# 五、Transformer 模型训练过程
# 实例化 Transformer 模型
model = TransformerTimeSeries(input_dim=1, model_dim=32, num_heads=4, num_layers=2, dropout=0.1)
# 定义损失函数为均方误差损失(MSE Loss)
criterion = nn.MSELoss()
# 采用 Adam 优化器,学习率设定为 0.001
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train_model(model, dataloader, epochs=50):
"""
对 Transformer 模型进行训练。训练过程中每个 batch 计算损失,然后反向传播更新模型参数。
参数:
model : Transformer 模型实例
dataloader: 训练数据加载器
epochs : 训练轮数
训练过程中,每个 epoch 后打印平均损失,便于观察训练趋势和模型收敛情况。
"""
model.train()
for epoch in range(epochs):
total_loss = 0.0
for X_batch, Y_batch in dataloader:
optimizer.zero_grad() # 清空梯度
# 前向传播:输入 X_batch,得到 Transformer 模型的输出(所有时刻的预测结果)
output = model(X_batch)
# 取每个序列最后一个时间步的预测值作为最终输出
Y_pred = output[:, -1, :].squeeze()
loss = criterion(Y_pred, Y_batch)
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数
total_loss += loss.item()
avg_loss = total_loss / len(dataloader)
print(f"Epoch {epoch+1:03d} / {epochs}, Loss: {avg_loss:.6f}")
# 开始训练模型
train_model(model, dataloader, epochs=50)
# 六、模型预测与数据可视化
# 在训练完成后,将 Transformer 模型设为评估模式,并利用训练数据集进行预测
model.eval()
with torch.no_grad():
# 对整个输入数据进行预测,取序列末尾的预测值作为最终结果
output = model(X_train)
y_transformer_pred = output[:, -1, :].squeeze().numpy()
# 七、数据可视化及图形说明
def plot_results():
"""
绘制包含4个子图的大图,展示以下数据:
1. Original Data vs True Signal
- 使用红色散点展示 Noisy Data,绿色曲线展示 True Signal
- 说明原始数据中噪声对信号的影响,以及真实信号的走向。
2. Kalman Filter Result
- 使用蓝色曲线展示经过卡尔曼滤波后的平滑信号
- 展示卡尔曼滤波在去噪和平滑方面的效果,对比原始数据能明显看出噪声被抑制。
3. Transformer Predicted Signal
- 使用洋红色曲线展示 Transformer 模型的预测结果
- 说明模型利用历史数据预测未来信号的能力,观察模型是否捕捉到趋势变化。
4. True Signal vs Transformer Prediction
- 同时绘制绿色曲线(真实信号)和洋红色虚线(Transformer 预测),便于对比模型预测结果与真实信号的吻合程度。
所有子图均采用具有感官冲击力的颜色,通过图例与标题详细说明每个子图的含义。
"""
# 建立一个 2x2 的子图结构,总图大小设定为 16x12 英寸
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
# 子图 1:Original Data vs True Signal
axes[0, 0].plot(t, y_noisy, 'r.', markersize=8, alpha=0.7, label='Noisy Data')
axes[0, 0].plot(t, y_true, 'g-', linewidth=2, label='True Signal')
axes[0, 0].set_title('Original Data vs True Signal', fontsize=14)
axes[0, 0].set_xlabel('Time', fontsize=12)
axes[0, 0].set_ylabel('Signal Value', fontsize=12)
axes[0, 0].legend(fontsize=12)
axes[0, 0].grid(True, linestyle='--', alpha=0.5)
# 子图 2:Kalman Filter Result
axes[0, 1].plot(t, y_kalman, 'b-', linewidth=2, label='Kalman Filtered')
axes[0, 1].set_title('Kalman Filter Result', fontsize=14)
axes[0, 1].set_xlabel('Time', fontsize=12)
axes[0, 1].set_ylabel('Filtered Value', fontsize=12)
axes[0, 1].legend(fontsize=12)
axes[0, 1].grid(True, linestyle='--', alpha=0.5)
# 子图 3:Transformer Predicted Signal
# 由于 Transformer 模型的预测是从训练数据的第 11 个时间点开始(序列长度为 10),因此对应时间轴需要偏移
predict_time = t[10:10+len(y_transformer_pred)]
axes[1, 0].plot(predict_time, y_transformer_pred, 'm-', linewidth=2, label='Transformer Prediction')
axes[1, 0].set_title('Transformer Predicted Signal', fontsize=14)
axes[1, 0].set_xlabel('Time', fontsize=12)
axes[1, 0].set_ylabel('Predicted Value', fontsize=12)
axes[1, 0].legend(fontsize=12)
axes[1, 0].grid(True, linestyle='--', alpha=0.5)
# 子图 4:True Signal vs Transformer Prediction
true_segment = y_true[10:10+len(y_transformer_pred)]
axes[1, 1].plot(predict_time, true_segment, 'g-', linewidth=2, label='True Signal')
axes[1, 1].plot(predict_time, y_transformer_pred, 'm--', linewidth=2, label='Transformer Prediction')
axes[1, 1].set_title('True Signal vs Transformer Prediction', fontsize=14)
axes[1, 1].set_xlabel('Time', fontsize=12)
axes[1, 1].set_ylabel('Signal Value', fontsize=12)
axes[1, 1].legend(fontsize=12)
axes[1, 1].grid(True, linestyle='--', alpha=0.5)
# 调整整体布局,使各子图之间不重叠,并设定总标题
plt.suptitle('Comparison of Noisy Data, Kalman Filtered, and Transformer Prediction', fontsize=16, y=0.95)
plt.tight_layout(rect=[0, 0, 1, 0.93])
plt.show()
plot_results()
- Original Data vs True Signal:用红色散点表示带噪声的原始数据,绿色曲线表示真实信号。可以明显看出原始数据噪声干扰较大,数据点分布离散。可以看到实际测量中常见的噪声问题,以及真实信号与观测信号之间存在较大差距,为后续滤波和预测任务提供直观背景。
- Kalman Filter Result:使用蓝色曲线展示卡尔曼滤波后的信号。滤波后的曲线明显比原始数据更加平滑,噪声被有效抑制,整体趋势与真实信号较为接近。通过对比左上图与右上图,可以直观地理解卡尔曼滤波在降噪方面的优势,说明其在状态估计问题中对抗噪声的有效性。
- Transformer Predicted Signal:Transformer 模型基于卡尔曼滤波数据训练后得到的预测结果。说明模型通过学习历史数据的依赖关系预测未来数据。该图能展示模型在捕捉数据动态变化和趋势方面的能力,虽然预测可能存在一定偏差,但总体上能够反映出数据的主要变化趋势。
- True Signal vs Transformer Prediction:同时绘制了真实信号(绿色曲线)与 Transformer 模型预测结果(红色虚线),用于对比模型预测与真实数据之间的吻合程度。如果两条曲线较为接近,则表明模型具有较高的预测精度;若存在较大偏差,则需要对模型结构、超参数或训练数据进行进一步调优。
整个案例展示了如何利用卡尔曼滤波与 Transformer 模型协同工作,既利用经典滤波技术去噪,又利用深度学习模型捕捉复杂的长程依赖关系,达到数据平滑与预测精度兼顾的效果。实际应用中,这种方法可推广到各类受噪声干扰的时序数据处理场景,如雷达目标跟踪、金融数据预测以及工业传感器数据分析等。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。