【问题标题】:Reasons for using the set.seed function使用 set.seed 函数的原因
【发布时间】:2012-11-16 07:34:50
【问题描述】:

在启动程序之前,我曾多次在 R 中看到 set.seed 函数。我知道它基本上用于随机数生成。有什么特别需要设置的吗?

【问题讨论】:

标签: r random


【解决方案1】:

需求是对可重现结果的可能期望,例如,这可能来自尝试调试您的程序,或者当然来自尝试重做它所做的事情:

这两个结果我们将“永远不会”重现,因为我只是要求一些“随机”的东西:

R> sample(LETTERS, 5)
[1] "K" "N" "R" "Z" "G"
R> sample(LETTERS, 5)
[1] "L" "P" "J" "E" "D"

然而,这两个是相同的因为我设置了种子

R> set.seed(42); sample(LETTERS, 5)
[1] "X" "Z" "G" "T" "O"
R> set.seed(42); sample(LETTERS, 5)
[1] "X" "Z" "G" "T" "O"
R> 

关于这一切有大量的文献;维基百科是一个好的开始。本质上,这些 RNG 被称为伪随机数生成器,因为它们实际上是完全算法:给定相同的种子,你会得到相同的序列。这是一个特性而不是一个错误。

【讨论】:

  • 感谢 Dirk,提供了这么好的例子。我已经清除了 99%,但仍有疑问。 1. 在您的回答中,您使用了 set.seed 和 42 作为参数。选择此值是否有任何相关原因?
  • 对于质量不错的普通 RNG,价值并不重要。 “42”是指名著;其他人使用他们的生日或“123”或仅使用“1”。
  • TeachingDemos 包中的char2seed 函数允许您根据字符串设置种子(或选择种子传递给set.seed)。例如,您可以让学生使用他们的姓名作为种子,然后每个学生都有一个唯一的数据集,但教师也可以创建相同的数据集进行评分。
  • 可以使用不同的种子重新运行相同的代码,直到获得“最佳”结果(我已经这样做了)。为了防止有人指责这样做,最好选择一个具有某些明显含义的种子,要么总是相同的种子,要么是日期,或者我使用char2seed 和项目主要调查员的姓氏。跨度>
  • @DirkEddelbuettel 种子值 可以 出于非计算原因,我的一个朋友在发布基于模拟的结果时遇到问题,因为代码以 set.seed(666) 开头,而审稿人不喜欢代码中的恶魔种子...
【解决方案2】:

您必须在每次想要获得可重现的随机结果时设置种子。

set.seed(1)
rnorm(4)
set.seed(1)
rnorm(4)

【讨论】:

    【解决方案3】:

    只是添加了一些附加方面。 需要设置种子:在学术界,如果有人声称他的算法在一次模拟中达到了 98.05% 的性能,那么其​​他人需要能够重现它。

    ?set.seed
    

    浏览这个函数的帮助文件,有一些有趣的事实:

    (1) set.seed() 返回 NULL,不可见

    (2) "一开始是没有种子的,需要的时候会根据当前时间和进程ID创建一个新的。因此,不同的会话默认会给出不同的模拟结果。但是,种子可能是如果先前保存的工作区已恢复,则从先前的会话中恢复。”,这就是为什么您希望在下次需要相同的随机序列时使用相同的整数值调用 set.seed()。

    【讨论】:

      【解决方案4】:

      基本上 set.seed() 函数将有助于重用相同的随机变量集,我们将来可能需要使用相同的随机变量再次评估特定任务

      我们只需要在使用任何随机数生成函数之前声明它。

      【讨论】:

        【解决方案5】:

        当我们尝试优化涉及随机生成数字的函数时(例如在基于模拟的估计中),修复种子至关重要。粗略地说,如果我们不固定种子,由于抽取不同的随机数引起的变化很可能导致优化算法失败。

        假设,由于某种原因,您想通过模拟估计给定样本的均值零正态分布的标准偏差 (sd)。这可以通过围绕步骤运行数值优化来实现

        1. (设置种子)
        2. 给定 sd 的值,生成正态分布数据
        3. 根据模拟分布评估数据的可能性

        以下函数执行此操作,一次没有步骤 1,一次包含它:

        # without fixing the seed
        simllh <- function(sd, y, Ns){
          simdist <- density(rnorm(Ns, mean = 0, sd = sd))
          llh <- sapply(y, function(x){ simdist$y[which.min((x - simdist$x)^2)] })
          return(-sum(log(llh)))
        }
        # same function with fixed seed
        simllh.fix.seed <- function(sd,y,Ns){
          set.seed(48)
          simdist <- density(rnorm(Ns,mean=0,sd=sd))
          llh <- sapply(y,function(x){simdist$y[which.min((x-simdist$x)^2)]})
          return(-sum(log(llh)))
        }
        

        我们可以通过简短的蒙特卡洛研究来检查这两个函数在发现真实参数值方面的相对性能:

        N <- 20; sd <- 2 # features of simulated data
        est1 <- rep(NA,1000); est2 <- rep(NA,1000) # initialize the estimate stores
        for (i in 1:1000) {
          as.numeric(Sys.time())-> t; set.seed((t - floor(t)) * 1e8 -> seed) # set the seed to random seed
          y <- rnorm(N, sd = sd) # generate the data
          est1[i] <- optim(1, simllh, y = y, Ns = 1000, lower = 0.01)$par
          est2[i] <- optim(1, simllh.fix.seed, y = y, Ns = 1000, lower = 0.01)$par
        }
        hist(est1)
        hist(est2)
        

        参数估计的结果分布是:

        当我们修复种子时,数值搜索最终会更频繁地接近真实参数值 2。

        【讨论】:

          【解决方案6】:

          set.seed 是一个基本函数,它能够(每次您想要)与其他函数(rnormrunifsample)一起生成相同的随机值。

          下面是一个示例没有 set.seed

          > set.seed(NULL)
          > rnorm(5)
          [1]  1.5982677 -2.2572974  2.3057461  0.5935456  0.1143519
          > rnorm(5)
          [1]  0.15135371  0.20266228  0.95084266  0.09319339 -1.11049182
          > set.seed(NULL)
          > runif(5)
          [1] 0.05697712 0.31892399 0.92547023 0.88360393 0.90015169
          > runif(5)
          [1] 0.09374559 0.64406494 0.65817582 0.30179009 0.19760375
          > set.seed(NULL)
          > sample(5)
          [1] 5 4 3 1 2
          > sample(5)
          [1] 2 1 5 4 3
          

          下面是一个使用 set.seed

          的示例
          > set.seed(123)
          > rnorm(5)
          [1] -0.56047565 -0.23017749  1.55870831  0.07050839  0.12928774
          > set.seed(123)
          > rnorm(5)
          [1] -0.56047565 -0.23017749  1.55870831  0.07050839  0.12928774
          > set.seed(123)
          > runif(5)
          [1] 0.2875775 0.7883051 0.4089769 0.8830174 0.9404673
          > set.seed(123)
          > runif(5)
          [1] 0.2875775 0.7883051 0.4089769 0.8830174 0.9404673
          > set.seed(123)
          > sample(5)
          [1] 3 2 5 4 1
          > set.seed(123)
          > sample(5)
          [1] 3 2 5 4 1
          

          【讨论】:

            【解决方案7】:

            只是进一步添加...如果您想要一致性,则每次执行一些随机操作时都需要设置种子。种子不会保持不变。

            set.seed(0)
            rnorm(3)
            set.seed(0)
            rnorm(3)
            
            [1]  1.2629543 -0.3262334  1.3297993
            [1]  1.2629543 -0.3262334  1.3297993
            
            set.seed(0)
            rnorm(3)
            rnorm(3)
            
            [1]  1.2629543 -0.3262334  1.3297993
            [1]  1.2724293  0.4146414 -1.5399500
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多