La fixation de jeu.des semences pour une session complète

j'utilise R pour construire un modèle basé sur les agents avec un processus de monte carlo. Cela signifie que j'ai beaucoup de fonctions qui utilisent un moteur aléatoire d'une sorte. Pour obtenir des résultats reproductibles, je dois réparer la graine. Mais, pour autant que je comprenne, je dois placer la graine avant chaque tirage au sort ou échantillon. C'est une vraie douleur dans le cou. Est-il un moyen de fixer la graine?

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
16
demandé sur A5C1D2H2I1M1N2O1R2T1 2013-12-17 06:12:04

5 réponses

il y a plusieurs options, selon vos besoins exacts. Je soupçonne la première option, la plus simple n'est pas suffisante, mais mes deuxième et troisième options peuvent être plus appropriées, avec la troisième option la plus automatisable.

Option 1

si vous savez à l'avance que la fonction utilisant / créant des nombres aléatoires va toujours dessiner le même nombre, et que vous ne réordonnez pas les appels de la fonction ou n'insérez pas un nouvel appel entre les appels existants, alors tout ce que vous avez besoin de faire est de définir la graine une fois. En effet, vous ne voulez probablement pas continuer à réinitialiser la graine car vous continuerez juste à obtenir le même ensemble de nombres aléatoires pour chaque appel de fonction.

Par exemple:

> 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

Option 2

si vous voulez vraiment vous assurer qu'une fonction utilise la même graine et que vous ne voulez la définir qu'une seule fois, passez la graine comme argument:

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)

(où .... signifie autres args à votre fonction; c'est du pseudo code).

Option 3

Si vous souhaitez automatiser ce encore plus, alors vous pourriez abus options mécanisme, ce qui est bien si vous faites ça dans un script (pour un paquet, vous devez utiliser votre propre objet d'options). Alors votre fonction peut chercher cette option. E. g.

foo <- function() {
  if (!is.null(seed <- getOption("myseed")))
    set.seed(seed)
  sample(10)
}

Puis dans l'utilisation que nous avons:

> 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
18
répondu Gavin Simpson 2013-12-17 02:38:15

je pense que cette question souffre d'une confusion. Dans l'exemple, la semence a a été fixé pour toute la session. Cependant, cela ne signifie pas qu'il produira le même ensemble de nombres à chaque fois que vous utilisez le print(sample)) commande lors d'une exécution; cela ne ressemblerait pas à un processus aléatoire, car il serait entièrement déterminé que les mêmes trois nombres apparaîtraient à chaque fois. Au lieu de cela, ce qui se passe réellement est qu'une fois que vous avez défini la graine, chaque fois que vous exécutez un script la même graine est utilisé pour produire une sélection pseudo-aléatoire de nombres, c'est-à-dire des nombres qui semblent être aléatoires mais qui sont en fait produits par un processus reproductible en utilisant la graine que vous avez définie.

si vous redirigez le script entier depuis le début, vous reproduisez ces nombres qui semblent aléatoires mais ne le sont pas. Donc, dans l'exemple, la deuxième fois que la graine est réglée à 123, la sortie est de nouveau 9, 10, et 1 ce qui est exactement ce que vous vous attendez à voir parce que le processus recommence à partir de la début. Si vous deviez continuer à reproduire votre première course en écrivant print(sample(1:10,3)), puis le deuxième ensemble de la production serait de nouveau 3, 8 et 4.

donc la réponse courte à la question Est: si vous voulez définir une graine pour créer un processus reproductible alors faites ce que vous avez fait et définissez la graine une fois; cependant, vous devriez définir la graine avant chaque tirage au sort parce que cela va recommencer le processus pseudo-aléatoire dès le début.

cette question Est ancien, mais vient toujours haut dans les résultats de recherche, et il a semblé intéressant d'étendre la réponse de Spacedman.

10
répondu TilmanHartley 2017-01-05 16:13:33

Pas besoin. Bien que les résultats soient différents d'un échantillon à l'autre (ce que vous voulez presque certainement, sinon le caractère aléatoire est très discutable), les résultats de l'exécution à l'exécution seront les mêmes. Voici la sortie de ma machine.

> set.seed(123)
> sample(1:10,3)
[1] 3 8 4
> sample(1:10,3)
[1]  9 10  1
2
répondu Aaron 2013-12-17 02:21:55

Tu pourrais faire une fonction wrapper, comme suit:

> 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

Il y a probablement une façon plus élégante, et je suis sûr que quelqu'un va suivre. Mais s'ils ne le font pas, ça devrait te faciliter la vie.

1
répondu hd1 2013-12-17 02:22:45

je suggère que vous set.seed avant d'appeler chaque générateur de nombres aléatoires en R. je pense que ce dont vous avez besoin est reproductibilité pour les simulations de Monte Carlo. Si dans un for boucle, vous pouvez set.seed(i) avant d'appeler sample, qui garantit une reproductibilité totale. Dans votre fonction externe, vous pouvez spécifier un argument seed=1 de sorte que dans le for boucle, vous utilisez set.seed(i+seed).

0
répondu alittleboy 2013-12-17 02:29:29