我是靠谱客的博主 幽默耳机,最近开发中收集的这篇文章主要介绍Eigen库学习 ---- 6.约化、访问和广播操作,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Eigen库学习 ---- 6.约化、访问和广播操作

上篇为:Eigen库学习 ---- 5.高级初始化操作
本篇为这个链接的学习笔记。

一、约化操作

  在Eigen中,约化是一个函数,它取一个矩阵或者数组,返回一个标量值。最常用的约化方法是.sum(),返回这个数组或者矩阵中的所有系数之和。例如如下操作:

Matrix2d mat;
mat << 1,2,3,4;
cout << "Here is mat.sum()		    " << mat.sum()      << endl;//求所有元素的和
cout << "Here is mat.prod()		" << mat.prod()     << endl;//求所有元素的积
cout << "Here is mat.mean()		" << mat.mean()     << endl;//求所有元素的平均值
cout << "Here is mat.minCoeff() " << mat.minCoeff() << endl;//求所有元素的最小值
cout << "Here is mat.maxCoeff() " << mat.maxCoeff() << endl;//求所有元素的最大值
cout << "Here is mat.trace()	" << mat.trace()    << endl;//求对角线元素之和

输出结果如下:

Here is mat.sum()               10
Here is mat.prod()              24
Here is mat.mean()              2.5
Here is mat.minCoeff() 		     1
Here is mat.maxCoeff() 		     4
Here is mat.trace()     		 5

  其中,a.trace()等价于a.diagonal().sum()

二、范数(规范化)

  向量的2-范数可以通过squaredNorm()得到。其余的范数Eigen也提供了相应的API。
例如:

VectorXf v(2);
MatrixXf m(2, 2), n(2, 2);
v << -1, 2;
m << 1, -2, 
	-3,  4;
//求v的所有元素的平方和
cout << "v.squareNorm()=" << v.squaredNorm() << endl;
//求v的所有元素的平方和再开根号
cout << "v.norm()=" << v.norm() << endl;
//求v的各个元素的L1范数
cout << "v.lpNorm<1>=" << v.lpNorm<1>() << endl;
//求v的各个元素的无穷范数
cout << "v.lpNorm<Infinity>()=" << v.lpNorm<Infinity>() << endl;
cout << endl;
//求m的各个元素的平方和
cout << "m.squareNorm()=" << m.squaredNorm() << endl;
//求m的各个元素的L1范数
cout << "m.lpNorm<1>()=" << m.lpNorm<1>() << endl;
//求m的各个元素的无穷范数
cout << "m.lpNorm<Infinity>()=" << m.lpNorm<Infinity>() << endl;

输出结果如下:

v.squareNorm()=5
v.norm()=2.23607
v.lpNorm<1>=3
v.lpNorm<Infinity>()=2

m.squareNorm()=30
m.lpNorm<1>()=10
m.lpNorm<Infinity>()=4

  另外,1范数和无穷范数可以轻松的用如下方法来实现:

MatrixXf m(2, 2);
m << 1, -2,
	-3, 4;
//先逐个元素取绝对值(.cwiseAbs()),
//再按照列(.colwise()求和(.sum())),即为列的1范数
//再取最大值(.maxCoeff())
cout << "1-norm(m).col     = " << m.cwiseAbs().colwise().sum().maxCoeff()
	 << " == " << m.colwise().lpNorm<1>().maxCoeff() << endl;
//先逐个元素取绝对值(.cwiseAbs()),
//再按照行(.rowwise())求和(.sum()),即为行的1范数
//再取最大值(.maxCoeff())
cout << "1-norm(m).row     = " << m.cwiseAbs().rowwise().sum().maxCoeff()
	<< " == " << m.rowwise().lpNorm<1>().maxCoeff() << endl;
//先逐个元素取绝对值(.cwiseAbs()),
//再按照行(.rowwise())求和(.sum()),
cout << "infty-norm(m).rowwise() = " << m.cwiseAbs().rowwise().sum().maxCoeff()
	 << " == " << m.rowwise().lpNorm<1>().maxCoeff() << endl;
//先逐个元素取绝对值(.cwiseAbs()),
//再按照列(.colwise())求和(.sum()),
cout << "infty-norm(m).colwise() = " << m.cwiseAbs().colwise().sum().maxCoeff()
	 << " == " << m.colwise().lpNorm<1>().maxCoeff() << endl;

输出结果如下:

1-norm(m).col     = 6 == 6
1-norm(m).row     = 7 == 7
infty-norm(m).rowwise() = 7 == 7
infty-norm(m).colwise() = 6 == 6

三、布尔约化

  下面这些操作都是布尔型的:

  1. all():如果矩阵或数组的元素都已经给定,则返回true,否则返回false
  2. any():如果矩阵或数组的元素至少一个给定,则返回true,否则返回false
  3. count():返回矩阵或数组中的元素个数
  4. array>0 是在array元素中大于零的改为true,否则改为false
  5. (array>0).all()测试所有的元素是否都大于零,是则返回true,否则返回false
    例如:
ArrayXXf a(2, 2);
a << 1,2,
	 3,4;
//判断是否所有元素都大于零
cout << "(a>0).all()=" << (a > 0).all() << endl;
//判断是否至少有一个元素大于零
cout << "(a>0).any()=" << (a > 0).any() << endl;
//判断大于零的个数
cout << "(a>0).count()=" << (a > 0).count() << endl;
cout << endl;
//判断是否所有元素都大于2
cout << "(a>2).all()=" << (a > 2).all() << endl;
//判断是否至少有一个元素大于2
cout << "(a>2).any()=" << (a > 2).any() << endl;
//判断大于2的个数
cout << "(a>2).count()=" << (a > 2).count() << endl;

输出结果如下:

(a>0).all()=1
(a>0).any()=1
(a>0).count()=4

(a>2).all()=0
(a>2).any()=1
(a>2).count()=2

四、访问

  maxCoeff(&x,&y)和minCoeff(&x,&y),可以用来查找矩阵或者数组中最大或最小系数的位置
例如:

MatrixXf m(2, 2);
m << 1,2,
	 3,4;
//获取最大值和最大值的索引
MatrixXf::Index maxRow, maxCol;
float max = m.maxCoeff(&maxRow, &maxCol);
//获取最小值和最小值的索引
MatrixXf::Index minRow, minCol;
float min = m.maxCoeff(&minRow, &minCol);
cout << "Max:" << max << ",at:" << maxRow << "," << maxCol << endl;
cout << "Min:" << min << ",at:" << minRow << "," << minCol << endl;

输出结果如下:

Max:4,at:1,1
Min:4,at:1,1

五、访问矩阵数组的一部分

  colwise()和rowwise()可以指定是将列行作为一部分进行操作,如下面操作,分别是获得每列的最大值和每行的最大值。

MatrixXf mat(2,4);
mat << 1,2,6,9,
	   3,1,7,2;
cout << "Column's maximum: " << endl << mat.colwise().maxCoeff() << endl;
cout << "Rowwise's maximum:" << endl << mat.rowwise().maxCoeff() << endl;

输出结果如下:

Column's maximum:
3 2 7 9
Rowwise's maximum:
9
7

  由此可以看出,按照行操作,返回的是一个列向量,按照列操作,返回的是一个行向量。
举例:求解矩阵m中,每列的和的最大值的索引列。
例如:

mat<<1,2,6,9
     3,1,7,2;

  其中第2列(6,7)的和最大,所以应该返回索引2

MatrixXf mat(2, 4);
mat << 1, 2, 6, 9,
	   3, 1, 7, 2;
MatrixXf::Index   maxIndex;
float maxNorm = mat.colwise().sum().maxCoeff(&maxIndex);
cout << "Maximum sum at position " << maxIndex << endl;
cout << "The corresponding vector is: " << endl;
cout << mat.col(maxIndex) << endl;
cout << "And its sum is is: " << maxNorm << endl;

输出结果如下:

Maximum sum at position 2
The corresponding vector is:
6
7
And its sum is is: 13

六、广播

  广播的概念在这里不介绍了,直接介绍使用,简记:将向量复制成矩阵。

MatrixXf mat(2, 4);
VectorXf v(2);
mat << 1, 2, 6, 9,
	   3, 1, 7, 2;
v << 0,
	 1;
//add v to each column of m
mat.colwise() += v;
cout << "Broadcasting result: " << endl;
cout << mat << endl;
输出结果如下:
Broadcasting result:
1 2 6 9
4 2 8 3

[ 1 2 6 9 3 1 7 2 ] + [ 0 0 0 0 1 1 1 1 ] = [ 1 2 6 9 4 2 8 3 ] begin{bmatrix} 1&2 &6 &9 \ 3&1 &7 &2 end{bmatrix}+ begin{bmatrix} 0&0 &0 &0 \ 1&1 &1 &1 end{bmatrix}= begin{bmatrix} 1&2 &6 &9 \ 4&2 &8 &3 end{bmatrix} [13216792]+[01010101]=[14226893]
  同样,也可以按行进行操作,
例如:

MatrixXf mat(2, 4);
VectorXf v(4);
mat << 1, 2, 6, 9,
	3, 1, 7, 2;
v << 0, 1, 2, 3;
//add v to each row of m
mat.rowwise() += v.transpose();
cout << "Broadcasting result: " << endl;
cout << mat << endl;

输出结果如下:

Broadcasting result:
 1  3  8 12
 3  2  9  5

  广播操作也可以结合其他的操作,之前学过的矩阵、数组的操作都可以结合进来,例如求解一个矩阵m中,离着向量v最近的列,即范数最小的列。
例如:

MatrixXf m(2, 4);
VectorXf v(2);
m << 1, 23, 6, 9,
	 3, 11, 7, 2;
v << 2,
	 3;
MatrixXf::Index index;
//找到离着v最近点一个列
//将m按列操作(.colwise),即将矩阵m分为4个列
//用广播操作,将每个列都减去v。(- v)
//将减掉之后的结果((m.colwise() - v))再按列操作,还是4列
//求平方和的根(.squaredNorm()),得到1行4列的数据
//求1行4列矩阵中最小的值(.minCoeff)的索引(&index)
(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);
cout << "Nearest neighbour is column " << index << ":" << endl;
cout << m.col(index) << endl;

输出结果如下:

Nearest neighbour is column 0:
1
3

下面我们逐步分析这一行:(注释里已经分析过了)

(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);

1. m . c o l w i s e ( ) − v m.colwise()-v m.colwise()v是一个广播操作,将m中的每一列都减去v,新矩阵的尺寸和原先的m一样。
      m . c o l w i s e ( ) − v = [ − 1 21 40 7 0 8 4 − 1 ] m.colwise()-v= begin{bmatrix} -1&21 &40 &7 \ 0&8 &4 &-1 end{bmatrix} m.colwise()v=[1021840471]
2. ( m . c o l w i s e ( ) − v ) . c o l w i s e ( ) . s q u a r e d N o r m ( ) (m.colwise()-v).colwise().squaredNorm() (m.colwise()v).colwise().squaredNorm()是一个偏置操作,计算每一个列的平方和根。返回的是一个行向量,元素值是m的每列和v的距离。
      ( m . c o l w i s e ( ) − v ) . c o l w i s e ( ) . s q u a r e d N o r m ( ) = [ 1 505 32 50 ] (m.colwise()-v).colwise().squaredNorm()= begin{bmatrix} 1&505 &32 &50 end{bmatrix} (m.colwise()v).colwise().squaredNorm()=[15053250]
3. . m i n C o e f f ( ) .minCoeff() .minCoeff()用来获得上述 [ 1 505 32 50 ] begin{bmatrix} 1&505 &32 &50 end{bmatrix} [15053250]中最小值的索引值0。

最后

以上就是幽默耳机为你收集整理的Eigen库学习 ---- 6.约化、访问和广播操作的全部内容,希望文章能够帮你解决Eigen库学习 ---- 6.约化、访问和广播操作所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部