SVD & PCA

本文讲解SVD和PCA

Singular Value Decomposition

abbr. SVD

The Singular Value Decomposition is a highlight of linear algebra. A is any m by n matrix, square or rectangular. Its rank is r . We will diagonalize this A , but not by S1AS . The eigenvectors in S have three big problems: They are usually not orthogonal, there are not always enough eigenvectors, and Ax=λx requires A to be square. The singular vectors of A solve all those problems in a perfect way.

A is diagonalized”

Av1=σ1u1Av2=σ2u2Avr=σrur

The singular vectors v1vr are in the row space of A. The singular values σ1σr are all positives number. When the vs and us go into the columns of V and U , orthogonality gives VTV=I and UTU=I . The σs go into diagonal matrix Σ .

proof:
v ATA 的eigen vector
那么 v A 的row space上
ATAvi=σ2ivi
ATA 一定是半正定的( XTATAX0 )
所以存在 r 个eigenvalue 大于0 (r为rank)

row space nullspace
(proof: row space是 ATy 的集合与 nullspace 中的 x 的dot product
XT(ATy)=(AX)Ty=0 )

V Rn 上,可以找出 r 个正交基( vs 是singular vector),可以在nullspace上找出 nr 个正交基,可以构造 Vn×n ,显然 VT=V

目标是 AV=UΣ
VT=V1
A=UΣVT
ATAvi=σ2ivi
vTiATAvi=σ2ivTivi
Avi2=σ2i so that Avi=σi
AATAvi=σ2iAvi gives ui=Avi/σi as a unit eigenvector of AAT

ui 在A的column space上,所以存在 r 个正交基,与 vs 对应,同理可以在left null space上找到m-r个正交基组成 U

A=UΣVT=u1σ1vT1++urσrvTr

将SVD用于降维:
Am×nVn×r=Um×rΣr×r
就是将 A 投影到 V 所以定义的space上,从而达到了降维。可以按照singular value的大小进行排列,如果前 k 个singular value的大小占据了90%(只是个例子),那么相应的 vi 就可以丢掉,从而继续降维。eigenvalue相当于把数据投影到eigenvector上后,所有点的方差(因为要构造unit vector)。

Principal Component Analysis

abbr. PCA
SVD是PCA的一种方法,还有一种常用的方法就是将SVD降维中所用到的 V 换成了 A 的协方差矩阵的eigenvalue所组成的投影矩阵。
PCA的目的是使投影后的矩阵各向量之间的协方差为0,既去除了各个向量之间的线性关系,并且使得投影后的矩阵的在各个方向上的方差达到最大化。可以参考主成分分分析这篇文章所讲的最大方差理论。简单的对于分类来说,方差越大那么区分度越高。

算法步骤:

  1. 求矩阵 Am×n 中的每一列的均值,可以得到一个 n×1 的vector m 。其中A的每一行代表一个数据点,而每一列就是一个feature;
  2. A 的每一行都减去 m
  3. A 的转置的协方差矩阵 C
  4. C 的eigenvalue和eigenvector;
  5. 根据eigenvalue对eigenvector进行排序,可根据需求舍弃较小的eigenvalue所对应的eigenvector;
  6. 将eigenvector所组成的矩阵进行转置( r×n )与转置的 A ( n×m )进行dot product,将结果转置既为所求结果。

因为用到了协方差矩阵,协方差矩阵中每一项度量的是两个随机变量的相关性, Σij=cov(Xi,Xj)=E[(Xiui)(Xjuj)T] ,协方差定义中的 Xi 是行向量,对应 Am×n 中的一列,既对一个random variable的一组观测值。所以需要对 A 进行转置,使得A的行向量成为feature。 cov(AT) 的对角线是每一个feature的方差,其他的则是两个feature的协方差。
假设投影后的矩阵为 Y ,那么 YT=PTAT ,这里的表述方法是为了方便表达协方差矩阵。并且 PT 是一个rotation matrix ,因为 PT=P1
那么 cov(YT)=E((YT)(YT)T)
=E((PTAT)(PTAT)T)
=E(PT(AT(AT)T)P)
=PTcov(AT)P
由于 cov(AT) 是一个对称矩阵,所以可以将其对角化,而对角化所用的矩阵就是 cov(AT) eigenvetor所组成的矩阵(spectral theorem)。所以 pi 就是 cov(AT) 的eigenvector。在推导的过程中,要注意A是已经减去了均值的,要不不能这么推,这个过程反推也是有意义的,也能说明第一步为什么不需要减去均值。
接着就可以按照eigenvalue对eigenvector进行排序,根据需要cover多少variance来选几个eigenvector了。为什么这么选,可以想一下coviance matrix对角线上的值的意义。

import numpy as np

def pca(data,normalise=1):

    # centre data
    m = np.mean(data, axis=0)
    data -= m

    # Covariance matrix
    C = np.cov(np.transpose(data))

    # Compute eigenvalues and sort into descending order
    evals, evecs = np.linalg.eig(C)
    indices = np.argsort(evals)
    indices = indices[::-1]
    evecs = evecs[:, indices]
    evals = evals[indices]


    evalsNorm = evals / np.sum(evals)
    cumEvals = np.cumsum(evalsNorm)
    evecs = evecs[:,:(np.where(cumEvals > 0.9)[0][0] + 1)]

    if normalise:
       for i in range(np.shape(evecs)[1]):
           evecs[:, i] = evecs[:, i] /  np.linalg.norm(evecs[:, i])

    # Produce the new data matrix
    # x = np.transpose(np.dot(np.transpose(evecs), np.transpose(data)))
    x = np.dot(data, evecs)

    # Compute the original data again
    y = np.transpose(np.dot(evecs, np.transpose(x))) + m

    return x,y,evals,evecs

iris = np.genfromtxt(r"/home/real/pca/iris.data", delimiter=",", dtype="str")
iris = iris[:, range(np.shape(iris[0])[0] - 1)]
iris = iris.astype(np.float)
x,y,evals,evecs = pca(iris)
np.savetxt("result.csv", x, delimiter=",")
np.savetxt("resulty.csv", y, delimiter=",")

你可能感兴趣的:(ML)