Raisons de l'utilisation de la fonction set.seed

185

Plusieurs fois, j'ai vu la set.seedfonction dans R, avant de démarrer le programme. Je sais qu'il est essentiellement utilisé pour la génération de nombres aléatoires. Y a-t-il un besoin spécifique de définir cela?

Vignesh
la source

Réponses:

264

Le besoin est le désir éventuel de résultats reproductibles, qui peuvent par exemple venir d'essayer de déboguer votre programme, ou bien sûr d'essayer de refaire ce qu'il fait:

Nous ne reproduirons "jamais" ces deux résultats car je viens de demander quelque chose de "aléatoire":

R> sample(LETTERS, 5)
[1] "K" "N" "R" "Z" "G"
R> sample(LETTERS, 5)
[1] "L" "P" "J" "E" "D"

Ces deux, cependant, sont identiques car j'ai mis la graine :

R> set.seed(42); sample(LETTERS, 5)
[1] "X" "Z" "G" "T" "O"
R> set.seed(42); sample(LETTERS, 5)
[1] "X" "Z" "G" "T" "O"
R> 

Il existe une vaste littérature sur tout cela; Wikipedia est un bon début. En substance, ces RNG sont appelés générateurs de nombres pseudo-aléatoires car ils sont en fait entièrement algorithmiques : avec la même graine, vous obtenez la même séquence. Et c'est une fonctionnalité et non un bug.

Dirk Eddelbuettel
la source
5
Merci Dirk, pour un si bel exemple .. Je l'ai effacé avec 99%, mais toujours question. 1. Dans votre réponse, vous avez utilisé set.seed avec 42 comme argument .. y a-t-il une raison connexe de choisir cette valeur?
Vignesh
43
Pour un RNG normal de qualité décente, la valeur n'a pas d'importance. "42" est une référence à un livre célèbre; d'autres personnes utilisent leur anniversaire ou "123" ou simplement "1".
Dirk Eddelbuettel
7
La char2seedfonction du package TeachingDemos vous permet de définir la valeur de départ (ou de choisir une valeur de départ dans laquelle passer set.seed) en fonction d'une chaîne de caractères. Par exemple, vous pouvez demander aux élèves d'utiliser leur nom comme germe, puis chaque élève dispose d'un ensemble de données unique, mais l'instructeur peut également créer les mêmes ensembles de données pour la notation.
Greg Snow
8
Il est possible de réexécuter le même code avec des graines différentes jusqu'à ce que vous obteniez le "meilleur" résultat (je l'ai fait pour des exemples). Pour se prémunir contre les accusations de faire cela, il est préférable de choisir une graine qui a une signification évidente, soit toujours la même graine, soit la date, soit j'utilise char2seedet le nom de famille du chercheur principal sur un projet.
Greg Snow
5
La valeur de départ de @DirkEddelbuettel peut avoir de l' importance pour des raisons non informatiques, un de mes amis a eu des problèmes avec la publication de ses résultats basés sur la simulation parce que le code a commencé set.seed(666)et que les critiques n'aimaient pas la graine de Devils dans le code ...
Tim
33

Vous devez définir des semences à chaque fois que vous souhaitez obtenir un résultat aléatoire reproductible.

set.seed(1)
rnorm(4)
set.seed(1)
rnorm(4)
Chia-hung
la source
17

Juste en ajoutant quelques aspects supplémentaires. Besoin de semer: dans le monde académique, si l'on prétend que son algorithme atteint, disons, 98,05% de performances dans une simulation, d'autres doivent pouvoir le reproduire.

?set.seed

En parcourant le fichier d'aide de cette fonction, voici quelques faits intéressants:

(1) set.seed () renvoie NULL, invisible

(2) "Au départ, il n'y a pas de valeur de départ; une nouvelle valeur est créée à partir de l'heure actuelle et de l'ID de processus, le cas échéant. Par conséquent, différentes sessions donneront des résultats de simulation différents, par défaut. Cependant, la valeur de départ peut être restaurée à partir d'un session précédente si un espace de travail précédemment enregistré est restauré. ", c'est pourquoi vous voudrez appeler set.seed () avec les mêmes valeurs entières la prochaine fois que vous voudrez une même séquence de séquence aléatoire.

Équitation
la source
7

La fixation de la graine est essentielle lorsque nous essayons d'optimiser une fonction qui implique des nombres générés aléatoirement (par exemple dans l'estimation basée sur la simulation). En gros, si nous ne corrigeons pas la graine, la variation due au dessin de nombres aléatoires différents entraînera probablement l'échec de l'algorithme d'optimisation.

Supposons que, pour une raison quelconque, vous souhaitiez estimer l'écart type (sd) d'une distribution normale moyenne nulle par simulation, à partir d'un échantillon. Ceci peut être réalisé en exécutant une optimisation numérique autour des étapes

  1. (Mettre la graine)
  2. Étant donné une valeur pour sd, générer des données normalement distribuées
  3. Évaluez la probabilité de vos données compte tenu des distributions simulées

Les fonctions suivantes le font, une fois sans l'étape 1., une fois en l'incluant:

# without fixing the seed
simllh <- function(sd, y, Ns){
  simdist <- density(rnorm(Ns, mean = 0, sd = sd))
  llh <- sapply(y, function(x){ simdist$y[which.min((x - simdist$x)^2)] })
  return(-sum(log(llh)))
}
# same function with fixed seed
simllh.fix.seed <- function(sd,y,Ns){
  set.seed(48)
  simdist <- density(rnorm(Ns,mean=0,sd=sd))
  llh <- sapply(y,function(x){simdist$y[which.min((x-simdist$x)^2)]})
  return(-sum(log(llh)))
}

Nous pouvons vérifier la performance relative des deux fonctions en découvrant la vraie valeur du paramètre avec une courte étude de Monte Carlo:

N <- 20; sd <- 2 # features of simulated data
est1 <- rep(NA,1000); est2 <- rep(NA,1000) # initialize the estimate stores
for (i in 1:1000) {
  as.numeric(Sys.time())-> t; set.seed((t - floor(t)) * 1e8 -> seed) # set the seed to random seed
  y <- rnorm(N, sd = sd) # generate the data
  est1[i] <- optim(1, simllh, y = y, Ns = 1000, lower = 0.01)$par
  est2[i] <- optim(1, simllh.fix.seed, y = y, Ns = 1000, lower = 0.01)$par
}
hist(est1)
hist(est2)

Les distributions résultantes des estimations des paramètres sont:

Histogramme des estimations de paramètres sans fixer la graine Histogramme des estimations de paramètres fixant la graine

Lorsque nous corrigeons la graine, la recherche numérique se termine beaucoup plus souvent près de la valeur réelle du paramètre 2.

Matthias Schmidtblaicher
la source
6

fondamentalement, la fonction set.seed () aidera à réutiliser le même ensemble de variables aléatoires, dont nous pourrions avoir besoin à l'avenir pour évaluer à nouveau une tâche particulière avec les mêmes variables aléatoires

nous avons juste besoin de le déclarer avant d'utiliser une fonction de génération de nombres aléatoires.

user4388407
la source
élaborer la réponse
Spry Techies