参考语句set.seed()
,如果我没有明确地设置代码,我可以在运行一些代码后获取种子吗?
我一直在重新运行一些代码(交互式地/在控制台上),其中包含一个随机化输入数据样本的函数(该函数是kohonen
包的一部分)。在玩了一段时间后看到各种输出(这是一个'不稳定'的问题),我注意到一个非常有趣的结果。我当然没有使用set.seed()
,但想知道在运行代码后我是否可以获得种子以重现结果?
在?set.seed
我看到了
.Random.seed保存统一随机数生成器的种子集
但我不知道这有多大帮助。
答案 0 :(得分:30)
如果你没有保留种子,那么在观察随机抽取后,没有通用的方法可以将随机数发生器“回滚”到之前的状态。展望未来,您可能想要做的是保存.Random.seed
的值以及计算结果。这样的事情。
x <- .Random.seed
result <- <your code goes here>
attr(result, "seed") <- x
然后您可以按如下方式重置PRNG; result2
应与result
相同。
.Random.seed <- attr(result, "seed")
result2 <- <your code goes here>
答案 1 :(得分:3)
要添加答案mpettis,如果您不想手动重新执行脚本 - 每次迭代生成新的随机种子 - 您可以执行以下操作:
# generate vector of seeds
eff_seeds <- sample(1:2^15, runs)
# perform 'runs' number of executions of your code
for(i in 1:runs) {
print(sprintf("Seed for this run: %s", eff_seeds[i]))
set.seed(eff_seeds[i])
# your code here
# don't forget to save your outputs somehow
}
变量&#39;运行&#39;是一个正整数,表示您希望运行代码的次数。
通过这种方式,您可以快速生成大量输出,并为每次迭代生成单独的种子,以实现可重复性。
答案 2 :(得分:2)
Hong的回答是强有力的。对于快速和脏的解决方案,我只是重新执行整个脚本,直到我得到有趣的行为,我随机选择一个整数,打印出来,然后将其用作种子。如果我的特定行为有趣,我注意到种子:
eff_seed <- sample(1:2^15, 1)
print(sprintf("Seed for session: %s", eff_seed))
set.seed(eff_seed)
答案 3 :(得分:2)
> rnorm(5)
[1] -0.17220331 -0.31506128 -0.35264299 0.07259645 -0.15518961
> Seed<-.Random.seed
> rnorm(5)
[1] -0.64965000 0.04787513 -0.14967549 0.12026774 -0.10934254
> set.seed(1234)
> rnorm(5)
[1] -1.2070657 0.2774292 1.0844412 -2.3456977 0.4291247
> .Random.seed<-Seed
> rnorm(5)
[1] -0.64965000 0.04787513 -0.14967549 0.12026774 -0.10934254
答案 4 :(得分:0)
这里尝试解决 getSeed
函数没有反 setSeed
函数的问题。大约十二小时前,我在 Using R, how to get.seed()? 上发布了一个类似的问题,该问题已被关闭,因为它被归类为“重复”......
我用需要全局变量 .random.seed.memory
的种子内存“破解”了一个解决方案。
utils::globalVariables(c(".random.seed.memory"));
时间很重要,因为我必须使用 set.seed
github.monte = "https://raw.githubusercontent.com/MonteShaffer/";
include.me = paste0(github.monte, "humanVerse/main/humanVerse/R/functions-str.R");
source(include.me); # trimMe function
include.me = paste0(github.monte, "humanVerse/main/humanVerse/R/functions-random.R");
source(include.me); # getSeed, setSeed, and so on.
函数 setSeed
的行为通常与 set.seed
类似,但任何传递给 set.seed
的自定义参数超出整数(kind、normal.kind、sample.kind)都需要在 {{ 1}} 作为 args.set
的省略号 ...
用于将参数传递给 setSeed
一个内部函数,该函数使 initSeed(...)
和 setSeed
能够工作。
我还编写了一个 C 标准 getSeed
函数,该函数传入 min、max、n、方法等。这就是我生成一个“整数”来提供 rand()
并存储在内存中的方式。我使用 setSeed
作为默认种子生成的最小值/最大值(Sys.time()
和 min = -1*as.integer(Sys.time())
)。 max = as.integer(Sys.time())
是一个坏主意,因为它必须在范围内创建一个向量来计算单个值,但它是 sample
的方法选项,它提供 rand()
。我发现默认的“high-low”比“floor”稍快。
initSeed
默认情况下,它将种子值存储到名为“last”的全局列表中的一个元素中......这使您能够根据正在运行的进程跟踪不同的内存种子。在下面的示例中,我专门访问“last”和“nsim”……存储在内存中的第二个种子……
### VERBOSITY is HIGH AT THE MOMENT ###
print("random 5"); rnorm(5);
setSeed(NULL); # this will automatically call initSeedMemory() if necessary
setSeed(.random.seed.memory$last); rnorm(5);
setSeed(getSeed()); rnorm(5);
print("random 5"); rnorm(5);
setSeed(getSeed()); rnorm(5);
当然,它可能有错误,如果发现任何建议或错误,我将不胜感激。
-- 2021 年 2 月 19 日太平洋标准时间凌晨 5 点左右 --
当然,传入固定种子的能力也是可以的。
### VERBOSITY is HIGH AT THE MOMENT ###
initSeedMemory( purge.memory = TRUE);
setSeed(NULL);
setSeed(.random.seed.memory$last); rnorm(5);
setSeed(getSeed()); rnorm(5);
getSeed(); # accessor to .random.seed.memory
.random.seed.memory;
print("random 5"); rnorm(5);
setSeed(NULL, key="nsim"); rnorm(5);
setSeed(.random.seed.memory$nsim, key="nsim"); rnorm(5);
setSeed(getSeed("nsim"), key="nsim"); rnorm(5);
getSeed("nsim"); # accessor to .random.seed.memory
.random.seed.memory;
print("random 5"); rnorm(5);
setSeed(.random.seed.memory$last); rnorm(5);
setSeed(getSeed()); rnorm(5);
.random.seed.memory;
set.seed(.random.seed.memory$last); rnorm(5);
set.seed(.random.seed.memory$nsim); rnorm(5);
.random.seed.memory;
print("random 5"); rnorm(5);