我写了一个非常简单的卡尔曼滤波器,它按时间序列运行(包括数据间隙)。它工作得很好,但我碰巧有一个数据立方体数据(形状Nt, Ny, Nx
的数组,比如说),我想对数据中的每个像素应用我的时间卡尔曼滤波器立方体。我做了很明显的事情(在最后两个维度上循环),但这需要相当长的时间。
最终,我总是不得不从单个“像素”中提取数据,并构建相关的矩阵/向量,因此过程非常缓慢(请注意每个时间序列中的间隙不同,通常情况下如此是将状态与观测结果联系起来的H矩阵。我不熟悉cython,它可能会有所帮助(只是我不熟悉它)。
我只是想知道问题的聪明改写或聪明的数据结构是否可以更有效地进行时间过滤。我宁愿这只使用numpy / scipy,而不是OpenCV,否则根据一个额外的包而不是麻烦。
答案 0 :(得分:3)
我制作了一个像这样的简单矢量化卡尔曼滤波器来处理电影帧。它非常快,但目前仅限于1D输入和输出,并且它不会对任何滤波器参数进行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
如果有人知道Python中的矢量化卡尔曼平滑实现支持多维输入/输出和EM参数优化,我很乐意听到它!我向PyKalman维护者发出了一个功能请求,但是他们说清晰度比速度更高。