C++-default_random_engine 始终创建相同的数字序列

c++-default_random_engine creates all the time same series of numbers

本文关键字:数字 字序 创建 random engine C++-default      更新时间:2023-10-16

我正在使用神经网络,我想随机创建权重。因此,如果我创建 30 个神经网络,它们中的每一个最终都具有相同的权重(应该是随机的),所以当我给它们所有相同的输入时,输出是相同的,而不应该。有什么帮助吗?

这是主要功能

int main(){
std::vector<Improved_NN> v;
std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_real_distribution<double> distribution(-1.0,1.0);
for(int i = 0; i < 30; i++)
{
    Improved_NN temp;
    temp.initialize_weights(generator, distribution);
    v.push_back(temp);
}
Board temp;
for(int i = 0; i < 30; i++)
{
    std::cout <<"n" << v[i].executeFromExternal(temp);
}

initialize_weights在这里:

 void Improved_NN::initialize_weights(std::default_random_engine gen,std::uniform_real_distribution<double> dist){
int k,v = 0;
for(k = 0;k<NUM_HIDDEN_1;k++){
    for(v = 0 ; v < NUM_INPUTS; v++){
        mlp_t.w_h1_i[k][v]=dist(gen);
        //std::cout<<mlp_t.w_h1_i[k][v]<<std::endl;
    }
}
for(k = 0;k<NUM_HIDDEN_2;k++){
    for(v = 0 ; v < NUM_HIDDEN_1; v++){
        mlp_t.w_h2_h1[k][v]=dist(gen);
        //std::cout<<mlp_t.w_h2_h1[k][v]<<std::endl;
    }
}
for(k = 0;k<NUM_HIDDEN_3;k++){
    for(v = 0 ; v < NUM_HIDDEN_2; v++){
        mlp_t.w_h3_h2[k][v]=dist(gen);
        //std::cout<<mlp_t.w_h3_h2[k][v]<<std::endl;
    }
}
    for (int a = 0 ; a < NUM_HIDDEN_3;a++){
        mlp_t.w_o_h[0][a] = dist(gen);
        //std::cout<<mlp_t.w_o_h[0][a]<<std::endl;
    }
}

这是我每次执行时得到的输出。

0.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.5214580.521458

谢谢。

好吧,与普通的旧rand()一样,您需要为生成器提供初始种子,该种子需要是不同的值,以便生成器生成不同的序列:

    std::random_device rd;
    std::default_random_engine generator(rd());

另外,正如user3018144指出的那样,使用单个生成器,而不是30个不同的生成器:

int main(){
    std::vector<Improved_NN> v;
    std::random_device rd;
    std::default_random_engine generator(rd());
    std::uniform_real_distribution<double> distribution(-1.0,1.0);
    for(int i = 0; i < 30; i++)
    {
        Improved_NN temp;
        /*Problem is here*/
        temp.initialize_weights(generator, distribution);
        v.push_back(temp);
    }
    Board temp;
    for(int i = 0; i < 30; i++)
    {
        std::cout <<"n" << v[i].executeFromExternal(temp);
    }

//for the number of generations, do this....
}

另外,就在这里:

 void Improved_NN::initialize_weights(std::default_random_engine gen,std::uniform_real_distribution<double> dist){

您正在按值传递生成器,这将创建现有生成器的副本。改为按引用传递:

 void Improved_NN::initialize_weights(std::default_random_engine& gen, std::uniform_real_distribution<double>& dist){

<random>的文档中,声明必须将生成器bind到发行版中才能重用它。

这里有一个小例子:

#include <functional>
#include <iostream>
#include <random>
int main(int argc, char *argv[])
{
    std::default_random_engine rd;
    std::uniform_real_distribution<double> distribution(-1.0, 1.0);
    auto weight = std::bind(distribution, rd);
    for (int i = 0; i < 30; ++i)
    {
        std::cout << weight() << " ";
    }
    return 0;
}

也许您可以通过将weight(如@NemanjaBoric所述通过引用)传递给initialize_weights方法来使其适应您的情况。

以下是编译和运行的方法:

c++ main.cpp -o rands -std=c++11 && ./rands
-0.736924 -0.0826997 -0.562082 0.357729 0.869386 0.0388327 -0.930856 0.0594004 -0.984604 -0.866316 0.373545 0.860873 0.0538576 0.307838 0.402381 0.524396 -0.905071 -0.343532 0.512821 -0.269323 0.965101 0.506712 -0.854628 0.769414 -0.127177 -0.0445365 -0.450186 -0.666986 0.795313 -0.878871

尝试:

 std::random_device mch;
 std::default_random_engine generator(mch());
 std::normal_distribution<double> distribution(0.0, 1.0);

使用相同的种子,随机引擎每次都会生成相同的数字。解决此问题的常用方法是使用 ctime 库中的 time() 函数作为种子。这是有效的,因为 time() 函数以秒为单位返回时间,因此每秒都会得到一个不同的数字。

在某些系统中,此代码将起作用:

#include <iostream>
#include <random>
#include <ctime>
using namespace std;
int main() {
    default_random_engine gen(time(0));
    // Random number for the range 1-100
    uniform_int_distribution<int> distr(1, 100); 
    for (auto i = 0; i<10; ++i){
        cout << distr(gen)<< endl;
        }
}

在某些系统中,此代码存在问题,即第一个随机数始终相同或仅相差 1。这可能是由于较大的时间值每秒仅更改 1,因此种子值每次都非常相似。

解决此问题的方法是定义随机数,以便多次执行调用distr(gen)以生成第一个随机数。这是有效的,因为由于某种原因,其他随机数并不相同,因此,如果通过将其他非静态数字放入混合中来定义第一个数字,我们也可以获得第一个数字变化值。

下面是如何实现此解决方案的示例:

#include <iostream>
#include <random>
#include <ctime>
using namespace std;
int main() {
    default_random_engine gen(time(0));
    uniform_int_distribution<int> distr(1, 100); 
    for (auto i = 0; i<10; ++i){
        int random_num = (distr(gen)*distr(gen))/distr(gen);
        // The while loop is to get the number on the 
        // range 0-100. 
        while (random_num > 100){
            if (random_num % 2 == 0){
                random_num = random_num/2;}
            else{
                random_num = (random_num-1)/2;}}
        cout << random_num << endl;
        }
}