C++-default_random_engine 始终创建相同的数字序列
c++-default_random_engine creates all the time same series of numbers
我正在使用神经网络,我想随机创建权重。因此,如果我创建 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;
}
}
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 当套接字连接断开时检测C/C++Unix
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 我怎么不能按课程代码的降序对数字进行排序
- 如何安全地将有符号字段从uint32_t提取到有符号数字(int或uint32_t)中
- 如何检查字段中输入的数字是否重复
- 在编译时根据字节序定义位字段
- 查找升序列表中降序的第一个和最后一个数字
- 用户定义字面值如何与数字分隔符一起使用
- 我将ASCII字转换成数字,但我一直试图解码它们.如何转换1=a, 2=b, 28=ab等?(psudeocode好)
- 一个数字和字段宽度的格式化输出,C++标准在哪里说明它
- linux/freebsd中的套接字描述符是否保证具有几乎连续的或可比较的数字?
- 概率以数字降序递增
- 使用constexpr将数字转换为字符串字面值