我的PCA出了什么问题?

pca*_*pca 9 python numpy machine-learning linear-algebra pca

我的代码:

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)
Run Code Online (Sandbox Code Playgroud)

虹膜数据集: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]]
Run Code Online (Sandbox Code Playgroud)

期望的输出:
特征值 - [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
Run Code Online (Sandbox Code Playgroud)

但它与我在网上找到的教程中的输出并不完全匹配.另外,如果我有4个维度,我认为我应该有4个特征值而不是像eig给我的150个特征值.难道我做错了什么?

编辑:我注意到值相差150,这是数据集中元素的数量.此外,假设特征值加上等于维数,在这种情况下,4.我不明白为什么会发生这种差异.如果我简单地将特征值除以len(data)我可以得到我想要的结果,但我不明白为什么.无论哪种方式,特征值的比例都没有改变,但它们对我很重要,所以我想了解发生了什么.

dou*_*oug 10

你分解了错误的矩阵.

主成分分析需要操纵协方差矩阵的特征向量/特征值,而不是数据本身.从mxn数据矩阵创建的协方差矩阵将是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)
Run Code Online (Sandbox Code Playgroud)

为了获得特征向量/特征值,我没有使用SVD分解协方差矩阵,但是,你当然可以.我更喜欢在NumPy(或SciPy)的LA模块中使用eig计算它们- 它比svd更容易使用,返回值是特征向量和特征值本身,没有别的.相比之下,如你所知,svd并没有直接返回这些.

当然,SVD函数将分解任何矩阵,而不仅仅是方形矩阵(eig函数受限); 然而,当进行PCA时,无论数据的形式如何,你都会有一个方形矩阵进行分解.这很明显,因为你在PCA中分解的矩阵是一个协方差矩阵,根据定义它总是方形的(即,列是原始矩阵的各个数据点,同样对于行,每个单元格是这两个点的协方差,如主对角线下方的那些 - 一个给定的数据点与自身具有完美的协方差) .

  • 不,第一行是错误的"你分解了错误的矩阵." PCA基本上有两种方法:1)计算*协方差*矩阵的特征向量2)或者计算*data*矩阵的SVD,左奇异向量是*协方差*矩阵的特征向量在第二种情况(SVD)中,您根本不需要计算协方差.在最初的问题中,他将SVD应用于数据矩阵,这完全是他应该做的.他只是忘了将他的数据标准化1 /(N-1),这就是为什么他得到150(N)因子.(见下面的答案) (5认同)
  • 我认为这是错误的.正如你所说,PCA导致协方差矩阵的特征值/向量,但几乎在所有情况下我都看到这些可以通过在(去除)数据矩阵本身上执行SVD来获得.这样做的效果要好得多,因为它不需要计算完整的协方差矩阵,而且数值更稳定(我不知道细节,但我知道SVD比eig更稳定).无法找到更易于理解的说明,但您可以在此处看到:http://public.lanl.gov/mewall/kluwer2002.html这是我见过的每个严肃实施中使用的方法. (3认同)