SciKit Pipelinesについての簡単な紹介’

SciKit Pipelinesの簡単な紹介

そしてなぜそれらを使い始めるべきか。

Sigmundによる写真、Unsplash

機械学習モデルをトレーニングしたことがあり、予測結果があまりにも素晴らしすぎると思ったことはありませんか?しかし、その後、トレーニングデータとテストデータの間にデータの漏洩があることに気づいたことはありませんか?

また、データの前処理に多くのステップが必要で、モデルトレーニングから本番環境への前処理ステップの移行が困難で実際の予測が難しい場合はありませんか?

また、前処理が乱雑になり、コードを読みやすく理解しやすい形式で共有することが難しい場合はありませんか?

そんな場合は、scikit-learnのパイプラインを試してみる価値があります。パイプラインは、MLのトレーニング、テスト、および本番環境のワークフローを設定するためのエレガントなソリューションであり、より簡単に、より再現性の高い結果を生み出します。

しかし、パイプラインとは何か、その利点は何か、そしてパイプラインをどのように設定するのかについて説明します。また、ビルディングブロックのコード例も示します。これらのビルディングブロックを組み合わせることで、ニーズに合わせたより洗練されたパイプラインを構築することができます。

パイプラインとは何ですか?

パイプラインは、データを変換するための複数のステップを順次組み立てることができるため、MLのワークフローにおいて、データを最終の推定器に渡す前に、前処理、特徴エンジニアリング、特徴選択のステップを含むことができます。

なぜパイプラインを使用すべきですか?

一般的に、パイプラインを使用することで、MLモデルの開発が容易になり、スピードアップされます。なぜなら、パイプラインは以下のような利点があるからです。

  • よりクリーンで理解しやすいコードになります。
  • データのワークフローを簡単に複製し、理解することができます。
  • 読みやすく調整しやすくなります。
  • パイプラインはデータの前処理を自動化するため、データの準備が速くなります。
  • データ漏洩を防ぐのに役立ちます。
  • ハイパーパラメータの最適化を一度にパイプライン内のすべての推定器とパラメータで実行できます。
  • パイプライン内のすべてのデータワークフローを一度に呼び出すだけで、fit()predict()を実行できるため、便利です。

モデルのトレーニングと最適化が完了し、結果に満足した場合、トレーニングされたパイプラインを簡単に保存できます。その後、モデルを実行する際は、事前にトレーニングされたパイプラインをロードするだけで、推論を行う準備ができます。これにより、非常にクリーンな方法でモデルを共有し、複製および理解することが容易になります。

パイプラインをどのように設定しますか?

scikit-learnを使用してパイプラインを設定するのは非常に簡単です。

scikit-learnPipelineは、値として適用するトランスフォーマーを含むキーと値のペアのリストを使用します。キーは任意に選択できます。キーは、ハイパーパラメータの最適化中にグリッドサーチを実行する場合など、トランスフォーマーのパラメータにアクセスするために使用できます。トランスフォーマーはリストに格納されているため、インデックスを使用してトランスフォーマーにアクセスすることもできます。

パイプラインにデータを適合させて予測を行うには、scikit-learnの他のトランスフォーマーや回帰器と同様に、fit()predict()を実行することができます。

非常にシンプルなパイプラインは次のようになります。

from sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import MinMaxScalerfrom sklearn.linear_model import LinearRegressionpipeline = Pipeline(   steps=[("imputer", SimpleImputer()),           ("scaler", MinMaxScaler()),           ("regression", LinearRegression())   ])pipeline.fit(X_train, y_train)y_pred = pipeline.predict(X_test)

ただし、scikit-learnは、トランスフォーマーのキー値を入力する必要がない場合でも、さらに簡単になります。代わりに、make_pipeline()関数を使用し、scikit-learnがトランスフォーマーのクラス名に基づいて名前を設定します。

from sklearn.impute import SimpleImputerfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import MinMaxScalerfrom sklearn.linear_model import LinearRegressionpipeline = make_pipeline(steps=[    SimpleImputer(),     MinMaxScaler(),     LinearRegression()    ])

これで、モデルのトレーニングと予測を開始するために使用できるシンプルなパイプラインを迅速にセットアップしました。パイプラインの見た目を確認したい場合は、パイプラインを印刷するだけで、scikit-learnがパイプラインのインタラクティブビューを表示します。

しかし、もっと複雑でカスタマイズ可能なものを構築したい場合はどうでしょうか?例えば、カテゴリカルな値と数値的な値を異なる方法で処理したり、特徴量を追加したり、ターゲット値を変換したりする場合です。

心配しないでください、scikit-learnはこれらの追加機能を提供しており、よりカスタムなパイプラインを作成し、パイプラインを次のレベルに引き上げることができます。これらの機能は次のとおりです。

  • ColumnTransformer
  • FeatureUnion
  • TransformedTargetRegressor

これらについて説明し、使用方法の例を示します。

選択した特徴の変換

もし、連続的な特徴とカテゴリカルな特徴など、異なる種類の特徴を持っている場合、これらの特徴を異なる方法で変換したいと思うかもしれません。例えば、連続的な特徴をスケーリングし、カテゴリカルな特徴をワンホットエンコードするなどです。

これらの前処理ステップをパイプラインに渡す前に行うこともできます。しかし、そうすることで、後でハイパーパラメータのサーチにこれらの前処理ステップとパラメータを含めることができなくなります。また、パイプラインに含めることで、MLモデルの取り扱いが簡単になります。

選択した列に対して変換や変換のシーケンスを適用するには、ColumnTransformerを使用します。使用方法はPipelineと非常に似ており、stepsにキーと値のペアを渡す代わりに、同じペアをtransformersに渡します。そして、作成したトランスフォーマをパイプラインのステップとして含めることができます。

from sklearn.compose import ColumnTransformerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import OneHotEncodercategorical_transformer = ColumnTransformer(    transformers=[("encode", OneHotEncoder())])pipeline = Pipeline(steps=[    ("categorical", categorical_transformer, ["col_name"])    ])

変換を特定の列にのみ適用したい場合は、パイプラインにこれらの列を渡す必要があります。さらに、ColumnTransformerに変換されない残りの列に対して何を行うかを伝えることもできます。例えば、変換されない列を保持したい場合は、remainderpassthroughに設定する必要があります。それ以外の場合、列は削除されます。何もしないか、列を削除する代わりに、別のトランスフォーマを渡すことで残りの列も変換することもできます。

from sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import MinMaxScaler, OneHotEncodercategorical_transformer = ColumnTransformer( transformers=[("encode", OneHotEncoder(), ["col_name"])], remainder="passthrough")categorical_transformer = ColumnTransformer( transformers=[("encode", OneHotEncoder(), ["col_name"])], remainder=MinMaxScaler())```

scikit-learnではパイプラインのスタックも可能なので、ColumnTransformerにはColumnTransformer自体で行いたい各変換を指定する代わりに、パイプラインを渡すこともできます。

from sklearn.compose import ColumnTransformerfrom sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import MinMaxScaler, OneHotEncodercategorical_transformer = Pipeline(steps=[("encode", OneHotEncoder())])numerical_transformer = Pipeline(   steps=[("imputation", SimpleImputer()), ("scaling", MinMaxScaler())])preprocessor = ColumnTransformer(   transfomers=[     ("numeric", numerical_transformer),     ("categoric", categorical_transformer, ["col_name"]),   ])pipeline = Pipeline(steps=["preprocesssing", preprocessor])

特徴の組み合わせ

今、異なる列に対して異なる前処理ステップを実行できるようになりましたが、データから新しい特徴を導出し、特徴セットに追加したい場合はどうでしょうか?

その場合、FeatureUnionを使用して、トランスフォーマオブジェクトを組み合わせて新しいトランスフォーマを作成し、パイプラインを実行することができます。各トランスフォーマを独立してフィットし、その出力を結合します。

例えば、移動平均を特徴として追加したい場合、次のようにすることができます:

from sklearn.compose import FeatureUnionfrom sklearn.pipeline import Pipelinepreprocessor = (   FeatureUnion(     [       ("moving_Average", MovingAverage(window=30)),       ("numerical", numerical_pipeline),     ]   ),)pipeline = Pipeline(steps=["preprocesssing", preprocessor])

ターゲット値の変換

回帰問題を解く場合、回帰に適合させる前にターゲットを変換することが役立つことがあります。

TransformedTargetRegressorクラスを使用して、このような変換を含めることができます。このクラスでは、scikit-learnが提供するMinMaxスケーラーのような変換器を使用するか、独自の変換関数を記述することができます。

TransformedTargetRegressorの大きな利点の一つは、逆変換によって予測結果を元の空間に自動的にマッピングすることです。したがって、モデルのトレーニングから本番の予測へ移行する際には、これについて心配する必要はありません。

from sklearn.compose import TransformedTargetRegressorfrom sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import MinMaxScalerregressor = TransformedTargetRegressor(    regressor=model,     func=np.log1p,     inverse_func=np.expm1)pipeline = Pipeline(   steps=[      ("imputer", SimpleImputer()),       ("scaler", MinMaxScaler()),       ("regressor", regressor)    ])pipeline.fit(X_train, y_train)y_pred = pipeline.predict(X_test)

独自のカスタム関数の作成

scikit-learnが提供する前処理メソッドだけでは十分ではない場合もあります。しかし、これはパイプラインを使用する際にあなたを後ろ向きにするべきではありません。パイプラインに含めることができる自分自身の関数を簡単に作成することができます。

そのためには、fit()メソッドとtransform()メソッドを含むクラスを作成する必要があります。これらのメソッドはパイプラインを実行する際に呼び出されるため、何もしない場合でも問題ありません。さらに、クラスをscikit-learnBaseEstimatorおよびTransformerMixinクラスから継承させることで、パイプラインに必要な基本機能を提供することができます。

たとえば、時系列データで予測を行い、すべての特徴を移動平均で平滑化したい場合を考えてみましょう。そのためには、平滑化部分を含むtransformメソッドを持つクラスを設定するだけです。

from sklearn.base import BaseEstimator, TransformerMixinfrom sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipelinefrom sklearn.preprocessing import MinMaxScalerclass MovingAverage(BaseEstimator, TransformerMixin):    def __init__(self, window=30):          self.window = window        def fit(self, X, y=None):          return self        def transform(self, X, y=None):        return X.rolling(window=self.window, min_periods=1, center=False).mean()pipeline = Pipeline(   steps=[       ("ma", MovingAverage(window=30)),       ("imputer", SimpleImputer()),       ("scaler", MinMaxScaler()),       ("regressor", model),   ])pipeline.fit(X_train, y_train)y_pred = pipeline.predict(X_test)

他に知るべきことは何かありますか?

scikit-learnの変換器のデフォルトの戻り値はnumpy配列です。これは、パイプラインで2番目のステップで特定の特徴にのみ変換を適用したい場合など、パイプラインを壊す可能性があります。

ただし、パイプラインが壊れるのを防ぐために、すべての変換器のデフォルトの戻り値をデータフレームに変更することができます。

from sklearn import set_configset_config(transform_output = "pandas")

ハイパーパラメータの最適化やパイプラインの単一パラメータのチェックを実行する際に、パラメータに直接アクセスすることは役立ちます。パラメータにアクセスするには、<estimator>__<parameter>の構文を使用できます。たとえば、上記の例では、MovingAverageトランスフォーマーのウィンドウ幅にアクセスするために、pipeline.set_params(pipeline__ma_window=7)と呼び出すことができます。

結論

scikit-learnのパイプラインを使用することで、新しい機械学習モデルを開発し、前処理手順を設定することが非常に簡単になります。多くの利点を持つだけでなく、パイプラインの設定もシンプルでわかりやすいです。それにもかかわらず、創造力によってのみ制約が設けられる洗練されたカスタマイズ可能な前処理パイプラインを構築することができます。

この記事が役に立った場合や質問がある場合は、コメントを残すか、お気軽にご連絡ください。また、scikit-learnのパイプラインに関するご意見やご体験もお聞かせください。

パイプラインについてもっと読みたいですか?以下のリンクをチェックしてください:

  • https://scikit-learn.org/stable/modules/compose.html#pipeline

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more