来自函数的高效特征矩阵

Efficient Eigen Matrix From Function

本文关键字:特征 高效 函数      更新时间:2023-10-16

我正在尝试从内核构建一个矩阵,使得 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++/特征实现的速度(我猜是由于矢量化)。

我已经浏览了大量的文档(例如unaryExpr函数),但似乎找不到我要找的东西。

感谢您的任何帮助。

您可以将 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 << "nn";
  std::cout << X*Y.transpose() << "nn";
}

如果不想apply_kernel做模板函数,可以使用 std::function 来传递内核。