План остановки дракона заставляет его восстанавливать цели, которые он уже построил ранее - PullRequest
0 голосов
/ 12 ноября 2018

В настоящее время я использую drake для запуска набора> 1k симуляций.Я подсчитал, что для запуска полного набора потребуется около двух дней, но я также ожидаю, что мой компьютер выйдет из строя в любой момент в течение этого периода, потому что, ну, в общем-то, это так.

Видимо, остановка плана отменяет любойцели, которые уже были построены, по сути, это означает, что я не могу использовать drake по прямому назначению.

Полагаю, я мог бы создать функцию, которая фактически редактирует R-файл, в котором указан план, чтобы сделатьdrake последовательно добавляет цели в свой кеш, но это кажется совершенно хакерским.

Есть идеи, как с этим справиться?

РЕДАКТИРОВАТЬ: Кажется, что настоящая проблема возникает из-за использования set.seed внутримои функции генерации данных.Я знал, что drake уже делает это для пользователя таким образом, чтобы обеспечить воспроизводимость, но я подумал, что если я просто оставлю свои функции такими, какими они были, это ничего не изменит, поскольку drake будет гарантировать, что случайныйсемя, которое я выбрал, всегда заканчивается тем же самым?Не думаю, но, поскольку я удалил этот шаг, все кешируется нормально, поэтому проблема решена.

1 Ответ

0 голосов
/ 13 ноября 2018

Чтобы привлечь внимание зрителей, я постараюсь объяснить проблему. @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.

Создано в 2018-11-12 пакетом Представление (v0.2.1)

Второй 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

Создан в 2018-11-12 пакетом Представить (v0.2.1)

Одно из решений - быть особенно осторожным, чтобы держаться за то же самое 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

Создано в 2018-11-12 пакетом представ. (v0.2.1)

Я действительно должен написать больше в руководстве о том, как семена работают в drake и выделить исходную ловушку, поднятую в этой теме. Я сомневаюсь, что вы единственный, кто боролся с этой проблемой.

...