train_test_splitでデータ分割を行う【sklearn】

train_test_splitでデータ分割を行う【sklearn】 機械学習

scikit-learn(sklearn)は、機械学習用ライブラリです。
でも、機械学習と言えばTensorFlowやPyTorchを使いますよね。

じゃあ、scikit-learnを使わないのでしょうか?
いやいや、TensorFlowやPyTorchと同じぐらいに使っている可能性があります。

そうです、「train_test_split」です。
機械学習では、この関数を目にすることが多いはず。

本記事の内容

  • train_test_splitとは?
  • train_test_splitの使い方
  • train_test_splitの動作確認

それでは、上記に沿って解説していきます。

train_test_splitとは?

train_test_splitは、scikit-learnに用意されている関数です。
scikit-learnに関しては、次の記事をご覧ください。

では、train_test_split関数の役割とは?
主な役割は、データを学習用(訓練用)とテスト用にデータ分割することです。

例えば、100個のデータがあったとします。
そのうちの80個をもとに学習したモデルを作ります。

そうやって出来上がったモデルが正しいかどうかを知りたくないですか?
その場合に、残りの20個をもとにテストします。

この際、一度学習したデータをテストしても意味ないですよね。
答えを覚えてしまっているから、意味がありません。

このようにして、学習で用いていないデータを利用することでモデルの精度を測定します。
だから、機械学習では学習用とテスト用のデータが必要になります。

以上より、機械学習において学習用データとテスト用データを用意することは必須と言えます。
それを用意をしてくれるのが、train_test_split関数となります。

train_test_splitが何たるかをイメージできたら、実際の関数定義を確認しましょう。

train_test_splitの使い方

scikit-learn公式サイトのtrain_test_splitページ
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

sklearn.model_selection.train_test_split(*arrays, test_size=None, train_size=None, random_state=None, shuffle=True, stratify=None)

パラメータは、以下。

  • arrays(必須)
  • test_size
  • train_size
  • random_state
  • shuffle
  • stratify

それぞれを説明していきます。

arrays

入力データです。
このデータを学習用データとテスト用データに分割します。

入力可能なデータは、以下。

  • リスト
  • Numpy配列
  • 疎行列(scipy.sparse)
  • データフレーム(pandas.DataFrame)

test_size

int型、float型の値を設定できます。
デフォルトは、Noneが設定されます。

各値の説明です。

int型

テストサンプルの絶対数を表します。
例えば、20と設定すれば20個のサンプル(データ)が選ばれます。

float型

0.0~1.0の値を設定します。
入力データサンプルの割合(比率)を表します。

例えば、入力データサンプル数を100個とします。
この場合に0.3を設定したなら、30個のサンプル(データ)が選ばれます。

None

train_sizeの補数が設定されます。

test_size + train_size = 入力サンプル数
test_size + train_size = 1.0

上記のようになるということですね。
また、train_sizeもNoneの場合は自動的に0.25が設定されます。

train_size

int型、float型の値を設定できます。
デフォルトは、Noneが設定されます。

int型

学習サンプルの絶対数を表します。
例えば、80と設定すれば80個のサンプル(データ)が選ばれます。

float型

0.0~1.0の値を設定します。
入力データサンプルの割合(比率)を表します。

例えば、入力データサンプル数を100個とします。
この場合に0.7を設定したなら、70個のサンプル(データ)が選ばれます。

None

test_sizeの補数が設定されます。

test_size + train_size = 入力サンプル数
test_size + train_size = 1.0

上記のようになるということですね。
また、test_sizeもNoneの場合は自動的に0.75が設定されます。

random_state

int型、RandomStateインスタンスを設定できます。
デフォルトは、Noneが設定されます。

基本的には、train_test_splitによるデータ分割は毎回異なります。
例えば、学習データ80個・テストデータ20個に分割するとします。

この場合、学習データ80個、テストデータ20個は毎回同じです。
そして、それぞれの中身が毎回不変だとどうなると思いますか?

何度学習させても同じ結果となります。
そんな固定したデータで学習したモデルに応用力があると思いますか?

ないでしょうね。
だからこそ、random_stateはデフォルトがNoneで毎回データの中身が異なります。

しかし、データの中身を固定したいというケースが出てくることもあります。
それは、機械学習モデルを使ったプログラムを組んでいる場合です。

例えば、機械学習の結果を利用して他の数値を算出するプログラムを開発しているとします。
その場合、毎回機械学習の結果がコロコロと変わるとプログラムを組みにくいです。

このような場合には、データの中身を固定して結果も固定したくなります。
そうしたときに、random_stateに値を設定します。

random_state=1と指定すれば、中身は常に同じモノとなります。
また、random_state=2と指定したら、random_state=1のときとは異なる値で固定されるようになります。

shuffle

TrueかFalseを指定します。
デフォルトは、Trueが設定されます。

分割前にデータをシャッフルするかどうかを指定します。
また、shuffle=Falseの場合、stratifyはNoneでなければなりません。

stratify

クラスのラベルとして使用して、データを層別に分割します。
これだけだと意味がわかりませんね。
具体例で説明します。

例えば、入力データが100個ある場合にラベル0が10個、ラベル1が90個だったとします。
そして、入力データを学習80個、テスト20個に分割します。

このとき、ラベルの比率も維持したいことがあります。
ラベル0とラベル1の比率は、1:9でした。
つまり、以下のような構成にしたい場合があるということです。

学習80個 = [ラベル0]8個 + [ラベル1]72個
テスト20個 = [ラベル0]2個 + [ラベル1]18個

このような場合に、stratifyに値を設定します。
stratifyに関しては、別記事でそれ専用にまとめようと思います。

追記 2021年1月26日
宣言通り、記事にまとめました。

train_test_splitの動作確認

公式サイトにあるサンプルを少し改良しました。

import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=2)

print(X)
print(list(y))
print("\n")

print(X_train)
print(y_train)
print("\n")

print(X_test)
print(y_test)

上記を実行すると、以下の結果となります。

[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
[0, 1, 2, 3, 4]

[[8 9]
[2 3]
[6 7]
[0 1]]
[4, 1, 3, 0]

[[4 5]]
[2]

5個あるデータを学習0.8(4個)とテスト0.2(1個)に分割しています。
random_state=2を指定しているので、同じ結果が出るはずです。

タイトルとURLをコピーしました