首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算Mahalanobis距离时遇到的问题

计算Mahalanobis距离时遇到的问题
EN

Stack Overflow用户
提问于 2015-04-18 12:19:56
回答 1查看 3.6K关注 0票数 2

当我试图用下面的python代码计算Mahalanobis距离时,我得到了一些结果。你对为什么会发生这种事有任何见解吗?我的data.shape = (181,1500)

代码语言:javascript
复制
from scipy.spatial.distance import pdist, squareform

data_log = log2(data + 1) # A log transform that I usually apply to my data
data_centered = data_log - data_log.mean(0) # zero centering
D = squareform( pdist(data_centered, 'mahalanobis' ) )

我也试过:

代码语言:javascript
复制
data_standard = data_centered / data_centered.std(0, ddof=1)
D = squareform( pdist(data_standard, 'mahalanobis' ) )

也有奶奶。输入没有损坏,其他距离(如相关距离)可以很好地计算。由于某些原因,当我减少功能的数量时,我就停止使用Nans了。例如,下面的示例没有任何意义:

代码语言:javascript
复制
D = squareform( pdist(data_centered[:,:200], 'mahalanobis' ) )
D = squareform( pdist(data_centered[:,180:480], 'mahalanobis' ) )

而其他人得到了南方人:

代码语言:javascript
复制
D = squareform( pdist(data_centered[:,:300], 'mahalanobis' ) )
D = squareform( pdist(data_centered[:,180:600], 'mahalanobis' ) )

有线索吗?如果输入的某些条件不满足,这是否是一种预期行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-18 14:01:31

您有较少的观测量比特征,因此协方差矩阵V计算的枕码是奇异的。代码不检查这一点,并且盲目地计算协方差矩阵的“逆”。因为这个数值计算的逆基本上是垃圾,所以产品(x-y)*inv(V)*(x-y) (其中xy是观测的)可能是负的。然后,该值的平方根将导致nan

例如,这个数组还会产生一个nan

代码语言:javascript
复制
In [265]: x
Out[265]: 
array([[-1. ,  0.5,  1. ,  2. ,  2. ],
       [ 2. ,  1. ,  2.5, -1.5,  1. ],
       [ 1.5, -0.5,  1. ,  2. ,  2.5]])

In [266]: squareform(pdist(x, 'mahalanobis'))
Out[266]: 
array([[ 0.        ,         nan,  1.90394328],
       [        nan,  0.        ,         nan],
       [ 1.90394328,         nan,  0.        ]])

下面是“手工”完成的Mahalanobis计算:

代码语言:javascript
复制
In [279]: V = np.cov(x.T)

理论上,V是奇异的;以下值实际上是0:

代码语言:javascript
复制
In [280]: np.linalg.det(V)
Out[280]: -2.968550671342364e-47

但是inv没有看到这个问题,并返回一个相反的:

代码语言:javascript
复制
In [281]: VI = np.linalg.inv(V)

让我们计算x[0]x[2]之间的距离,并验证使用VIpdist返回的非nan值(1.9039)是否相同。

代码语言:javascript
复制
In [295]: delta = x[0] - x[2]

In [296]: np.dot(np.dot(delta, VI), delta)
Out[296]: 3.625

In [297]: np.sqrt(np.dot(np.dot(delta, VI), delta))
Out[297]: 1.9039432764659772

当我们试图计算x[0]x[1]之间的距离时,会发生这样的情况

代码语言:javascript
复制
In [300]: delta = x[0] - x[1]

In [301]: np.dot(np.dot(delta, VI), delta)
Out[301]: -1.75

然后该值的平方根将给出nan

在ciply0.16(将于2015年6月发布)中,您将得到一个错误,而不是nan或垃圾。错误消息描述了这个问题:

代码语言:javascript
复制
In [4]: x = array([[-1. ,  0.5,  1. ,  2. ,  2. ],
   ...:        [ 2. ,  1. ,  2.5, -1.5,  1. ],
   ...:        [ 1.5, -0.5,  1. ,  2. ,  2.5]])

In [5]: pdist(x, 'mahalanobis')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-a3453ff6fe48> in <module>()
----> 1 pdist(x, 'mahalanobis')

/Users/warren/local_scipy/lib/python2.7/site-packages/scipy/spatial/distance.pyc in pdist(X, metric, p, w, V, VI)
   1298                                      "singular. For observations with %d "
   1299                                      "dimensions, at least %d observations "
-> 1300                                      "are required." % (m, n, n + 1))
   1301                 V = np.atleast_2d(np.cov(X.T))
   1302                 VI = _convert_to_double(np.linalg.inv(V).T.copy())

ValueError: The number of observations (3) is too small; the covariance matrix is singular. For observations with 5 dimensions, at least 6 observations are required.
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29717269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档