8.1 処理フローのコンポネント化22
さらに, 取り込んだデータの値を変換する前処理にはいろいろな種類がありますが, そのうちどれが有効なのかはデータだけでなく使用する学習器に依存します. 前処理のクラスもまた, 変換器 (transformer) と呼ばれるクラスとして定義され, 一貫性を持ちます. これらの部品を接続するのが Pipeline
です23. 例えば, 数値特徴量を標準化する StandardScaler
と主成分分析によって主成分に変換する PCA
という変換器が用意されており, 以下のように組み合わせることができます.
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# standardizing + logisitic
logis_std = Pipeline([
('standardzize', StandardScaler()),
('logistic', logis)
])
logis_std.fit(X, y)
## Pipeline(steps=[('standardzize', StandardScaler()),
## ('logistic', LogisticRegression(random_state=42))])
## array([0, 1, 0, 1, 0])
## Pipeline(steps=[('PCA', PCA()),
## ('logistic', LogisticRegression(random_state=42))])
## array([0, 1, 0, 1, 0])
変換器と学習器を与えた Pipeline()
オブジェクトは, 再び学習器と同じように .fit()
と .predict()
メソッドを持ちます.
もちろん, もっと複雑なデータのフローを表現することも可能です. 例えば, PCA はその性質上, 多くの場合で入力データを標準化することが望ましいことが多いです24. すると, まず標準化の変換器を通してからPCAをやる必要が出てきます. パイプラインはこのような処理にも対応できます.
logis_std_pca = Pipeline([
('standardize', StandardScaler()),
('PCA', PCA()),
('logistic', logis)
])
Pipeline()
は入力から出力へと向かう「垂直方向」のフローを表現できます. 一方で, 特徴量ごとに異なる処理をするとか, 同じ特徴量に異なる複数の変換を並列して実行するといった, 「水平方向」のフローを表現する手段もあります. これは単なる特徴量変換ではなく, いわゆるアンサンブル学習を表現することにも使えます25. 新たに導入するクラスは, ColumnTransformer
と FeatureUnion
です26. 前者は入力の特徴量行列ごとに異なる前処理を適用するためのもので, 後者は複数の変換器を同じ特徴量行列に適用するためのものです.
文で説明するより, 視覚的に見るほうがよいでしょう. そのために estimator_html_repr()
が用意されています. この関数はフローを描画する html ソースを返します. jupyter で以下のようにしてそれぞれのパイプラインのフローを視覚化してみましょう.
from sklearn.utils import estimator_html_repr
from IPython.core.display import display, HTML
logis_col = Pipeline([
('colwise', ColumnTransformer([
('center', StandardScaler(with_std=False), [0, 1]),
('standardize', StandardScaler(), slice(2, 4))
]))
])
logis_union = Pipeline([
('union', FeatureUnion([
('standardize', StandardScaler()),
('PCA', PCA())
]))
])
display(HTML(estimator_html_repr(logis_std_pca)))
display(HTML(estimator_html_repr(logis_col)))
display(HTML(estimator_html_repr(logis_union)))
出力される html
はクリックで展開できる詳細情報が折りたたまれています (図 8.1).

図 8.1: パイプラインの視覚化
また, jupyter 上で以下のように設定することで学習器オブジェクトを呼び出したときに常にこの図を返すようになります. ただし, HTML であるため ipynb
ファイルをHTML以外の媒体にエクスポートする際は表示されないことがあります.
参考文献一覧
このサブセクションでは, 以前『Python でのデータ分析作業をスマートにするために』(https://qiita.com/s_katagiri/items/a6c3914e7623b4d7b5a3) で書いたものとおおむね同じことを説明していますが,
scikit-learn
の更新により当時から環境の多少の変化があります. 公式ドキュメントでは “6.1. Pipelines and composite estimators” (https://scikit-learn.org/stable/modules/compose.html?highlight=columntransformer) で言及されている内容です.↩︎Pipeline()
は変換器, 学習器にそれぞれ名称を指定する必要がありますが,make_pipeline()
というバリエーションは自動で命名してくれます.↩︎Géron (2017) においても, PCAは入力データの中心化が必要と注意書きがされていますが, なぜ必要なのかには深く踏み込んでいません. さらに近年機械学習に関する書籍が多く出版されていますが, PCA を紹介していても PCA 必要な前処理に一切言及してないものも少なくありません. 本稿ではこういう実用上重要な話もなるべく余さず解説するようにしています.↩︎
例えば, バギングを行う
baggingClassifier
, スタッキングのためのStackingClassifier
/StackingRegressor
などがsklearn.ensemble
に用意されています.↩︎Pipeline()
に対するmake_pipeline()
のように,FeatureUnion()
に対して変換器の命名が不要なmake_union()
が存在します.↩︎