Краткое введение в SciKit Pipelines

SciKit Pipelines Brief Introduction

И почему вам следует начать использовать их.

Фото от Sigmund на Unsplash

Вы когда-нибудь обучали модель машинного обучения, и ваши прогнозы выглядели слишком хорошо, чтобы быть правдой? Но потом вы поняли, что у вас была утечка данных между обучением и тестированием?

Или у вас было много предварительных обработок данных, чтобы подготовить их так, чтобы было сложно передать предварительные обработки из обучения модели в производство для фактических прогнозов?

Или ваша предварительная обработка становится беспорядочной, и трудно делиться вашим кодом в читаемой и понятной форме?

Тогда вам может захотеться попробовать scikit-learn Pipeline. Pipeline – это элегантное решение для настройки вашего рабочего процесса для обучения, тестирования и производства МО, что делает вашу жизнь проще и ваши результаты более воспроизводимыми.

Но что такое пайплайн, каковы его преимущества и как настроить пайплайн? Я рассмотрю эти вопросы и дам вам несколько примеров кода строительных блоков. Комбинируя эти строительные блоки, вы можете создавать более сложные пайплайны, которые соответствуют вашим потребностям.

Что такое пайплайн?

Пайплайн позволяет вам собирать несколько этапов в вашем рабочем процессе МО, которые последовательно преобразуют ваши данные перед передачей данных оценщику. Таким образом, пайплайн может состоять из этапов предварительной обработки, инженерии признаков и выбора признаков перед передачей данных финальному оценщику для задач классификации или регрессии.

Почему я должен использовать пайплайн?

В целом, использование пайплайна делает вашу жизнь проще и ускоряет разработку моделей МО. Это потому, что пайплайн

  • приводит к более чистому и понятному коду
  • легко воспроизводит и понимает рабочие процессы с данными
  • легче читать и настраивать
  • ускоряет подготовку данных, так как пайплайн автоматизирует подготовку данных
  • помогает избежать утечки данных
  • позволяет запускать оптимизацию гиперпараметров по всем оценщикам и параметрам в пайплайне одновременно
  • удобен, так как вам нужно вызывать только fit() и predict() один раз для выполнения всего рабочего процесса с данными

После того, как вы обучили и оптимизировали свою модель и довольны результатами, вы можете легко сохранить обученный пайплайн. Затем, когда вы хотите запустить свою модель, просто загрузите предварительно обученный пайплайн, и вы готовы к некоторым выводам. Таким образом, вы можете легко делиться своей моделью очень чистым способом, который легко воспроизводится и понимается.

Как настроить пайплайн?

Настройка пайплайна с использованием scikit-learn очень проста и прямолинейна.

scikit-learn Pipeline использует список пар ключ-значение, который содержит преобразователи, которые вы хотите применить к вашим данным в качестве значений. Ключи можно выбирать произвольно. Ключи могут использоваться для доступа к параметрам преобразователей, например, при выполнении поиска по сетке во время оптимизации гиперпараметров. Поскольку преобразователи хранятся в списке, вы также можете получить доступ к преобразователям по индексу.

Чтобы соответствовать данным в вашем пайплайне и делать прогнозы, вы можете запустить fit() и predict(), как вы это делаете с любым преобразователем или регрессором в scikit-learn.

Очень простой пайплайн может выглядеть так:

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

Я рассмотрю их и покажу вам примеры использования.

Преобразование выбранных признаков

Если у вас есть разные типы признаков, например, непрерывные и категориальные, вам, вероятно, захочется преобразовывать эти признаки по-разному. Например, масштабировать непрерывные признаки, в то время как категориальные признаки кодировать с помощью one-hot-кодирования.

Вы можете выполнить эти предварительные обработки перед передачей признаков в конвейер. Но, сделав это, вы не сможете включить эти предварительные обработки и параметры в ваш поиск гиперпараметров позже. Кроме того, включение их в конвейер упрощает работу с вашей моделью машинного обучения.

Чтобы применить преобразование или даже последовательность преобразований только к выбранным столбцам, вы можете использовать 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, что мы хотим сделать с оставшимися столбцами. Например, если вы хотите сохранить столбцы, которые не изменяются преобразователем, необходимо установить remainder в значение passthrough. В противном случае столбцы удаляются. Вместо того, чтобы ничего не делать или удалять столбцы, вы также можете преобразовать оставшиеся столбцы, передав преобразователь.

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, который объединяет объекты преобразователей в новый преобразователь с объединенными объектами. Запуск конвейера с 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 трансформаторы, такие как MinMaxScaler, так и написать свои собственные функции преобразования.

Одним из главных преимуществ 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(), так как они вызываются при выполнении конвейера. Однако эти методы не обязательно должны выполнять какие-либо действия. Кроме того, мы можем наследовать класс от классов BaseEstimator и TransformerMixin из scikit-learn, чтобы получить некоторую базовую функциональность, которая нам нужна для конвейера.

Например, предположим, что мы хотим делать прогнозы по временным рядам и мы хотим сгладить все признаки с помощью скользящего среднего. Для этого мы просто создаем класс с методом 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. Это может привести к проблемам в вашем конвейере, если вы хотите применить преобразование только к определенным признакам на втором шаге конвейера, например, только категориальным признакам.

Однако, чтобы предотвратить поломку конвейера, вы можете изменить значение возврата по умолчанию всех трансформаторов на dataframe, указав

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