liboctave for windows MSVC or linux g++ 2008
liboctave以外には,IT++などのライブラリがあり,(これはliboctaveと異なり,そもそもAPIとして設計されたものなので)ドキュメントが豊富です.この情報もメモしておきます.
以下に2001,2002年あたりの古い情報がありましたが,あまりにも古くなってきたので使用例を除いて削除しました.
Octave C++で数値計算例
固有値分解
EIG
#include <iostream> #include <octave/config.h> #include <octave/Matrix.h> using namespace std; int main() { Matrix m(2, 2); m(0,0) = 3; m(0,1) = 2; m(1,0) = 2; m(1,1) = 0; cout << "Original Matrix" << endl << m << endl; EIG eig(m); cout << "Eigen Vectors" << endl << eig.eigenvectors() << endl; cout << "Eigen Values" << endl << eig.eigenvalues() << endl; cout << "Recomposed Matrix" << endl << eig.eigenvectors() *ComplexMatrix(ComplexDiagMatrix(eig.eigenvalues())) *eig.eigenvectors().inverse() << endl; return 0; }
特異値分解
#include <iostream> #include <octave/config.h> #include <octave/Matrix.h> using namespace std; int main() { Matrix m(3, 2); m(0,0) = 3; m(0,1) = 2; m(1,0) = 2; m(1,1) = 0; m(2,0) = 4; m(2,1) = 2; cout << "Original Matrix" << endl << m << endl; SVD svd(m); cout << "Left Singular Matrix" << endl << svd.left_singular_matrix() << endl; cout << "Singular Values" << endl << svd.singular_values() << endl; cout << "Right Singular Matrix" << endl << svd.right_singular_matrix() << endl; cout << "Recomposed Matrix" << endl << svd.left_singular_matrix() *Matrix(DiagMatrix(svd.singular_values())) *svd.right_singular_matrix() << endl; return 0; }
Octave C++で多変量解析
平均と共分散・相関係数
#include <iostream> #include <octave/config.h> #include <octave/Matrix.h> #include "octaveio.h" using namespace std; int main(int argc, char **argv) { Matrix X; "X.dat" >> X; // 各列がサンプルデータ int dim = X.rows(); // ベクトルの次元数 int nsample = X.cols(); // サンプルベクトル数 cout << "X\n" << X << endl; // 平均ベクトルの計算 ColumnVector mean(dim); mean = (X.sum(1) / nsample).column(0); // X.sum(1)/nsample だとMatrix型のまま cout << "mean\n" << mean << endl; // 共分散行列の計算 Matrix Cov(dim, dim); Matrix Xd(dim, nsample); // 平均ベクトルを各列から引いた行列 for(int i=0; i < nsample; i++){ Xd.insert(X.column(i) - mean, 0, i); } Cov = Xd*Xd.transpose() / nsample; // 不偏量を考えるなら nsample - 1 で割る cout << "Cov\n" << Cov << endl; // 相関係数行列の計算 Matrix Corr(dim, dim); Matrix Xn(dim, nsample); // 各行を正規化した行列 for(int i=0; i < dim; i++){ Xn.insert(X.row(i)/sqrt(X.row(i)*X.row(i).transpose()), i, 0); } Corr = Xn*Xn.transpose(); cout << "Corr\n" << Corr << endl; return 0; }
主成分分析
#include <iostream> #include <octave/config.h> #include <octave/Matrix.h> #include "octaveio.h" using namespace std; int main(int argc, char **argv) { Matrix X; "X.dat" >> X; // 各列がサンプルデータ int dim = X.rows(); // ベクトルの次元数 int nsample = X.cols(); // サンプルベクトル数 cout << "X\n" << X << endl; ColumnVector mean(dim); // 平均ベクトル Matrix Xd(dim, nsample); // 平均ベクトルを各列から引いた行列 Matrix Cov(dim, dim); // 共分散行列 mean = (X.sum(1) / nsample).column(0); for(int i=0; i < nsample; i++){ Xd.insert(X.column(i) - mean, 0, i); } Cov = Xd*Xd.transpose() / nsample; // 主成分分析(固有値分解を用いて) EIG eig(Cov); cout << "eigen vectors\n" << eig.eigenvectors() << endl; // 主成分 cout << "eigen values\n" << eig.eigenvalues() << endl; // 固有値(昇順) // 主成分分析(特異値分解を用いて) SVD svd(Xd); cout << "eigen vectors\n" << svd.left_singular_matrix() << endl; ColumnVector eigenvalues(dim); for(int i=0; i < dim; i++){ // Xdを直接分解したので共分散行列の固有値のサンプル数倍 eigenvalues(i) = svd.singular_values()(i,i)*svd.singular_values()(i,i) / nsample; } cout << "eigen values\n" << eigenvalues << endl; // 固有値(降順) return 0; }
正準相関分析
#include <iostream> #include <octave/config.h> #include <octave/Matrix.h> #include "octaveio.h" using namespace std; int main() { // 2組の2次元変数群(x_i, y_i (i=1,...,nsample))を読み込む // ただし平均が0であることを仮定する Matrix X; Matrix Y; "X.dat" >> X; "Y.dat" >> Y; cout << "X\n" << X << endl; cout << "Y\n" << Y << endl; int dim = X.rows(); int nsample = X.cols(); // それぞれの変数群を白色化するために,主成分分析を行う Matrix Ux, Uy; DiagMatrix Sx_inv, Sy_inv; EIG eig_X(X*X.transpose()/nsample); EIG eig_Y(Y*Y.transpose()/nsample); Ux = real(eig_X.eigenvectors()); Uy = real(eig_Y.eigenvectors()); ColumnVector Sx = real(eig_X.eigenvalues()); ColumnVector Sy = real(eig_Y.eigenvalues()); Sx_inv.resize(dim,dim); Sy_inv.resize(dim,dim); for(int i=0; i < dim; i++){ Sx_inv(i,i) = 1.0/sqrt(Sx(i)); Sy_inv(i,i) = 1.0/sqrt(Sy(i)); } // 白色化する行列 (XX'/nsample)^(-1/2), (YY'/nsample)^(-1/2) Matrix Wx = Ux*(Matrix)Sx_inv*Ux.transpose(); Matrix Wy = Uy*(Matrix)Sy_inv*Uy.transpose(); // 白色化された変量群 Matrix Xw = Wx * X; Matrix Yw = Wy * Y; // 白色化された変量群間の相互相関を特異値分解する SVD svd_R(Yw*Xw.transpose()/nsample, SVD::economy); // 係数行列 Matrix A = svd_R.right_singular_matrix().transpose() * Wx; Matrix B = svd_R.left_singular_matrix().transpose() * Wy; cerr << "A\n" << A << endl; // 正準相関係数 DiagMatrix Sr = svd_R.singular_values(); cerr << "Sr\n" << Sr << endl; //-------------------------------------------------- // 検証 //-------------------------------------------------- // 正準変量群 Matrix Xc = A * X; Matrix Yc = B * Y; cout << "Xc\n" << Xc << endl; cout << "Yc\n" << Yc << endl; // 正準変量群間の相互相関は,正準相関係数が対角に並んだ行列 cout << "Xc*Yc'/nsample\n" << Xc*Yc.transpose()/nsample << endl; return 0; }