LoginSignup
38
23

More than 5 years have passed since last update.

sklearnのpipelineに自分で定義した関数を流し込む

Last updated at Posted at 2017-12-06

はじめに

データ分析のコードを書く時に,自分で定義した関数やモジュールがとっちらかったりすることがよくあります.(僕だけかもしれない)

簡単に書けて,どんな処理をしているかわかりやすい管理の仕方はないかと考えたところ,sklearnのpipelineにそのまま乗っかるのがいいのではないかという結論に至りました.

自分で定義した関数をpipelineで用いるのは割と簡単にできて,
1. sklearnからpipelineに流せるクラスを持ってくる
2. そのクラスに自分の関数をtransformという名前で定義する.
だけです.

環境

  • Python 3.6.0
  • sklearn 0.18.1

pipelineに流せるベースクラスの定義

skPlumber.py
from sklearn.base import BaseEstimator, TransformerMixin

class skPlumberBase(BaseEstimator, TransformerMixin):
    def __init__(self):
        pass

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        return self

skleanのコードを見るとpipelineに流せるものは,BaseEstimator, TransformerMixinを継承しています.
それにわかりやすい名前をつけてベースクラスとしておきます.
(ちなみにplumberは配管工という意味らしいです.sklearnのパイプを継ぎ接ぎするという意味を込めて.)

自分の関数の定義

skPlumber_example.py
from skPlumber import skPlumberBase

class MyProcess(skPlumberBase):
    def __init__(self, param1=10):
        self.param1 = param1

    def transform(self, X):
        Y = self.param1*X
        return Y

skPlumberをどこかに置いておいて,それをインポートします.
また,何かパラメータを求めたりせず,処理をするだけであればtransformという名前でメソッドを定義してあげます.

パイプに流してみる

これだけです.
というわけで試してみましょう.

skPlumber_example.py
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import FeatureUnion, Pipeline

iris = load_iris()
X = iris["data"]
t = iris["target"]

estimators = [('scaler', StandardScaler()), ('my_process', MyProcess(param1=-10))]
pipe = Pipeline(estimators)
X2 = pipe.fit_transform(X)
X2.shape
(150, 4)

X2
array([[  9.00681170e+00,  -1.03205722e+01,   1.34127240e+01,
          1.31297673e+01],
       [  1.14301691e+01,   1.24957601e+00,   1.34127240e+01,
          1.31297673e+01],
       [  1.38535265e+01,  -3.37848329e+00,   1.39813811e+01,
          1.31297673e+01],

続けて処理をしてくれていそうですね.

さらにFeatureUnionを使えば,いくつか特徴量を計算してそれをまとめたものを返すというようなこともできます.

skPlumber_example.py
estimators = [('my_process', MyProcess(param1=10)), ('my_process2', MyProcess(param1=-10))]
combined = FeatureUnion(estimators)
X3 = combined.fit_transform(X)
X3.shape
(150, 8)

X3
array([[ 51.,  35.,  14., ..., -35., -14.,  -2.],
       [ 49.,  30.,  14., ..., -30., -14.,  -2.],
       [ 47.,  32.,  13., ..., -32., -13.,  -2.],
       ...,
       [ 65.,  30.,  52., ..., -30., -52., -20.],
       [ 62.,  34.,  54., ..., -34., -54., -23.],
       [ 59.,  30.,  51., ..., -30., -51., -18.]])

おわりに

試しにしばらくこれでやってみて使い心地を試したいです.

追記:参考になりそうなリンク

ラップしてpipeに流せるようにする
こんな感じですでに定義された関数をラップしまくったコードを書く方が簡単そうだ.

sklearn準拠モデルの作り方
モデルをメインに解説してくれている.先に読みたかった.

38
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
23