PCA的目的:  pca算法,也叫主成分分析法,能够对一个多样本的多维特征向量构成的矩阵进行分析,分析主成分并去除维度之间的相关性,使线性相关的向量组变成线性无关的向量组。  并且可以对样本进行降维,降高维向量映射到低维度空间,同时确保纬度之间的信息损失尽可能小。

首先给出PCA算法的过程:

  1. 对每一维度均值化为0,计算出每一维度的均值,每一个数均减去这个均值
  2. 对于均值化为零的矩阵,求其维度的协方差矩阵C
  3. 求C矩阵的特征值V和特征向量矩阵P
  4. 用P作基底,将原来的特征矩阵映射到这一正交基上

基础知识:

首先理解正交基分解:

我们默认一个n维向量v=(x1,x2,x3……xn)是一个n维空间的以n个单位基底(1,0,0,……),(0,1,0,0……)……所表示的坐标形式。

例如,向量(1,2)可以表示为以(1,0),(0,1)为基底的一个向量。以下称这种基底为默认基底。

同时,在一个n维向量空间中,理论上是有无数多对基底的,要从默认基底变化到任意基底的坐标表示情况,首先要明确,向量v在n维空间上i维的坐标可以表示为v与第i个基底的内积(数量积),即可表示为v=(vi, vk, vj……)其中i,j,k……为选取的基底集合。

那么由m个样本构成的n维特征,表示为n行m列的矩阵X。则将在默认基底下的矩阵X变换到以n个k维为基底的表示,其矩阵表示为Y=PX ,其中P是kxn的n个变换基向量构成的矩阵,Y是变换结果。

那么一个n维的特征矩阵就可以通过正交基P变换到k维空间。


接下来写一下为什么要这样做,为什么通过这一系列操作,就能达到PCA的目的呢?

首先理解一下协方差矩阵:  协方差矩阵的对角线上的值代表这一维度的方差,而方差能够代表能量,方差越大,这一维度的能量越大(代表特征的能力越大)。非对角线上的元素代表了两个维度之间的协方差,协方差越小,相关性越小,协方差为0时,两个维度线性无关。

所以假设我们最后经过PCA处理要得到矩阵Y,Y是通过P这一正交基映得到的,即Y = PX, 那么我们要尽可能的使Y的协方差矩阵主对角线上的元素值尽可能大,而非对角线上的元素值尽可能为0。

假设Y的协方差矩阵为D,则:

我们要找的P恰好就是能让C对角化的P,根据线性代数知识,我们知道要使一个矩阵对角化,只需要求其特征值和特征向量,使用特征向量就能通过矩阵乘法将其对角化。

所以P就是C的特征向量矩阵。

这也就是我们所做的要求协方差矩阵,求其特征值和特征向量的原因。

但为了达到降维的目的,我们不能单纯的取全部特征向量来做,这样做的话维度是不变的,只是去除了一些相关性。所以我们要选取一部分特征向量来用。

衡量特征向量好坏的标准就是特征值,特征值越大,其对应的特征向量的维度分量上能量越大。我们对特征值进行从大到小排序,选取前K大的特征值对应的向量作为基底。

K的选取取决于我们想保留多少信息,这个计算方式为 sum(前k特征值)/ sum(所有特征值)

接下来附c++实现代码并带有注释:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<fstream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
void featurenormalize(MatrixXd &X)
{//计算每一维度均值MatrixXd meanval = X.colwise().mean();//每一列的矩阵,列降维RowVectorXd meanvecRow = meanval;//样本均值化为0X.rowwise() -= meanvecRow;}
void computeCov(MatrixXd &X, MatrixXd &C)
{//计算协方差矩阵C = XTX / n-1;C = X.adjoint() * X;//C = X * X.adjoint() ;MatrixXd Y;Y = X.adjoint();//转置矩阵+for (int i = 0; i < Y.rows(); i++){for (int j = 0; j < Y.cols(); j++){cout << " " << Y(i, j);}cout << " " << endl;}//C = C.array() / X.rows() - 1;//C = C.array() / (X.rows() - 1);C = C.array() / (X.cols() - 1);for (int i = 0; i < C.rows(); i++){for (int j = 0; j < C.cols(); j++){cout << " " << C(i, j);}cout << " " << endl;}
}
void computeEig(MatrixXd &C, MatrixXd &vec, MatrixXd &val)
{//计算特征值和特征向量,使用selfadjont按照对阵矩阵的算法去计算,可以让产生的vec和val按照有序排列SelfAdjointEigenSolver<MatrixXd> eig(C);vec = eig.eigenvectors();val = eig.eigenvalues();
}
int computeDim(MatrixXd &val)
{int dim;double sum = 0;for (int i = val.rows() - 1; i >= 0; --i){sum += val(i, 0);dim = i;if (sum / val.sum() >= 0.95)break;}//std::cout << "sum: " << sum << " val.sum(): " << val.sum() << "  rows: " << val.rows() << "  dim: " << dim << std::endl;return val.rows() - dim;
}
int main()
{ifstream fin("siftsmallD.txt");ofstream fout("output.txt");/*const int m = 10000, n = 128;MatrixXd X(10000, 128), C(128, 128);*/const int m = 8, n = 6;MatrixXd X(m, n), C(3, 3);MatrixXd vec, val;//读取数据//initdouble in[200];for (int i = 0; i < m; ++i){for (int j = 0; j < n; ++j)fin >> in[j];for (int j = 1; j <= n; ++j){X(i, j - 1) = in[j - 1];//cout << " " << X(i, j - 1);}//cout << " " << endl;}//cout << "X.rows(): " << X.rows() << "  X.cols(): " << X.cols() << endl;//pca//零均值化featurenormalize(X);//计算协方差computeCov(X, C);//计算特征值和特征向量computeEig(C, vec, val);//计算损失率,确定降低维数int dim = computeDim(val);std::cout << "dim: " << dim << std::endl;//计算结果MatrixXd res = X * vec.rightCols(dim);//输出结果fout << "the result is " << res.rows() << "x" << res.cols() << " after pca algorithm." << endl;fout << res;system("pause");return 0;
}

PCA算法的原理C++ Eigen库实现(附源码下载)相关推荐

  1. css 商城 两列_如何使用css伪元素实现超实用的图标库(附源码)

    今天我们来复盘一下前端中css伪元素的知识以及如何用css伪元素来减轻javascript的压力,做出一些脑洞大开的图形. 预备知识 伪元素 伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特 ...

  2. css 商城 两列_css大法之使用伪元素实现超实用的图标库(附源码

    今天我们来复盘一下前端中css伪元素的知识以及如何用css伪元素来减轻javascript的压力,做出一些脑洞大开的图形. 预备知识 伪元素 伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特 ...

  3. IAR新建stm32工程,完美移植stm32标准库(附源码)

    开发环境:Window 10 64bit 开发工具:IAR Embedded Workbench 硬件:stm32f103c8t6 基于IAR 开发工具,新建立STM32F1系列的最小开发例程,并加入 ...

  4. 【Python自然语言处理】隐马尔可夫模型中维特比(Viterbi)算法解决商务选择问题实战(附源码 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.统计分词 统计分词基本逻辑是把每个词语看做由单字组成,利用统计学原理计算连接字在不同文本中出现的次数,以此判断相连字属于特定词语的概率. 二.隐马尔可 ...

  5. 【人脸识别】基于主成分分析PCA算法人脸识别门禁系统含Matlab源码

    1 简介 人脸是反应人身份的最直接的,最可靠的信息资源.通过人脸我们可以很快辨识一个人,这就是所谓的人脸识别.最初的人脸研究人员是一些从事社会心理学的工作者,从20世纪50年代开始有一些文献资料陆续发 ...

  6. 如何快糙好猛的使用Shiqi.Yu老师的公开人脸检测库(附源码)

    前言 本次编写所用的库为于仕祺老师免费提供的人脸检测库.真心好用,识别率和识别速度完全不是Opencv自带的程序能够比拟的.将其配合Opencv的EigenFace算法,基本上可以形成一个小型的毕业设 ...

  7. SHA512/384 原理及C语言实现(附源码)

    闲来无事,造个哈希轮子,SHA384/SHA512这两者原理及实现一样的,只是输出和初始化的向量不一样. 原型 hash_val = sha512/384(message). hash_val: SH ...

  8. Python+审计实务与案例分析库 毕业设计-附源码211526

    Python审计实务与案例分析库 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识 ...

  9. B树的原理以及C++实现(附源码和文档)

    B树的C++实现 之前课程设计做的一个BTrees数据结构,在这里添加了算法说明的PDF文档以及配套的Latex文档,同时有源代码和详细的说明,算法思路全部来自于算法导论,,需要的同学直接拿走..喜欢 ...

最新文章

  1. 当有人看不起你时,要懂得反省自己
  2. 动态导航与动态路由绑定
  3. Miniconda3及pip换源(conda清华源关闭)
  4. opencv 简单、常用的图像处理函数(2)
  5. swagger的使用(com.spring4all)
  6. unity: GetLocalizedString can only be called from the main thread 异常解决
  7. flashcs3java_Flash CS3组件开发图文教程
  8. 生命游戏(Anylogic实现)
  9. PLSQL下载、安装、配置、连接详细教程
  10. 13-[LVI-SAM]visual_odometry_初探
  11. python 网络设备巡检_Python自动巡检H3C交换机实现过程解析
  12. 《第五项修炼》读后感
  13. 团队建设:如何打造一个优秀的团队
  14. 电子邮件发送服务器怎么看钱,验证电子邮件的验证码是发到哪里
  15. Linux如何让程序在后台运行
  16. 斯坦福大学机器学习——K-means算法
  17. 后代选择器与子元素选择器
  18. TAKE2获GRAIL 授权早期鼻咽癌检测技术
  19. PVM58N-YY1AGR0BN-1213光电采样编码器
  20. 标题DSP 数字信号处理:线性卷积、循环卷积、圆周卷积计算

热门文章

  1. laravel按月/时间区间查询数据
  2. DDD(Domain-Driven Design)领域驱动设计-(三)命令风暴寻找聚合
  3. GPU:上的了AI,下的了游戏 | 简谈计算机图形学、深度学习与硬件的“三角关系“
  4. C#笔记13 匿名类型、集合初始化器、扩展方法和查询表达式
  5. Linux 邮件服务器 之跟我一步一步来实现一个邮件系统
  6. 自动化测试之java的job任务
  7. setTimeout(〒︿〒) 请原谅我一直以来对你的忽视
  8. Android开发之动态加载,运行未安装apk
  9. visual studio如何用低版本打开高版本项目
  10. mysql 多端口备份_mysql数据库迁移、多端口运行、innobackupex备份