Pythonでデータを学習用と検証用に分割する

機械学習用のデータをScikit-Learnを使って学習用と検証用に分割します。

目次

  1. なぜデータを分割するのか
  2. Scikit-Learnでデータを分割する
  3. Irisデータセットを分割してみる

なぜデータを分割するのか

機械学習のモデルを作る際に集めたデータはひとかたまりのデータになっています。

このデータを使って、モデルの学習を行い、さらにそのモデルがどの程度の性能があるかの検証を行います。

そこで、元のデータを学習用に使用するデータと検証用に使用するデータに分ける場合があるわけです。

Scikit-Learnでデータを分割する

Scikit-Learnにtrain_test_splitというデータ分割用の関数がありますので、これを利用してデータの分割を行います。

from sklearn.model_selection import train_test_split

ret = train_test_split(arrays, [test_size], [train_size], [random_state], [shuffle], [stratify])

変数

内容

arrays

分割されるデータ。list、ndarray、DataFrameなど。

test_size

int, float

省略可。規定値はNone。検証用データの数または割合。

train_size

int, float

省略可。規定値はNone。学習用データの数または割合。

random_state

int

省略可。規定値はNone。乱数のシード。

shuffle

bool

省略可。規定値はTrue。データをシャッフルするかどうか。

stratify

array

省略可。規定値はNone。データを抽出する基準の指定。

ret

list

分割されたデータのリスト。

arraysにDataFrameを1つ指定すると、分割されたDataFrameが2つ入ったリストが返されます。返り値を受け取る際はリストで受け取るのでは無く、それぞれのデータフレームを分けて受け取ることが多いです。また、arraysに複数のデータを指定すると、それぞれが分割されます。

train, test = train_test_split(df)
X1, y1, X2, y2 = train_test_split(df1, df2)

test_sizeとtrain_sizeでデータの分割の割合を指定します。どちらも指定しない場合は、学習用データに75%、検証用データに25%が割り振られます。

test_sizeとtrain_sizeに0.0~1.0の少数を指定した場合は、指定した割合でデータが分割されます。整数を指定した場合は、指定した個数で分割されます。

stratifyにデータを指定すると、そのデータの各要素の比率に合わせてデータが分割されます。

Irisデータセットを分割してみる

Scikit-LearnのIrisデータセットを使って、分割を試してみます。

Irisデータセットは3種類のアヤメの花の4つの特徴量(がく片の長さと幅、花びらの長さと幅)を集めたデータです。データ数は150個です。4つの特徴量から花の種類の分類をすることを想定したものです。

まず、データをダウンロードして、データ中に3種類のアヤメがどれくらいの割合で存在するのか見てみましょう。

value_counts()メソッドの使い方については、こちらを参照してください。

import pandas as pd
from sklearn.datasets import load_iris

data = load_iris()
X = pd.DataFrame(data.data, columns=data.feature_names)
Y = pd.Series(data.target)

print(X.shape)
print(Y.shape)
print(Y.value_counts())
(150, 4)

(150,)

0    50
1    50
2    50
dtype: int64

データが150個あることがわかります。また、目的変数が3種類(0, 1, 2)でそれぞれ50個ずつのデータがあることがわかります。目的変数が数値になっていますが、これはアヤメの品種名setosa、versicolor、virginicaが数値に変換されたものです。

では、検証用データの割合を30%に指定して分割してみます。

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
X = pd.DataFrame(data.data, columns=data.feature_names)
Y = pd.Series(data.target)

train_X, test_X, train_y, test_y = train_test_split(X, Y, test_size=0.3, random_state=0)

print(train_X.shape)
print(test_X.shape)
print(train_y.shape)
print(test_y.shape)
print(train_y.value_counts())
print(test_y.value_counts())
(105, 4)

(45, 4)

(105,)

(45,)

2    39
0    34
1    32
dtype: int64

1    18
0    16
2    11
dtype: int64

検証用データが30%(45/150)、学習用データが70%(105/150)に分割されました。

ただし、value_countsメソッドの結果を見ると、データが特定の品種に偏っていることがわかります。

そこで、stratifyを指定して元データと同じ割合で分割してみます。

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
X = pd.DataFrame(data.data, columns=data.feature_names)
Y = pd.Series(data.target)

train_X, test_X, train_y, test_y = train_test_split(X, Y, test_size=0.3, random_state=0, stratify=Y)

print(train_X.shape)
print(test_X.shape)
print(train_y.shape)
print(test_y.shape)
print(train_y.value_counts())
print(test_y.value_counts())
(105, 4)

(45, 4)

(105,)

(45,)

0    35
1    35
2    35
dtype: int64

0    15
1    15
2    15
dtype: int64

各品種が同じ割合で分割されました。

公開日

広告