我注意到您可以在numpy.random.seed()
内添加各种数字,例如numpy.random.seed(1)
,numpy.random.seed(101)
。不同的数字是什么意思?你如何选择数字?
答案 0 :(得分:9)
考虑一个非常基本的随机数生成器:
Z[i] = (a*Z[i-1] + c) % m
此处,Z[i]
是ith
随机数,a
是乘数,c
是增量 - 对于不同的a
,{{1} }和c
组合你有不同的生成器。这被称为Lehmer引入的linear congruential generator。该除法的余数或模数(m
)将生成0到%
之间的数字,通过设置m-1
,您可以获得0到1之间的随机数。
您可能已经注意到,为了开始这个生成过程 - 为了获得U[i] = Z[i] / m
,您需要Z[1]
- 初始值。启动该过程的初始值称为种子。看一下这个例子:
初始值,种子被确定为7以开始该过程。但是,该值不用于生成随机数。相反,它用于生成第一个Z[0]
。
伪随机数发生器最重要的特征是它的不可预测性。一般来说,只要你不分享你的种子,你对所有种子都没问题,因为今天的发电机比这复杂得多。但是,作为进一步的步骤,您也可以随机生成种子。您可以跳过第一个Z
号码作为另一种选择。
主要来源:Law,A。M.(2007)。仿真建模和分析。 Tata McGraw-Hill。
答案 1 :(得分:4)
实际上通常称为随机数序列的是“伪随机”数字序列,因为这些值是使用确定性算法计算的,并且概率不起作用。
“种子”是序列的起点,保证如果从同一种子开始,您将得到相同的数字序列。这对于调试非常有用(当您在程序中查找错误时需要能够重现问题并对其进行研究时,非确定性程序将难以调试,因为每次运行都会有所不同)
答案 2 :(得分:2)
答案简短:
seed()
中有numpy.random
随机数生成器的方法有三种:
不使用参数或使用None
- RNG从操作系统的随机数生成器(通常是加密随机)初始化自己
使用一些32位整数N - RNG将使用它来基于确定性函数(相同种子→相同状态)初始化其状态
使用类似于32位整数的数组序列n 0 ,n 1 ,n 2 等 - - 再次,RNG将使用它来基于确定性函数初始化其状态(种子→相同状态的相同值)。这是为了使用各种哈希函数来完成,虽然源代码中有魔术数字,并且不清楚为什么他们正在做他们正在做的事情。
如果您想要做一些可重复且简单的事情,请使用单个整数。
如果你想做一些可重复但不太可能让第三方猜测的东西,可以使用元组或列表或包含一些32位整数序列的numpy数组。例如,您可以使用numpy.random
种子None
从OS的RNG生成一堆32位整数(例如,其中32个,这将生成总共1024位) ,存储在一些保存在某个秘密位置的种子S
中,然后使用该种子生成您希望的任何序列R的伪随机数。然后,您可以稍后通过再次使用S
重新播种来重新创建该序列,并且只要保持S
的值为秘密(以及生成的数字R),就没有人能够重现那个序列R.如果你只使用一个整数,那么只有40亿种可能性,有人可能会尝试所有这些。这可能是偏执狂方面的一点,但你可以做到。
更长的答案
numpy.random
模块使用Mersenne Twister算法,您可以通过以下两种方式之一确认自己:
通过查看numpy.random.RandomState
的文档,numpy.random
使用numpy.random.*
函数的实例(但您也可以使用隔离的独立实例)< / p>
查看source code中的mtrand.pyx,它使用名为Pyrex的内容来包装快速C实现,以及randomkit.c和initarray.c。
< / LI>无论如何,这是numpy.random.RandomState
文档中关于seed()
所说的内容:
兼容性保证使用相同参数的固定种子和对
RandomState
方法的固定系列调用将始终产生相同的结果,直到舍入误差,除非值不正确。将修复不正确的值,并在相关文档字符串中记录进行修复的NumPy版本。只要先前的行为保持不变,就允许扩展现有参数范围并添加新参数。<强>参数:
种子 :{None,int,array_like},可选用于初始化伪随机数生成器的随机种子。可以是0到2 ** 32 - 1之间的任何整数,这种整数的数组(或其他序列),或
None
(默认值)。如果种子是None
,那么RandomState将尝试从/dev/urandom
(或Windows模拟)中读取数据(如果可用),否则将从时钟读取种子。
没有说明如何使用种子,但是如果你深入研究源代码,它就会引用init_by_array
函数:( docstring elided)
def seed(self, seed=None):
cdef rk_error errcode
cdef ndarray obj "arrayObject_obj"
try:
if seed is None:
with self.lock:
errcode = rk_randomseed(self.internal_state)
else:
idx = operator.index(seed)
if idx > int(2**32 - 1) or idx < 0:
raise ValueError("Seed must be between 0 and 2**32 - 1")
with self.lock:
rk_seed(idx, self.internal_state)
except TypeError:
obj = np.asarray(seed).astype(np.int64, casting='safe')
if ((obj > int(2**32 - 1)) | (obj < 0)).any():
raise ValueError("Seed must be between 0 and 2**32 - 1")
obj = obj.astype('L', casting='unsafe')
with self.lock:
init_by_array(self.internal_state, <unsigned long *>PyArray_DATA(obj),
PyArray_DIM(obj, 0))
以下是init_by_array
函数的样子:
extern void
init_by_array(rk_state *self, unsigned long init_key[], npy_intp key_length)
{
/* was signed in the original code. RDH 12/16/2002 */
npy_intp i = 1;
npy_intp j = 0;
unsigned long *mt = self->key;
npy_intp k;
init_genrand(self, 19650218UL);
k = (RK_STATE_LEN > key_length ? RK_STATE_LEN : key_length);
for (; k; k--) {
/* non linear */
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL))
+ init_key[j] + j;
/* for > 32 bit machines */
mt[i] &= 0xffffffffUL;
i++;
j++;
if (i >= RK_STATE_LEN) {
mt[0] = mt[RK_STATE_LEN - 1];
i = 1;
}
if (j >= key_length) {
j = 0;
}
}
for (k = RK_STATE_LEN - 1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i >= RK_STATE_LEN) {
mt[0] = mt[RK_STATE_LEN - 1];
i = 1;
}
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
self->gauss = 0;
self->has_gauss = 0;
self->has_binomial = 0;
}
这基本上使用提供的种子值序列中的每个值,以非线性类似哈希的方法“随机”使用随机数状态。
答案 3 :(得分:0)
基本上,这个数字每次都保证了相同的“随机性”。
更准确地说,数字是种子,可以是整数,任何长度的整数数组(或其他序列),或默认值(无)。如果seed为none,则random将尝试从/ dev / urandom读取数据(如果可用),否则从时钟生成种子。
编辑:在最诚实的情况下,只要您的程序不是需要超级安全的东西,那么您选择的内容应该无关紧要。如果是这种情况,请不要使用这些方法 - 如果您需要加密安全的伪随机数生成器,请使用os.urandom()
或SystemRandom
。
这里要理解的最重要的概念是伪随机性。一旦理解了这个想法,就可以确定你的程序是否真的需要种子等。我建议你阅读here。
答案 4 :(得分:0)
要理解随机种子的含义,你需要先了解&#34;伪随机&#34;数字序列,因为这些值是使用确定性算法计算的。
因此,您可以将此数字视为起始值来计算从随机生成器获得的下一个数字。在此处设置相同的值将使您的程序变得相同&#34;随机&#34;每次都有价值,所以你的程序变得具有确定性。
正如本post
所述他们(
numpy.random
和random.random
)都使用梅森捻线序列来生成随机数,并且它们都是完全确定性的 - 也就是说,如果您知道几个关键位信息,可以绝对肯定地预测接下来会有多少数字。
如果您真的关心随机性,请让用户产生一些噪音(一些仲裁词)或者只是将系统时间作为种子。
如果您的代码在Intel CPU(或具有最新芯片的AMD)上运行,我还建议您检查使用cpu指令rdrand
的{{3}}包以收集&#34; true&#34; (硬件)随机性。
参考文献:
答案 5 :(得分:0)
一个非常具体的答案:TypeWrappedSerializer
可以从np.random.seed
取值,而有趣的是与0 and 2**32 - 1
可以取任何可哈希对象的值。