はじめに
データ分析のコードを書く時に,自分で定義した関数やモジュールがとっちらかったりすることがよくあります.(僕だけかもしれない)
簡単に書けて,どんな処理をしているかわかりやすい管理の仕方はないかと考えたところ,sklearnのpipelineにそのまま乗っかるのがいいのではないかという結論に至りました.
自分で定義した関数をpipelineで用いるのは割と簡単にできて,
- sklearnからpipelineに流せるクラスを持ってくる
- そのクラスに自分の関数をtransformという名前で定義する.
だけです.
環境
- Python 3.6.0
- sklearn 0.18.1
pipelineに流せるベースクラスの定義
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のパイプを継ぎ接ぎするという意味を込めて.)
自分の関数の定義
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という名前でメソッドを定義してあげます.
パイプに流してみる
これだけです.
というわけで試してみましょう.
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
を使えば,いくつか特徴量を計算してそれをまとめたものを返すというようなこともできます.
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準拠モデルの作り方
モデルをメインに解説してくれている.先に読みたかった.