用散列设置R的随机种子

用散列设置R的随机种子,r,random,R,Random,R提供一个函数set.seed,用一个整数为RNG设定种子。标准包摘要可以使用各种哈希算法对对象进行哈希,可以输出哈希的ASCII表示或原始字节向量,但不能生成整数。如何使用任意对象的散列来为RNG设定种子?要设置.seed的接口确实已给定,并且只接受一个整数。这是一个设计决策,也不是一个糟糕的决策:set.seed123很容易写下来,并且之后的受控行为是有保证的 如果你真的挖得更深,在倍数中还有更多的方法!!R使用的RNG。有不同的RNG,您可以在它们之间切换,即使在默认情况下,您也可以使用不

R提供一个函数set.seed,用一个整数为RNG设定种子。标准包摘要可以使用各种哈希算法对对象进行哈希,可以输出哈希的ASCII表示或原始字节向量,但不能生成整数。如何使用任意对象的散列来为RNG设定种子?

要设置.seed的接口确实已给定,并且只接受一个整数。这是一个设计决策,也不是一个糟糕的决策:set.seed123很容易写下来,并且之后的受控行为是有保证的

如果你真的挖得更深,在倍数中还有更多的方法!!R使用的RNG。有不同的RNG,您可以在它们之间切换,即使在默认情况下,您也可以使用不同的RNG进行统一绘制和普通绘制。尽管如此,播种界面还是涵盖了这两个方面

在C级,有一个更大更复杂的数据结构在起作用


现在,我的包裹。它确实对返回字符串对象的任意R对象进行操作。因此,它对set.seed没有帮助,因为这些字符不是整数。但您可以设置一个中间层,在该层中再次将这些字符串“哈希映射”为整数

简而言之,我认为你需要重新思考一下你的设计

编辑:根据请求,即使我认为这不是一种方法:

 R> c2i <- function(s) sum(as.integer(charToRaw(s)))
 R> c2i(digest(42))
 [1] 2332
 R> set.seed(c2i(digest(42)))
set.seed的接口确实是给定的,并且只接受一个整数。这是一个设计决策,也不是一个糟糕的决策:set.seed123很容易写下来,并且之后的受控行为是有保证的

如果你真的挖得更深,在倍数中还有更多的方法!!R使用的RNG。有不同的RNG,您可以在它们之间切换,即使在默认情况下,您也可以使用不同的RNG进行统一绘制和普通绘制。尽管如此,播种界面还是涵盖了这两个方面

在C级,有一个更大更复杂的数据结构在起作用


现在,我的包裹。它确实对返回字符串对象的任意R对象进行操作。因此,它对set.seed没有帮助,因为这些字符不是整数。但您可以设置一个中间层,在该层中再次将这些字符串“哈希映射”为整数

简而言之,我认为你需要重新思考一下你的设计

编辑:根据请求,即使我认为这不是一种方法:

 R> c2i <- function(s) sum(as.integer(charToRaw(s)))
 R> c2i(digest(42))
 [1] 2332
 R> set.seed(c2i(digest(42)))
看起来set.seed是播种R的RNG的唯一接口。R整数总是32位,即使在64位机器上也是如此。所以我们需要使用32位散列。digest提供了几个32位散列,但是对所有的32位散列都忽略了raw=TRUE,所以我们需要对散列的十六进制表示进行一些字符串操作。总而言之:

set.seed.obj = function(x)
   {x = as.raw(as.hexmode(substring(
        digest::digest(x, algo = "xxhash32"),
        c(1, 3, 5, 7),
        c(2, 4, 6, 8))))
    x = rawConnection(x)
    set.seed(readBin(x, "int"))
    close(x)}

set.seed.obj("hello world")
print(rnorm(3))
set.seed.obj("goodbye world")
print(rnorm(3))
set.seed.obj("hello world")
print(rnorm(3))
令人惊讶的是,对x的第一个赋值是必要的:在as.raw上调用rawConnection。。。表达式直接导致rawConnection中出现错误…:无效的“description”参数。显然,R在尝试为连接的description属性的参数创建字符串表示时崩溃。

看起来set.seed是播种R的RNG的唯一接口。R整数总是32位,即使在64位机器上也是如此。所以我们需要使用32位散列。digest提供了几个32位散列,但是对所有的32位散列都忽略了raw=TRUE,所以我们需要对散列的十六进制表示进行一些字符串操作。总而言之:

set.seed.obj = function(x)
   {x = as.raw(as.hexmode(substring(
        digest::digest(x, algo = "xxhash32"),
        c(1, 3, 5, 7),
        c(2, 4, 6, 8))))
    x = rawConnection(x)
    set.seed(readBin(x, "int"))
    close(x)}

set.seed.obj("hello world")
print(rnorm(3))
set.seed.obj("goodbye world")
print(rnorm(3))
set.seed.obj("hello world")
print(rnorm(3))

令人惊讶的是,对x的第一个赋值是必要的:在as.raw上调用rawConnection。。。表达式直接导致rawConnection中出现错误…:无效的“description”参数。显然,R在试图为连接的description属性的参数创建字符串表示形式时崩溃。

但是,例如,您可以设置一个中间层,在该层中再次将这些字符串“哈希映射”为整数。-将散列值本身解释为整数似乎更为直接。我们在兜圈子。set.seeddigestsomeObj仍然是一个错误,因为这两个函数的定义都不同,并且不会因为希望它不同而改变。我不希望set.seeddigestsomeObj调用神奇地开始工作,但例如,代码将digestsomeObj的字节,raw=T解释为整数,例如,以Python 3的struct.unpack的方式,因此,可以将结果输入set.seed.so。如果需要映射器函数,请编写映射器函数。这就是我的答案,这正是我要问的。或者对于同一目的的其他方法,例如将原始字节馈送给某个内部R函数,该函数将接受它们而不是整数。但是,例如,您可以设置一个中间层,在该层中再次将这些字符串“哈希映射”为整数。-将散列值本身解释为整数似乎更为直接。我们在兜圈子。set.seeddigestsomeObj仍然是一个错误,因为这两个函数的定义都是错误的,并且不会因为希望它不同而改变。我不希望
调用set.seeddigestsomeObj神奇地开始工作,但例如,将digestsomeObj的字节raw=T解释为整数的代码,例如,以Python 3的struct.unpack的方式,这样就可以将结果提供给set.seed。因此,如果需要映射器函数,请编写映射器函数。这就是我的答案,这正是我要问的。或者对于同一目的的其他方法,例如将原始字节馈送给某个内部R函数,该函数将接受它们而不是整数。为什么要这样做?设定种子是指能够重现RNG产生的数字。如果这不重要,那么您可以忽略设置种子,因为R将正确初始化它的RNG系统。@RalfStubner我确实想要再现性。我有一个功能,作为数据设置过程的一部分,选择交叉验证折叠,需要在各种设置中彼此独立选择,因为指定给折叠的对象集可以更改,但也需要可复制。一种干净的安排方式是,根据函数相关参数的散列或要分配给折叠的对象集,或类似的内容,为RNG种子。在这种情况下,我将尝试使用独立但可重复的随机流,用于并行计算。rngtools::RNGseq提供了一个易于使用的接口。@RalfStubner有趣。我不确定我是否理解RNGseq的文档,但看起来我必须事先知道我想要多少流,然后决定一个方案,将每个场景映射到一个流编号。知道流编号会很有帮助。使用底层的parallel::nextRNGream应该可以在没有这些知识的情况下设计类似的东西,但这会涉及更多的内容。为什么要这样做?设定种子是指能够重现RNG产生的数字。如果这不重要,那么您可以忽略设置种子,因为R将正确初始化它的RNG系统。@RalfStubner我确实想要再现性。我有一个功能,作为数据设置过程的一部分,选择交叉验证折叠,需要在各种设置中彼此独立选择,因为指定给折叠的对象集可以更改,但也需要可复制。一种干净的安排方式是,根据函数相关参数的散列或要分配给折叠的对象集,或类似的内容,为RNG种子。在这种情况下,我将尝试使用独立但可重复的随机流,用于并行计算。rngtools::RNGseq提供了一个易于使用的接口。@RalfStubner有趣。我不确定我是否理解RNGseq的文档,但看起来我必须事先知道我想要多少流,然后决定一个方案,将每个场景映射到一个流编号。知道流编号会很有帮助。在没有这些知识的情况下,应该可以使用底层的parallel::nextRNGream来设计类似的东西,但这将涉及更多内容。