2013-06-07 11 views
12

私はsklearn、pandas、numpyで多次元スケーリングを試しています。使用するデータファイルImには10個の数値列があり、欠損値はありません。Numpy、Pandas、Sklearnの多次元スケーリングフィッティング(ValueError)

import numpy as np 
import pandas as pd 
from sklearn import manifold 
from sklearn.metrics import euclidean_distances 

seed = np.random.RandomState(seed=3) 
data = pd.read_csv('data/big-file.csv') 

# start small dont take all the data, 
# its about 200k records 
subset = data[:10000] 
similarities = euclidean_distances(subset) 

mds = manifold.MDS(n_components=2, max_iter=3000, eps=1e-9, 
     random_state=seed, dissimilarity="precomputed", n_jobs=1) 

pos = mds.fit(similarities).embedding_ 

しかし、私は、この値のエラーを取得する:私は、この10次元データを取得し、次のようにsklearn.manifoldの多次元尺度と2次元でそれを視覚化しようとしています

Traceback (most recent call last): 
    File "demo/mds-demo.py", line 18, in <module> 
    pos = mds.fit(similarities).embedding_ 
    File "/Users/dwilliams/Desktop/Anaconda/lib/python2.7/site-packages/sklearn/manifold/mds.py", line 360, in fit 
    self.fit_transform(X, init=init) 
    File "/Users/dwilliams/Desktop/Anaconda/lib/python2.7/site-packages/sklearn/manifold/mds.py", line 395, in fit_transform 
eps=self.eps, random_state=self.random_state) 
    File "/Users/dwilliams/Desktop/Anaconda/lib/python2.7/site-packages/sklearn/manifold/mds.py", line 242, in smacof 
eps=eps, random_state=random_state) 
    File "/Users/dwilliams/Desktop/Anaconda/lib/python2.7/site-packages/sklearn/manifold/mds.py", line 73, in _smacof_single 
raise ValueError("similarities must be symmetric") 
ValueError: similarities must be symmetric 

私はeuclidean_distancesが返さ思いました対称行列。私は間違って何をしているのですか?どうすれば修正できますか?

+2

最初のチェック。これをランダムな入力で試してみるとうまくいきます。ランダムな入力を試すことができますか? –

+0

'scipy.spatial.distance_matrix'を試してみませんか?とにかくユークリッド距離を使っているだけなら、skimではdissimilarity = "euclidean"を使って計算することができます。 –

+0

私は同様の問題に遭遇し、sklearn/manifold/mds.pyのL71に20の公差を乗じてパッチを適用しなければならなかった。 ( 'np.abs(similarities-similarities.T).max()'は〜1e-12だった – jorgeca

答えて

7

同じ問題が発生しました。データがnp.float32の配列であることが判明し、浮動小数点精度が低下したために距離行列が非対称になっていました。 MDSを実行する前にデータをnp.float64に変換して問題を修正しました。ここで

は、問題を説明するために、ランダムなデータを使用する例です:

import numpy as np 
from sklearn.manifold import MDS 
from sklearn.metrics import euclidean_distances 
from sklearn.datasets import make_classification 

data, labels = make_classification() 
mds = MDS(n_components=2) 

similarities = euclidean_distances(data.astype(np.float64)) 
print np.abs(similarities - similarities.T).max() 
# Prints 1.7763568394e-15 
mds.fit(data.astype(np.float64)) 
# Succeeds 

similarities = euclidean_distances(data.astype(np.float32)) 
print np.abs(similarities - similarities.T).max() 
# Prints 9.53674e-07 
mds.fit(data.astype(np.float32)) 
# Fails with "ValueError: similarities must be symmetric" 
+0

Thx、実際に動作しますが、float64に変更した後、 私は別の警告があります: /Library/Python/2.7/site-packages/sklearn/manifold/mds.py:396:UserWarnin g:MDS APIが変更されました。 '' fit''はデータから相違行列を構成します。カスタム非類似行列を使用するには、 '' dissimilarity = 'precomputed'''を設定します。 – NullPointer

6

はしばらく前に同じ問題を抱えていました。私がはるかに効率的だと信じている別の解決策は、上三角マトリックスの距離だけを計算し、後で下の部分にコピーすることです。

次のようにscipyのダウンロードで行うことができる: `np.allclose(類似、similarites.T)は` true`をあること

from scipy.spatial.distance import squareform,pdist                
similarities = squareform(pdist(data,'speuclidean'))