web-dev-qa-db-ja.com

セッション全体のset.seedを修正する

私はRを使用して、モンテカルロプロセスでエージェントベースのモデルを構築しています。これは、ある種のランダムエンジンを使用する多くの関数を取得したことを意味します。再現性のある結果を得るには、シードを修正する必要があります。しかし、私が理解している限り、ランダムな描画またはサンプルの前にシードを設定する必要があります。これは首の本当の痛みです。種を固定する方法はありますか?

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
27
Elad663

正確なニーズに応じて、いくつかのオプションがあります。私は最初のオプションを疑っていますが、最も単純なものでは不十分ですが、2番目と3番目のオプションの方が適切かもしれません。3番目のオプションが最も自動化可能です。

オプション1

乱数を使用/作成する関数が常に同じ数を描画することが事前にわかっていて、関数呼び出しを並べ替えたり、既存の呼び出しの間に新しい呼び出しを挿入したりしない場合は、シードを一度設定するだけで済みます。実際、関数の呼び出しごとに同じ乱数のセットを取得し続けるだけなので、シードをリセットし続けたくないでしょう。

例えば:

> 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

オプション2

関数が同じシードを使用することを本当に確認したいが、一度だけ設定したい場合は、シードを引数として渡します。

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)

(どこ ....は、関数の他の引数を意味します。これは擬似コードです)。

オプション3

これをさらに自動化したい場合は、optionsメカニズムを悪用することができます。これは、スクリプトでこれを実行しているだけであれば問題ありません(パッケージの場合は、独自のオプションオブジェクトを使用する必要があります)。その後、関数はこのオプションを探すことができます。例えば。

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

次に、使用中:

> 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
23
Gavin Simpson

この質問には混乱があると思います。この例では、シードhasがセッション全体に設定されています。ただし、これは、実行中にprint(sample))コマンドを使用するたびに同じ数のセットが生成されることを意味するものではありません。それはランダムなプロセスに似ていません。毎回同じ3つの数字が現れることを完全に確定するからです。代わりに、実際に何が起こるかというと、シードを設定すると、スクリプトを実行するたびに同じシードを使用して、数値の疑似ランダムな選択が生成されるということです。設定したシードを使用して、再現可能なプロセスによって生成されます。

スクリプト全体を最初から再実行すると、ランダムに見えるがそうではない数値が再現されます。したがって、この例では、2回目にシードが123に設定されると、出力は再び9、10、および1になります。これは、プロセスが最初から再開されているため、期待どおりです。 print(sample(1:10,3))を書いて最初の実行を再現し続けると、2番目の出力セットは再び3、8、および4になります。

したがって、質問に対する簡単な答えは、再現可能なプロセスを作成するためにシードを設定する場合は、実行したことを実行し、シードを1回設定します。ただし、すべてのランダム描画の前にシードを設定する必要がありますnotこれにより、擬似ランダムプロセスが最初から再び開始されます。

この質問は古くなっていますが、それでも検索結果で高いので、Spacedmanの答えをさらに詳しく説明する価値があるように思われました。

13
TilmanHartley

必要なし。結果はサンプルごとに異なります(ほぼ確実に必要ですが、そうでない場合、ランダム性は非常に疑わしいです)、実行ごとの結果は同じになります。ほら、これが私のマシンからの出力です。

> set.seed(123)
> sample(1:10,3)
[1] 3 8 4
> sample(1:10,3)
[1]  9 10  1
2
Aaron

次のようなラッパー関数を実行できます。

> 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

おそらくもっとエレガントな方法があり、誰かがそれを利用するでしょう。しかし、そうでない場合、これはあなたの人生を楽にするでしょう。

2
hd1

ランダムなプロセスからalwaysが同じ結果を返すを使用する場合は、次のコマンドを使用してシードを常に設定します。

addTaskCallback(function(...) {set.seed(123);TRUE})

今度は出力は毎回同じです:

print(sample(1:10,3))
# [1] 3 8 4
print(sample(1:10,3))
# [1] 3 8 4
1
stevec

Rの各乱数ジェネレータを呼び出す前に_set.seed_することをお勧めします。モンテカルロシミュレーションでは、必要なのはreproducibilityだと思います。 forループの場合、sampleを呼び出す前にset.seed(i)を実行できます。これにより、完全に再現可能であることが保証されます。外部関数では、引数_seed=1_を指定して、forループでset.seed(i+seed)を使用できます。

0
alittleboy