LoginSignup
26
19

More than 1 year has passed since last update.

Eigenの便利な機能あれこれ

Last updated at Posted at 2019-01-22

機械学習を行う上で欠かせないのが行列演算ライブラリです。

pythonにnumpyがあるように、C++のデファクトスタンダードな行列計算ライブラリにEigenというものがあります。ヘッダのみのライブラリなのでプロジェクトに組み込みやすくSIMDとかも使って最適化してくれるので計算も速いです。
ここ最近でEigenを使った際に便利に感じた機能をまとめたいと思います。

Slicing and Indexing

v3.3.90から配列のSlicingとIndexingが便利に行えるようになりました。それまではblockAPIやhead/tail関数などを駆使していましたが、pythonのような要素指定が可能になりました。
以下にnumpyとEigenの要素指定方法の比較を載せました。

Eigen numpy
A(seq(i,last), seqN(0,n)) A[i:, :n]
A(seqN(i,m), seqN(i,n)) A[i:i+m, i:i+n]
A(seq(i0,i1), seq(j0,j1)) A[i0:i1+1, j0:j0+1]
A(all, seq(0,last,2)) A[:, ::2]
A(last/2,all) A[(A.shape[0]-1)/2, :]
v(lastN(n)) v[-n:]
A(all, seq(20, 10, fix<-2>)) A[:, 20:9:-2]
A(seqN(last, n, fix<-1>), all) A[:-n:-1, :]
A(lastN(n).reverse(), all) A[:-n:-1, :]
A(all,{4,2,5,5,3}) A[:, [4,2,5,5,3]]

最近傍点を見つけるコードを1行で書く

ドキュメントにも載っているのですが、これが1行で書けるのに少し感動したので紹介します。

#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 neighbor
  (m.colwise() - v).colwise().squaredNorm().minCoeff(&index);
  cout << "Nearest neighbor is column " << index << ":" << endl;
  cout << m.col(index) << endl;
}

該当の部分は(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);のところですが、行列mの中からベクトルvと最も近い列ベクトルのインデックスと距離を算出しています。

pybind11でpythonラッパにする

C++のコードのpythonラッパを作成するpybind11は標準でEigenとnumpyの変換を行ってくれます。
バインディングを行うコードでpybind11/eigen.hをインクルードするだけで、EigenのMatrix型をnumpyのndarrayに変換してくれます。

プラグインで機能拡張

EigenのMatrixやその他の型にはユーザが新たに関数追加を行うためのプラグイン機能があります。
プラグインと言っても以下のようにMatrixBase型などの中にマクロが埋め込まれており、ユーザ側で追加機能が書かれたファイルをEIGEN_MATRIX_BASE_PLUGINとして定義することでユーザが定義した関数や変数をクラスの中に追加することができます。

class MatrixBase {
  // ...
  #ifdef EIGEN_MATRIXBASE_PLUGIN
  #include EIGEN_MATRIXBASE_PLUGIN
  #endif
};

たとえばMatrixPlugin.hの中身を以下のように記述します。

MatrixPlugin.h
inline Scalar hoge() const { return this->operator()(0, 0); }

実際に使用するコードで、Eigenをインクルードする前に#define EIGEN_MATRIXBASE_PLUGIN "MatrixPlugin.h"を記述することで、Matrixからhoge関数を呼ぶことが可能になります。

Unsupported modules

公式にEigenがサポートしていないモジュールですが、色々入ってます。

  • Tensor(3次元以上の配列)の計算
  • 非線形最適化
  • オイラー角の計算
  • 自動微分

などなど。

26
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
19