如何选择种子参数?我可以服用 10、100 或 1000 甚至更多或更少吗?为什么?
您指向的 PyTorch 文档页面除了说明种子是 64 位整数之外没有提及任何特殊内容。
所以是的,1000 是可以的。正如您对现代伪随机数生成器所期望的那样,您所依赖的伪随机序列的统计属性确实不取决于种子的选择。
对于大多数运行,您可能会重复使用上一次运行的种子,实际的做法是将随机种子作为命令行参数。在那些你必须想出一个全新的种子的情况下,你可以从头顶偷看一个,或者只是玩骰子来得到它。
重要的是要有一个每次运行所用种子的记录。
好的,但是...
话虽如此,很多人似乎对“猜测”某个任意数字的任务感到不舒服。有(至少)两种常见的权宜之计可以以看似适当的“随机”方式获得一些种子。
第一个是使用操作系统官方源来获取真正的(非伪)随机位。在 Python 中,这通常呈现为 os.urandom()。因此,要在 Python 中将种子作为 64 位整数,您可以使用如下代码:
import functools
import os
# returns a list of 8 random small integers between 0 and 255
def get8RandomBytesFromOS():
r8 = os.urandom(8) # official OS entropy source
byteCodes = list(map(ord, r8.decode('Latin-1'))) # type conversion
return byteCodes
# make a single long integer from a list of 8 integers between 0 and 255
def getIntFromBytes(bs):
# force highest bit to 0 to avoid overflow
bs2 = [bs[0] if (bs[0] < 128) else (bs[0]-128)] + bs[1:8]
num = functools.reduce(lambda acc,n: acc*256+n, bs2)
return num
# Main user entry point:
def getRandomSeedFromOS():
rbs8 = get8RandomBytesFromOS()
return (getIntFromBytes(rbs8))
第二个常见的权宜之计是散列一个包含当前日期和时间的字符串,可能带有一些前缀。使用 Python,时间包括微秒。当人类用户启动脚本时,启动时间的微秒数可以说是随机。可以使用这样的代码,使用一种 SHA(安全哈希算法):
import hashlib
import datetime
def getRandomSeedFromTime():
prefix = 'dl.cs.univ-stackoverflow.edu'
timeString1 = str(datetime.datetime.now())
timeString2 = prefix + ' ' + timeString1
hash = hashlib.sha256(timeString2.encode('ascii'))
bytes = (hash.digest())[24:32] # 8 rightmost bytes of hash
byteCodes = list(map(ord, bytes.decode('Latin-1'))) # type conversion
return (getIntFromBytes(byteCodes))
但是,1000 基本上是可以的。散列时间字符串的想法,而不是仅仅将自 Epoch 以来的微秒数作为种子,可能来自于一些早期随机数生成器使用它们的种子作为偏移量的事实 变成一个普通的、不是那么大的全局序列。因此,如果您的程序天真地在没有散列的情况下以快速序列获取两个种子,那么您的两个序列之间存在重叠的风险。幸运的是,现在的伪随机数生成器比以前要好得多。
(附录 - 取自评论)
请注意,种子是外围的东西。重要的是自动机的状态,它可以比种子大得多,因此就是“种子”这个词。常用的Mersenne Twister 方案有大约 20,000 位的内部状态,您不能要求用户提供 20,000 位。有时会出现行为不良的初始状态,但随机数库始终有责任以某种方式将用户提供的任意种子扩展为行为良好的初始状态。