为什么这4个不同的随机数生成器函数会产生相同的一系列数字



我正在调试过程中的神经进化程序不会每次调用时都会产生随机值。在程序中,通过以下语句初始化网络对象的向量:

vector<Network> population(POPULATION_SIZE, Network(sizes, inputCount));

为什么我认为该计划不融合到最佳解决方案的原因是,前100个人口始终是相同的。当以这种方式初始化网络时,连接权重和神经元偏差(每个(都使用以下类函数初始化:

double Network::randDouble(double low, double high) {
    /*default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
    uniform_real_distribution<double> distribution(low, high);
    return distribution(generator);*/
    /*srand(time(NULL));
    double temp;
    if (low > high) {
        temp = low;
        low = high;
        high = temp;
    }
    temp = (rand() / (static_cast<double>(RAND_MAX) + 1.0)) * (high - low) + low;
    return temp;*/
    /*mt19937 rgn(std::chrono::system_clock::now().time_since_epoch().count());
    uniform_real_distribution<double> gen(low, high);
    return gen(rgn);*/
    default_random_engine rd;
    uniform_real_distribution<double> gen(low, high);
    auto val = std::bind(gen, rd);
    return val();
}

以前,以前尝试了3个注释的部分来生成所需的功能。在每种情况下,它们都会为每个网络产生相同的数字(从1个权重到另一个重量,但不是1个网络到另一个网络(。尝试的方法基于此处的答案:

  1. c -default_random_engine始终创建同一系列数字
  2. http://en.cppreference.com/w/cpp/numeric/random/random/uniform_real_distribution

另外,第二种方法在有或没有种子的情况下产生相同的结果。我肯定错过了什么。

另一个,尽管可能无关紧要的是,使用此功能可能是使用OpenMP并行化的,并且在并行称为结果时,结果可能相同。

您的问题是您每次生成数字时都在初始化(播种(随机生成器。在简单的srand()情况下,您应该在程序启动过程中仅一次调用srand(),然后每次需要一个号码时致电rand()。在更复杂的情况下,您应该仅构建一次发电机(在整个程序中运行(,并根据需要使用多次。

C 11标准随机数发动机(以及大多数随机生成器(实际上是 pseudo - 随机数的生成器。伪随机意味着序列是可重复的。每当给定的伪随机发电机都用相同的种子播种时,它将始终产生相同的序列。(但这并不是您的代码中发生的事情。请继续。(

在C 11中,播种发生在随机数发动机实例化时发生。这意味着您需要实例化引擎每个pseudorandom序列。您的代码在每个呼叫网络:: randdouble((方法中播种引擎的方式,您无法期望获得发动机旨在生产的伪随机序列。取而代之的是,您将从呼叫的system_clock :: ...或time((方法中获得一系列的第一个数字。

调用System_clock :: Now((。time_since_epoch((。count((返回 erece 的整数返回时间。期间是指模板类STD :: Chrono ::持续时间的专业化,该时间由time_since_epoch((返回。该期间默认情况下可能是秒,这可以解释为什么您的所有网络对象在每个呼叫网络中都会获得相同的种子:: randdouble((。

如果您想要每个网络的不同顺序网络类。这意味着引擎或引擎对象的指针应为班级成员。

示例:

class Network {
...
protected:
    mt19937 rd;
...
}
Network::Network(int rndseed) :
    rd(rndseed)
{
...
}
double Network::randDouble(double low, double high) {
    uniform_real_distribution<double> gen(low, high);
    auto val = gen(rd);
    return val;
}

要确保伪内引擎的每个实例都会获得不同的种子,您可以使用像整数数字一样简单的东西。如果您想使用系统时钟,即使您使用std :: chrono :: high_resolution_clock,也要确保种子每次都不同,这要棘手得多。CPU非常快,您需要特别注意确保所使用的时钟计数实际上在两个呼叫之间发生了变化。

相关内容

最新更新