R 正在修复整个会话的set.seed
我使用R构建了一个基于代理的蒙特卡罗过程模型。这意味着我得到了许多使用某种随机引擎的函数。为了得到可重复的结果,我必须修复种子。但是,据我所知,我必须在每次随机抽签或抽样之前设定种子。这真是令人头痛。有没有办法固定种子R 正在修复整个会话的set.seed,r,montecarlo,random-sample,agent-based-modeling,R,Montecarlo,Random Sample,Agent Based Modeling,我使用R构建了一个基于代理的蒙特卡罗过程模型。这意味着我得到了许多使用某种随机引擎的函数。为了得到可重复的结果,我必须修复种子。但是,据我所知,我必须在每次随机抽签或抽样之前设定种子。这真是令人头痛。有没有办法固定种子 set.seed(123) print(sample(1:10,3)) # [1] 3 8 4 print(sample(1:10,3)) # [1] 9 10 1 set.seed(123) print(sample(1:10,3)) # [1] 3 8 4 没必要。虽然
set.seed(123)
print(sample(1:10,3))
# [1] 3 8 4
print(sample(1:10,3))
# [1] 9 10 1
set.seed(123)
print(sample(1:10,3))
# [1] 3 8 4
没必要。虽然每个样本的结果都不一样(这是您几乎肯定想要的,否则随机性是非常值得怀疑的),但每次运行的结果都是相同的。看,这是我机器的输出
> set.seed(123)
> sample(1:10,3)
[1] 3 8 4
> sample(1:10,3)
[1] 9 10 1
您可以执行包装器函数,如下所示:
> wrap.3.digit.sample <- function(x) {
+ set.seed(123)
+ return(sample(x, 3))
+ }
> wrap.3.digit.sample(c(1:10))
[1] 3 8 4
> wrap.3.digit.sample(c(1:10))
[1] 3 8 4
>wrap.3.digit.sample wrap.3.digit.sample(c(1:10))
[1] 3 8 4
>包装3.数字样品(c(1:10))
[1] 3 8 4
也许有一种更优雅的方式,我相信有人会赞同。但是,如果他们不这样做,这应该会让你的生活更轻松。我建议你在调用R中的每个随机数生成器之前设置.seed。我认为你需要的是蒙特卡罗模拟的再现性。如果在
for
循环中,您可以在调用sample
之前设置.seed(i)
,这保证了完全可复制。在外部函数中,您可以指定一个参数seed=1
,以便在for
循环中,使用set.seed(i+seed)
,根据您的具体需要,有几个选项。我怀疑第一个选项,最简单的是不够的,但我的第二个和第三个选项可能更合适,第三个选项是最自动化的
选择1
如果您事先知道使用/创建随机数的函数将始终绘制相同的数字,并且您没有对函数调用重新排序或在现有调用之间插入新调用,那么您所需要做的就是设置一次种子。实际上,您可能不想继续重置种子,因为您只需要继续为每个函数调用获取相同的随机数集
例如:
> set.seed(1)
> sample(10)
[1] 3 4 5 7 2 8 9 6 10 1
> sample(10)
[1] 3 2 6 10 5 7 8 4 1 9
>
> ## second time round
> set.seed(1)
> sample(10)
[1] 3 4 5 7 2 8 9 6 10 1
> sample(10)
[1] 3 2 6 10 5 7 8 4 1 9
选择2
如果确实要确保函数使用相同的种子,并且只想设置一次,请将种子作为参数传递:
foo <- function(...., seed) {
## set the seed
if (!missing(seed))
set.seed(seed)
## do other stuff
....
}
my.seed <- 42
bar <- foo(...., seed = my.seed)
fbar <- foo(...., seed = my.seed)
在使用中,我们有:
> getOption("myseed")
NULL
> foo()
[1] 1 2 9 4 8 7 10 6 3 5
> foo()
[1] 6 2 3 5 7 8 1 4 10 9
> options(myseed = 42)
> foo()
[1] 10 9 3 6 4 8 5 1 2 7
> foo()
[1] 10 9 3 6 4 8 5 1 2 7
> foo()
[1] 10 9 3 6 4 8 5 1 2 7
> foo()
[1] 10 9 3 6 4 8 5 1 2 7
我认为这个问题令人困惑。在本例中,已为整个会话设置种子。但是,这并不意味着每次在运行期间使用
print(sample))
命令时,它都会生成相同的一组数字;这不会像一个随机过程,因为它将完全确定每次都会出现相同的三个数字。相反,实际发生的情况是,一旦设置了种子,每次运行脚本时,都会使用相同的种子生成伪随机数字选择,也就是说,这些数字看起来似乎是随机的,但实际上是通过使用已设置种子的可复制过程生成的
如果从一开始就重新运行整个脚本,则会复制看似随机但并非随机的数字。因此,在本例中,第二次将种子设置为123时,输出再次为9、10和1,这正是您希望看到的结果,因为该过程将从头开始。如果您要通过写入print(示例(1:10,3))
继续复制第一次运行,那么第二组输出将再次为3、8和4
因此,对这个问题的简短回答是:如果你想设定一个种子来创造一个可复制的过程,那么做你已经做的事情,设定一次种子;但是,您不应该在每次随机抽取之前设置种子,因为这将从一开始就再次启动伪随机过程
这个问题很老了,但在搜索结果中仍然很重要,似乎值得在Spacedman的答案上进行扩展。如果您想始终从随机过程返回相同的结果,只需始终保留种子集:
addTaskCallback(function(...) {set.seed(123);TRUE})
现在,每次输出都是相同的:
打印(样本(1:10,3))
# [1] 3 8 4
打印(样本(1:10,3))
# [1] 3 8 4
为什么要将它们全部修复?仅仅在开始时设置一次种子,然后运行3个或多个操作还不够吗?如果您在开始时设置一次种子,并且从不触摸它,您将从计算机程序中获得可复制的结果。例如,如果希望使用随机数的代理在每次执行操作时表现相同,则可能需要在程序中设置种子。在这种情况下,让代理设定它的种子。我不认为你所说的从OP得到了重点。我认为重点是“可复制”的结果。你可以得到不同的样品,但在你的电脑里你无法控制它approach@alittleboy好吧,现在还不清楚OP需要什么。例如,如果我有一个脚本调用函数foo()
4次,并且每一次都使用10个随机数,那么我所需要做的就是在脚本开始时设置一次种子。如果运行脚本,结果是可复制的。如果您需要单独运行并独立运行,那么您需要另一种方法。你的答案是一个,非常具体,并且假设OP没有说很多。例如,我做了很多蒙特卡罗的事情,我不会按照你的方式做。所以上下文就是这里的一切。@GavinSimpson问题是长度是动态的,因为代理模型是动态的。然后,因为结构是不固定的,我可以得到相同的种子不同的结果。我认为这是你提出问题的有用信息。在这种情况下,您可能希望遵循我的答案中的选项2或3。但我不确定你真的想这么做;函数的每次调用都将使用完全相同的初始随机数集,直到动态位生效,这有关系吗?@GavinSimpson你是对的,这应该是问题的一部分。从这里的讨论中,我更加怀疑正确的实施。让我们看看我的顾问怎么说。。谢谢你
addTaskCallback(function(...) {set.seed(123);TRUE})