【问题标题】:Can I get.seed() somehow?我能以某种方式获取.seed() 吗?
【发布时间】:2021-05-22 02:13:08
【问题描述】:

参考声明set.seed(),如果我没有明确设置,我可以在运行一些代码后获取种子吗?

我一直在重新运行一些代码(以交互方式/在控制台上),其中包含一个随机化输入数据样本的函数(该函数是 kohonen 包的一部分)。在玩了一段时间以查看输出的多样性(这是一个“不稳定”的问题)之后,我注意到一个非常有趣的结果。我当然没用过set.seed(),但是想知道运行代码复现结果后能不能拿到种子?

?set.seed我看到了

.Random.seed 保存统一随机数生成器的种子集

但我不知道这有什么帮助。

【问题讨论】:

  • 威廉邓拉普here的回答有一些相关信息。

标签: r


【解决方案1】:

这里尝试解决setSeed 函数没有逆getSeed 函数的问题。大约十二小时前,我在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)都需要在args.set 中作为省略号@987654332 列出@ for setSeed 用于将参数传递给initSeed(...) 一个使setSeedgetSeed 能够工作的内部函数。

我还编写了一个 C 标准的 rand() 函数,它传入一个 min、max、n、方法等。这就是我如何生成一个“整数”来提供setSeed 并存储在内存中。我使用Sys.time() 作为默认种子生成的最小值/最大值(min = -1*as.integer(Sys.time())max = as.integer(Sys.time()))。 sample 是个坏主意,因为它必须在范围内创建一个向量来计算单个值,但它是 rand() 的一个方法选项,它提供 initSeed。我发现默认的“high-low”比“floor”略快。

用法

### 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);

默认情况下,它将种子值存储到全局列表中名为“last”的元素中……这使您能够根据正在运行的进程跟踪不同的内存种子。在下面的示例中,我专门访问“last”和“nsim”......存储在内存中的第二个种子......

### 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);

当然,它可能有错误,如果发现任何建议或错误,我将不胜感激。

-- 2021 年 2 月 19 日,太平洋标准时间凌晨 5 点左右--

当然,传递固定种子的能力也是可以的。

setSeed(NULL, "nsim"); rnorm(5);  # randomly generated seed under the hood, but stored
setSeed(123, "z5"); rnorm(5);     # you can still fix the seed manually yourself, still stored and accessible in the list
setSeed(getSeed("nsim"), "nsim"); rnorm(5);
setSeed(getSeed("z5"), "z5"); rnorm(5);

【讨论】:

  • 如果我们可以将“数字”种子附加为rnorm 对象的属性会很好...x=rnorm(5); attributes(x)[["seed"]] = 123;
【解决方案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

【讨论】:

    【解决方案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
    }
    

    其中变量“runs”是一个正整数,表示您想要运行代码的次数。

    通过这种方式,您可以快速生成大量输出,并且每次迭代都有单独的种子以实现可重复性。

    【讨论】:

      【解决方案4】:

      Hong 的上述回答是稳健的。对于快速而肮脏的解决方案,我只是重新执行整个脚本直到我得到有趣的行为,我随机选择一个整数,将其打印出来,然后将其用作种子。如果我的特定运行有有趣的行为,我会注意到种子:

      eff_seed <- sample(1:2^15, 1)
      print(sprintf("Seed for session: %s", eff_seed))
      set.seed(eff_seed)
      

      【讨论】:

        【解决方案5】:

        如果您没有保留种子,在观察随机绘制后,没有一般的方式将随机数发生器“滚回”到以前的状态。展望未来,您可能想要做的是节省.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>
        

        【讨论】:

        • 谢谢洪。我刚刚澄清关于这个关于在控制台工作的问题的问题,但我认为你已经提供了解决方案。运行代码后,我仍然可以保存.Random.seed右? span>
        • 如何获得当前种子? span>
        • 请注意。random.seed在您的会话中使用某些随机性直到它。因此,您应该prepend if(!exists(".Random.seed")) set.seed(NULL)初始化它。 span>
        • 我想知道是否存在任何一对一的对应关系,在整数和r中随机数生成器的状态之间存在?如果有,它在我看来,r可以产生不超过2 ^ 32可能的随机数。 span>
        猜你喜欢
        • 2023-02-14
        • 1970-01-01
        • 2015-07-05
        • 1970-01-01
        • 1970-01-01
        • 2019-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多