3-Eigen库常用功能

包含头文件:#include<Eigen\Dense>

Eigen文档地址:Eigen: The Matrix class

1、定义矩阵、初始化和赋值:

注:这里<>中定义固定矩阵的大小不能用变量

//定义
Eigen::Matrix<double, 3, 1> pc1;
Eigen::Vector3d pc2;//等价
Eigen::Matrix3f pc3;//3*3的float矩阵
int size = 5;
Eigen::Matrix<double, 3, size> pc_error;//这样我实验了会报错,<>里得是常量

//初始化
Eigen::Matrix<int, 2, 3> pc4{
        {2, 3, 4},//第一行
        {5, 6, 7}//第二行
};
Eigen::Matrix<int, 1, 5> pc5 = {1,2,3,4,5};//赋值初始化
Eigen::vector3d pc6(5.0, 6.0, 7.0);

//赋值
pc1(0,0) = 1;//(行,列).(1,2,3)的转置
pc1(1,0) = 2;
pc1(2,0) = 3;

pc2(0) = 1;//等价
pc2(1) = 2;
pc3(2) = 3;

pc3<<1,2,3, //第一行
     4,5,6, //第二行
     7,8,9; //第三行
std::cout<<pc3<<std::endl;

//行数、列数
std::cout<<"the pc2 is of size: "<<pc2.rows()<<"x"<<pc2.cols()<<std::endl; //行数*列数

2、动态矩阵相关

可参考链接:https://zhuanlan.zhihu.com/p/677438920

int size = 5;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> X;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> X2(3, size);
Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::RowMajor> X3 = Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::ColMajor>::Zero(3, size);//储存列优先
Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::ColMajor> X4 = Eigen::Matrix<double, 2, Eigen::Dynamic, Eigen::ColMajor>::Zero(2, 5);//储存列优先

X4<<1,2,3,4,5,6,7,8,9,10; //注意<<符号不管行优先还是列优先都是按行赋值,赋值完第一行再到第二行

for (int i = 0; i < size; i++)//X2矩阵每一列都赋成1,2,3
	{
		X2(0, i) = 1;
		X2(1, i) = 2;
		X2(2, i) = 3;
	}

3、块操作、取行、取列

官方教程链接:Eigen: Block operations

#include <Eigen/Dense>
#include <iostream>
 
using namespace std;
 
int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  cout << "Block in the middle" << endl;
  //取块Block
  //第一种取法从位置(row,col)(1,1)开始,取大小为2*2的块。结果为
  //{6,7;
  //10,11}
  cout << m.block<2,2>(1,1) << endl << endl;
  for (int i = 1; i <= 3; ++i)
  {
    cout << "Block of size " << i << "x" << i << endl;
    //第二种取法:从位置(row,col)(0,0)开始,取大小为i*i的块
    cout << m.block(0,0,i,i) << endl << endl;
  }


 //取行或列
 cout<<"m的第一列:"<< m.col(0) << endl;
 cout<<"m的第一行:"<< m.row(0) << endl;

}

4、SVD分解

官方链接:Eigen: SVD module

给了两种,JacobiSVDBDCSVD 。其中JacobiSVD对于小矩阵来说速度很快,但是对于大矩阵来说速度很慢。BDCSVD对大问题保持了快速。

这里给出JacobiSVD使用的例子:

Eigen::Matrix<double, 3, 3> H = X * X.transpose();//X是3*n的矩阵,之前定义的

//SVD分解H得到特征向量矩阵U
//奇异值从大到小排列,U中对应的特征向量也是对应从大到小的特征值排列
Eigen::JacobiSVD<Eigen::Matrix<double, 3, 3>> svd(H, Eigen::ComputeFullU | Eigen::ComputeFullV);//括号里得有Eigen::ComputeFullU | Eigen::ComputeFullV才会计算对应的U和V,不然只计算奇异值

cout << "Its singular values are:" << endl << svd.singularValues() << endl;
cout << "Its left singular vectors are the columns of the thin U matrix:" << endl << endl << svd.matrixU() << endl;//列是对应的特征向量
cout << "Its right singular vectors are the columns of the thin V matrix:" << endl << endl << svd.matrixV() << endl;

6、求解Ax=b

官方链接:Eigen: Linear algebra and decompositions

官方列出了不同求解方法的精度和效率,可以根据要求解的问题进行选择:

给出例子:直线y=3x+2,设ax+by+1=0,给定两个点p1(0,2), p2(10,32),求解参数a和b。

即:

Eigen::Matrix<double, 2, 2> A{ {0, 2} ,
							{10,32} };
Eigen::Vector2d b{ -1, -1 };//这里的类型double应该要跟A的double统一
Eigen::Vector2d x = A.colPivHouseholderQr().solve(b);//求解出直线的参数{a,b}

7、特征值分解

这里使用Eigen::SelfAdjointEigenSolver,功能为:Computes eigenvalues and eigenvectors of selfadjoint matrices. 计算自伴矩阵的特征值与特征矢量。定义在#include <Eigen/Eigenvalues> 

对于自伴矩阵的说明,可以参考博客:Eigen中用于特征值分解的几个类的介绍_selfadjointeigensolver-优快云博客

反正这里知道:SelfAdjointEigenSolver可以用来计算实对称矩阵的特征值与特征向量即可。

特征值分解相关的官方网址:Eigen: Catalogue of dense decompositions

函数官方网址:Eigen: Eigen::SelfAdjointEigenSolver< MatrixType_ > Class Template Reference

Eigen::Matrix<double, 3, 3> H = X * X.transpose();//X是3*n的矩阵,之前定义的

//特征值分解H得到特征向量矩阵U  这个理论基础更好。这里就用这个吧。
	Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, 3, 3>> es;
	es.compute(H);


    double value_min = es.eigenvalues()[0]; //取出最小的特征值
    Eigen::Vector3d v = es.eigenvectors().col(0);//取出最小的特征值对应的特征向量
	cout << "特征值分解H的结果:" << endl;
	cout << "特征值是:" << es.eigenvalues()<<endl;//特征值是从小到大排列
	cout << "特正向量是:" << es.eigenvectors() << endl;//每一列是一个特征向量,分别对应到由小到大排列的特征值

注:在PCA主成分分析中,这里建议对H=XX^{T}进行特征值分解来得到特征向量矩阵U。虽然进行奇异值分解(SVD)得到的结果也能使用,但SVD的U跟这里特征值分解的实际的H的特征向量的U会有负号上的差距。当然这个差距在PCA里求出来实际就是一个向量的方向的正负,对最后结果没有影响。但个人认为使用特征值分解来说理论解释更加直观。

注:直接对X进行SVD分解得到的U跟对H进行特征值分解得到的U一样,都是H的特征向量。但这里为何不对X进行SVD分解呢,因为若X的列数n很大,就会导致SVD分解耗时很长,甚至解不出来,所以这里还是推荐对H进行特征值分解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值