5

Eigen::Matrix 有一个 setRandom() 方法,它将矩阵的所有系数设置为随机值。但是,在指定要使用的分布时,是否有一种内置方法可以将所有矩阵系数设置为随机值。

有没有办法实现以下目标:

Eigen::Matrix3f myMatrix;
std::tr1::mt19937 gen;
std::tr1::uniform_int<int> dist(0,MT_MAX);
myMatrix.setRandom(dist(gen));
4

4 回答 4

3

你可以使用 Boost 和 unaryExpr 做你想做的事。您传递给 unaryExpr 的函数需要接受一个您可以忽略的虚拟输入。

#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
#include <Eigen/Dense>

using namespace std;
using namespace boost;
using namespace Eigen;

double sample(double dummy)
{
  static mt19937 rng;
  static normal_distribution<> nd(3.0,1.0);
  return nd(rng);
}

int main()
{
  MatrixXd m =MatrixXd::Zero(2,3).unaryExpr(ptr_fun(sample));
  cout << m << endl;
  return 0;
}
于 2013-07-27T00:50:28.613 回答
2

如果有人遇到此线程,我将发布一个更简单的答案,现在可以使用并且不需要提升。我在一份旧的 Eigen Bugzilla Report中发现了这一点。所有的功劳归于作者 Gael Guennebaud,他提出了以下简单的方法:

#include <Eigen/Sparse>
#include <iostream>
#include <random>

using namespace Eigen;

int main() {
  std::default_random_engine generator;
  std::poisson_distribution<int> distribution(4.1);
  auto poisson = [&] (int) {return distribution(generator);};

  RowVectorXi v = RowVectorXi::NullaryExpr(10, poisson );
  std::cout << v << "\n";
}

请注意,带有intlambda 函数参数的签名是 Eigen NullaryExpr 所必需的,尽管在此示例中未使用。

于 2020-01-22T02:09:09.907 回答
1

除了均匀分布,我不知道可以直接在矩阵上使用的任何其他类型的分布。您可以做的是将 Eigen 提供的统一分布直接映射到您的自定义分布(如果存在映射)。

假设您的分布是 sigmoid。您可以使用函数 y = a / ( b + c exp(x) ) 将均匀分布映射到 sigmoid 分布。

通过临时将矩阵转换为数组,您可以对矩阵的所有值进行元素操作:

Matrix3f uniformM;
uniformM.setRandom();

Matrix3f sigmoidM;
sigmoidM.array() = a * ((0.5*uniformM+0.5).array().exp() * c + b).inv();
于 2013-03-28T14:27:28.467 回答
0

我遇到了类似问题,并尝试使用 NullaryExpr 解决它。但是 NullaryExpr 的一个问题是它不能被明确地向量化。因此,使用 NullaryExpr 的解决方案运行速度很慢。

因此,我开发了EigenRand,这是 Eigen 随机分布的附加组件。我认为它将帮助那些想要快速轻松地生成随机数的人。

#include <Eigen/Dense>
#include <EigenRand/EigenRand>
#include <iostream>

using namespace Eigen;

int main() {
  Rand::Vmt19937_64 generator;

  // poisson distribution with rate = 4.1
  MatrixXi v = Rand::poisson<MatrixXi>(4, 4, generator, 4.1);
  std::cout << v << std::endl;

  // normal distribution with mean = 3.0, stdev = 1.0
  MatrixXf u = Rand::normal<MatrixXf>(4, 4, generator, 3.0, 1.0);
  std::cout << u << std::endl;

  return 0;
}
于 2020-07-04T06:51:01.180 回答