1

我目前正在drake运行一组 >1k 的模拟。我估计运行完整集大约需要两天时间,但我也预计我的计算机在此期间的任何时候都会崩溃,因为它已经崩溃了。

显然,停止该计划会丢弃任何已经构建的目标,因此本质上这意味着我不能将drake其用于其预期目的。

我想我可以创建一个函数来实际编辑指定计划的 R 文件,以便drake按顺序将目标添加到其缓存中,但这似乎完全不合时宜。

关于如何处理这个问题的任何想法?

编辑:实际问题似乎来自使用set.seed我的数据生成函数内部。我知道drake已经以确保可重复性的方式为用户执行此操作,但我认为如果我只是按照它们的方式保留函数,它不会改变任何东西,因为drake将确保我选择的随机种子总是结束一样吗?猜不出来,但是由于我删除了该步骤,因此缓存很好,因此问题得到了解决。

4

1 回答 1

2

为了让旁观者快速了解,我将尝试说明问题。@zipzapboing,如果我的描述偏离目标,请纠正我。

假设您有一个生成drake计划并执行它的脚本。

library(drake)

simulate_data <- function(seed){
  set.seed(seed)
  rnorm(100)
}

seed_grid <- data.frame(
  id = paste0("target_", 1:3),
  seed = sample.int(1e6, 3)
)

print(seed_grid)
#>         id   seed
#> 1 target_1 581687
#> 2 target_2 700363
#> 3 target_3 914982

plan <- map_plan(seed_grid, simulate_data)

print(plan)
#> # A tibble: 3 x 2
#>   target   command                      
#>   <chr>    <chr>                        
#> 1 target_1 simulate_data(seed = 581687L)
#> 2 target_2 simulate_data(seed = 700363L)
#> 3 target_3 simulate_data(seed = 914982L)

make(plan)
#> target target_1
#> target target_2
#> target target_3
make(plan)
#> All targets are already up to date.

reprex 包(v0.2.1)于 2018 年 11 月 12 日创建

第二个make()工作得很好,对吧?但是,如果您要在不同的会话中运行相同的脚本,您最终会得到不同的计划。随机生成的seed参数simulate_data()会有所不同,因此您的所有目标都将从头开始构建。

library(drake)

simulate_data <- function(seed){
  set.seed(seed)
  rnorm(100)
}

seed_grid <- data.frame(
  id = paste0("target_", 1:3),
  seed = sample.int(1e6, 3)
)

print(seed_grid)
#>         id   seed
#> 1 target_1 654304
#> 2 target_2 252208
#> 3 target_3 781158

plan <- map_plan(seed_grid, simulate_data)

print(plan)
#> # A tibble: 3 x 2
#>   target   command                      
#>   <chr>    <chr>                        
#> 1 target_1 simulate_data(seed = 654304L)
#> 2 target_2 simulate_data(seed = 252208L)
#> 3 target_3 simulate_data(seed = 781158L)

make(plan)
#> target target_1
#> target target_2
#> target target_3

reprex 包(v0.2.1)于 2018 年 11 月 12 日创建

一种解决方案是要格外小心地抓住相同的plan. 但是,还有一种更简单的方法:让我们drake为您设置种子。drake自动为每个目标提供自己的可重现随机种子。这些目标级种子由根种子( 的seed参数make())和目标名称确定性地生成。

library(digest)
library(drake)
library(magrittr) # defines %>%

simulate_data <- function(){
  mean(rnorm(100))
}

plan <- drake_plan(target = simulate_data()) %>%
  expand_plan(values = 1:3)

print(plan)
#> # A tibble: 3 x 2
#>   target   command        
#>   <chr>    <chr>          
#> 1 target_1 simulate_data()
#> 2 target_2 simulate_data()
#> 3 target_3 simulate_data()

tmp <- rnorm(1)
digest(.Random.seed) # Fingerprint of the current seed.
#> [1] "0bbddc33a4afe7cd1c1742223764661c"

make(plan)
#> target target_1
#> target target_2
#> target target_3
make(plan)
#> All targets are already up to date.

# The targets have different seeds and different values.
readd(target_1)
#> [1] -0.05530201
readd(target_2)
#> [1] 0.03698055
readd(target_3)
#> [1] 0.05990671

clean() # Destroy the targets.
tmp <- rnorm(1) # Change the global seed.
digest(.Random.seed) # The seed changed.
#> [1] "5993aa5cff4b72a0e14fa58dc5c5e3bf"

make(plan)
#> target target_1
#> target target_2
#> target target_3

# The targets were regenerated with the same values (same seeds).
readd(target_1)
#> [1] -0.05530201
readd(target_2)
#> [1] 0.03698055
readd(target_3)
#> [1] 0.05990671

# You can recover a target's seed from its metadata.
seed <- diagnose(target_1)$seed
print(seed)
#> [1] 1875584181

# And you can use that seed to reproduce
# the target's value outside make().
set.seed(seed)
mean(rnorm(100))
#> [1] -0.05530201

reprex 包(v0.2.1)于 2018 年 11 月 12 日创建

我真的应该在手册中写更多关于种子如何工作的内容,drake并强调在这个线程中提出的原始陷阱。我怀疑你是唯一一个在这个问题上苦苦挣扎的人。

于 2018-11-13T02:13:49.087 回答