2
私は、カーネルから行列を構築しようとしているので、A(i、j)= f(i、j)ここでi、jは両方のベクトルです(したがって、2つの行列x、y各行は点/ベクトルに対応する)。私の現在の機能は次のようになります。効率的な固有行列関数から
Eigen::MatrixXd get_kernel_matrix(const Eigen::MatrixXd& x, const Eigen::MatrixXd& y, double(&kernel)(const Eigen::VectorXd&)) {
Eigen::MatrixXd res (x.rows(), y.rows());
for(int i = 0; i < res.rows() ; i++) {
for(int j = 0; j < res.cols(); j++) {
res(i, j) = kernel(x.row(i), y.row(j));
}
}
}
return res;
}
(私の場合はそうはゼロによる除算を引き起こすことになる)対角線のためのいくつかのロジックと一緒に。
これを行うにはより効率的/イディオム的な方法がありますか?私のテストの中には、Matlabのコードが私のC++/Eigenの実装の速度を上回っているようです(私はベクトル化のために推測しています)。
私はかなりの量の文書(例えば、unaryExprの機能)を調べましたが、探しているものが見つからないようです。
ありがとうございました。そうしないと
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
double my_kernel(const MatrixXd::ConstRowXpr &x, const MatrixXd::ConstRowXpr &y) {
return x.dot(y);
}
template<typename Kernel>
MatrixXd apply_kernel(const MatrixXd& x, const MatrixXd& y, Kernel kernel) {
return MatrixXd::NullaryExpr(x.rows(), y.rows(),
[&x,&y,&kernel](int i,int j) { return kernel(x.row(i), y.row(j)); });
}
int main()
{
int n = 10;
MatrixXd X = MatrixXd::Random(n,n);
MatrixXd Y = MatrixXd::Random(n,n);
MatrixXd R = apply_kernel(X,Y,std::ptr_fun(my_kernel));
std::cout << R << "\n\n";
std::cout << X*Y.transpose() << "\n\n";
}
:
ここMatrixXd res = MatrixXd::NullaryExpr(x.rows(), y.rows(),
[&x,&y,&kernel](int i,int j) { return kernel(x.row(i), y.row(j)); });
は行列積を再現する作業を自己完結型の例である:あなたはあなたのためのループを削除するには、適切なラムダとNullaryExprを使用することができます
ありがとうございます!それは私がそれが欲しいものを行うべきであるように見えます。私はC++のラムダ式には新しく、カーネル関数を使うのに問題がありますが、修正ができたらうまくいきます。 –
私は作業完了例を追加しました。 – ggael
ありがとう、これは私の必要性を完全に満たしています。 –