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
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
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.
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
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.
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)
.