Debugging AI With Adversarial Validation
Статья описывает метод Adversarial Validation — простой способ обнаружения дрифта (внезапных изменений) в данных для AI/ML-моделей. Суть метода: два набора данных размечаются метками 0 и 1, затем обучается бинарный классификатор; если AUC ≥ 0.60, значит дрифт присутствует. Автор представляет CLI-инструмент ft_drift для обнаружения расхождений между двумя JSONL-файлами с данными для файн-тюнинга OpenAI. Метод не требует сложной инфраструктуры и позволяет через интерпретируемые модели (логистическая регрессия, случайный лес) определить первопричину дрифта. Hamel Husain рекомендует регулярно проверять все AI/ML-проекты на дрифт как высокоэффективную практику.
На протяжении многих лет я полагался на простой метод для выявления внезапных изменений во входных данных модели или обучающих данных, известных как «дрифт». Этот метод — Adversarial Validation1 — одновременно прост и эффективен. И лучшее в нём? Он не требует сложных инструментов или инфраструктуры.
Примеры того, как дрифт может вызывать баги в вашем AI:
Ваши данные для оценок существенно отличаются от входных данных, которые модель получает в продакшене, из-за чего результаты оценок вводят в заблуждение. Обновления промптов, функций, RAG и аналогичных элементов не учитываются в ваших данных для файн-тюнинга или обучения, что приводит к неожиданному поведению модели в продакшене.
Как бы тщательно вы ни работали, баги всё равно могут проскользнуть. Высокоэффективная практика — регулярно проверять все ваши AI/ML-проекты на дрифт.
Как это работает
Метод настолько прост, что может показаться несерьёзным. Вы точно не впечатлите им дата-сайентистов. Тем не менее он слишком ценен, чтобы его игнорировать.
Этот слайд из моего доклада об инструментах MLOps объясняет технику Adversarial Validation2:
Процесс выглядит следующим образом:
Соберите два набора данных для сравнения. Например: Обучающие данные из двух разных запусков файн-тюнинга Обучающие данные vs. данные для оценки Обучающие данные vs. данные из продакшена (приведённые к одному формату) Данные из двух разных временных периодов Создайте признаки из набора данных. Базовый пример создания признаков из токенов показан здесь.3 Присвойте набору данных №1 метку 0, а набору данных №2 — метку 1. Обучите бинарный классификатор (случайный лес, логистическую регрессию и т.д.) различать два набора данных. Если классификатор демонстрирует достаточную предсказательную способность (например, AUC ≥ 0.60), значит дрифт присутствует. Если вы использовали интерпретируемую модель (логистическую регрессию, случайный лес и т.д.), можно изучить метрики важности признаков, чтобы понять первопричину дрифта. Если вы используете более сложную модель (например, нейронную сеть), можно применить SHAP values или другие методы для понимания причин дрифта. Я рекомендую начинать с простой интерпретируемой модели.
Если этот процесс не обнаружил дрифт, это не означает, что дрифта нет. Это лишь значит, что мы не смогли его обнаружить с помощью выбранной модели и признаков.
Минимальный пример: ft_drift
Я работаю со множеством людей, которые файн-тюнят модели через OpenAI API. Я создал небольшой CLI-инструмент ft_drift, который обнаруживает дрифт между двумя JSONL-файлами в формате многоходового чата. На данный момент ft_drift обнаруживает дрифт только в шаблонах промптов, схемах и другой токен-основанный дрифт (в отличие от семантического дрифта). Тем не менее это хорошая отправная точка для понимания общей концепции adversarial validation. Вот демонстрация работы инструмента:
Демонстрация основана на реальном случае, когда непреднамеренное изменение шаблона промпта вызвало неожиданное поведение модели. Демо показывает, как инструмент обнаруживает различие между двумя наборами данных — file_a.jsonl и file_b.jsonl. Затем выводится таблица важных токенов, объясняющих дрифт, таких как END-UI-FORMAT, UI-FORMAT и т.д. Мы смогли применить инструмент и быстро найти первопричину проблемы. Код моделирования предельно прост и находится в ft_drift/model.py. Суть в том, что для начала не нужны сложные техники. Затем вы можете развить этот подход, добавив эмбеддинги в признаки для обнаружения семантического дрифта. Аналогично можно добавить дополнительные признаки вручную — количество ходов в разговоре, длину сообщений и т.д.
Примечания
Впервые я узнал об этой технике в 2016 году из этого поста Zygmunt Zając. На протяжении многих лет я видел, как эта техника применяется в различных контекстах, иногда под другими названиями.↩︎ В этом слайде используется слово «skew», которое в данном контексте взаимозаменяемо с «drift».↩︎ Для классического ML, если вы уже обучаете модель на этих данных, у вас, вероятно, есть пайплайн создания признаков, который можно переиспользовать.↩︎