主成分分析(Principal components analysis,简称PCA)是最重要的降维方法之一。在数据压缩消除冗余和数据噪音消除等领域都有广泛的应用。一般我们提到降维最容易想到的算法就是PCA。
PCA顾名思义,就是找出数据里最主要的方面,用数据最主要的方面来替代原始的数据,具体的,加入我们的数据集是n维的,共有m个数据(x(1),x(2),…,x(m),我们希望将这m个数据维度从n维降到n’ 维,希望m个n’ 维的数据集尽可能的代表原始的数据集。换句话来讲,就是将n维特征映射到n’维空间上(n’<n),这n’维特征是全新的正交特征,是重新构造出来的n’维特征,而不是简单地从n维特征中去除其余n−n’维特征。我们知道数据从n维降到n’ 维肯定会有损失,但是我们希望损失尽可能的小。
我们先看看最简单的情况,n=2,n’ = 1,也就是将数据从二维降到一维,数据如下图,我们希望找到某个维度的方向,他可以代表这两个维度的数据,图中,列了两个向量方向,u1 和 u2 ,那么那个向量可以更好的代表原始数据集呢?从直观上也可以看出,u1 要比 u2好。
在这里有两种解释,第一种解释是样本点到这个支线的距离足够的近,第二种解释是样本点在这个直线上的投影尽可能的分开。
假如我们把n’从一位推广到任意维,则我们的希望即降为的标准为:样本点到这个超平面的距离足够的近,或者说样本点在这个超平面上的投影尽可能的分开。
基于上边两种标准,我们可以得到PCA的两种等价的推导。
#主成分分析
import numpy as np
#去中心化
def Mean(data_matrix):
#求均值
mean_val = np.mean(data_matrix,axis = 0)
#去中心化
new_data = data_matrix - mean_val
return new_data,mean_val
def PCA(data_matrix,n):
#得到去中心化后的矩阵及平均值
new_data ,mean_val = Mean(data_matrix)
#求协方差,rowvar = 0,传入的数据一行代表一个样本,rowvar非0,一列代表一个样本
cov_matrix = np.cov(new_data,rowvar = 0)
#计算特征值和特征矩阵,利用numpy.linalg
eigenvalues,eigenVects = np.linalg.eig(np.mat(cov_matrix))
#保留主要成分前n个,组成了新的特征空间的一组基n_eigVects
eigValIndice = np.argsort(eigenvalues)#对特征值从小到大排序
n_eigValIndice = eigValIndice[-1:-(n-1):-1]#取最大的n个特征值的下标
n_eigVect = eigenVects[:,n_eigValIndice]#最大n个特征值的特征向量
low_data_mat = new_data * n_eigVect#低维空间数据
re_mat = (low_data_mat * n_eigVect.T) + mean_val#重构数据
return low_data_mat,re_mat
#根据阈值求n
def percentage2n(eigenvalues,percentage):
sortArray = np.sort(eigenvalues)
sortArray = sortArray[-1::-1]
arraySum = sum(sortArray)
tmp = 0
num = 0
for i in sortArray:
tmp+=i
num+=1
if tmpSum >= arraySum*percentage:
return num
#指定一个降维到的主成分比重阈值percentage=0.99
def p_PCA(data_matrix,percentage=0.99):
#得到去中心化后的矩阵及平均值
new_data ,mean_val = Mean(data_matrix)
#求协方差,rowvar = 0,传入的数据一行代表一个样本,rowvar非0,一列代表一个样本
cov_matrix = np.cov(new_data,rowvar = 0)
#计算特征值和特征矩阵,利用numpy.linalg
eigenvalues,eigenVects = np.linalg.eig(np.mat(cov_matrix))
#计算所降的维度n
n = percentage2n(eigenvalues,percentage)
#保留主要成分前n个,组成了新的特征空间的一组基n_eigVects
egiValIndice = np.argsort(eigenvalues)#对特征值从小到大排序
n_eigValIndice = egiValIndice[-1:-(n-1):-1]#取最大的n个特征值的下标
n_eigVect = eigenVects[:,n_eigValIndice]#最大n个特征值的特征向量
low_data_mat = new_data * n_eigVect#低维空间数据
re_mat = (low_data_mat * n_eigVect.T) + mean_val#重构数据
return low_data_mat,re_mat
if __name__ == "__main__":
#data
data_matrix = [[-0.2314987 , 0.08387106],
[ 0.66963671 , 1.38535319],
[ 0.97355908 , 0.04134561],
[ 0.38108224 , 0.9434845 ],
[ 0.11467758 ,-0.72613803]]
#PCA方法一
low_data,re_mat = PCA(data_matrix,1)
print(low_data,'\n',re_mat)
#PCA方法二
low_data1,re_mat1 =p_PCA(data_matrix,percentage=0.99)
print(low_data1,'\n',re_mat1)
作为一个非监督学习的降维方法,它只需要特征值分解,就可以对数据进行压缩,去噪。为了克服PCA的一些缺点,出现了很多PCA的变种,比如解决非线性降维的KPCA,还有解决内存限制的增量PCA方法Incremental PCA,以及解决稀疏数据降维的PCA方法Sparse PCA等。
PCA算法的主要优点有:
1)仅仅需要以方差衡量信息量,不受数据集以外的因素影响。
2)各主成分之间正交,可消除原始数据成分间的相互影响的因素。
3)计算方法简单,主要运算是特征值分解,易于实现。
PCA算法的主要缺点有:
1)主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强。
2)方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响。