简体   繁体   English

网格数据上的有效卡尔曼滤波器实现

[英]Efficient Kalman filter implementation on gridded data

I have written a very simple Kalman filter that operates on time series (with data gaps included). 我编写了一个非常简单的卡尔曼滤波器,该滤波器可以按时间序列运行(包括数据间隔)。 It works nicely, but I happen to have a data cube of data (an array of shape Nt, Ny, Nx , say), and I want to apply my temporal Kalman filter for each pixel in the data cube. 它工作得很好,但是我碰巧有一个数据数据立方体 (形状为Nt, Ny, Nx的数组),并且我想对数据立方体中的每个像素应用我的时间Kalman滤波器。 I have done the obvious (loop over the last two dimensions), but this takes quite a long time. 我已经做了很明显的事情(在最后两个维度上循环),但这花费了相当长的时间。

Ultimately, I always end up having to extract data from individual "pixels", and constructing the relevant matrices/vectors, so the process is quite slow (note that the gaps in each individual time series are different, and typically, so is the H matrix that links the state to the observations). 最终,我总是总是不得不从各个“像素”中提取数据,并构造相关的矩阵/向量,因此该过程相当缓慢(请注意,每个各个时间序列中的间隔是不同的,通常,H将状态链接到观察值的矩阵)。 I'm not familiar with cython, and it might help (only that I'm not familiar with it). 我不熟悉cython,它可能会有所帮助(只是我不熟悉它)。

I was just wondering whether a clever rephrasing of the problem, or a clever data structure, might allow to do the temporal filtering far more efficiently. 我只是想知道,对问题进行巧妙的措辞,或者巧妙的数据结构,是否可以使时间过滤效率更高。 I'd rather this only used numpy/scipy, and not OpenCV, as otherwise it's a hassle depending on an extra package. 我宁愿只使用numpy / scipy,而不要使用OpenCV,否则,根据额外的软件包,这将是一个麻烦。

I made a simple vectorised Kalman filter like this for processing movie frames. 我制作了一个像这样的简单矢量化卡尔曼滤波器来处理电影帧。 It's pretty quick but currently limited to 1D inputs and outputs, and it doesn't do EM optimisation of any of the filter parameters. 它非常快速,但目前仅限于一维输入和输出,并且不对任何滤波器参数进行EM优化。

import numpy as np

def runkalman(y, RQratio=10., meanwindow=10):
    """
    A simple vectorised 1D Kalman smoother

    y       Input array. Smoothing is always applied over the first 
            dimension

    RQratio     An estimate of the ratio of the variance of the output 
            to the variance of the state. A higher RQ ratio will 
            result in more smoothing.

    meanwindow  The initial mean and variance of the output are 
            estimated over this number of timepoints from the start 
            of the array

    References:
        Ghahramani, Z., & Hinton, G. E. (1996). Parameter Estimation for
        Linear Dynamical Systems.
        http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.55.5997

        Yu, B., Shenoy, K., & Sahani, M. (2004). Derivation of Extented
        Kalman Filtering and Smoothing Equations.
        http://www-npl.stanford.edu/~byronyu/papers/derive_eks.pdf
    """

    x,vpre,vpost = forwardfilter(y, RQratio=RQratio, meanwindow=meanwindow)
    x,v = backpass(x, vpre, vpost)
    x[np.isnan(x)] = 0.
    return x

def forwardfilter(y, RQratio=10., meanwindow=10):
    """
    the Kalman forward (filter) pass:

        xpost,Vpre,Vpost = forwardfilter(y)
    """

    y = np.array(y,copy=False,subok=True,dtype=np.float32)

    xpre = np.empty_like(y)
    xpost = np.empty_like(y)
    Vpre = np.empty_like(y)
    Vpost = np.empty_like(y)
    K = np.empty_like(y)

    # initial conditions
    pi0 = y[:meanwindow].mean(0)
    ystd = np.std(y,0)
    R = ystd * ystd
    Q = R / RQratio
    V0 = Q

    xpre[0] = xpost[0] = pi0
    Vpre[0] = Vpost[0] = V0
    K[0] = 0

    # loop forwards through time
    for tt in xrange(1, y.shape[0]):

        xpre[tt] = xpost[tt-1]
        Vpre[tt] = Vpost[tt-1] + Q

        K[tt] = Vpre[tt] / (Vpre[tt] + R)
        xpost[tt] = xpre[tt] + K[tt] * (y[tt] - xpre[tt])
        Vpost[tt] = Vpre[tt] - K[tt] * (Vpre[tt])

    return xpost,Vpre,Vpost

def backpass(x, Vpre, V):
    """ 
    the Kalman backward (smoothing) pass:

        xpost,Vpost = backpass(x,Vpre,V)
    """

    xpost = np.empty_like(x)
    Vpost = np.empty_like(x)
    J = np.empty_like(x)

    xpost[-1] = x[-1]
    Vpost[-1] = V[-1]

    # loop backwards through time
    for tt in xrange(x.shape[0]-1, 0, -1):
        J[tt-1] = V[tt-1] / Vpre[tt]
        xpost[tt-1] = x[tt-1] + J[tt-1] * (xpost[tt] - x[tt-1])
        Vpost[tt-1] = V[tt-1] + J[tt-1] * (Vpost[tt] - Vpre[tt]) * J[tt-1]

    return xpost,Vpost 

If anyone knows of a vectorised Kalman smoother implementation in Python that supports multidimensional inputs/outputs and EM parameter optimisation, I'd love to hear about it! 如果有人知道Python中支持多维输入/输出和EM参数优化的矢量化Kalman平滑器实现,我很想听听它! I made a feature request to the PyKalman maintainers, but they said that clarity was a higher priority than speed. 我向PyKalman维护人员提出了功能要求,但他们说,清晰度是重中之重,而不是速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM