2014-04-07 1 views
5

Sto lavorando con le reti neurali e voglio creare i pesi a caso. Quindi, se creo 30 reti neurali, ognuna di esse finisce per avere gli stessi pesi (che si suppone siano casuali), quindi quando do loro tutti lo stesso input l'output è lo stesso, quando non dovrebbe. Qualsiasi aiuto?C++ - default_random_engine crea sempre la stessa serie di numeri

Qui è la funzione principale

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); 
} 

E i initialize_weights è qui:

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; 
    } 
} 

Questa è l'uscita ottengo ogni volta che eseguo.

0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458 0,521458

La ringrazio molto.

+1

torso solo generatore – user3018144

risposta

6

Beh, come con Plain Old rand() è necessario fornire seme iniziale per il generatore che deve essere un valore diverso al fine per il generatore di generare diversa sequenza:

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

Inoltre, come user3018144 ha sottolineato, l'uso unico generatore, invece di 30 differenti:

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.... 
} 

Inoltre, proprio qui:

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

stai passando i generatori per valore, che creerà una copia del generatore esistente. Passare per riferimento invece:

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

Ok ora almeno mostra numeri differenza ogni esecuzione, ma ancora ottenere gli stessi 30 uscite (anche se diverso per ogni esecuzione) – kakashi1208

+0

@ kakashi1208 Vedi la modifica. –

+0

Ho cambiato anche quello e ho ancora lo stesso risultato. Ho modificato la domanda mostrando come appare ora il codice. – kakashi1208

1

Nel documentation of <random>, si afferma che bisogna bind il generatore alla distribuzione per riutilizzarlo.

Ecco un piccolo esempio:

#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; 
} 

Probabilmente si può adattarlo al vostro caso, passando weight (per riferimento, come ha notato @NemanjaBoric) al metodo initialize_weights.

Ecco come compilare ed eseguire:

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