回答編集履歴

1 文章修正

raccy

raccy score 20900

2015/08/30 20:28  投稿

1回目の`np.random.randn(N, 2)`によって乱数がまわっているため、2回目以降は次の乱数から生成されるためです。もし、同じ値にしたい場合は、毎回`np.random.seed(0)`を実行してください。
一般的な疑似乱数生成器は回す度に異なる乱数を返します。これは、内部で以前生成した乱数から次の乱数を次々求めるようになっているからです。そして、一番最初の乱数を求めるのに使われるのがシード値というものです。`np.random.seed(0)`は、まさしくこのシード値を0にするという意味です。なので、次に乱数を求めると、必ずいつも同じ値になります。ただ、乱数を求めた後にもう一度乱数を求めた場合は、つまり、2回目の処理ではシード値を元にしていません。もう、乱数を1回求めているので、1回目の処理で求めた乱数から次の乱数を求めてしまいます。これをリセットした場合は再度シード値を設定する必要があります。疑似乱数生成器によっては処理はもうちょっと複雑な場合もあるのですが、まとめますと、
一般的な疑似乱数生成器は回す度に異なる乱数を返します。これは、内部で以前生成した乱数から次の乱数を次々求めるようになっているからです。そして、一番最初の乱数を求めるのに使われるのがシード値というものです。`np.random.seed(0)`は、まさしくこのシード値を0にするという意味です。なので、次に乱数を求めると、必ずいつも同じ値になります。ただ、乱数を求めた後にもう一度乱数を求めた場合は、つまり、2回目の処理ではシード値を元にしていません。もう、乱数を1回求めているので、1回目の処理で求めた乱数から次の乱数を求めてしまいます。これを1回目と同じにしたい場合は再度シード値を設定する必要があります。疑似乱数生成器によっては処理はもうちょっと複雑な場合もあるのですが、まとめますと、
1. 初回はシード値によって決まる。(シード値を設定しない場合にどうするかは、疑似乱数生成機によって違う)
2. 2回目以降は前に生成した乱数を元に決まる。(実際は内部の値を元にします。生成される数の精度以上に内部に情報を持っている場合もあります。例えば、メルセンヌ・ツイスタという疑似乱数生成機の実装では、2496バイトも使います。)
3. もし、シード値を再度設定した場合は、次回は1の処理を行う。(逆に言うと、シード値を設定し直さない限り、2.を繰り返します。)
となっています。
逆に言いますと、同じコードを実行した場合、2回目の`np.random.randn(N, 2)`も毎回同じになっているのが確認できると思います。シード値と乱数を回した回数から、乱数が何になるのか必ずわかるようになっています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る