1 假设有m个样本,每个样本有n维,则定义输入dataMat为m*n的矩阵
2 对输入dataMat矩阵进行均值化处理,就是将m个样本中每一个维度值进行取平均,然后每个样本的值在减去这个平均值,记为newData,这个新矩阵对应每一维的均值是0,依然是
m
∗
n
m*n
m∗n矩阵
3 进行主成分分析降维,是为了找一个
n
∗
d
n*d
n∗d矩阵,将newData矩阵进行线性变换成lowData矩阵,降维成d维,该矩阵为
m
∗
d
m*d
m∗d矩阵。
4进行变换的目的,是对新生成的d维矩阵中,每一维自身方差最大,对应互相两维之间协方差为0.对应newData矩阵,进行线性变换之后得到的lowDData维矩阵,对应的每一维均值依然是0。
5 所以为了保证每一维自身方差最大,对应互相两维之间协方差为0,发现lowDData矩阵的转置矩阵乘以该矩阵,得到一个
d
∗
d
d*d
d∗d矩阵,对角线值为每一维的方差,其余值为互相两维的协方差,且该矩阵是个对称矩阵(我们讨论实数范围内,即为实对称矩阵)。那我们最希望的就是该协方差矩阵对角线的值从大到小拍了,其余值为0.
6 假设原矩阵为X,变换矩阵为D,得到C=XD,X是
m
∗
n
m*n
m∗n矩阵,D是
n
∗
d
n*d
n∗d矩阵,得到的C是
m
∗
d
m*d
m∗d矩阵.C矩阵的协方差矩阵为
C
T
C
=
D
T
X
T
X
D
C^{T}C=D^{T}X^{T}XD
CTC=DTXTXD,因为实对称矩阵
X
T
X
=
W
λ
W
T
X^{T}X=W{\lambda}W^{T}
XTX=WλWT,所以
C
T
C
=
D
T
W
λ
W
T
D
C^{T}C=D^{T}W{\lambda}W^{T}D
CTC=DTWλWTD,为了使
C
T
C
=
λ
C^{T}C={\lambda}
CTC=λ,即
D
=
W
D=W
D=W。
7 主成分分析降维,即是取输入样本X矩阵,对应的
X
T
X
X^{T}X
XTX的前d个特征向量,作为线性变换矩阵D,其中通过python numpy计算 np.linalg.eig(X,rowvar=0)得到的是矩阵(
X
T
X
X^{T}X
XTX)的特征向量,所以该特征向量的前d列基向量就是组成我们想D要得到的线性变换矩阵D
8 对应的python代码如下:
import numpy as np
def pca(dataMat,d):
# 输入是m*n的矩阵,即m个样本,每个样本n维
# 计算平均值
meanValue = np.mean(dataMat,axis=0)
# 减去平均值,生成新矩阵X
newData = dataMat - meanValue
# 根据输入矩阵X得到相应协方差矩阵:X的转置矩阵乘以X
covMat = np.cov(newData,rowvar=0)
eigValues, eigVectors = np.linalg.eig(covMat)
eigValuesInd = np.argsort(eigValues)
# 因为np.argsort(eigValues)排序是从小到大排序,所以后面取倒数d个特征值对应的向量
eigValuesInd = eigValuesInd[-1:-d-1:-1]
print('index: ',eigValuesInd)
n_eigVectors = eigVectors[:,eigValuesInd]
# 此为C=XD,得到降维后的矩阵值
lowDDataMat = np.dot(newData, n_eigVectors)
# 此为重构,即得到X=CD(T)+均值
reconData = np.dot(lowDDataMat,n_eigVectors.T) + meanValue
return lowDDataMat, reconData