こちらの記事、でscikit-learnのpipelineモジュールを用いた機械学習パイプラインの作成を紹介した。
pipelineモジュールに組み込めるのは、fit, transformメソッドなど持つ、sklean準拠の変換器(transformer)や推定器(Estimator)である。
そのため、独自の処理や予測手法を用いる場合には、これらを自作する必要がある。
本記事では変換器(transformer)や推定器(Estimator)の自作方法についてまとめた。
コード
Transformerを実装する手順(参考)
BaseEstimator
を継承する。(set_params
とget_params
を使用できるようにするため)TransformerMixin
を継承する。(fit_transform
を使用できるようにするため)fit
を実装する。transform
を実装する。
Estimatorを実装する手順(参考)
BaseEstimator
を継承する。(set_params
とget_params
を使用できるようにするため)- 回帰なら
RegressorMixin
・分類ならClassifierMixin
、もしくはTransformerMixin
を継承する。(fit_transform
を使用できるようにするため。RegressorMixin
,ClassifierMixin
を継承しているとscore
メソッドが使える様になるとのこと) fit
を実装する。predict
を実装する。
### データの準備
import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
# サンプルデータの用意
boston = load_boston()
df_X = pd.DataFrame(data=boston.data, columns=boston.feature_names)
df_y = pd.Series(boston.target, name="MEDV")
train_X, test_X, train_y, test_y = train_test_split(df_X,df_y)
# 検証用に欠損値を作る
train_X.iloc[5,5:8] = np.nan
print("欠損値のある列",train_X.columns[train_X.isnull().any()])
"""output
欠損値のある列 Index(['RM', 'AGE', 'DIS'], dtype='object')
"""
Transformerの自作
欠損値がある列を削除するメソッドを実装してみる。
(pandasのdropna
を使えば一発で削除できるが、練習のため)
from sklearn.base import BaseEstimator, TransformerMixin
class DeleteNullFeatures(BaseEstimator, TransformerMixin):
def __init__(self,delete_col=None):
self.delete_col = delete_col
def fit(self, X, y=None):
# 欠損値のある列の検出
self.delete_col = df_X.columns[df_X.isnull().any()]
return self
def transform(self, X):
if self.delete_col is None:
return X
else:
return X.drop(self.delete_col,axis=1)
preprocess = DeleteNullFeatures()
train_X_transformed = preprocess.fit_transform(train_X)
test_X_transformed = preprocess.transform(test_X)
print(train_X_transformed.columns)
print(test_X_transformed.columns)
"""output
Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT'],
dtype='object')
Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT'],
dtype='object')
"""
Estimatorの自作
yの平均値を予測値として返すEstimatorを実装してみる
from sklearn.base import BaseEstimator,RegressorMixin
class MeanEstimator(BaseEstimator,RegressorMixin):
def __init__(self):
self.y_mean = None
def fit(self, X, y=None):
self.y_mean = y.mean()
return self
def predict(self, X):
return np.full(X.shape[0],self.y_mean)
mean_model = MeanEstimator()
mean_model.fit(train_X,train_y)
train_y_pred = mean_model.predict(train_X)
test_y_pred = mean_model.predict(test_X)
print(train_y_pred[:10])
print(test_y_pred[:10])
"""output
[22.25567282 22.25567282 22.25567282 22.25567282 22.25567282 22.25567282
22.25567282 22.25567282 22.25567282 22.25567282]
[22.25567282 22.25567282 22.25567282 22.25567282 22.25567282 22.25567282
22.25567282 22.25567282 22.25567282 22.25567282]
"""
(おまけ)PipeLineへの組み込み
from sklearn.pipeline import Pipeline
pipeline = Pipeline(steps=[
('standard_scaler', DeleteNullFeatures()),
('regressor', MeanEstimator())
])
pipeline.fit(train_X,train_y)
train_y_pred = pipeline.predict(train_X)
test_y_pred = pipeline.predict(test_X)
print(train_y_pred[:10])
print(test_y_pred[:10])
"""output
[22.25567282 22.25567282 22.25567282 22.25567282 22.25567282 22.25567282
22.25567282 22.25567282 22.25567282 22.25567282]
[22.25567282 22.25567282 22.25567282 22.25567282 22.25567282 22.25567282
22.25567282 22.25567282 22.25567282 22.25567282]
"""
参考
参考HP
- Python: scikit-learn の Pipeline を使ってみる
- scikit-learnのAPIとPipelineの基本的な仕組みと使い方について
- scikit-learn で最低限の自作推定器(Estimator)を実装する
- sklearn準拠モデルの作り方
関連書籍
Pythonではじめる機械学習 ―scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎
Python 実践データ分析 100本ノック
スッキリわかるPythonによる機械学習入門