【问题标题】:Which seed when using `pytorch.manual_seed(seed)`?使用 `pytorch.manual_seed(seed)` 时使用哪个种子?
【发布时间】:2021-10-20 00:50:07
【问题描述】:

我已经使用 ImageNet 训练了一个模型。我有一个新的 GPU,我还想在不同的 GPU 上训练相同的模型。

我想比较结果是否不同,因此我想使用torch.manual_seed(seed)

阅读文档https://pytorch.org/docs/stable/generated/torch.manual_seed.html 后,仍不清楚我应该为参数种子取哪个数字。

如何选择种子参数?我可以服用 10、100 或 1000 甚至更多或更少吗?为什么?

【问题讨论】:

标签: python-3.x random pytorch random-seed


【解决方案1】:
如何选择种子参数?我可以服用 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 位。有时会出现行为不良的初始状态,但随机数库始终有责任以某种方式将用户提供的任意种子扩展为行为良好的初始状态。

【讨论】:

  • 我拍了2,我猜这个太少了
  • 为什么觉得它太小了?
  • 您指向的文档没有说反对将小数字作为种子偷看,并且大概您没有收到任何错误消息。其实种子是外围的东西。重要的是自动机的状态,它可以比种子大得多。常用的 Mersenne Twister 方案有 20,000 字节的内部状态,不能要求用户提供 20,000 字节。有时会出现行为不良的初始状态,但始终是随机数库的责任> 以某种方式将用户提供的种子扩展为行为良好的初始状态。
猜你喜欢
  • 2021-09-01
  • 2015-02-02
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
相关资源
最近更新 更多