PyKalman 中非恒定过程噪声矩阵的卡尔曼滤波器状态协方差矩阵

信息处理 Python 估计 卡尔曼滤波器 协方差 动态系统
2022-01-03 01:47:40

我正在尝试使用pykalmanPython 库来了解卡尔曼滤波器。在下面的代码中,我正在生成一个随机游走,其中每一步都是最后一步乘以 1 加上一些噪声:1 + std_dev在第一个块中,KF 的协方差矩阵(使用一维信号/状态,所以它实际上只是一个方差)似乎收敛到大约0.62. 即使我设置grow_std_dev=True,导致噪声随时间显着增长,协方差矩阵仍会收敛到该值。

import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter

def generate_random_walk(seed=1, n_steps=100, grow_std_dev=False):
    np.random.seed(seed)
    rand_walk = [1]
    std_devs = []

    for n in range(n_steps):
        if grow_std_dev:
            std_dev = np.random.normal(0,0.01 * (1 + n))
        else:
            std_dev = np.random.normal(0,0.01)
        val = rand_walk[-1] * (1 + std_dev)
        std_devs.append(std_dev)
        rand_walk.append(val)
      
    return np.array(rand_walk), np.array(std_devs)


kf = KalmanFilter(transition_matrices = [1],
    observation_matrices = [1],
    initial_state_mean = 1,
    initial_state_covariance = 1,
    observation_covariance=1,
    transition_covariance=1)

rand_walk, std_devs = generate_random_walk(0)
state_means, state_cov = kf.filter(rand_walk)


plt.plot(std_devs)
plt.show()
plt.plot(rand_walk_1)
plt.show()
plt.plot(state_cov.flatten())

上述代码产生的图:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

我在其他地方读到,KF 可用于在两个变量之间执行递归线性回归(我相信这是正确的术语),方法是传递一个变量作为observation_matrices参数,另一个作为过滤值。因此,在下面的块中,我使用不同的种子生成第二个随机游走,并将其传递给observation_matrices而不是[1]第一个块中的固定矩阵。与第一个示例不同,这会导致协方差矩阵不收敛。

rand_walk_2, _ = generate_random_walk(1)

kf = KalmanFilter(transition_matrices = [1],
    observation_matrices = rand_walk_2[:,None,None],
    initial_state_mean = 1,
    initial_state_covariance = 1,
    observation_covariance=1,
    transition_covariance=1)


state_means, state_cov = kf.filter(rand_walk_1)

plt.plot(rand_walk_2)
plt.show()
plt.plot(state_cov.flatten())

在此处输入图像描述 在此处输入图像描述

除了表明协方差矩阵可能不收敛之外,我真的不关心第二个示例。在学习卡尔曼滤波器时,我的理解是,部分价值在于估计的不确定性在每个时间步被量化,即协方差矩阵随着状态估计而发展。同样,通过设置grow_std_dev=True,我希望协方差矩阵需要更改才能使滤波器做出最佳预测。

话虽如此,我想知道我是否遗漏了一些关于 KF 应该如何工作的内容,遗漏了一个论点,或者其他。

任何帮助表示赞赏。

1个回答

对于经典卡尔曼滤波器,其中,即过程噪声协方差和测量噪声协方差(我使用维基百科 - 卡尔曼滤波器符号)后协方差是一个独立于测量本身的确定性矩阵。Qk=QRk=RPk

由于您的代码将测量值和过程噪声设置为恒定,因此卡尔曼滤波器不知道您创建的过程的不断增长的方差。

PyKalman中,卡尔曼滤波器的初始化KalmanFilter()不允许随时间变化的矩阵。但是您有filter_update()一种方法可以让您设置transition_covarianceobservation_covariance每次迭代,这是您需要做的。