本系列以书中源码为主,稍作修改并添加注释,均实际运行可行。为免后来者踩坑,特此公开!欢迎打赏!
转载请注明出处!
from numpy import *
import matplotlib
import matplotlib.pyplot as plt
#PCA算法,共两个函数
#第一个函数,用于清洗数据
#输入:原始数据集,分隔符
#输出:清洗后的数据集,一个可以计算的矩阵
def loadDataSet(fileName,delim='\t'):
fr = open(fileName)
stringArr = [line.strip().split(delim) for line in fr.readlines()]
dataArr = [list(map(float,line)) for line in stringArr]
return mat(dataArr)
#第二个函数,PCA主函数
#输入:数据集,主成分个数.注意这里的数据集矩阵中每行代表一个元素,每个元素有两个特征(书本中的数据)值
#输出:
def pca(dataMat,topNfeat=9999999):
#求每列(即特征值)的平均值(压缩为1行),若为1则是求每行平均值(压缩为1列)
meanVals = mean(dataMat,axis=0)
meanRemoved = dataMat - meanVals#平移到以0为中心的地方,便于计算
covMat =cov(meanRemoved,rowvar =0)#计算协方差矩阵
eigVals,eigVects = linalg.eig(mat(covMat))#计算特征值,特征向量
eigValInd = argsort(eigVals) #默认快排,从小到大进行排序
#得到topNfeat个特征值,大的特征值排在前,若topNfeat为1,则取1个特征值
eigValInd = eigValInd[:-(topNfeat+1):-1]
#获得topNfeat个主成分,即坐标轴
redEigVects = eigVects[:,eigValInd]#将对应topNfeat个特征值对应的特征向量取出来
#利用主成分矩阵将原中心化后的矩阵转为新的矩阵
lowDDataMat = meanRemoved * redEigVects
#还原降维后的矩阵。因为已经去掉了部分维数(在课本实例中去掉了一维),所以在图像上显示仍为一条直线。
#正交阵的逆等于其转置。redEigVects为SVD分解中的右奇异正交阵
reconMat = (lowDDataMat * redEigVects.T) + meanVals
return lowDDataMat,reconMat
#测试以上代码
dataMat = loadDataSet(r'选择你自己的数据集路径')
lowDMat,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 ='*',s=90)
#利用PCA对半导体制造数据降维
def replaceNanWithMean():
datMat = loadDataSet('secom.data','')
numFeat = shape(datMat)[1]
for i in range(numFeat):
meanVal = mean(datMat[nonzero(~isnan(datMat[:,i].A))[0],i])
datMat[nonzero(isnan(datMat[;,i].A))[0],i] = meanVal
return datMat
dataMat = replaceNanWithMean()
meanVals = mean(dataMat,axis=0)
meanRemoved = dataMat - meanVals
covMat = cov(meanRemoved,rowvar=0)
eigVals,eigVects = linalg.eig(mat(covMat))
eigVals