Eigen入门之密集矩阵 6 - Reductions, visitors and broadcasting
簡介
本文介紹一下Dense Matrix的3中操作: reduction, visitor, broadcasting.
歸約計算reduction.
Eigen的歸約計算是這樣的一類計算,它是對矩陣或者數組進行的計算,并返回一個標量。可能其中最常用的就是sum()計算,它返回的是系數的和。
比如,前面曾經用到的示例:
#include <iostream> #include <Eigen/Dense> using namespace std; int main() {Eigen::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范式計算 (Norm comptation)
以下列出常用的向量范數和矩陣范數的定義,以及對應的MATLAB的函數:
1、向量范數
- 1-范數:,即向量元素絕對值之和,matlab調用函數norm(x, 1) 。
- 2-范數:,Euclid范數(歐幾里得范數,常用計算向量長度),即向量元素絕對值的平方和再開方,matlab調用函數norm(x, 2)。
- ∞-范數:,即所有向量元素絕對值中的最大值,matlab調用函數norm(x, inf)。
- -∞-范數:,即所有向量元素絕對值中的最小值,matlab調用函數norm(x, -inf)。
- p-范數:,即向量元素絕對值的p次方和的1/p次冪,matlab調用函數norm(x, p)。
2、矩陣范數
- 1-范數:, 列和范數,即所有矩陣列向量絕對值之和的最大值,matlab調用函數norm(A, 1)。
- 2-范數:,譜范數,即A’A矩陣的最大特征值的開平方。matlab調用函數norm(x, 2)。
- ∞-范數:,行和范數,即所有矩陣行向量絕對值之和的最大值,matlab調用函數norm(A, inf)。
- F-范數:,Frobenius范數,即矩陣元素絕對值的平方和再開平方,matlab調用函數norm(A, ’fro‘)。
在Eigen中,提供了計算范式的一些方法。
- squaredNorm 向量的平方范式,2-范式,?2\ell^2?2的范式,可以使用方法squaredNorm(),即所有系數的平方之和,數學上是一個向量與自身的點乘。
- norm 即稱歐拉范式,squaredNorm結果再開平方,得到平方根。
當這些計算作用于矩陣時, 一個 nXp的矩陣,可以當做一個大小為(n*p)的向量,比如"Frobenius" or "Hilbert-Schmidt" norm。
我們避免提矩陣的?2\ell^2?2的范式(歐拉平方范式)運算,這樣會導致歧義。
Eigen也額外提供了一些對系數進行歐拉范式操作方法,如?p\ell^p?p范式,可以使用lpNorm<p>()方法。如果要計算?∞\ell^\infty?∞ 范式,模板參數p取特殊值Infinity
即可,這得到系數絕對值的最大值。
示例:
//matrix_norm1.cpp#include <Eigen/Dense> #include <iostream>using namespace std; using namespace Eigen;int main() {VectorXf v(2);MatrixXf m(2,2), n(2,2);v << -1,2;cout << "vector v: "<<endl<<v<<endl;cout << "v.squaredNorm() = " << v.squaredNorm() << endl;cout << "v.norm() = " << v.norm() << endl;cout << "v.lpNorm<1>() = " << v.lpNorm<1>() << endl;cout << "v.lpNorm<Infinity>() = " << v.lpNorm<Infinity>() << endl;cout << endl;m << 1,-2,-3,4;cout << "matrix m: "<<endl<<m<<endl;cout << "m.squaredNorm() = " << m.squaredNorm() << endl;cout << "m.norm() = " << m.norm() << endl;cout << "m.lpNorm<1>() = " << m.lpNorm<1>() << endl;cout << "m.lpNorm<Infinity>() = " << m.lpNorm<Infinity>() << endl; }執(zhí)行結果:
$ g++ -I /usr/local/include/eigen3 matrix_norm1.cpp -o matrix_norm1 $ ./matrix_norm1 vector v: -12 v.squaredNorm() = 5 v.norm() = 2.23607 v.lpNorm<1>() = 3 v.lpNorm<Infinity>() = 2matrix m: 1 -2 -3 4 m.squaredNorm() = 30 m.norm() = 5.47723 m.lpNorm<1>() = 10 m.lpNorm<Infinity>() = 4boolean 歸約
Eigen提供了一些針對Boolean運算的歸約操作。
- all() : 如果系數全部滿足Boolean計算結果,則結果為true;否則為false。
- any() : 如果系數有任何滿足Boolean計算的結果,則結果為true;否則為false。
- count() : 返回滿足條件的系數的數。
給一個示例:
#include <Eigen/Dense> #include <iostream>using namespace std; using namespace Eigen;int main() {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;cout << "(a > 2).all() = " << (a > 2).all() << endl;cout << "(a > 2).any() = " << (a > 2).any() << endl;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訪問子 visitor
訪問子visitor用于訪問矩陣或數組內的系數及系數的位置。最簡單的是前面曾經使用到的maxCoeff(&x,&y) , minCoeff(&x,&y)。
示例請看下面的Partial reduction中的例子程序。
Partial reductions 局部歸約
Eigen提供了針對矩陣的列或者行的歸約操作,它們對矩陣的每行/每列進行操作,并返回結果向量。
對應的函數為colwise() , rowwise()。
Note colwise() 返回的是一個行向量,而rowwise()返回的是一個列向量。
示例:
//matrix_norm2.cpp#include <iostream> #include <Eigen/Dense>using namespace std;int main() {Eigen::MatrixXf mat(2,4);mat << 1, 2, 6, 9,3, 1, 7, 2;std::cout << "Column's maximum: " << std::endl<< mat.colwise().maxCoeff() << std::endl;std::cout << "Row's maximum: " << std::endl<< mat.rowwise().maxCoeff() << std::endl;}執(zhí)行:
$ g++ -I /usr/local/include/eigen3 matrix_norm2.cpp -o matrix_norm2 $ ./matrix_norm2 Column's maximum: 3 2 7 9 Row's maximum: 9 7broadcasting
廣播broadcasting比Partial reduction多了一個操作。其把一個向量賦值多次,結合成一個矩陣,可以和以及矩陣進行運算。
下面是一個簡單的示例程序:
//matrix_broadcast.cpp #include <iostream> #include <Eigen/Dense>using namespace std;int main() {Eigen::MatrixXf mat(2,4);Eigen::VectorXf v(2);mat << 1, 2, 6, 9,3, 1, 7, 2;v << 0,1;//add v to each column of mmat.colwise() += v;std::cout << "Broadcasting result1: " << std::endl;std::cout << mat << std::endl;// -------------Eigen::MatrixXf mm(2,2);mm<<1,2,3,4;v << 1,1;mm.rowwise() += v.transpose();std::cout << "Broadcasting result2: " << std::endl;std::cout << mm << std::endl;}執(zhí)行的情況類似:
[12693172]+[00001111]=[12694283].\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}. [13?21?67?92?]+[01?01?01?01?]=[14?22?68?93?].
[1234]+[1111]=[2345].\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 1 & 1 \\ 1 & 1 \end{bmatrix} = \begin{bmatrix} 2 & 3 \\ 4 & 5 \end{bmatrix}. [13?24?]+[11?11?]=[24?35?].
執(zhí)行結果:
$ g++ -I /usr/local/include/eigen3 matrix_broadcast.cpp -o matrix_broadcast $ $ ./matrix_broadcast Broadcasting result1: 1 2 6 9 4 2 8 3 Broadcasting result2: 2 3 4 5綜合: 結合broadcasting和其他的操作及運算
//matrix_broadcast2.cpp #include <iostream> #include <Eigen/Dense>using namespace std; using namespace Eigen;int main() {Eigen::MatrixXf m(2,4);Eigen::VectorXf v(2);m << 1, 23, 6, 9,3, 11, 7, 2;v << 2,3;MatrixXf::Index index;// find nearest neighbour(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);cout << "Nearest neighbour is column " << index << ":" << endl;cout << "Nearest column vector: " << endl << m.col(index) << endl; }-
計算m.colwise() - v:
[1236931172]?[22223333]=[?12147084?1]\begin{bmatrix} 1 & 23 & 6 & 9 \\ 3 & 11 & 7 & 2 \end{bmatrix} - \begin{bmatrix} 2 & 2 & 2 & 2 \\ 3 & 3 & 3 & 3 \end{bmatrix} = \begin{bmatrix} -1 & 21 & 4 & 7 \\ 0 & 8 & 4 & -1 \end{bmatrix} [13?2311?67?92?]?[23?23?23?23?]=[?10?218?44?7?1?] -
計算(m.colwise() - v).colwise().squaredNorm():
(m.colwise() - v).colwise().squaredNorm() = [ \begin{bmatrix} 1 & 505 & 32 & 50 \end{bmatrix} ]
- minCoeff(&index) 用來獲得在m矩陣內,最小的系數位置索引,該列向量與向量v具有最短歐拉距離。
執(zhí)行結果:
$ g++ -I /usr/local/include/eigen3 matrix_broadcast2.cpp -o matrix_broadcast2 $ ./matrix_broadcast2 Nearest neighbour is column 0: Nearest column vector: 1 3[431311431311431311]\begin{bmatrix} 4 & 3 & 13 & 11 \\ 4 & 3 & 13 & 11\\4 & 3 & 13 & 11 \end{bmatrix} ???444?333?131313?111111????
[431311]\begin{bmatrix} 4 & 3 & 13 & 11 \end{bmatrix} [4?3?13?11?]
總結
以上是生活随笔為你收集整理的Eigen入门之密集矩阵 6 - Reductions, visitors and broadcasting的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吉利熊猫 mini 开启预售,最高续航
- 下一篇: Eigen入门之密集矩阵 7 - Map