概述
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
三、布尔约化
下面这些操作都是布尔型的:
- all():如果矩阵或数组的元素都已经给定,则返回true,否则返回false
- any():如果矩阵或数组的元素至少一个给定,则返回true,否则返回false
- count():返回矩阵或数组中的元素个数
- array>0 是在array元素中大于零的改为true,否则改为false
- (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=[−102184047−1]
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.约化、访问和广播操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复