【问题标题】:Questions about set.seed() in R关于 R 中的 set.seed() 的问题
【发布时间】:2012-06-10 06:16:08
【问题描述】:

我了解set.seed() 的作用以及何时可以使用它,但我对该功能仍有很多疑问。以下是一些:

  1. 如果您在会话早些时候调用了set.seed(),是否可以将set.seed()“重置”为“更随机”?这还有必要吗?
  2. 是否可以查看 R 当前使用的种子?
  3. 有没有办法让set.seed() 允许字母数字种子,可以在random.org 输入它们的方式(确保您处于高级模式,请参阅表格的“第 3 部分”以了解我的意思)?

【问题讨论】:

  • 1.我认为没有必要; 2.?.Random.seed(比这复杂一点,但也许其他人会回答)
  • 阅读?RNG 以获得大部分答案

标签: r random


【解决方案1】:

只是为了好玩:

set.seed.alpha <- function(x) {
  require("digest")
  hexval <- paste0("0x",digest(x,"crc32"))
  intval <- type.convert(hexval) %% .Machine$integer.max
  set.seed(intval)
}

所以你可以这样做:

set.seed.alpha("hello world")

(实际上x可以是任何R对象,而不仅仅是字母数字字符串)

【讨论】:

  • 不错的“只是为了好玩”的答案。实际上,我想创建一个种子向量以在函数中使用。所以,假设我基于一个名为village.names 的对象创建种子,我可能会做更多类似的事情:hexval &lt;- paste0("0x", sapply(village.names, digest, "crc32")); intval &lt;- type.convert(hexval) %% .Machine$integer.max 来生成一个种子列表以传递给另一个函数。感谢您迄今为止的所有建议!
【解决方案2】:

这是可能的,如果你将种子设置为你的时间纪元的最后数字,但这真的没有必要。 PRNG 的预期用途是在会话开始时设置一次种子,并使用由此生成的连续变量。以不同的方式做事,您将无法享受 R RNG 所具有的各种良好的理论和经验特性。

但我不确定您是否真的了解 set.seed 的用途。获得“更多随机”数字并不是真的存在。如果您正在执行某种 R PRNG 不足的应用程序(例如,如果您需要加密随机性),您不妨通过某种替代方法生成所有随机数并直接使用它们。 set.seed 的真正目的是使用 RNG 生成结果的可重复性。如果您使用相同的随机数生成序列开始相同的分析,并将种子设置为相同的值,您将始终得到相同的结果。这有助于调试以及其他人查看您的结果。

要使用纪元时间,请执行以下操作

t <- as.numeric(Sys.time())
seed <- 1e8 * (t - floor(t))
set.seed(seed); print(seed)

【讨论】:

  • 我理解set.seed() 在使事物可重现等方面的目的。我在看的是,假设我做了set.seed(123); a = sample(300, 30); b = sample(300, 30),但我只对使a“可重复”感兴趣——我希望b 的结果每次都不同。对我来说,这意味着在运行ab 之间,我需要以某种方式重置种子。
  • 哦,好吧。好吧,尝试as.numeric(Sys.time())-&gt; t; set.seed((t - floor(t)) * 1e8 -&gt; seed); print(seed) 之类的方法对大多数用途都很有效。
  • Fhnuzoag 这应该是一个答案,而不是评论,IMO。
  • @JDLong,与rm(.Random.seed, envir=globalenv()) 相比,除了能够看到新的随机种子之外,Fhnuzoag 的解决方案还有什么优势吗?在我对 R 的有限使用中,我没有对globalenv() 做太多事情,所以我不太清楚我在做什么。不过,我可以理解我在用 Fhnuzoag 的解决方案做什么。我问是因为.Random.seed 的帮助文件指出它不应由用户更改,但它在其示例中建议rm(.Random.seed)....
【解决方案3】:

对于您的问题 3,TeachingDemos 包中的 char2seed 函数将采用字符串(alhpa 数字)并将其转换为整数,默认情况下使用它来设置新种子。这个想法是学生可以使用他们的名字(或一些名字的组合/子集)作为种子,这样每个学生都会得到一个不同的数据集,但是老师可以复制每个学生的数据集。

【讨论】:

  • 感谢您的建议。我没有在我的原始问题中指定它,但我需要基于字符串向量实际创建一个种子向量。您的功能似乎无法做到这一点;我对么?顺便说一句,很棒的包裹。
  • 当前版本只会生成 1 个种子,而不是向量(为上述目的而设计),有一个 [[1]] 硬编码。但可以修改(使用 sapply 代替抓取strsplit) 的结果的第一个元素来处理向量,或者简单地使用sapplymapplyVectorize 可以与char2seed 一起使用以从向量中获取向量结果输入。
【解决方案4】:

关于 2 的答案,请先查看帮助页面?RNGkind

要查找正在使用的 RNG 类型:

RNGkind()
# [1] "Mersenne-Twister" "Inversion" 

Mersenne Twister 是默认设置。

从帮助页面:

“Mersenne-Twister”:来自松本和西村(1998 年)。一种 扭曲的 GFSR 周期为 2^19937 - 1 且在 623 个连续维度(在整个期间)。这 ‘seed’ 是一个 624 维的 32 位整数集合加上一个 该集合中的当前位置。

要找到当前正在使用的种子,需要先调用随机数生成器。

runif(1, 0, 1)                                                                                                                                                  
# [1] 0.9834062                                                                                                                                                      
.Random.seed
# [Gives a 626 length vector]

调用set.seed(some_integer),然后是.Random.seed, 如果您使用相同的some_integer,将始终给出相同的 626 长度向量。换句话说,长度为 626 的向量仅由 some_integer 确定,当然前提是使用 Mersenne Twister。

当然,当然,将set.seed 运行到某个固定值将为您调用跟随它的随机数例程提供相同的值。这是它在实践中的主要用途,以提供可重复性。例如

set.seed(1)
runif(5, 0, 1)
# [1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819
rnorm(1, 0, 1)
# [1] 1.272429
set.seed(1)
runif(5, 0, 1)
# [1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819
rnorm(1, 0, 1)
# [1] 1.272429

R中的所有基本数字生成器代码都在源代码的src/main/RNG.c文件中。

它是用 C 语言编写的,但相当容易理解。

【讨论】:

    【解决方案5】:

    我遇到了与问题 1 相同的问题。然后我想我可以通过以下方式简单地在循环中重置种子:

    set.seed(123)
    x<- rnorm(10,1,1)
    set.seed(null)
    

    这样,在每个循环结束时,种子就被删除了。它对我有用。

    【讨论】:

    • 感谢您的回答。更常见/正统的方法是rm(.Random.seed, envir=globalenv()),在?.Random.seed 的帮助文件中提到了...
    • set.seed(null) 对我不起作用。有没有其他方法可以重置种子值或使其无效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2020-07-18
    • 1970-01-01
    • 2021-05-15
    • 2015-08-06
    • 2023-03-22
    相关资源
    最近更新 更多