【问题标题】:One dimensional Mahalanobis Distance in PythonPython中的一维马氏距离
【发布时间】:2012-04-13 16:24:50
【问题描述】:

我一直在尝试验证我的代码以计算用 Python 编写的 Mahalanobis 距离(并仔细检查以比较 OpenCV 中的结果) 我的数据点每个都是 1 维(5 行 x 1 列)。

OpenCV (C++)中,当数据点的维度为上述维度时,我成功计算了马氏距离。

当矩阵的维度为 5 行 x 1 列时,以下代码在计算马氏距离时不成功但是当矩阵中的列数超过1时它起作用

import numpy;
import scipy.spatial.distance;
s = numpy.array([[20],[123],[113],[103],[123]]);
covar = numpy.cov(s, rowvar=0);
invcovar = numpy.linalg.inv(covar)
print scipy.spatial.distance.mahalanobis(s[0],s[1],invcovar);

我收到以下错误:

Traceback (most recent call last):
  File "/home/abc/Desktop/Return.py", line 6, in <module>
    invcovar = numpy.linalg.inv(covar)
  File "/usr/lib/python2.6/dist-packages/numpy/linalg/linalg.py", line 355, in inv
    return wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))
IndexError: tuple index out of range

【问题讨论】:

  • 如果我理解正确,numpy.linalg.inv 方法需要square matrix,但您似乎给了它一个单元素数组。
  • 我明白这一点。那么,有解决办法吗?
  • 一维马氏距离称为 z-score。此链接可能会有所帮助:statisticshowto.datasciencecentral.com/…

标签: python classification


【解决方案1】:

一维马氏距离真的很容易手动计算:

import numpy as np
s = np.array([[20], [123], [113], [103], [123]])
std = s.std()
print np.abs(s[0] - s[1]) / std

(将the formula 简化为一维情况)。

但是scipy.spatial.distance 的问题在于,由于某种原因,np.cov 在给定一组一维变量时返回一个标量,即一个零维数组。你想传入一个二维数组:

>>> covar = np.cov(s, rowvar=0)

>>> covar.shape
()

>>> invcovar = np.linalg.inv(covar.reshape((1,1)))

>>> invcovar.shape
(1, 1)

>>> mahalanobis(s[0], s[1], invcovar)
2.3674720531046645

【讨论】:

  • 这很有帮助。但是,我似乎没有掌握它。与下面使用scipy.spatial.distance.mahalanobis 的方法相比,您描述的上述手动技术给了我不同的答案。我能够将这个(第二种技术)结果与 OpenCV 中的结果相匹配。我在这里错过了什么吗?
  • @raul_w 那是因为我很愚蠢。 :) (你需要除以标准差,而不是方差——我也忘了取平方数。)
  • 好吧,它仍然不匹配 :p 。使用标准偏差给出 2.64 的结果......并在重塑矩阵后使用内置函数,给出 2.36(我认为这是正确的,因为它与 OpenCV 中的结果匹配)。感谢您的帮助。
  • 差异的原因是np.cov默认给出方差的无偏估计量(除以N-1),而np.std默认给出有偏估计量(除以N)。您可以使用 ddof 参数来协调两者。这里“正确”的定义完全取决于您想要做什么,但np.cov 方式更标准(正如 OpenCV 所做的事实所证明的那样:p)。
  • 一维马氏距离称为 z-score。此链接可能会有所帮助:statisticshowto.datasciencecentral.com/…
【解决方案2】:

协方差需要 2 个数组进行比较。在 np.cov() 和 Opencv CalcCovarMatrix 中,它期望两个数组相互堆叠(使用 vstack)。如果您在 numpy 中将 Rowvar 更改为 false 或在 opencv 中使用 COVAR_COL,您也可以让 2 个数组并排。如果您的数组是多维的,只需先将它们 flatten() 即可。

所以如果我想比较两个 24x24 的图像,我会将它们都展平为 2 个 1x1024 的图像,然后将两者叠加得到 2x1024,这就是 np.cov() 的第一个参数。

然后您应该得到一个大方阵,其中显示了将 array1 中的每个元素与 array2 中的每个元素进行比较的结果。在我的示例中,它将是 1024x1024。这就是你传递给你的 invert 函数的内容。

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 2019-12-19
    相关资源
    最近更新 更多