回帰分析でStratifiedKFoldの交差検証を行う

機械学習を行う際、交差検証(Cross Validation, CV)に基づいてモデルの良し悪しを判断することが多い。

クラス分類であればStratifiedKFoldがそのまま使えるが、回帰の場合は工夫が必要になる。

以下の本を参考に、ビニング(binning)することで連続値を離散値に変換し、クラス分類であるかのようにfoldを振り分けてみた。

この本の元になった英語版の原著はオンラインで無料で読める。この記事に関係するのは26ページあたり。

https://github.com/abhishekkrthakur/approachingalmost/blob/master/AAAMLP.pdf

まずは練習用データを10000個生成。

import pandas as pd
import numpy as np
from sklearn import datasets

n_samples = 10000
_, y = datasets.make_regression(n_samples=10000, n_features=10, n_targets=1)

df = pd.DataFrame({"target":y})
df.hist()

次にビニングを行う。wikipediaによるとビニングの方法は複数通りあるようだが、本にならってスタージェスの公式を適応すると14個にビニングされた。

ヒストグラム - Wikipedia
num_bins = int(np.floor(1+np.log2(len(df))))
num_bins # 14

pandas.cutでビニングする。

pandas.cut — pandas 2.2.3 documentation
df["bins"] = pd.cut(df["target"], bins=num_bins, labels=False)
df["bins"].hist()

ちょっとヒストグラムの形が変わった。

あとはビニングした値に対してStratifiedKFoldすればOK。

from sklearn.model_selection import StratifiedKFold

df["fold"] = -1
kf = StratifiedKFold(n_splits=3, random_state=42, shuffle=True)
for i, (_, idx) in enumerate(kf.split(df, df["bins"])):
    df.loc[idx, "fold"] = i

生データに比べるとヒストグラムの形は変わってしまったが、何も考慮せずにKFoldするよりは良いCVが出来そう。

コメント

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