1

次の python コードを使用してマハラノビス距離を計算しようとすると、結果にいくつかの 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' ) )

ナンもゲット。入力は壊れておらず、相関距離などの他の距離は問題なく計算できます。なんらかの理由で、機能の数を減らすと、Nan が表示されなくなります。たとえば、次の例では 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' ) )

どんな手掛かり?入力の条件が満たされない場合、これは予想される動作ですか?

4

1 に答える 1

4

特徴よりも観測が少ないためV、scipy コードによって計算された共分散行列は特異です。コードはこれをチェックせず、やみくもに共分散行列の「逆」を計算します。この数値的に計算された逆数は基本的にガベージであるため、積(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]と同じ非 nan 値 (1.9039) が返されることを確認しましょう。pdistVI

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

次に、その値の平方根は を与えnanます。


scipy 0.16 (2015 年 6 月リリース予定) では、nan や Garbage の代わりにエラーが発生します。エラーメッセージは問題を説明しています:

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.
于 2015-04-18T14:01:31.527 に答える