Scipy - Nan计算马哈拉诺比斯距离时

时间:2015-04-18 12:19:56

标签: python numpy statistics scipy mahalanobis

当我尝试使用以下python代码计算Mahalanobis距离时,我在结果中得到一些Nan条目。您对此为何会有任何见解吗? 我的data.shape =(181,1500)

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' ) )

我也尝试过:

data_standard = data_centered / data_centered.std(0, ddof=1)
D = squareform( pdist(data_standard, 'mahalanobis' ) )

也有nans。 输入没有被破坏,其他距离,例如相关距离,可以很好地计算。 出于某种原因,当我减少功能的数量时,我停止了Nans。例如,以下示例没有得到任何Nan:

D = squareform( pdist(data_centered[:,:200], 'mahalanobis' ) )
D = squareform( pdist(data_centered[:,180:480], 'mahalanobis' ) )

而其他人得到Nans:

D = squareform( pdist(data_centered[:,:300], 'mahalanobis' ) )
D = squareform( pdist(data_centered[:,180:600], 'mahalanobis' ) )

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

1 个答案:

答案 0 :(得分:3)

观察的数量少于特征,因此由scipy代码计算的协方差矩阵V是单数。代码没有检查这一点,并盲目地计算"反向"协方差矩阵。因为这个数值计算的逆基本上是垃圾,所以产品(x-y)*inv(V)*(x-y)(其中xy是观察结果)可能会变成负数。然后,该值的平方根将生成nan

例如,此数组也会生成nan

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.        ]])

这是马哈拉诺比斯的计算完成"手工":

In [279]: V = np.cov(x.T)

理论上,V是单数;以下值实际上是0:

In [280]: np.linalg.det(V)
Out[280]: -2.968550671342364e-47

inv没有看到问题,并返回反向:

In [281]: VI = np.linalg.inv(V)

让我们计算x[0]x[2]之间的距离,并验证当我们使用{{1}时我们得到pdist返回的相同的非纳米值(1.9039) }}:

VI

我们尝试计算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]

然后该值的平方根得到In [300]: delta = x[0] - x[1] In [301]: np.dot(np.dot(delta, VI), delta) Out[301]: -1.75


在scipy 0.16(将于2015年6月发布)中,您将收到错误而不是nan或垃圾。错误消息描述了问题:

nan