维度不匹配:数组'cov'的形状为(1, 1),但'mean'是长度为2的向量。

3

我正在尝试执行以下代码

p, c = [], []
for z in mes:
    print (z)
    print (c)
    print (p)
    p.append(kf.x)
    c.append(kf.P)
    kf.predict()
    kf.update(z) #error on this line

我遇到了错误:
ValueError: 维度不匹配:数组'cov'的形状为(1,1),但是'mean'是长度为2的向量。
这是屏幕上显示的输出。
[512  102]
[array([[ 1000.,     0.,     0.,     0.],
       [    0.,  1000.,     0.,     0.],
       [    0.,     0.,  1000.,     0.],
       [    0.,     0.,     0.,  1000.]])]
[array([[ 396.],
       [  187.],
       [    0.],
       [    0.]])]

如果我只取z的第一个元素,那么它可以正常工作,但这不是我想要的行为。
p, c = [], []
for z in mes:
    print (z)
    print (c)
    print (p)
    p.append(kf.x)
    c.append(kf.P)
    kf.predict()
    kf.update(z[0]) 

更新附加信息

这个错误来自于scipy中的multivariate.py。我似乎无法改变cov的形状,它始终是(1,1)。我可以通过使用z[0]来改变mean的长度,但这并不是期望的结果。我想按照原样使用z。我已经在gist中发布了整个代码。我还使用filterpy库进行卡尔曼滤波。有一个实时python笔记本使用这个卡尔曼滤波器,但它没有像我的情况那样使用z

你能否包含定义 kfmes 的代码(或虚拟代码)?我无法理解你的代码尝试做什么。 - maxymoo
错误本身很简单:在kf.update()的实现中,某个涉及名为cmean的变量的操作(我猜测是kf.update()的参数)需要这些变量的维度兼容才能正常工作。可能是矩阵乘法。但是,如果不知道您使用的卡尔曼滤波器实现,我无法提供更多信息,尤其是如何修复它。同时,了解您要完成的任务的高级描述也会很有帮助。 - David Z
@Anthony 好的,这很有帮助。但是我建议把这些评论的内容编辑到问题中。即使这些评论被删除了,拥有这个信息也很重要。 - David Z
实际上,你的代码还不是_完全_完成的,因为它需要一个输入文件。我想你可以将一个样本输入文件的链接(显示问题)编辑到问题中。或者,你可以开发一个更短的程序,它是自包含的,并且也显示了这个问题。无论如何,我会研究一下的;也许,现在我知道你正在使用哪个过滤器实现,我可以提供一些有用的东西。 - David Z
让我们在聊天中继续这个讨论。点击此处进入聊天室 - David Z
显示剩余3条评论
1个回答

1
使用filterpy库时,您需要自己设置卡尔曼滤波器的初始状态,并且各种矩阵的维度需要兼容。如果您查看KalmanFilter.update()方法,可以跟踪其计算并得出以下矩阵维度的约束条件:
R.shape == (dim_z, dim_z)
H.shape == (dim_z, dim_x)
P.shape == (dim_x, dim_x)
x.shape == (dim_x, 1...)
z.shape == (dim_z, 1...)

其中1...可以表示大小为1的一些维度序列,对于两者来说是相同的。例如,在您的情况下,dim_x == 4dim_z == 2,因此您可以有x.shape == (4, 1)z.shape == (2, 1),或者您可以有x.shape == (4,)z.shape == (2,),但不能混合使用。(请注意,KalmanFilter.__init__()文档似乎给出了H所需的错误维度。)

您的代码在两个地方设置了错误的尺寸:

  • You set H to be a 1x4 matrix instead of 2x4 as it should be. (I notice here you've got valid code commented out.)
  • You set R to be a scalar value instead of a 2x2 matrix. Arguably the Kalman filter implementation should account for this, but it only does so when you pass R as a parameter to update(), not when you set it in advance. (Be careful though: the code will still work if you set R to be a scalar! It'll do what I believe to be the wrong thing, though: adding 2 to every element of a matrix instead of adding 2 times the identity matrix.)
  • When you pass z to the update() method, you're passing a two-element list which gets converted into a 2-element vector, not a 2x1 matrix as it should be to be compatible with x (which is 4x1). You can fix this by running z = np.array([z]).T in the body of the loop before calling update(). But I think there's a better way: leave z as it is, and just make x a 4-element vector:

    x = np.array([measurements[0][0],measurements[0][1],0.,0.])
    

    I'm not sure if this is meant to work by the author, but it does (at the moment), and it probably should. I think it's sort of silly to require converting each measurement to a 2x1 matrix before passing it in.

KalmanFilter 包括一个 test_matrix_dimensions() 方法,您可以使用它来检查设置中的错误。但我对此有些矛盾,因为如果您将 x 设置为一个四元素向量,就像我在上一段中建议的那样,它会将其标记为不正确。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接