PCA原理不说了,真的我也讲不明白…………,但是这篇博客写的真的不错在此记录一下 。传送门在这
但是还有疑惑啊啊啊!!
对于原文中的这句话,“寻找一个矩阵P,满足



是一个对角矩阵,并且对角元素按从大到小依次排列,那么P的前K行就是要寻找的基,用P的前K行组成的矩阵乘以X就使得X从N维降到了K维并满足上述优化条件。”
不知道为什么要按照对角元素从大到小排列?
对于这个问题我们就要了解特征值和特征向量的意义了,在给个传送门
我们通过特征值分解得到的前N个特征向量,那么就对应了这个矩阵最主要的N个变化方向。我们利用这前N个变化方向,就可以近似这个矩阵(变换)。也就是之前说的:提取这个矩阵最重要的特征。总结一下,特征值分解可以得到特征值与特征向量,特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么,可以将每一个特征向量理解为一个线性的子空间,我们可以利用这些线性的子空间干很多的事情。不过,特征值分解也有很多的局限,比如说变换的矩阵必须是方阵。
给出伪代码
设有m条n维数据。
1)将原始数据按列组成n行m列矩阵X
2)将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值
3)求出协方差矩阵
4)求出协方差矩阵的特征值及对应的特征向量
5)将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P
6)即为降维到k维后的数据
#encoding:utf-8
from numpy import *
def loadDataSet(filename, delim = '\t'):
fr = open(filename)
stringArr = [line.strip().split('\t') for line in fr.readlines()]
datArr = [map(float, line) for line in stringArr]
return mat(datArr)
def pca(datMat, topNfeat = 99999):
meanVals = mean(datMat, axis = 0) #求每一个特征值的均值
meanRemoved = datMat - meanVals #进行零均值化
#rowvar=0,代表一段数据是一行,行的个数代表样本个数,列代表特征值
#rowvar=1, 代表一段数据是一列,行的个数代表特征的的个数,列的个数代表样本的个数
covMat = cov(meanRemoved,rowvar = 0)#计算协方差矩阵 注意分母除的是(N-1)样本的数目减一
eigVals, eigVects = linalg.eig(covMat)#求出特征值,特征向量
eigValsInd = argsort(eigVals)#返回特征值从小到大的索引
eigValsInd = eigValsInd[:-(topNfeat+1):-1]
redEigVects = eigVects[:,eigValsInd]#注意特征向量是列向量
lowDataMat = meanRemoved*redEigVects#将数据转化到新空间
recondMat = (lowDataMat*redEigVects.T)+meanVals#将新坐标旋转到跟旧坐标相对的位置
return lowDataMat,recondMat
def draw(dataMat,recondMat):
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataMat[:,0].flatten().A[0], dataMat[:,1].flatten().A[0],marker='o',s=20,c='black')
ax.scatter(recondMat[:,0].flatten().A[0], recondMat[:,1].flatten().A[0],marker='o',s=20,c='red')
plt.show()
if __name__ == '__main__':
datMat = loadDataSet('testSet.txt')
lowData, recordMat = pca(datMat,1)
draw(datMat,recordMat)
测试
测试数据集传送门
如图列所示,我们将蓝色的点,降维到了一维,也就是红色那个点集