我试图从内核构建矩阵,这样A(i,j)= f(i,j)其中i,j都是向量(因此我从两个矩阵x,y构建A)每行对应一个点/向量)。我目前的功能与此类似:
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函数),但似乎无法找到我正在寻找的内容。
感谢您的帮助。
答案 0 :(得分:1)
您可以将NullaryExpr与适当的lambda一起使用来删除for循环:
MatrixXd res = MatrixXd::NullaryExpr(x.rows(), y.rows(),
[&x,&y,&kernel](int i,int j) { return kernel(x.row(i), y.row(j)); });
这是一个重现矩阵产品的工作自包含示例:
#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";
}
如果您不想让apply_kernel成为模板函数,可以使用std :: function来传递内核。