基于PCA的人脸识别系统(JAVA版)(二) PCA原理介绍

本文介绍了主成分分析(PCA)的基本原理及其在Matlab和Python中的实现过程。PCA是一种用于数据降维的重要方法,能有效减少数据维度并保留关键信息。

         前面一篇博客介绍了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)


### 实现PCA的数据特征提取Java中实现PCA(主成分分析),主要涉及以下几个方面的工作: #### 数据标准化 由于不同维度上的数值范围可能差异很大,在计算协方差之前通常先对原始数据做零均值化处理,即减去各列平均数并除以其标准偏差。 ```java public static double[][] standardize(double[][] data) { int n = data.length; int d = data[0].length; // 计算每列的均值和标准差 double[] means = new double[d]; double[] stds = new double[d]; for (int j = 0; j < d; ++j) { for (int i = 0; i < n; ++i) means[j] += data[i][j]; means[j] /= n; for (int i = 0; i < n; ++i) stds[j] += Math.pow(data[i][j] - means[j], 2); stds[j] = Math.sqrt(stds[j] / n); } // 对每一项应用变换 for (int i = 0; i < n; ++i) for (int j = 0; j < d; ++j) if (stds[j] != 0) data[i][j] = (data[i][j] - means[j]) / stds[j]; return data; } ``` #### 构建协方差矩阵并求解其特征值与特征向量 通过构建样本间的协方差矩阵来捕捉变量之间的线性关系。接着利用某些库函数获取该矩阵的所有特征值及其对应的正交单位特征向量[^1]。 对于大型稀疏矩阵可以考虑采用更高效的迭代算法如Arnoldi/Lanczos方法;而对于稠密的小规模问题可以直接调用通用的Eigenvalue Decomposition API完成此操作。 ```java import org.ejml.simple.SimpleMatrix; // 假设输入已经过标准化处理后的数据中心本Xc SimpleMatrix covMat = Xc.mult(Xc.transpose()).scale(1.0/(n-1)); EigenDecomposition evd = CommonOps.computeEig(covMat); double[] eigenValues = evd.getRealEigenvalues(); Complex_F64[] eigenVectors = evd.getEigenVector(i).getDDRM().getData(); ``` 这里使用了`ejml`库来进行简单的矩阵运算以及特征分解任务。实际项目开发时可根据具体需求选用其他更适合的第三方科学计算包。 #### 特征选择与投影转换 按照从大到小顺序排列上述得到的特征值,并选取前K个最大的作为新的坐标轴方向。将这些选定的方向组合成一个投影矩阵P,最后把原高维空间中的点映射至低维子空间内表示出来[^3]。 ```java List<Integer> indices = IntStream.rangeClosed(0, p-1) .boxed() .sorted((a,b)->Double.compare(eigenValues[b],eigenValues[a])) .collect(Collectors.toList()); // 取前k个最大特征值对应索引位置处的特征向量组成投影矩阵P SimpleMatrix P = SimpleMatrix.empty(k,d); for(int idx : indices.subList(0,k)) { Complex_F64 vec = ... ; // 获取第idx个特征向量 P.setRow(idx,new DenseMatrix(vec.toArray())); } // 将标准化后的数据集D乘上投影矩阵获得最终降维结果Y=D*P' SimpleMatrix Y = D.mult(P.transpose()); ``` 以上就是基于Java语言的一个基本框架用于执行PCA过程以达到降低多维数据复杂度的目的。值得注意的是,为了提高效率和稳定性,在工程实践中往往还会涉及到更多细节优化措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值