Pipeline в машинном обучении: как создавать сложные модели без боли и утечек данных. ColumnTransformer.. ColumnTransformer. data leakage.. ColumnTransformer. data leakage. ml-модель.. ColumnTransformer. data leakage. ml-модель. pipeline.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn. Кросс-валидация.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn. Кросс-валидация. Машинное обучение.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn. Кросс-валидация. Машинное обучение. пайплайн данных.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn. Кросс-валидация. Машинное обучение. пайплайн данных. предобработка данных.. ColumnTransformer. data leakage. ml-модель. pipeline. sklearn. Кросс-валидация. Машинное обучение. пайплайн данных. предобработка данных. трансформеры.

Меня зовут Андрей Бирюков. Я — независимый эксперт в области ИТ и ИБ, преподаю в учебных центрах и пишу статьи и книги. И сегодня мы поговорим об использовании Pipeline для задач машинного обучения.

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

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

Вы когда‑нибудь сталкивались с ситуацией, когда:

  • После изменения одного шага предобработки перестала работать вся модель?

  • Вы забыли применить transform к тестовой выборке после fit на обучающей?

  • Не могли использовать кросс‑валидацию, потому что данные нужно было предобрабатывать?

  • Ваш коллега не смог воспроизвести ваш эксперимент?

Решением этих проблем является Pipeline на основе библиотеки sklearn.

Pipeline в машинном обучении: как создавать сложные модели без боли и утечек данных - 1

Что такое Pipeline и с чем его едят

Pipeline — это класс, который последовательно применяет список трансформаций к данным, а затем передает результат в финальную модель. Вот его базовая структура:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier

pipeline = Pipeline([
    ('scaler', StandardScaler()),     # Шаг 1: трансформер
    ('classifier', RandomForestClassifier())  # Шаг 2: модель
])

Принцип работы этого класса, если говорить простыми словами, состоит из двух действий: обучения и предсказания.

Процесс обучения содержит:

  • Шаг 1, на котором класс получает сырые данные, делает fit_transform, после чего передает результат Шагу 2.

  • Шаг 2 (финальный) получает обработанные данные, после чего делает fit.

Процесс предсказания:

  • Шаг 1 получает новые данные, затем делает только transform и передает Шагу 2.

  • Шаг 2 делает predict.

Для того, чтобы лучше разобраться в том, как работает Pipiline, давайте напишем первое приложение с оригинальным названием «Hello, Pipeline».

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Входные данные
X, y = make_classification(n_samples=1000, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

# Создаем сам pipeline

pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('classifier', LogisticRegression())
])

# Используем как обычную модель

pipeline.fit(X_train, y_train)
accuracy = pipeline.score(X_test, y_test)

print(f"Точность: {accuracy:.3f}") 

Как видно, здесь всё достаточно просто. Сначала мы получаем данные на вход, после чего используем Pipeline для того, чтобы применить трансформации к данным и, в итоге, передать результаты в финальную модель.

Ядро Pipeline. Как управлять данными

Перед тем как перейти к управлению данными с помощью Pipeline, давайте рассмотрим основные методы этого класса.

  1. Начнем с метода fit(X, y). Он обучает все шаги на X, y, и обычно его применяют на тренировочных данных.

  2. Метод predict(X) предсказывает для новых X, и обычно его используют на тестовых или новых данных.

  3. Еще один метод fit_transform(X, y=None) обучает и трансформирует и используется только для первого шага в цепочке.

  4. Метод score(X, y) возвращает метрику (accuracy/R2) и применяется для быстрой оценки. В свою очередь, метод predict_proba(X) возвращает вероятности, и он нужен для задач классификации.

  5. Наконец, метод transform(X) только трансформирует модель без обучения, и он редко используется напрямую.

Далее мы перейдем непосредственно к этапам, связанным с настройкой собственного пайплайна. Для начала мы рассмотрим некоторые типовые операции, которые могут вам потребоваться при работе с Pipeline.

Шаг 0. Доступ к шагам Pipeline и настройка параметров

Если нам необходимо получить доступ к шагам нашего пайплайна, то мы можем прибегнуть к нескольким различным способам.

Первый способ предлагает обращаться к шагам по индексу:

first_step = pipeline[0]  # ('scaler', StandardScaler())
first_transformer = pipeline[0][1]

Второй способ предполагает получение всех параметров пайплана:

all_params = pipeline.get_params()
print(all_params.keys())
# Вывод: 'scaler', 'classifier', 'scaler__with_mean', 'classifier__n_estimators' и т.д.

Но рекомендуемым является третий способ доступа к шагам пайплайна по имени

scaler = pipeline.named_steps['scaler']
classifier = pipeline.named_steps['classifier']

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

Так мы можем выполнить прямую установку нужного параметра. Например:

pipeline.set_params(classifier__n_estimators=100)

Либо можно передать нужные параметры через словарь

params = {
    'scaler__with_mean': True,
    'scaler__with_std': False,
    'classifier__max_depth': 10
}

pipeline.set_params(**params)

Выбор конкретного способа зависит от того, какие параметры вам необходимо установить или настроить.

Ну а теперь, когда мы определились с основными подготовительными действиями, давайте рассмотрим процесс пошагового создания полного конвейера. По сути, мы просто усложним пайплайн Hello World, приведенный в начале статьи.

Шаг 1. Определяем колонки

Для начала нам необходимо определить колонки для структуры входных данных. Реальные данные, которые подаются на вход, содержат колонки разных типов: числовые (возраст, доход, опыт, количество обращений), категориальные (город, профессия, метод оплаты, образование).

numeric_cols = ['age', 'income', 'years_experience', 'support_calls']
categorical_nominal_cols = ['city', 'profession', 'payment_method']  # Без порядка
categorical_ordinal_cols = ['education']  # С порядком
binary_cols = ['has_phone', 'has_email']

Шаг 2. Создаем пайплайны

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

# Числовой пайплайн

numeric_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),  # Заполняем пропуски
    ('scaler', StandardScaler())  # Масштабируем
])

# Номинальные категории (One-Hot Encoding)
nominal_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='constant', fill_value='unknown')),
    ('encoder', OneHotEncoder(sparse_output=False, handle_unknown='ignore'))
])

# Порядковые категории (Ordinal Encoding)
ordinal_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
    ('encoder', OrdinalEncoder(categories=[['school', 'college', 'bachelor', 'master', 'phd']]))
])

# Бинарные колонки (просто заполняем пропуски)
binary_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy='constant', fill_value=False))
])

Шаг 3. Трансформеры

Затем ColumnTransformer применит разные трансформеры к разным колонкам параллельно.

preprocessor = ColumnTransformer([
    ('numeric', numeric_pipeline, numeric_cols),
    ('nominal', nominal_pipeline, categorical_nominal_cols),
    ('ordinal', ordinal_pipeline, categorical_ordinal_cols),
    ('binary', binary_pipeline, binary_cols)
])

Шаг 4. Добавляем модель

А этот шаг является, по сути, ядром промышленного ML‑пайплайна, так как именно здесь мы воплощаем главную идею нашего гайда: вся сложность предобработки и моделирования инкапсулирована в один объект.

full_pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(random_state=42))
])

По сути, без этой строки кода все предыдущие усилия по созданию preprocessor были бы просто набором трансформеров, которые легко сломать при использовании. Но с этой строкой наша система готова к применению в продуктивной среде.

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

Шаг 5: Визуализация Pipeline

Визуализация Pipeline нужна для быстрого понимания архитектуры конвейера, отладки и документирования: она позволяет одним взглядом оценить последовательность и вложенность шагов (включая ColumnTransformer и FeatureUnion), проверить правильность взаимодействия компонентов, увидеть, какие трансформеры применяются к каким колонкам, и легко обнаружить ошибки (например, пропущенный шаг или неверный порядок обработки).

Это критически важно при работе со сложными, многоступенчатыми конвейерами, где без визуализации трудно понять, что именно происходит с данными на каждом этапе, особенно когда вы возвращаетесь к проекту через несколько месяцев или передаёте его коллегам.

Пайплайн можно представить в текстовом и графическом виде:

from sklearn import set_config

# Текстовое представление
print(pipeline)

# Графическое (Jupyter Notebook)
set_config(display='diagram')
pipeline  

Pipeline в машинном обучении: как создавать сложные модели без боли и утечек данных - 2

Шаг Х. Типичная ошибка новичка и как ее избежать

В качестве завершающего шага давайте рассмотрим типичную ошибку, которую допускают многие новички при выполнении предобработки.

Предобработка вне Pipeline создает высокий риск утечки данных (data leakage) и гарантирует несоответствие между обучением и предсказанием, что делает вашу модель бесполезной в продуктивной среде.

Ниже небольшой пример неправильной предобработки вне Pipeline.

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
model = RandomForestClassifier().fit(X_train_scaled, y_train)

Здесь мы применяем fit_transform на всем X_train до того, как кросс‑валидация разобьет данные на подмножества (фолды). В результате информация из валидационных подвыборок «просочится» в обучающие через параметры масштабирования (среднее и стандартное отклонение), то есть произойдет утечка данных.

Правильным вариантом предобработки является выполнение данной операции внутри Pipeline.

pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('classifier', RandomForestClassifier())
])

cross_val_score(pipeline, X, y, cv=5)  

Подведем итог

Pipeline в машинном обучении — это не просто синтаксический сахар и не очередная абстракция ради абстракции. Это архитектурный паттерн, который превращает хаотичный набор трансформаций данных в предсказуемый, воспроизводимый и безопасный производственный конвейер.

Как вы убедились на примерах из этого гайда, Pipeline решает следующие проблемы: предотвращает утечку данных при кросс‑валидации, автоматически синхронизирует обработку обучающей и тестовой выборок и превращает сложный многошаговый процесс в единый объект, который можно сохранить, загрузить и использовать в продакшене одной строкой кода.

Главный вывод, который стоит вынести из этого руководства: любая модель сложнее линейной регрессии на сырых данных требует Pipeline. Начните с малого, постепенно усложняйте конвейеры, и ваши ML‑проекты перестанут быть источником головной боли при передаче в продакшен или другому разработчику. Pipeline — это инвестиция в надежность вашего кода и спокойствие вашей команды.

Pipeline в машинном обучении: как создавать сложные модели без боли и утечек данных - 3

Если хотите глубже разобраться с ML не только на уровне отдельных алгоритмов, присмотритесь к курсу «Машинное обучение. Продвинутый уровень». Там работаем с моделями, пайплайнами, качеством предсказаний и практическими задачами, где важно не просто обучить алгоритм, а понимать, что происходит с данными и результатами.

В рамках курса пройдет бесплатный открытый урок:

Хотите выбрать ещё несколько тем для прокачки? Больше бесплатных уроков июня — в дайджесте.

Автор: Andrey_Biryukov

Источник