基本思路:

(1)对所有的样本进行demean处理。

(2)梯度上升法求系数。注意:和线性回归不同点。

      每次求一个单位向量;初始化w不能为0向量;不能使用sklearn进行标准化了。

(3)批量和随机梯度同样适用梯度上升法。

(4) 第一主成分和后续主成分。先将数据进行改变,将数据在第一主分上的分量去掉。

在新的数据上求第二主成分。这是循环往复过程。


一、PCA算法简介


主成分分析(Principal Components Analysis),简称为:PCA,是一种常见的数据降维技术,用于数据预处理的非常好的工具。一般我们获取的原始数据维度都很高,比如图像文件,几百上千个特征维度值已经很正常。但实际上,这些高维度数据不但含有很多的噪声,还存在很多维度数据存在冗余,也就是相关性太高,真正能用到的特征数据也就是几十个上百个,这样在实际进行机器学习算法过程中,通过PCA,可以大大减少运算量,节约计算时间,并且还能够达到同样的处理效果。




主要原因如下:

  1. 数据更易使用
  2. 降低很多算法的计算开销
  3. 去除噪声
  4. 使得结果更容易解读


二、PCA算法实现


先对原始样本数据去均值化,然后求协方差矩阵,接着对协方差矩阵求特征值和特征向量,实际上,这些特征向量就组成了新的特征空间。如果想了解更多原理,可以搜索学习相关资料,这里不赘述。


(1)零均值化


假如原始数据集为矩阵dataMat,dataMat中每一行代表一个样本,每一列代表同一个特征。零均值化就是求每一列的平均值,然后该列上的所有数都减去这个均值。也就是说,这里零均值化是对每一个特征而言的,零均值化都,每个特征的均值变成0。实现代码如下:


import numpy as np

meanVals=mean(dataMat,axis=0)

#按列求均值,即求各个特征的均值  

meanRemoved=dataMat-meanVals 

#去均值的数据。也就是移动坐标轴

#print("meanRemoved",meanRemoved)


(2)求协方差矩阵


covMat=cov(meanRemoved,rowvar=0) #计算协方差矩阵

#其中,rowvar=0,说明传入的数据一行代表一个样本


(3)求特征值、特征矩阵


eigvals,eigVects=linalg.eig(mat(covMat)) 

#对协方差矩阵进行矩阵特征向量求解

print("eigvals",eigvals,"eigVects",eigVects)


(4)保留n个主成分特征


在第三步,得到了特征值向量eigVals,假设里面有m个特征值,需要对这m个特征值进行排序,排在前面的n个特征值所对应的特征向量就是我们要保留的。代码如下:


eigValInd=argsort(eigvals)  #对求解后的特征值进行排序,从小到大排序。

    print("eigValInd front",eigValInd)

eigValInd=eigValInd[:-(topNfeat+1):-1]

#python从左到右不能出界;但从右到左可以出界哦。

    print(eigValInd)#本例中第2个特征排在前。

    redEigVects=eigVects[:,eigValInd]#将原来的特征向量重新调换。

    print("redEigVects=",redEigVects)

    lowDataMat=meanRemoved * redEigVects  

    #去均值化后的数据和特征向量求解.

    #print(redEigVects*redEigVects.T)#单位矩阵,保证模不变。

    reconMat=(lowDataMat*redEigVects.T)+meanVals

return lowDataMat,reconMat#前者是pca分析后的值,后者就是主成分分析后的矩阵数据。


(5)、选择合适的主成分个数


应用PCA的时候,对于一个1000维的数据,我们怎么知道要降到几维的数据才是合理的?即n要取多少,才能保留最多信息同时去除,最多的噪声?一般,我们是通过方差百分比来确定n,这里我们调用sklearn. decomposition中PCA进行评估。


实例数据为:


digits=datasets.load_digits()

x=digits.data

y=digits.target

代码如下:

from sklearn.decomposition import PCA

pca=PCA()  

pca.fit(x_train)

plt.figure()

plt.plot([i for i in range(x_train.shape[1])],[np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(x_train.shape[1])])

plt.show()