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 pltdef 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 meancovMat = 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 dimensionsredEigVects = eigVects[:,eigValInd] #reorganize eig vects largest to smallestlowDDataMat = meanRemoved * redEigVects #transform data into new dimensionsreconMat = (lowDDataMat * redEigVects.T) + meanVals #重构原始数据return lowDDataMat, reconMatdef 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 meanreturn datMatif __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 - meanValscovMat = np.cov(meanRemoved, rowvar=0) #计算协方差矩阵eigVals,eigVects = np.linalg.eig(np.mat(covMat)) #计算特征值和特征向量print(eigVals) #查看特征值,从而找出合适的降低维数nlowMat1,reconMat1=pca(dataMat1,) #降到一维