[英]Why do these 4 different random number generator functions produce the same series of numbers?
我正在調試的神經進化程序每次調用時都不會產生隨機值。 在程序中,使用以下語句初始化Network對象的向量:
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個網絡到另一個網絡)。 嘗試的方法基於這里的答案:
此外,第二種方法在有或沒有種子的情況下產生相同的結果。 我肯定錯過了什么。
另一個盡管可能無關緊要的問題是,使用它的函數可以使用OpenMP並行化,並且當並行調用時,結果可能是相同的。
您的問題是每次生成數字時都在初始化(播種)隨機生成器。 在簡單的srand()
情況下,你應該在程序啟動時只調用一次srand()
,然后每次需要一個數字時調用rand()
。 在更復雜的情況下,您應該只構建一次生成器(在整個程序運行中),並根據需要多次使用它。
C ++ 11標准隨機數引擎(以及大多數其他隨機生成器)實際上是偽隨機數字序列的生成器。 偽隨機意味着序列是可重復的。 每次給定的偽隨機生成器播種相同的種子時,它將始終產生相同的序列。 (但這並不是你代碼中發生的事情。請繼續閱讀。)
在C ++ 11中,播種發生在實例化隨機數引擎時。 這意味着您需要按偽隨機序列實例化引擎一次 。 你的代碼在每次調用Network :: randDouble()方法時播放引擎的方式,都不能指望得到引擎設計產生的偽隨機序列。 相反,您將從調用system_clock :: ...或time()方法的序列中獲得一系列第一個數字。
對system_clock :: now()。time_since_epoch()。count()的調用以整數個周期返回時間。 句點指的是模板類std :: chrono :: duration的特化,它由time_since_epoch()返回。 默認情況下,該時間段可能是秒,這可以解釋為什么所有網絡對象在每次調用Network :: randDouble()時都獲得相同的種子。
如果您希望每個網絡都有不同的序列,則最好在Network類的c-tor中實例化偽隨機引擎,並為Network類的每個對象使用不同的種子播種。 這意味着引擎或引擎對象的指針應該是類的成員。
例:
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非常快,您需要特別注意確保您使用的時鍾計數實際上在兩次調用之間發生了變化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.