【sklearn】PipelineやColumnTransformerの使い方が分かる【Kaggle Course Intermediate Machine Learning 4】機械学習のパイプライン

Kaggle

アメリカのデータ分析コンペKaggleでは、世界中の優秀なデータサイエンティストによって作成された様々なeラーニング教材が無料で公開されています。

その中でも、この記事では以下の講座について解説します。

ただ、全編英語ですし、ところどころ説明を省略しているところもあるので、私なりにかみ砕いて解説していきます。

この記事で取り扱うライブラリ、クラスは以下の通りです。

sklearn.compose.ColumnTransformer
sklearn.pipeline.Pipeline

Pipelines(パイプライン)

Introduction(イントロダクション)

パイプラインとは、データの前処理やモデリングのコードを整理する方法です。

具体的には、前処理やモデリングのステップを束ね、全体を1つの命令かのように使用することができます

パイプラインを使うメリット

コードがきれいになる
バグが減る
製品化が容易になる
モデル検証の選択肢が増える

Example(具体例)

今回もメルボルンの住宅価格のデータセットを使います。

まず、データセットをX_train, X_valid, y_train, y_validという、4つの学習データと検証データに分割します。

head()メソッドでX_trainを見てみると、BuildingAreaYearBuiltなどのカテゴリに欠損値があるのが分かります。これらについて、パイプラインを使って処理していきます。

X_train.head()

パイプラインは以下の3ステップで構築します。

ステップ1 前処理の定義

コードの全体像です。順を追って説明してきます。

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)
    ])
数値の欠損値の処理方法を定義
# Preprocessing for numerical data
numerical_transformer = SimpleImputer(strategy='constant')

まず、数値の欠損値の処理方法を定義します。ここではSimpleImputerを使用します。

SimpleImputerの解説は前回に記事を参照してください。

strategy=’constant’となっているので、数値の欠損はすべて定数で埋めます。ここでは定数を指定していないので、デフォルトの0になります

定数を指定する場合はfill_valueで指定できます。

カテゴリ変数の欠損値の処理方法を定義
# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

次に、カテゴリ変数(BuildingAreaYearBuiltなど)の欠損値の処理方法を定義します。ここではPipelineSimpleImputerOneHotEncoderを使っています。

OneHotEncoderの解説は前回に記事を参照してください。

まず、strategy=’most_frequent’となっているので、カテゴリ変数の欠損は最頻値で埋めます。

その後、OneHotEncoderでカテゴリ変数を0と1の値を持つ新しい特徴量で置き換えます。handle_unknown=’ignore’となっていますので、fit時には存在しなかったカテゴリが見つかっても無視します。

最後に、Pipelineでこの2つの処理を結合します。Pipelineではsteps(‘処理の名前’, ‘処理内容’)のリスト[]を指定します。

前処理をColumnTransformerで束ねる
# Bundle preprocessing for numerical and categorical data
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numerical_transformer, numerical_cols),
        ('cat', categorical_transformer, categorical_cols)
    ])

最後に、先ほど定義した2つの前処理をColumnTransformerで束ねます。

transformers(‘処理の名前’, ‘処理内容’, ‘対象の列’)のリストを指定します。

ちなみに、対象の列は下記のコードで指定済みです。

# "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']]

ステップ2 モデルの定義

次に、機械学習のモデルを定義します。ここではランダムフォレストを指定します。

n_estimators=100木の数は100本とし、random_state=0で毎回同じデータが生成されるようにしています。

from sklearn.ensemble import RandomForestRegressor

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

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

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

最後に、ステップ1,2で定義した前処理とモデルをパイプラインPipelineで結合し、学習データでトレーニングfit、検証データで予測predictし、MAEスコアの算出mean_absolute_errorを行います。

Conclusion(結論)

パイプラインは、機械学習のコードをきれいにし、バグを回避するのに役立ちます。

特に、膨大なデータを処理するときに有効です。

Your Turn(練習問題)

この講座で学んだパイプラインを練習問題で実装してみましょう。

今回はKaggle Courseで機械学習のパイプラインについて学びました。ColumnTransformerPipelineを使いこなせるようになれば、少しこなれたデータサイエンティストのようです。次回は交差検証について学んでいきます。

おまけ

set_configを使うと、パイプラインの流れを図示することができます。

from sklearn import set_config
set_config(display='diagram')
my_pipeline

このように、シンプルなコードでHTML形式の図が表示されます。個人的にちょっと感動しました。

以上、最後までお読みいただきありがとうございました。

コメント

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