簡介
本文介紹一下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-範式,的範式,可以使用方法
squaredNorm()
,即所有係數的平方之和,數學上是一個向量與自身的點乘。 - norm 即稱歐拉範式,squaredNorm結果再開平方,得到平方根。
當這些計算作用於矩陣時, 一個 nXp的矩陣,可以當做一個大小爲(n*p)的向量,比如"Frobenius" or "Hilbert-Schmidt" norm
。
我們避免提矩陣的的範式(歐拉平方範式)運算,這樣會導致歧義。
Eigen也額外提供了一些對係數進行歐拉範式操作方法,如範式,可以使用lpNorm<p>()
方法。如果要計算 範式,模板參數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;
}
執行結果:
$ g++ -I /usr/local/include/eigen3 matrix_norm1.cpp -o matrix_norm1
$ ./matrix_norm1
vector v:
-1
2
v.squaredNorm() = 5
v.norm() = 2.23607
v.lpNorm<1>() = 3
v.lpNorm<Infinity>() = 2
matrix m:
1 -2
-3 4
m.squaredNorm() = 30
m.norm() = 5.47723
m.lpNorm<1>() = 10
m.lpNorm<Infinity>() = 4
boolean 歸約
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;
}
執行:
$ 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
7
broadcasting
廣播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 m
mat.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;
}
執行的情況類似:
[ \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}. ]
[ \begin{bmatrix} 1 & 2 \ 3 & 4 \end{bmatrix} + \begin{bmatrix} 1 & 1 \ 1 & 1 \end{bmatrix} = \begin{bmatrix} 2 & 3 \ 4 & 5 \end{bmatrix}. ]
執行結果:
$ 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
:
[ \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}] -
計算
(m.colwise() - v).colwise().squaredNorm()
:
(m.colwise() - v).colwise().squaredNorm() = [ \begin{bmatrix} 1 & 505 & 32 & 50 \end{bmatrix} ]
- minCoeff(&index) 用來獲得在m矩陣內,最小的係數位置索引,該列向量與向量v具有最短歐拉距離。
執行結果:
$ g++ -I /usr/local/include/eigen3 matrix_broadcast2.cpp -o matrix_broadcast2
$ ./matrix_broadcast2
Nearest neighbour is column 0:
Nearest column vector:
1
3
[ \begin{bmatrix} 4 & 3 & 13 & 11 \ 4 & 3 & 13 & 11\4 & 3 & 13 & 11 \end{bmatrix} ]
[ \begin{bmatrix} 4 & 3 & 13 & 11 \end{bmatrix} ]