前面一篇博客介绍了JAVA环境上怎么配置OpenCV。这篇简单介绍了一下PCA的原理,并且在Matlab和Python上分别进行了编码实现。
1 PCA原理
主成分分析 ( Principal ComponentAnalysis, PCA)或者主元分析。计算主成分的目的是将高维数据投影到较低维空间。
PCA是基于原始数据空间, 通过
• 构造一组新的潜隐变量来降低原始数据空间的
维数
• 再从新的映射空间抽取主要变化信息,提取统
计特征
• 从而构成对原始数据空间特性的理解。
从线性代数角度来看,PCA目标是找到一组新正交基去重新描述得到的数据空间,这个维度就是主元。
PCA的主要步骤如下:
1.去除平均值,归一化
2.计算协方差矩阵的特征值和特征向量
3.将特征值从大道小排序,取前N个特征向量
4.将数据转换到上述N个特征向量构建的新空间中
2 Matlab程序
%% PCA Demo write by jianglei 2017.12.11
%% 加载数据
fileName='testSet.txt';
data=load(fileName);
%% PCA运算
meanVal=mean(data);
trainNum=size(data,1);
%% 去均值
meanRemoved=[];
for i=1:trainNum
temp=data(i,:)-meanVal;
meanRemoved=[meanRemoved;temp];
end
%% 计算协方差矩阵和特征值特征向量
covMat=cov(meanRemoved);
[eigVects,eigVals]=eig(covMat);
onesMat=ones(size(eigVals,1),1);
eigValToVert=eigVals*onesMat;%将特征值得特征向量转化为列向量
eigValToVert=sort(eigValToVert,'descend');%降序排序
N=1;
eigValToVert=eigValToVert(1:N);%取前N个特征
exctEigVect=[];
for i=1:size(eigValToVert,1)
for j=1:size(eigVals,1)
if(eigValToVert(i)==eigVals(j,j))
exctEigVect=[exctEigVect;eigVects(:,j)];
end
end
if(i>N) %已经找到了前N个特征值得特征向量,退出循环
break;
end
end
%% 转换到低维空间,以提取的特征向量为基底,实现降维
lowDataMat=meanRemoved*exctEigVect;
reconMat=[];
temp=lowDataMat*exctEigVect';
for i=1:trainNum
reconMat=[reconMat;temp(i,:)+meanVal];
end
%% 降维结果显示
figure();
plot(data(:,1),data(:,2),'b*');
hold on
plot(reconMat(:,1),reconMat(:,2),'ro');
hold off
3 Python程序
from numpy import *
import matplotlib.pyplot as plt
#coding=utf-8
#读入数据文件
def loadDataSet(fileName,delim='\t'):
fr = open(fileName)
stringArr = [line.strip().split(delim) for line in fr.readlines()]
datArr = [list(map(float,line)) for line in stringArr]
return mat(datArr)
#PCA运算 topNfeat = 9999999可选参数,即应用N个特征。不指定才采取全部特征
def pca(dataMat,topNfeat = 9999999):
#去均值
meanVal = mean(dataMat,axis=0)
meanRemoved = dataMat-meanVal
#计算协方差矩阵的特征值特征向量
covMat = cov(meanRemoved,rowvar=0)
eigVals,eigVects = linalg.eig(covMat)
eigValsInd = argsort(eigVals)
eigValsInd = eigValsInd[:-(topNfeat):-1]#取后面的topNfeat个数,但是不包括-topNfeat
redEigVects=eigVects[:,eigValsInd]
lowDataMat=meanRemoved*redEigVects
reconMat=(lowDataMat * redEigVects.T)+meanVal
return lowDataMat,reconMat
#显示结果
def showResoult(dataMat,reconsMat):
fig=plt.figure();
fig.add_subplot(111);
plt.plot(dataMat[:,0],dataMat[:,1],'b*');
plt.plot(reconsMat[:,0],reconsMat[:,1],'ro');
plt.show()
datasMat=loadDataSet('testSet.txt')
lowData,reconsMat=pca(datasMat,2)
shape(lowData)
showResoult(datasMat,reconsMat)