scikit-learnにてrandom_stateを指定したときの動作が何のオブジェクトを加えたかによって変わるので備忘録的にメモ。
from typing import Union, Optional
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
data = load_iris(as_frame=True)
X = data.data
y = data.target
数字で指定する場合
def test_train_test_split(
iter: int, random_state: Optional[Union[np.random.RandomState, int]]
) -> None:
X_train, X_test, y_train, y_test = train_test_split(
X, y, random_state=random_state, test_size=0.2
)
print(f"iter: {iter}")
display(y_train.to_frame().head(), y_test.to_frame().head())
for iter in range(3):
test_train_test_split(iter=iter, random_state=0)
iter: 0
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
iter: 1
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
iter: 2
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
同じ結果が得られる。
numpy.random.RandomStateで指定する場合
事前に変数として持っておくケース
rng_ = np.random.RandomState(0)
for iter in range(3):
test_train_test_split(iter=iter, random_state=rng_)
iter: 0
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
iter: 1
| target |
| 52 | 1 |
| 131 | 2 |
| 113 | 2 |
| 98 | 1 |
| 30 | 0 |
| target |
| 92 | 1 |
| 141 | 2 |
| 130 | 2 |
| 119 | 2 |
| 48 | 0 |
iter: 2
| target |
| 107 | 2 |
| 90 | 1 |
| 9 | 0 |
| 147 | 2 |
| 148 | 2 |
| target |
| 85 | 1 |
| 137 | 2 |
| 77 | 1 |
| 108 | 2 |
| 122 | 2 |
同じ結果にならない。
直接指定する場合
for iter in range(3):
test_train_test_split(iter=iter, random_state=np.random.RandomState(0))
iter: 0
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
iter: 1
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
iter: 2
| target |
| 137 | 2 |
| 84 | 1 |
| 27 | 0 |
| 127 | 2 |
| 132 | 2 |
| target |
| 114 | 2 |
| 62 | 1 |
| 33 | 0 |
| 107 | 2 |
| 7 | 0 |
数字で指定したのと同じ効果。再現できる。
考え方
上記の例だと少し複雑だが、簡単な例で書き換えると以下と同じ。
for i in range(3):
rng_ = np.random.RandomState(0)
print(rng_.rand())
0.5488135039273248
0.5488135039273248
0.5488135039273248
rng_ = np.random.RandomState(0)
for i in range(3):
print(rng_.rand())
0.5488135039273248
0.7151893663724195
0.6027633760716439