CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: scikit-learn の Pipeline 機能をデバッグする

今回はだいぶ小ネタ。 以前にこのブログでも記事にしたことがある scikit-learn の Pipeline 機能について。

blog.amedama.jp

scikit-learn の Pipeline 機能は機械学習に必要となる複数の工程を一つのパイプラインで表現できる。 ただ、パイプラインを組んでしまうと途中のフェーズで出力がどうなっているか、とかが確認しにくい問題がある。 この問題について調べると以下の StackOverflow が見つかるんだけど、なかなかシンプルな解決方法だった。

stackoverflow.com

先に概要を述べると、特に何もしないフェーズを用意して、そこでデバッグ用の出力をするというもの。

下準備

まずは必要になるパッケージをインストールしておく。

$ pip install pandas scikit-learn scipy numpy

Pipeline に組み込むデバッグ用のオブジェクト

早速だけど以下にサンプルコードを示す。 このコードでは Debug という名前でデバッグ用のクラスを用意している。 このクラスは scikit-learn の Pipeline に組み込むことができる。 実体としては Pipeline が使うメソッドでデバッグ用の出力をするだけの内容になっている。

#!/usr/bin/env python
# -*- coding: utf-8 -*-


from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.base import BaseEstimator
from sklearn.base import TransformerMixin

import pandas as pd


class Debug(BaseEstimator, TransformerMixin):
    """Pipelineをデバッグするためのクラス"""

    def transform(self, X):
        # 受け取った X を DataFrame に変換して先頭部分だけを出力する
        print(pd.DataFrame(X).head())
        # データはそのまま横流しする
        return X

    def fit(self, X, y=None, **fit_params):
        # 特に何もしない
        return self


def main():
    # Iris データセットを読み込む
    dataset = datasets.load_iris()
    X, y = dataset.data, dataset.target

    # パイプラインを構成する
    steps = [
        ('pca', PCA()),
        ('debug', Debug()),  # PCA の出力結果を確認する
        ('rf', RandomForestClassifier()),
    ]
    pipeline = Pipeline(steps=steps)

    # 学習
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
    pipeline.fit(X_train, y_train)

    # 推論
    y_pred = pipeline.predict(X_test)
    score = accuracy_score(y_test, y_pred)
    print(score)


if __name__ == '__main__':
    main()

上記を実行してみよう。 すると、Iris データセットを PCA (主成分分析) した結果の先頭部分が標準出力にプリントされる。 二回出力されているのは、モデルの学習 (fit() メソッド) と評価 (predict()) の二回で呼び出されているため。

$ python debug.py                            
          0         1         2         3
0  0.321625 -0.235144  0.057917  0.125637
1  3.355396  0.578542 -0.331641  0.076760
2  0.606069 -0.315582  0.300426  0.187366
3 -2.727847  0.438338  0.013295  0.002542
4  3.455577  0.501194 -0.562918  0.098940
          0         1         2         3
0  0.868341 -0.114257 -0.250542  0.271719
1 -2.233869  0.987378 -0.045914 -0.029639
2  3.746741  0.287862 -0.513685 -0.094163
3  0.760309 -0.111519  0.023542  0.020324
4  1.283430  0.320953 -0.507830 -0.063090
0.96

ばっちり。