Eigen库学习 ---- 6.约化、访问和广播操作
上篇为:Eigen库学习 ---- 5.高级初始化操作
本篇为这个链接的学习笔记。
一、约化操作
在Eigen中,约化是一个函数,它取一个矩阵或者数组,返回一个标量值。最常用的约化方法是.sum(),返回这个数组或者矩阵中的所有系数之和。例如如下操作:
1
2
3
4
5
6
7
8
9Matrix2d 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
7Here 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
21VectorXf 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
9v.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
22MatrixXf 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
51-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
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17ArrayXXf 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
12MatrixXf 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
3Max:4,at:1,1 Min:4,at:1,1
五、访问矩阵数组的一部分
colwise()和rowwise()可以指定是将列行作为一部分进行操作,如下面操作,分别是获得每列的最大值和每行的最大值。
1
2
3
4
5
6MatrixXf 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
6Column's maximum: 3 2 7 9 Rowwise's maximum: 9 7
由此可以看出,按照行操作,返回的是一个列向量,按照列操作,返回的是一个行向量。
举例:求解矩阵m中,每列的和的最大值的索引列。
例如:
1
2
3mat<<1,2,6,9 3,1,7,2;
其中第2列(6,7)的和最大,所以应该返回索引2
1
2
3
4
5
6
7
8
9
10MatrixXf 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
6Maximum 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
11MatrixXf 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
10MatrixXf 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
4Broadcasting 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
17MatrixXf 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
4Nearest 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=[−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库学习内容请搜索靠谱客的其他文章。
发表评论 取消回复