結論から
np.randomは広範囲に影響があるので、RandomStateを使いましょう。
はじめに
hoge君が以下のようなコードを作りました。
import numpy as np
np.random.seed(1234)
# 処理Aのブロック
for i in range(1,5):
arr1 = np.random.randint(1,10,10)
#------------------------------------
# ...(略:arr1を使った具体的な処理)...
#------------------------------------
後日、hoge君は処理Aの前に処理Bを実装する必要が出てきました。
import numpy as np
np.random.seed(1234)
# 処理B
arr2 = np.random.randint(1,10,10)
#------------------------------------
# ...(略:arr2を使った具体的な処理)...
#------------------------------------
# 処理Aのブロック
for i in range(1,5):
arr = np.random.randint(1,10,10)
print(aaa)
#------------------------------------
# ...(略:arr1を使った具体的な処理)...
#------------------------------------
A君「ああ、まずい。これでは処理Aの結果が以前と変わってしまう。。。」
A君「あ!でももう一度シード設定すればいっか」(安易)
import numpy as np
# 処理B
np.random.seed(2345) # 一応別のシードにした
arr2 = np.random.randint(1,10,10)
#------------------------------------
# ...(略:arr2を使った具体的な処理)...
#------------------------------------
# 処理Aのブロック
np.random.seed(1234) # こっちはさっきと同じシード
for i in range(1,5):
arr = np.random.randint(1,10,10)
print(aaa)
#------------------------------------
# ...(略:arr1を使った具体的な処理)...
#------------------------------------
A君「これで一安心~」
数日後
先輩「この前作ってもらった処理、ユーザー毎にマルチスレッドで処理したいんだよね」
A君「」
結論
要はnp.random.seed()はグローバルにいろんな範囲に影響あるからやめようねって話です。
一人での開発ならばなんとか管理できるかもしれないけど、複数人の開発や
並列処理や関数化・クラス化などの実装を進めると、どこで再現性が取れなくなっているか追えなくなります。
RandomStateを使えば、ほかの処理に影響を与えずに乱数生成ができる。
import numpy as np
# 処理B
rs2 = np.random.RandomState(2345)
arr2 = rs2.randint(1,10,10)
# ...(略:具体的な処理)...
# 処理Aのブロック
rs1 = np.random.RandomState(1234)
for i in range(1,5):
arr = rs1.randint(1,10,10)
print(aaa)
# ...(略:具体的な処理)...
補足
ちなみに以下は同じ乱数列を返します。
グローバルなseed=1234と、RandomStateのseed=1234は同じ乱数を生成する。
import numpy as np
np.random.seed(1234)
print(np.random.randint(1,10,10))
rs = np.random.RandomState(1234)
print(rs.randint(1,10,10))