使用该集合的原因。种子功能

在开始程序之前,我多次在R中看到set.seed函数。我知道它基本上是用来生成随机数的。有什么特殊的需要设置这个吗?

342906 次浏览

需求是对可复制结果的可能愿望,例如,这可能来自于试图调试你的程序,当然也可能来自于试图重做它所做的事情:

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

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被称为伪随机数生成器,因为它们实际上是完整的算法:给定相同的种子,你会得到相同的序列。而那是一个特性并不是一个bug。

每次你想要得到一个可重复的随机结果时,你都必须设置种子。

set.seed(1)
rnorm(4)
set.seed(1)
rnorm(4)
只是添加了一些附加方面。 需要设置种子:在学术界,如果有人声称他的算法在一次模拟中实现了98.05%的性能,那么其他人需要能够复制它
?set.seed

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

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

(2)“最初,没有种子;根据当前时间和进程ID创建一个新的进程。因此,默认情况下,不同的会话将给出不同的模拟结果。但是,如果之前保存的工作空间被恢复,那么种子可能会从以前的会话中恢复。”,这就是为什么下次需要相同的随机序列序列时,需要调用具有相同整数值的set.seed()。

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

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

当我们尝试优化一个涉及随机生成数字的函数时(例如,在基于模拟的估计中),固定种子是必不可少的。松散地说,如果我们不固定种子,由于绘制不同的随机数而产生的变化很可能导致优化算法失败。

假设,由于某种原因,你想通过模拟估计一个均值为零的正态分布的标准差(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。

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

再补充一点…如果你想要一致性,每次你做一些随机的事情时你都需要设置种子。种子不会一直凝固。

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