9

私のコード:

from numpy import *

def pca(orig_data):
    data = array(orig_data)
    data = (data - data.mean(axis=0)) / data.std(axis=0)
    u, s, v = linalg.svd(data)
    print s #should be s**2 instead!
    print v

def load_iris(path):
    lines = []
    with open(path) as input_file:
        lines = input_file.readlines()
    data = []
    for line in lines:
        cur_line = line.rstrip().split(',')
        cur_line = cur_line[:-1]
        cur_line = [float(elem) for elem in cur_line]
        data.append(array(cur_line))
    return array(data)

if __name__ == '__main__':
    data = load_iris('iris.data')
    pca(data)

アイリス データセット: http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data

出力:

[ 20.89551896  11.75513248   4.7013819    1.75816839]
[[ 0.52237162 -0.26335492  0.58125401  0.56561105]
 [-0.37231836 -0.92555649 -0.02109478 -0.06541577]
 [ 0.72101681 -0.24203288 -0.14089226 -0.6338014 ]
 [ 0.26199559 -0.12413481 -0.80115427  0.52354627]]

望ましい出力:
固有値 -[2.9108 0.9212 0.1474 0.0206]
主成分 -Same as I got but transposed大丈夫だと思い ます

また、linalg.eig 関数の出力はどうなっていますか? ウィキペディアの PCA の説明によると、次のようになっています。

cov_mat = cov(orig_data)
val, vec = linalg.eig(cov_mat)
print val

しかし、オンラインで見つけたチュートリアルの出力とは実際には一致しません。さらに、4 つの次元がある場合、eig のように 150 ではなく、4 つの固有値を持つべきだと考えました。私は何か間違ったことをしていますか?

編集: データセット内の要素の数である 150 だけ値が異なることに気付きました。また、固有値は、次元数 (この場合は 4) に等しくなるように追加する必要があります。私が理解できないのは、この違いがなぜ起こっているのかということです。単純に固有値を で割ると、len(data)必要な結果が得られますが、その理由がわかりません。いずれにせよ、固有値の比率は変更されませんが、私にとっては重要なので、何が起こっているのかを理解したいと思います.

4

4 に答える 4

10

間違った行列を分解しました。

主成分分析では、データ自体ではなく、共分散行列の固有ベクトル/固有値を操作する必要があります。mxn データ行列から作成された共分散行列は、主対角に沿って 1 を持つ mxm 行列になります。

確かにcov関数を使用できますが、データをさらに操作する必要があります。同様の関数corrcoefを使用する方がおそらく少し簡単です。

import numpy as NP
import numpy.linalg as LA

# a simulated data set with 8 data points, each point having five features
data = NP.random.randint(0, 10, 40).reshape(8, 5)

# usually a good idea to mean center your data first:
data -= NP.mean(data, axis=0)

# calculate the covariance matrix 
C = NP.corrcoef(data, rowvar=0)
# returns an m x m matrix, or here a 5 x 5 matrix)

# now get the eigenvalues/eigenvectors of C:
eval, evec = LA.eig(C)

固有ベクトル/固有値を取得するために、SVD を使用して共分散行列を分解しませんでしたが、確かにできます。私の好みは、NumPy (または SciPy) の LA モジュールでeigを使用してそれらを計算することです。これはsvdよりも操作が少し簡単で、戻り値は固有ベクトルと固有値そのものであり、それ以外は何もありません。対照的に、ご存知のように、svdはこれらを直接返しません。

確かに、SVD 関数は ( eig関数が制限されている) 正方行列だけでなく、任意の行列を分解します。ただし、PCA を実行する場合、データの形式に関係なく、分解する正方行列が常に存在します。PCA で分解する行列は共分散行列であり、定義により常に正方行列であるため、これは明らかです (つまり、 、列は元の行列の個々のデータポイントであり、行も同様です。各セルは、主対角線の下にあるものによって証明されるように、これらの2つのポイントの共分散です-特定のデータポイントはそれ自体と完全な共分散を持っています) .

于 2011-01-26T09:48:21.903 に答える
3

SVD(A) によって返される左特異値は、AA^T の固有ベクトルです。

データセット A の共分散行列は : 1/(N-1) * AA^T

ここで、SVD を使用して PCA を実行する場合、A 行列の各エントリを (N-1) で除算して、正しいスケールで共分散の固有値を取得する必要があります。

あなたの場合、 N=150 であり、この除算を行っていないため、不一致が生じます。

こちらで詳しく説明されています

于 2012-03-19T16:30:26.970 に答える
2

(質問を 1 つお願いできますか? または、少なくとも質問を個別にリストしてください。あなたの投稿は、1 つの質問をしているわけではないため、意識の流れのように読みます。)

  1. cov最初に行列を転置しないという誤った使い方をした可能性があります。cov_matが 4行 4 列の場合eig、4 つの固有値と 4 つの固有ベクトルが生成されます。

  2. SVD と PCA は関連していますが、まったく同じではないことに注意してください。X を観測値の 4 行 150 列の行列とし、各 4 要素列が 1 つの観測値であるとします。次に、以下は同等です。

    を。X の左特異ベクトル、

    b. X の主成分

    c. XX^T の固有ベクトル。

    また、XX^T の固有値は、X の特異値の 2 乗に等しくなります。これをすべて確認するには、X に SVD X = QSV^T を持たせます。ここで、S は特異値の対角行列です。次に、固有分解 D = Q^TXX^TQ を考えます。ここで、D は固有値の対角行列です。X をその SVD に置き換えて、何が起こるか見てみましょう。

于 2011-01-26T06:00:02.417 に答える
0

すでに解決された質問: Python での主成分分析

于 2011-01-26T04:08:05.577 に答える