сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Классический ML

Утечки данных в ML

Зачем это спрашивают

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

Профессиональный рефлекс, который хотят услышать, звучит так: идеальная метрика - не повод радоваться, а первый повод искать утечку. Кто ликует от AUC (area under the curve) 0.99, тот ещё не обжигался в проде.

// Типовые формулировки: «на валидации 0.99, в проде монетка - что ищешь?», «почему нельзя fit скейлера до сплита?», «как разрезать данные, если у одного пользователя много событий?».

Что это такое и самая наглая её форма

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

Прямее всего выглядит утечка целевой переменной - когда признак появляется одновременно с ответом или уже после него. «Дата оплаты» в задаче про прогноз оплаты. «Счёт закрыт» в прогнозе оттока. Такой признак выглядит как гениальный предиктор, потому что он и есть ответ, просто переодетый.

// Проверка простая и всегда одна и та же: в тот момент, когда модель делает прогноз в бою, значение этого признака уже существует и известно? Если нет, выкидывай, каким бы сильным он ни казался на графике важности.

утечка целевой переменной
признак доступен только вместе с ответом или после него

Тихая утечка через подготовку данных

Эта версия куда коварнее, потому что выглядит совершенно невинно. Ты обучил скейлер, заполнитель пропусков, PCA (principal component analysis) или отбор признаков на всём датасете, а разбил на обучение и тест уже потом. Формально ты ничего про ответы не подглядел - но статистики тестовой части попали в обучающую, и оценка перестала быть честной.

В кросс-валидации то же самое происходит ещё тише: применил преобразование ко всем данным один раз до разбиения на части, и каждая часть теперь знает что-то про остальные.

// Лечится это не бдительностью, а конструкцией: препроцессинг заворачивают в Pipeline, и тогда он обучается внутри каждого фолда заново, только на его обучающей половине. Проверочная часть остаётся по-настоящему невидимой, и оценка перестаёт врать.

Pipeline
связка препроцессинга и модели, которая обучается целиком внутри фолда

Время, группы и таргет-энкодинг

Утечка времени: если данные привязаны к датам, а разбиение сделано случайно, в обучение попадёт завтрашний день, и модель будет «предсказывать» вчера, зная про завтра. Лечение единственное - резать по времени: обучение до какого-то момента, проверка после.

Утечка групп: когда у одного объекта несколько записей - снимки одного пациента, ракурсы одного товара, события одного пользователя, - при случайном разбиении часть из них попадёт в обучение, а часть в проверку. Модель запомнит сам объект и получит отличную метрику, не научившись ничему. Режут по группам.

// И отдельная ловушка: кодирование категории средним значением ответа, посчитанным по всем данным сразу. Это буквально впускает ответ в признак. Делают такое кодирование out-of-fold - строку кодируют по остальным частям данных, не включая её саму.

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

Как отвечать: «Валидация даёт AUC 0.99, в проде - как монетка. Что ищешь?»

Утечку. Такой разрыв почти всегда означает, что при обучении модель видела то, чего в проде нет. Сначала смотрю важность признаков: если один доминирует, проверяю, доступен ли он в момент предсказания и не кодирует ли ответ напрямую или окольным путём. Потом проверяю пайплайн - не обучены ли скейлер, заполнитель пропусков или отбор признаков на всём датасете до разбиения. И проверяю само разбиение: временные данные должны быть разрезаны по времени, а связанные записи по группам. Дальше убираю подозреваемого и смотрю, не он ли один и тянул всю метрику.

Диагностический маршрут от самого частого к более редкому, с проверкой в конце. Так отвечает тот, кто эту ошибку уже разбирал на собственном проекте.

На чём валят

  • Обучать скейлер или заполнитель пропусков на всём датасете до разбиения: статистики проверки утекают в обучение.
  • Случайное разбиение временных данных: будущее оказывается в обучении, метрика оптимистична, прод рушится.
  • Несколько записей одного объекта по обе стороны разбиения: модель его запомнила, а не обобщила.
  • Кодировать категорию средним ответа по всем данным без out-of-fold: ответ утекает прямо в признак.
  • Радоваться идеальной метрике на валидации вместо того, чтобы сразу пойти искать утечку.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 13, остальные разбираются в тренажёре.

  1. #data_leakage1 / 5
    Модель показала AUC 0.99 на валидации, но в проде работает как подбрасывание монеты. Первое подозрение?
    A)Модель серьёзно недообучена, стоит добавить эпох и увеличить глубину сети
    B)Утечка данных: на валидации модель имела доступ к тому, чего нет в проде
    C)Валидационная выборка оказалась слишком большой
    D)Метрика AUC не подходит для этой задачи в принципе
    показать ответ и разбор
    +B)Утечка данных: на валидации модель имела доступ к тому, чего нет в проде

    // разбор: Почти идеальная метрика на валидации при провале в проде — классический симптом утечки: модель на обучении видела признак, несущий ответ, которого в реальном предсказании нет. Недообучение дало бы низкую метрику и на валидации, размер выборки так не ломает прод, а AUC для ранжирования вполне уместна. Первым делом ищут фичу-читера.

  2. #data_leakage2 / 5
    Предсказываем, оплатит ли клиент заказ. Какая фича почти наверняка даёт target leakage?
    A)Категория товара, выбранного клиентом в заказе
    B)Количество прошлых заказов клиента на момент оформления
    C)Дата и время зачисления оплаты по этому заказу
    D)Регион доставки, указанный при оформлении заказа
    показать ответ и разбор
    +C)Дата и время зачисления оплаты по этому заказу

    // разбор: Дата зачисления оплаты существует только ПОСЛЕ факта оплаты — на момент, когда мы прогнозируем оплату, её нет. Такая фича прямо кодирует таргет, и модель получит идеальную метрику на истории, но в проде значения не будет. Категория, история заказов и регион известны в момент оформления и утечки не несут. Правило: фича должна существовать на момент предсказания.

  3. #data_leakage3 / 5
    Пропуски в признаках заполнили медианой, посчитанной по всему датасету, и потом разбили на train/test. В чём проблема?
    A)Медиана — плохой выбор, надо было заполнять средним значением
    B)Пропуски перед обучением заполнять не стоит, лучше удалять строки
    C)Проблемы нет: заполнение пропусков от порядка операций не зависит
    D)Медиана впитала значения теста — статистика теста утекла в обучение
    показать ответ и разбор
    +D)Медиана впитала значения теста — статистика теста утекла в обучение

    // разбор: Медиана, посчитанная по всему датасету, включает и тестовые строки — значит статистика теста просочилась в подготовку трейна (train-test contamination). Impute, как и scaling, обучают ТОЛЬКО на train, а к test применяют уже готовое значение. Медиана против среднего тут вторична, удалять строки не обязательно, а порядок операций как раз критичен.

  4. #data_leakage4 / 5
    Почему масштабирование и отбор признаков нужно класть ВНУТРЬ кросс-валидации через Pipeline?
    A)Иначе препроцессинг обучается на всех фолдах сразу и каждый фолд подглядывает остальные
    B)Pipeline заметно ускоряет кросс-валидацию за счёт внутреннего кэширования промежуточных результатов
    C)Без Pipeline не получится применить более одного препроцессора
    D)Так требуется синтаксисом sklearn, иначе код не запустится
    показать ответ и разбор
    +A)Иначе препроцессинг обучается на всех фолдах сразу и каждый фолд подглядывает остальные

    // разбор: Если fit_transform сделать на всём датасете до CV, статистики (среднее, отобранные фичи) вбирают все фолды, и каждый валидационный фолд оказывается «подсмотрен» на этапе препроцессинга — оценка качества оптимистично смещена. Pipeline переносит fit препроцессора внутрь каждого train-фолда, так что валидационный фолд остаётся честно невидимым. Дело в корректности оценки, не в скорости или синтаксисе.

  5. #data_leakage5 / 5
    Прогноз спроса по историческим продажам разбили на train/test случайно. Какую утечку это создаёт?
    A)Никакой: случайное разбиение — золотой стандарт для табличных данных
    B)Temporal leakage: в трейн попадает будущее относительно теста
    C)Group leakage: один товар оказался в обеих выборках
    D)Target leakage: таргет напрямую попал в признаки
    показать ответ и разбор
    +B)Temporal leakage: в трейн попадает будущее относительно теста

    // разбор: На временных данных случайный сплит перемешивает даты, и в обучение попадают дни ПОЗЖЕ тех, что в тесте, — модель фактически заглядывает в будущее, а метрика выходит оптимистичной. Нужен time-based split: трейн до некоторой даты, тест после, валидация тоже хронологическая. Это не про группы и не про прямое попадание таргета, а именно про нарушение хронологии.

дальше

Теорию прочитали. Навык ставится повторением

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