В scikit-learn есть специальный класс Pipeline, с помощью которого можно создавать конструктор определяющий последовательность из шагов, трансформирующих данные в нужном порядке.
Выглядит это примерно так:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
transform_pipeline = Pipeline([
('std_scaler', StandardScaler()),
('pd_to_np', FunctionTransformer(PdtoNp, validate=False)),
])
Вызов метода fit() запускает всю цепочку и приводит к последовательному выполнению трансформаций.
В данном случае в конвейер включены два шага трансформации данных. Первый - базовый scikit-learn-овский метод стандартизации данных (подробнее). А второй — это кастомный трансформатор.
Самый простой способ создать собственный трансформатор - это импортировать FunctionTransformer из sklearn.preprocessing. FunctionTransformer отправляет X и опционально y (массив данных и массив меток), а так же пользовательские аргументы в указанную функцию и возвращает результат. В примитивном примере я трансформирую произвольные данные в numpy массив.
from sklearn.preprocessing import FunctionTransformer
def PdtoNp(some_data):
return some_data.values
Подробнее можно прочитать базе знаний scikit-learn
Чтобы создать более сложную конструкцию, можно реализовать собственный класс, а в нем три базовых метода scikit-learn — fit() (должен возвращать self), transform() (собственно сам трансформер) и fit_transform(). Для всех трех методов обязательным аргументом является X. Если унаследовать класс от TransformerMixin, то fit_transformer() можно не задавать, а если добавить в качестве базового класса BaseEstimator и не реализовывать *args, **kwargs в конструкторе, то будут доступны методы get_params() и set_params()
from sklearn.base import BaseEstimator, TransformerMixin
class That(BaseEstimator, TransformerMixin):
def __init__(self, this = True):
self.this = this
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
that = self.this
return that
transformer = That(this=False)
my_data = transformer.transform(my_data)
Ну и, наконец, можно собирать несколько конвейеров трансформации в один, например, так:
transform_pipeline1 = Pipeline([
('std_scaler', StandardScaler()),
])
transform_pipeline2 = Pipeline([
('pd_to_np', FunctionTransformer(PdtoNp, validate=False)),
])
full_transform_pipeline = Pipeline([
('transform_pipeline1', transform_pipeline1)),
('transform_pipeline2', transform_pipeline1)),
])
Весь этот набор инструментов scikit-learn превращает обработку данных в довольно креативный и удобный для пользователя процесс.