PCA 算法也叫主成分分析(principal components analysis),主要是用于数据降维的。其核心思想就是将 n 维特征映射到 k 维上(k < n),这 k 维是全新的正交特征。我们将这 k 维成为主元,是重新构造出来的 k 维特征,而不是简单地从 n 维特征中取出其余 n-k 维特征。
由于数据的最大方差给出了数据的最重要的信息。则第一主成分是从方差最大的方向提取出来的,第二个主成分则来自于方差次大的方向,且与第一主成分方向正交。
pca降维的步骤:1、特征中心化,即所有的样例都减去对应的均值
2、求特征协方差矩阵
3、求解协方差矩阵的特征值和特征向量
4、将特征值从大到小进行排序,选择其中最大的 k 个,然后将其对应的 k 个特征向量分别作为列向量组成特征矩阵
5、 将样本点投影到选取的特征向量上
Python实现:
import numpy as np import matplotlib import matplotlib.pyplot as plt def loadDataSet(fileName, delim='\t'): fr = open(fileName) stringArr = [line.strip().split(delim) for line in fr.readlines()] datArr = [map(float,line) for line in stringArr] return np.mat(datArr) def pca(dataMat, topNfeat=9999999): meanVals = np.mean(dataMat, axis=0) #计算均值 meanRemoved = dataMat - meanVals #remove mean covMat = np.cov(meanRemoved, rowvar=0) #计算协方差矩阵 eigVals,eigVects = np.linalg.eig(np.mat(covMat)) #计算特征值和特征向量 eigValInd = np.argsort(eigVals) #sort, sort goes smallest to largest 从低到高排序 eigValInd = eigValInd[:-(topNfeat+1):-1] #cut off unwanted dimensions redEigVects = eigVects[:,eigValInd] #reorganize eig vects largest to smallest lowDDataMat = meanRemoved * redEigVects #transform data into new dimensions reconMat = (lowDDataMat * redEigVects.T) + meanVals #重构原始数据 return lowDDataMat, reconMat def replaceNanWithMean(): #将NaN替换为平均值的函数 datMat = loadDataSet('secom.data', ' ') numFeat = np.shape(datMat)[1] for i in range(numFeat): meanVal = np.mean(datMat[np.nonzero(~np.isnan(datMat[:,i].A))[0],i]) #values that are not NaN (a number) datMat[np.nonzero(np.isnan(datMat[:,i].A))[0],i] = meanVal #set NaN values to mean return datMat if __name__ == "__main__": dataMat=loadDataSet('testSet4.txt') lowMat,reconMat=pca(dataMat,1) #降到一维 #绘出数据 fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(dataMat[:,0].flatten().A[0],dataMat[:,1].flatten().A[0],marker='^',s=90) ax.scatter(reconMat[:,0].flatten().A[0],reconMat[:,1].flatten().A[0],marker='o',s=50,c='red') #对半导体制造数据降维 dataMat1=replaceNanWithMean() meanVals = np.mean(dataMat1, axis=0) meanRemoved = dataMat1 - meanVals covMat = np.cov(meanRemoved, rowvar=0) #计算协方差矩阵 eigVals,eigVects = np.linalg.eig(np.mat(covMat)) #计算特征值和特征向量 print(eigVals) #查看特征值,从而找出合适的降低维数n lowMat1,reconMat1=pca(dataMat1,) #降到一维