common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Terms of service

Privacy policy

Contact
Research

Sign in
Sign up
common.title

Kaggleのイントロを見る。機械学習中級編。。。パイプラインとクロスバリデーション

Yuichiro Minato

2023/10/14 08:27

ほぼコピペですが、頑張ります。

https://www.kaggle.com/code/alexisbcook/pipelines

導入

パイプラインは、データ前処理とモデリングコードを整理するシンプルな方法です。具体的には、パイプラインは前処理とモデリングのステップを束ねて、1つのステップであるかのように全体を使用できるようにします。

多くのデータサイエンティストはパイプラインなしでモデルを組み立てますが、パイプラインにはいくつかの重要な利点があります。それらには以下のようなものがあります:

クリーナーコード:前処理の各ステップでデータを考慮するのは煩雑になることがあります。パイプラインがあれば、各ステップで手動でトレーニングデータと検証データを追跡する必要はありません。

バグが少ない:ステップを誤って適用するか、前処理のステップを忘れる機会が少なくなります。

プロダクション化が容易:モデルをプロトタイプから大規模に展開可能なものに移行するのは意外と難しいことがあります。ここでは多くの関連する懸念について詳しく説明しませんが、パイプラインは役立ちます。

モデル検証のオプションが増える:次のチュートリアルでクロスバリデーションをカバーしているので、例を見ることができます。

前回のチュートリアルと同様に、Melbourne Housingデータセットを使用します。

データの読み込みステップに焦点を当てることはありません。代わりに、すでにX_train、X_valid、y_train、およびy_validでトレーニングデータと検証データを持っている段階を想像してください。

import pandas as pd
from sklearn.model_selection import train_test_split

Read the data

data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

Separate target from predictors

y = data.Price
X = data.drop(['Price'], axis=1)

Divide data into training and validation subsets

X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2,
random_state=0)

"Cardinality" means the number of unique values in a column

Select categorical columns with relatively low cardinality (convenient but arbitrary)

categorical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and
X_train_full[cname].dtype == "object"]

Select numerical columns

numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]

Keep selected columns only

my_cols = categorical_cols + numerical_cols
X_train = X_train_full[my_cols].copy()
X_valid = X_valid_full[my_cols].copy()

以下のhead()メソッドでトレーニングデータを一覧表示します。データにはカテゴリデータと欠損値を持つ列の両方が含まれていることに注意してください。パイプラインがあれば、両方の取り扱いが簡単になります!

X_train.head()

完全なパイプラインを3つのステップで構築します。

ステップ1:前処理ステップの定義

パイプラインが前処理とモデリングのステップをバンドルする方法に似て、異なる前処理ステップをバンドルするためにColumnTransformerクラスを使用します。以下のコードは、次の2つの前処理ステップをまとめます。

1. 数値データの欠損値を補完します。

2. カテゴリデータの欠損値を補完し、ワンホットエンコーディングを適用します。

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

Preprocessing for numerical data

numerical_transformer = SimpleImputer(strategy='constant')

Preprocessing for categorical data

categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])

Bundle preprocessing for numerical and categorical data

preprocessor = ColumnTransformer(
transformers=[
('num', numerical_transformer, numerical_cols),
('cat', categorical_transformer, categorical_cols)
])

ステップ2:モデルの定義

次に、おなじみのRandomForestRegressorクラスを使用してランダムフォレストモデルを定義します。

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)

ステップ3:パイプラインの作成と評価

最後に、前処理とモデリングのステップをバンドルするためにPipelineクラスを使用します。いくつか重要なことに注意してください。

パイプラインを使用すると、トレーニングデータを前処理し、モデルを単一のコード行でフィットさせることができます。(対照的に、パイプラインを使用しない場合、欠損値の補完、ワンホットエンコーディング、およびモデルトレーニングを個別のステップで行う必要があります。これは特に数値変数とカテゴリカル変数の両方を扱わなければならない場合に混乱しやすくなります!)

パイプラインを使用すると、予測を生成する前にX_validの未加工の特徴をpredict()コマンドに供給し、パイプラインが自動的に特徴を前処理します。(対照的に、パイプラインを使用しない場合、予測を生成する前に検証データを前処理することを覚えておかなければなりません。)

from sklearn.metrics import mean_absolute_error

Bundle preprocessing and modeling code in a pipeline

my_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
('model', model)
])

Preprocessing of training data, fit model

my_pipeline.fit(X_train, y_train)

Preprocessing of validation data, get predictions

preds = my_pipeline.predict(X_valid)

Evaluate the model

score = mean_absolute_error(y_valid, preds)
print('MAE:', score)
MAE: 160679.18917034855

結論

パイプラインは、機械学習コードの整理とエラーの回避に価値があり、特に洗練されたデータ前処理を含むワークフローに非常に役立ちます。

クロスバリデーション

https://www.kaggle.com/code/alexisbcook/cross-validation

導入

機械学習は反復的なプロセスです。

予測変数を選択するか、どの種類のモデルを使用するか、それらのモデルに提供する引数は、何を選択するかについての選択肢があります。これまで、バリデーション(またはホールドアウト)セットを使用してモデルの品質を測定することで、これらの選択をデータ駆動の方法で行ってきました。

しかし、このアプローチにはいくつかの欠点があります。これを理解するために、5000行のデータセットがあると想像してください。通常、データの約20%をバリデーションデータセットとして保持し、1000行を使用します。しかし、これによりモデルのスコアの決定にはランダムな要因が残ります。つまり、モデルは異なる1000行の別のセットで不正確である場合でも、1つの1000行のセットでうまく機能することがあります。

極端な場合、バリデーションセットにデータの行が1つしかないと想像できます。代替モデルを比較する場合、1つのデータポイントに対する最良の予測を行うモデルは、ほとんど運の問題になります!

一般的には、バリデーションセットが大きいほど、モデル品質の測定値にランダム性(ノイズとも呼ばれます)が少なく、信頼性が高くなります。残念ながら、トレーニングデータから行を削除して大規模なバリデーションセットを取得できるだけで、トレーニングデータセットが小さいほど、モデルが悪くなります!

クロスバリデーションとは何ですか?

クロスバリデーションでは、モデル品質の複数の測定値を得るために、データの異なるサブセットでモデリングプロセスを実行します。

たとえば、データを5つの部分に分割することから始めることができ、各部分はフルデータセットの20%です。この場合、データを5つの「フォールド」に分割したと言います。

次に、各フォールドごとに1つの実験を実行します。

実験1では、最初のフォールドをバリデーション(またはホールドアウト)セットとして使用し、それ以外のすべてをトレーニングデータとして使用します。これにより、20%のホールドアウトセットに基づくモデル品質の測定値が得られます。

実験2では、2番目のフォールドからデータを保持(トレーニングデータとして2番目のフォールド以外のすべてを使用してモデルをトレーニング)し、ホールドアウトセットはモデル品質の第二の推定値を得るために使用されます。

このプロセスを繰り返し、各フォールドを少なくとも1回ホールドアウトセットとして使用します。これをまとめると、データセットのすべての行に基づいたモデル品質の測定値が得られます(すべての行を同時に使用しなくても)。

クロスバリデーションを使用すべきタイミングはいつですか?

クロスバリデーションは、モデル品質のより正確な測定値を提供し、特に多くのモデリング決定を行っている場合に重要です。ただし、各フォールドごとに1つのモデルを推定するため、実行に時間がかかることがあります。

したがって、これらのトレードオフを考慮した場合、どのアプローチを使用すべきですか?

小規模なデータセットの場合、追加の計算負荷が大きな問題でない場合は、クロスバリデーションを実行する必要があります。

大規模なデータセットの場合、単一のバリデーションセットが十分です。コードの実行が速くなり、ホールドアウトに一部のデータを再利用する必要性が少ない場合があります。

大規模か小規模かを区別するための単純なしきい値はありません。ただし、モデルの実行に2分程度かかる場合、クロスバリデーションに切り替える価値があるでしょう。

また、クロスバリデーションを実行し、各実験のスコアが似ているかどうかを確認できます。各実験が同じ結果を示す場合、単一のバリデーションセットが十分である可能性があります。

前のチュートリアルと同じデータを使用します。入力データはXに、出力データはyに読み込みます。

import pandas as pd

Read the data

data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

Select subset of predictors

cols_to_use = ['Rooms', 'Distance', 'Landsize', 'BuildingArea', 'YearBuilt']
X = data[cols_to_use]

Select target

y = data.Price

次に、欠損値を補完するためのイミュータと、予測を行うためのランダムフォレストモデルを使用するパイプラインを定義します。

パイプラインを使用せずにクロスバリデーションを行うことは可能ですが、かなり難しいです!パイプラインを使用すると、コードが非常に簡潔になります。

from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

my_pipeline = Pipeline(steps=[('preprocessor', SimpleImputer()),
('model', RandomForestRegressor(n_estimators=50,
random_state=0))
])

scikit-learnのcross_val_score()関数を使用して、クロスバリデーションのスコアを取得します。cvパラメーターでフォールドの数を設定します。

from sklearn.model_selection import cross_val_score

Multiply by -1 since sklearn calculates *negative* MAE

scores = -1 * cross_val_score(my_pipeline, X, y,
cv=5,
scoring='neg_mean_absolute_error')

print("MAE scores:\n", scores)
MAE scores:
[301628.7893587 303164.4782723 287298.331666 236061.84754543
260383.45111427]

scikit-learnの`scoring`パラメータは、報告するモデルの品質の尺度を選択します。この場合、私たちは負の平均絶対誤差(MAE)を選択しました。scikit-learnのドキュメントにはオプションの一覧が表示されています。

負のMAEを指定することが少し驚くかもしれません。scikit-learnには、すべてのメトリクスが高い数値が良いと定義されている慣例があります。ここで負の値を使用することで、それらの慣例に一貫性を持たせることができますが、負のMAEはほとんど他では見かけないものです。

通常、代替モデルを比較するためにモデルの品質を単一の尺度で求めたいです。そのため、実験全体での平均を取ります。

print("Average MAE score (across experiments):")
print(scores.mean())
Average MAE score (across experiments):
277707.3795913405

クロスバリデーションを使用することで、モデルの品質のはるかに優れた尺度が得られ、コードが整理されるという利点もあります。別々のトレーニングセットとバリデーションセットを追跡する必要がなくなったことに注意してください。したがって、特に小さなデータセットの場合、これは良い改善です!

© 2025, blueqat Inc. All rights reserved