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

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

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

一、约化操作

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

复制代码
1
2
3
4
5
6
7
8
9
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;//求对角线元素之和

输出结果如下:

复制代码
1
2
3
4
5
6
7
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。
例如:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;

输出结果如下:

复制代码
1
2
3
4
5
6
7
8
9
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范数和无穷范数可以轻松的用如下方法来实现:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
2
3
4
5
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
    例如:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;

输出结果如下:

复制代码
1
2
3
4
5
6
7
8
(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),可以用来查找矩阵或者数组中最大或最小系数的位置
例如:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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;

输出结果如下:

复制代码
1
2
3
Max:4,at:1,1 Min:4,at:1,1

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

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

复制代码
1
2
3
4
5
6
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;

输出结果如下:

复制代码
1
2
3
4
5
6
Column's maximum: 3 2 7 9 Rowwise's maximum: 9 7

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

复制代码
1
2
3
mat<<1,2,6,9 3,1,7,2;

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

复制代码
1
2
3
4
5
6
7
8
9
10
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;

输出结果如下:

复制代码
1
2
3
4
5
6
Maximum sum at position 2 The corresponding vector is: 6 7 And its sum is is: 13

六、广播

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
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;
复制代码
1
2
3
4
5
输出结果如下: 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]
  同样,也可以按行进行操作,
例如:

复制代码
1
2
3
4
5
6
7
8
9
10
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;

输出结果如下:

复制代码
1
2
3
4
Broadcasting result: 1 3 8 12 3 2 9 5

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;

输出结果如下:

复制代码
1
2
3
4
Nearest neighbour is column 0: 1 3

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

复制代码
1
2
(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库学习内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部