奇异值分解
A
=
U
D
V
T
其中
A
是一个
m
×
n
的矩阵,
U
是一个
m
×
m
矩阵,
D
是一个
m
×
n
的矩阵,
V
是一个
n
×
n
矩阵。
U
和
V
是正交矩阵,
D
是对角矩阵。D的对角线元素就是奇异值。
U
和
V
的列向量称为左右奇异向量。
实际上对应特征值与奇异值有如下关系:
(
A
T
A
)
ν
i
=
λ
i
ν
i
其中
σ
i
=
λ
i
−
−
√
μ
i
=
1
σ
i
A
ν
i
σ
是奇异值,
μ
是左奇异向量,
ν
是右奇异向量。
在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上了。也就是说,我们也可以用前
r
大的奇异值来近似描述矩阵。
Moore-Penrose伪逆
若有
A
与其左逆
B
,有
A
x
=
y
以及
x
=
B
y
,则Moore-Penrose伪逆为
A
+
=
V
D
+
U
T
D
的伪逆为非零元素取倒数之后再转置得到。
A
的列数大于行数,得到就是所有可行解中
L
2
范数最小的一个,如果相反,就是
L
2
(
A
x
−
y
)
最小。
PCA
计算步骤
1. 计算均值并减去均值
2. 计算协方差矩阵
3. 求协方差的特征值和特征向量
4. 将特征值按照从大到小的顺序排序,选择其中最大的
k
个,然后将其对应的
k
个特征向量分别作为列向量组成特征向量矩阵
5. 将样本点投影到选取的特征向量上
r
e
c
o
n
M
a
t
=
d
a
t
a
M
a
t
×
F
e
a
t
u
r
e
V
e
c
t
o
r
python实现PCA
import numpy as np
def calMean(dataMat):
"""
dataMat: 原数据
return:
mean: 均值
newData: 原数据 - 均值
"""
mean = np.mean(dataMat,axis = 0)
newData = dataMat - mean
return newData, mean
def getK(eigVals, percentage):
"""
确定选择k多少
"""
sortEigvals = np.sort(eigvals)
sortEigvals = sortEigvals[-1::-1]
sum = sum(sortEigvals)
temSum = 0
for k, eigval in enumerate(sortEigvals):
temSum += eigval
if temSum >= sum * percentage:
return k
def pca(dataMat,percentage=0.99):
newData,mean=calMean(dataMat)
covMat=np.cov(newData,rowvar=0) #求协方差矩阵,return ndarray;若rowvar非0,一列代表一个样本,为0,一行代表一个样本
eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量
k=getK(eigVals,percentage) #要达到percent的方差百分比,需要前n个特征向量
eigValIndice=np.argsort(eigVals) #对特征值从小到大排序
k_eigValIndice=eigValIndice[-1:-(k+1):-1] #最大的n个特征值的下标
k_eigVect=eigVects[:,k_eigValIndice] #最大的n个特征值对应的特征向量
lowDataMat=newData*k_eigVect #低维特征空间的数据
reconMat=(lowDataMat*k_eigVect.T)+meanVal #重构数据
return lowDataMat,reconMat
参考资料