No history yet

Инженерия признаков

От сырых данных к ценным признакам

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

Продвинутая обработка пропусков

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

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
import numpy as np

# Пример данных с пропусками
X = np.array([
    [1, 2, np.nan],
    [3, 4, 5],
    [np.nan, 6, 7],
    [8, 9, 10]
])

# Создаем объект импутера
imputer = IterativeImputer(max_iter=10, random_state=0)

# Обучаем и трансформируем данные
X_filled = imputer.fit_transform(X)

print(X_filled)

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

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

Кодирование категорий и утечка данных

Категориальные признаки с большим количеством уникальных значений (высокой кардинальностью), например, почтовые индексы или ID товаров, создают проблему. Стандартное One-Hot Encoding порождает тысячи новых столбцов, делая модель громоздкой и медленной. Здесь на помощь приходит целевое кодирование, или

Идея проста: каждая категория заменяется средним значением целевой переменной для этой категории. Например, если мы предсказываем отток клиентов, категорию «Город А» можно заменить на средний процент оттока в этом городе. Звучит отлично, но здесь кроется главная опасность: (data leakage).

Если вычислять среднее по всей выборке, а затем использовать его для обучения, модель получит информацию о целевой переменной напрямую. Чтобы этого избежать, всегда вычисляйте значения для кодирования только на обучающей выборке и применяйте их к валидационной и тестовой. Еще надежнее — использовать схемы с кросс-валидацией, где для каждой части (фолда) среднее вычисляется по остальным частям.

Автоматизация конвейеров обработки

В реальных наборах данных часто смешаны числовые и категориальные признаки, и к каждому типу нужно применять свою логику обработки: к числовым — масштабирование и импутацию, к категориальным — кодирование. Объединить эти шаги в единый конвейер помогают инструменты Scikit-learn.

Lesson image

ColumnTransformer — это мощный инструмент, который позволяет применять разные преобразования к разным столбцам датасета. Вы можете указать, что числовые столбцы нужно обработать одним пайплайном (например, импутация + масштабирование), а категориальные — другим (импутация + OneHotEncoder). Все это объединяется в один шаг, который легко встраивается в общий пайплайн модели.

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder

# Определяем шаги для числовых признаков
numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())])

# Определяем шаги для категориальных признаков
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))])

# Создаем препроцессор с ColumnTransformer
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, ['age', 'income']),
        ('cat', categorical_transformer, ['city', 'gender'])])

# Теперь preprocessor можно встроить в пайплайн с моделью
# model = Pipeline(steps=[('preprocessor', preprocessor),
#                         ('classifier', LogisticRegression())])

Помимо ColumnTransformer, существует и FeatureUnion. Он применяет несколько преобразователей к одному и тому же набору данных параллельно и объединяет их результаты. Это полезно, когда вы хотите извлечь из одних и тех же данных признаки разного типа, например, посчитать и TF-IDF, и длину текста для текстовых данных.

Создание таких конвейеров не только упорядочивает код, но и является ключевым элементом для предотвращения утечки данных. Все параметры преобразований (например, среднее для импутации, параметры масштабирования) вычисляются строго на обучающих данных (fit_transform) и затем применяются к тестовым (transform), что гарантирует честную оценку модели.

Quiz Questions 1/5

В чем заключается основной принцип работы итеративной импутации для заполнения пропущенных значений?

Quiz Questions 2/5

Какая основная опасность связана с использованием целевого кодирования (Target Encoding)?

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