Всем привет! С вами на связи дата-сайентисты банка "Открытие" Иван Кондраков и Константин Грушин. В прошлой статье мы рассказывали про решение, которое позволило повысить эффективность в проверке гипотез для моделей. Если вы успели с ней ознакомиться, то уже знаете, что наша команда занимается разработкой и развитием пула моделей принятия решений о выдаче кредитных продуктов и банковских гарантий для малого и среднего бизнеса.

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

Проблематика

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

Как нам помогает справиться разработанный пайплайн:

  1. Повышает скорость разработки при отсутствии бейзлайна и готовых сниппетов, предоставляя уже проверенные методы и библиотеки;

  2. Отбор лучших факторов производится по провалидированному алгоритму и за адекватное время;

  3. Повышает уровень доверия к решению, минимизирует операционный и, как следствие, модельный риск;

  4. Является базисом, с результатом которого сравниваются новые гипотезы и методы с целью проверки вносимого вклада.

Рассмотрим, что представляет из себя пайплайн.

Решение

Условие задачи и ограничения пайплайна. У нас имеются собранные и первично подготовленные данные для обучения модели, а также есть рассчитанная целевая переменная (таргет). Требуется решить задачу классификации с использованием модели логистической регрессии. Зафиксирована необходимость энкодинга с помощью метода WoE (Weight of Evidence). Метрика, которую мы будем максимизировать — это GINI. При этом итоговая модель должна быть построена только на стабильных во времени факторах.

1. Выделение выборки обучения, валидации и тестирования

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

В зависимости от заданных пользователем параметров это может быть:

  • Разделение 60/20/20 (train/val/test соответственно) или любое другое;
    — в том числе использование в качестве тестирования выборки, выделенной во времени (т.н. OOT выборка);

  • Разделение со стратификацией по выбранным полям;

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

При этом осуществляем контроль качества разбиения с помощью следующих параметров:

  • Отклонение внутри страт и по всем стратам одновременно:
    — ожидаемой доли наблюдений (всех/целевых/нецелевых) от фактической в выборке(train/val/test);
    — уровня целевого события (train/val/test).

2. Проверка базовых статистик

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

Нет никакого смысла оставлять факторы, которые нельзя было рассчитать ретроспективно и, как следствие, нельзя будет рассчитать на применении. Равно как и нет смысла включать факторы бесполезные или почти бесполезные.

Поэтому на данном этапе избавляемся от факторов:

  • Со слишком высоким % пропусков;

  • Содержащих только одно значение;

  • Изначально размеченных как технические.

3. Первичный WOE-энкодинг и фильтрация

Сама процедура WOE-энкодинга не имеет прямого отношения к этой статье. Данный способ энкодинга хорошо раскрыт в книге “Intelligent Credit Scoring” Наима Сиддики, Senior Advisor известной в банковском секторе компании SAS. Так уж сложилось, что WOE-энкодинг (или как его еще называют “биннинг”, “бакетирование”) используется в банках повсеместно в части решения задач кредитного скоринга. Хотя на сегодняшний день придумано множество других эффективных методов решения задач классификации, но требование к интерпретируемости для части из них осталось. А такой энкодинг в связке с логистической регрессией позволяет точно оценить вклад в итоговую оценку клиента, что может быть полезно в том числе с точки зрения прозрачности для заказчиков модели. Чем, например, не могут похвастаться модели логистической регрессии без группировки значений в факторах или модели бустинга.

В своей работе мы используем open source библиотеку оптимального биннинга, разработанную Guillermo Navas-Palencia, ознакомиться с ней можно здесь. Применяем энкодинг WOE для каждого фактора, максимизируя выбранную дивергенцию с заданными ограничениями, получаем массив преобразованных факторов, из которых будем отбирать топ % или топ # лучших по метрике IV (Information Value) и GINI. Ознакомиться с метриками можно в данном разделе документации.

На данном этапе разработчик управляет следующими параметрами:

  • Показатели IV и GINI итогового WOE-фактора, которые моделист готов рассмотреть для кандидатов в итоговую модель;

  • Способ предварительного бакетирования;

  • Метрика, которую максимизируем (дивергенция);

  • Максимальное количество групп после предварительного бакетирования и минимальная доля наблюдений в группе;

  • Минимальное и максимальное количество групп итого;

  • Минимальная и максимальная доля групп итого;

  • Минимальное и максимальное количество наблюдений со сработавшим и несработавшим целевым событием в группе;

  • Граница p-value и алгоритм проверки;

  • Специальные значения, количество значащих цифр для разбиения и прочие.

А затем контролируем # и % отфильтрованных факторов. На данном этапе обычно отсекается от 50% до 70% всех подготовленных факторов.

4. Проверка стабильности факторов

На этом этапе оцениваем статистики PSI (Population Stability Index) и двухвыборочный критерий KS (Kolmogorov-Smirnov) для проверки стабильности факторов в различных срезах.

  1. Обучение vs Валидация. Проверяем адекватность распределения факторов в связке с адекватностью разбиения выборок;

  2. Стабильность во времени. Проверяем стабильность факторов по годам (изменения год к году), месяцам и прочим выбранным временным срезам. Оставляем только факторы, которые снизят вероятность деградации модели со временем.

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

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

5. Начинаем строить модели

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

В качестве модели используем класс statsmodels.Logit и собственную реализацию stepwise-регресии по следующему алгоритму в формате псевдо-кода:

Формируем точки отсечения и массивы для работы алгоритма:
    correlation_threshold := 0.7
    vif_treshold := 4
    p_value_threshold := 0.05
    n_max_factors := 30
    best_comb := [] # лучшая комбинация факторов
    modeling_result := [] # результаты оценки моделей

Работа алгоритма:
  FOR cnt_features от 1 до n_max_factors:
      # Forward step
      FOR каждый фактор:
          1	- ЕСЛИ добавленный фактор не проходит по 
            correlation_threshold
          ТОГДА переходим к следующему фактору
          2	- Строим модель по факторам из 
            best_comb + добавленный фактор
          3	- ЕСЛИ модель с добавленным факторов не проходит по 
            p_value_threshold
              ИЛИ
            vif_treshold
              ИЛИ
            знаку коэффициента перед WOE-факторов
          ТОГДА переходим к следующему фактору
          ИНАЧЕ добавляем в modeling_result построенную модель
      # Store results (1)
      СОРТИРУЕМ modeling_result по среднему GINI train и val
      ПОЛУЧАЕМ комбинацию с лучшим средним GINI и запишем в best_comb
      # Backward step
      FOR каждый фактор:
          1	- ЕСЛИ cnt_features <= 1 ТОГДА пропускаем backward-step
          2	- Проводим аналогичную процедуру п.1-3 forward step 
          но с заменой предпоследнего фактора из best_comb 
          рассматриваемым фактором
      # Store results (2)
      СОРТИРУЕМ modeling_result по среднему GINI train и val
      ПОЛУЧАЕМ комбинацию с лучшим средним GINI и запишем в best_comb

Таким образом остановка алгоритма произойдет либо по достижению n_max_factors, либо в момент, когда не останется факторов, прошедших заданные условия (по p-value, корреляциям и т.п.). Лучшая модель будет определена как лучшая на среднем качестве GINI на обучающей и валидационной выборках для определенного количества факторов.

6. Отсечение по приросту GINI

Максимизируя качество модели, не забываем о модельном риске, который несет большое количество факторов в модели. Поэтому мы готовы на компромисс между количеством факторов и качеством модели. Поэтому на данном этапе производим отсечение по приросту качества модели при последовательном добавлении от лучшего до худшего фактора по GINI в модель. Разумным считаем не добавлять фактор и следующие, если добавление фактора вносит менее чем 0,3% абсолютного роста качества модели на валидационной выборке.

На графике ниже пример выхода на плато качества модели и, соответственно, пользы от такого отсечения. Когда зеленая линия (прирост качества) пересекает красную (точку отсечения) — мы можем остановиться и не рассматривать следующие модели.

Пример используемого графика по приросту GINI
Пример используемого графика по приросту GINI

7. Корректировка факторов

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

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

Например, для фактора "Федеральный закон, в рамках которого запрошена банковская гарантия" из заявочной информации запроса на банковскую гарантию встречаются различные литералы. Их смысл может быть один: "44-ФЗ" и "44ФЗ" отличны только с точки зрения актуальности системы, в которой этот литерал был присвоен и могут быть объединены в одну группу оценки на данном этапе. Стоит отметить, что с необходимостью таких корректировок мы перестали сталкиваться после внедрения инструмента генерации длинного списка факторов для рассмотрения в модели. Напомним ссылку на нашу статью по этой теме: если вы все еще с ней не ознакомились, то настоятельно рекомендуем.

Читатель имеет полное право возразить, что изменение распределения факторов может негативно сказаться на качестве как фактора, так и модели. И будет абсолютно прав. Можно также сказать, что модель на скорректированных факторах может быть просто-напросто хуже модели, которая была чуть ниже в ранжировании по итогам stepwise, но в которую не пришлось бы вносить корректировки. Но, базируясь на нашем опыте, исходим из априорного факта, что какую бы комбинацию после этапа 5 ни возьмешь, нам пришлось бы вносить какие-либо корректировки в нее, и как следствие, повлиять на качество.

8. Обучение итоговой модели

По итогам корректировок мы обучаем итоговую модель на скорректированных факторах и оцениваем ее качество на выборках обучения, валидации и тестирования. Рассчитываем интересующие нас статистики и сводники по разработанной модели. Затем детально проверяем логику расчета вошедших в нее факторов, делаем review модели и кода внутри команды, а затем отдаем на проверку независимому валидатору (привет нашему коллеге Леше!).

Модель построена, проверки пройдены, слышим звук уведомлений, смело проверяем телефон и видим приятные слова и благодарности от коллег.

9. Интегрирование модели

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

Реализация стекинга моделей логистической регрессии
Реализация стекинга моделей логистической регрессии

Перед выполнением стекинга оцениваем каждой моделью логистической регрессии выборку для построения общей модели в соответствии с правилами для применения модели. Дальнейшим шагом является использование трансформера векторов для стекинговой модели. Первый из них, Missing Filler, заполняет пропущенные значения, например, на среднее, либо на некую оценку уровня целевого события для наблюдений с пропуском. Второй, Standard Scaler, является стандартным инструментом приведения вектора к нулевому среднему и стандартному отклонению равному единице. На последнем этапе рассматриваем полученные вектора как факторы и обучаем стекинговую модель.

Итого

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

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

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

Комментарии (1)


  1. CrazyElf
    00.00.0000 00:00

    Почему-то график "Динамика Gini" вставлен очень расплывчатый, глаза режет. Нельзя ли заменить на более чёткий? Спасибо, было интересно прочитать.