Собесов

ML — спрогнозировать бинарный target по клиентским признакам

ML / Data ScienceБинарная классификацияСредняяMiddle

Условие

Имеется выборка по клиентам со списком признаков:

ID, SEX, CHILD_BOOL, REALTY_BOOL, HAVE_ACCOUNT_BOOL, EMAIL_BOOL, DCI, PROFIT_FAMILY, UCI, FOREIGN_PASSPORT_BOOL, SIML, EDUCATION, TRANSPORT_AMOUNT, target

Где target — бинарный флаг (1/0). Любым выбранным методом постройте модель, прогнозирующую target. Обоснуйте выбор по максимально возможному количеству критериев. Дополнительно: стабилен ли ваш прогноз? Не переобучили ли вы модель? Объясните почему.

Задача проверяет не «получите AUC X», а процесс: декомпозиция, EDA, выбор модели, валидация, разговор о переобучении.

Решение

Шаг 1. Понять задачу и метрику

  • Что значит target=1 бизнес-вижн? (например, «откликнулся на предложение» / «дефолт»). От ответа зависит, что считать ошибкой первого/второго рода.
  • Сбалансирован ли таргет? Если редкий — accuracy бесполезна, нужны ROC-AUC, PR-AUC, recall@k.
  • Стоимость FP/FN. Скоринг на дорогой продукт — recall важнее; антифрод — precision.

В отсутствие подробностей берём как baseline ROC-AUC + F1 на пороге 0.5, потом обсуждаем оптимальный порог.

Шаг 2. EDA

import pandas as pd
df = pd.read_excel("data.xlsx", sheet_name="Задача1")
 
print(df.shape, df.dtypes)
print(df.target.value_counts(normalize=True))
print(df.describe(include="all"))
print(df.isna().mean().sort_values(ascending=False))

Что искать:

  • Доля target=1. Если 1–5% — классовый дисбаланс, нужны class_weight / SMOTE / specialized loss.
  • Распределения: PROFIT_FAMILY, DCI, UCI могут иметь длинные хвосты и нули — обычно нужна логарифм-трансформация.
  • Категориальные булевы: проверить связь с target через groupby(col).target.mean() — это уже даёт прокси-силу признака.
  • Утечки: ID — не признак (выбросить).

Шаг 3. Препроцессинг и валидация

Разбиваем данные до любого fit, чтобы не подсунуть тесту знания о трейне:

from sklearn.model_selection import StratifiedKFold, train_test_split
 
X = df.drop(columns=["ID", "target"])
y = df["target"]
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

Преобразования (в Pipeline, чтобы fit-ить только на train):

  • бинарные оставляем как есть;
  • EDUCATION → one-hot или target encoding (с CV-фолдами, иначе утечка);
  • числовые: лог + стандартизация для линейных моделей; для деревьев — без преобразований.

Шаг 4. Выбор модели

Сравниваем три кандидата (по возрастанию сложности):

Модель Плюсы Минусы
Logistic Regression Интерпретируема, быстра, baseline Нелинейности захватывает только через feature engineering
Random Forest Нелинейности, устойчив к шуму Хуже калибровка вероятностей
Gradient Boosting (LightGBM/CatBoost) Лучшее качество на табличке Риск переобучения, нужна настройка
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import lightgbm as lgb
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_val_score
 
models = {
    "logreg": LogisticRegression(max_iter=2000, class_weight="balanced"),
    "rf":     RandomForestClassifier(n_estimators=500, class_weight="balanced", n_jobs=-1, random_state=42),
    "lgb":    lgb.LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=31, random_state=42),
}
 
for name, m in models.items():
    auc = cross_val_score(m, X_tr_prep, y_tr, scoring="roc_auc", cv=cv, n_jobs=-1).mean()
    print(name, round(auc, 4))

Решение принимаем по CV-AUC, не по trainscore.

Шаг 5. Стабильность и переобучение

«Стабилен ли прогноз?» — три проверки:

  1. CV vs holdout. Если AUC на 5-fold CV ≈ AUC на отложенном тесте — модель стабильна. Большая разница (0.85 на CV, 0.72 на тесте) = переобучение.
  2. Шум в фолдах. Стандартное отклонение AUC между фолдами. Если mean=0.80, std=0.04 — нестабильно.
  3. Bootstrap CI. Реземплируем тест и считаем 95% CI на AUC. Узкий — стабильно.

Признаки переобучения:

  • AUC на train сильно выше, чем на test/CV (у бустинга — типично, лечится min_data_in_leaf, ранней остановкой, регуляризацией).
  • Малое число наблюдений по сравнению с числом признаков: при n100n \approx 100 и 13 фичах LightGBM с дефолтами выучит шум. Имеет смысл отдать предпочтение logreg / небольшому RF.

Шаг 6. Интерпретация

  • LogReg: коэффициенты после стандартизации = «вклад» в логиты.
  • Tree-based: feature_importances_ или SHAP для глобальной/локальной интерпретации.
  • Разговор «почему именно эта модель» строим вокруг трёх осей: качество, стабильность, интерпретируемость для бизнеса.

Подводные камни

  1. Утечки. ID, дата создания, агрегаты, считающиеся «по будущему». Всегда проверяйте, что фичи доступны на момент предсказания.
  2. Дисбаланс классов. Не оценивайте по accuracy. Сразу AUC + PR-AUC + матрица ошибок на оптимальном пороге.
  3. Категориальные с малой кардинальностью + target encoding на одном фолде. Вызывает оптимистическое смещение CV. Используйте category_encoders.TargetEncoder внутри Pipeline или out-of-fold.
  4. Маленькая выборка. При n<200n < 200 предпочтительнее простые модели и регуляризация. CV — обязательно стратифицированный.
  5. Один тест-сплит → false confidence. На малой выборке одно разбиение не показатель. Делайте повторяемый k-fold + bootstrap CI.
  6. «Запомнил ID». Если в фичи попадает ID или сильный квази-айди (вроде SIML, который коррелирует с порядковой записью), модель «запомнит» обучение и не обобщится.

Эталонный ответ (структура)

  1. Метрика: ROC-AUC + F1, обоснование по бизнесу.
  2. EDA: распределения, пропуски, дисбаланс target.
  3. Pipeline: препроцессинг (log + стандартизация для линейных, OHE для EDUCATION).
  4. Модели: LogReg → RF → LightGBM, выбор по 5-fold CV-AUC.
  5. Стабильность: CV vs holdout, std AUC по фолдам, bootstrap CI.
  6. Защита от переобучения: ранняя остановка, регуляризация, ограничение глубины, контроль train/test gap.
  7. Интерпретация: SHAP / коэффициенты, бизнес-вывод.

Главное на собесе — проговорить процесс и риски. Конкретное число AUC второстепенно.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти