web-dev-qa-db-ja.com

Numpyの多次元尺度構成法フィッティング、PandasおよびSklearn(ValueError)

Sklearn、pandas、numpy)を使用して多次元尺度構成法を試しています。使用しているデータファイルには10個の数値列があり、欠測値はありません。この10次元データを取得して、次のようにsklearn.manifoldの多次元尺度構成法を使用した2次元:

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_

しかし、私はこの値のエラーを受け取ります:

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は対称行列を返すと思いました。何が間違っているので、どうすれば修正できますか?

17
David Williams

私は同じ問題に遭遇しました。私のデータは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"
12
Josh Rosen

しばらく前に同じ問題がありました。もう1つの解決策は、はるかに効率的だと思いますが、上三角行列の距離のみを計算し、後で下の部分にコピーすることです。

それは次のようにscipyで行うことができます:

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