Всем привет! Мы команда прикладных исследований и разработки моделей глубокого обучения Альфа-банка. В этой статье мы хотели бы рассказать о наших самых актуальных разработках в области нейросетевых подходов к решению задачи кредитного скоринга физических лиц. Ранее мы уже писали на эту тему:
Нейросетевой подход к моделированию транзакций расчетного счета
Нейросетевой подход к кредитному скорингу на данных кредитных историй
Последняя статья предыдущего цикла датирована 2023 годом. За это время мы смогли значительно продвинуться в исследовании способов решения данной задачи.
Постановка задачи
Коротко напомним про постановку проблемы. Суть кредитного скоринга заключается в оценке рисков банка при выдаче кредита заемщику. Для этого вводится понятие вероятности дефолта (далее — PD). Классическое определение дефолта — наличие просроченной задолженности в течение более 90 дней подряд на горизонте года от даты скоринга. Пример случая дефолта приведен на картинке ниже.

Для каждого клиента модель рассчитывает скоринговый балл (далее — скор), на основе которого кредитный конвейер делит клиентов на надежных и ненадежных заемщиков.
Наша PD модель является модульной и состоит из двух больших компонент: градиентного бустинга на табличных данных и нейросетевого скора, которые затем смешиваются с помощью логистической регрессии. Мы остановимся на разборе архитектуры нейросетевого скора.
Он состоит их 5 основных компонент:
Модуль на карточных транзакциях (далее КТ).
Модуль на транзакциях расчетного счёта (далее ТРС).
Модуль на данных кредитной истории (далее БКИ).
Графовая нейронная сеть на данных социальных связей клиентов.
Common модуль, объединяющий результаты предыдущих 4х компонент.

В этой статье мы разберем первые три компоненты, а компонентам 4 и 5 посвятим отдельные публикации.
Краткое напоминание
Напомним наш подход к решению описанной задачи.
В банке накоплено много источников данных, имеющих природу последовательностей. Такие данные являются отличными кандидатами на тестирование нейросетевого подхода для моделирования целевой переменной с их помощью. Основными доменами, подходящими под задачу кредитного скоринга, являются карточные транзакции, транзакции расчётного счёта и кредитная история.
Классическим подходом для построения моделей на этих данных уже долгое время является анализ этих источников как табличных, генерация фичей, проверка гипотез и построение интерпретируемой модели на их основе.
Мы решили работать с этими данными методами, унаследованными из задач обработки естественного языка. Основные этапы их обработки заключаются в следующем:
Приводим вещественные признаки к категориальным, заменяя значения признака на номер квантиля, в который это значение попадает.
Для каждого категориального признака получаем векторное представление — эмбеддинг.
Конкатенируем представления для разных признаков и получаем общий эмбеддинг данного клиента для данного домена данных.
Дальше последовательность общих эмбеддингов идёт на вход нейронной сети.
На выходе получаем некоторое закодированное векторное представление домена для данного клиента.
Более подробно этот подход и использовавшиеся ранее архитектуры описаны в статьях, ссылки на которые приведены в начале.
Архитектура решения
Чтобы не превращать этот текст в пересказ уже проделанной работы, оставим старые архитектуры за рамками статьи. Вместо этого сосредоточимся на изменениях, которые действительно повлияли на качество, а также честно разберём, какие идеи не взлетели.
Спойлер: таких оказалось больше, чем хотелось бы. Поехали!
Начнём с, казалось бы, очевидного, но на практике крайне важного наблюдения. По мере роста обучающей выборки качество нейросетевого скора стабильно улучшается. За время работы над моделью нам удалось расширить датасет, добавив данные за последние два года. В итоге распределение обучающей выборки теперь покрывает период с 2017 по 2024 год.
Это позволило заметно улучшить качество моделей, в том числе за счёт лучшего покрытия различных клиентских сегментов.
Впрочем, подход «смешать всё, что есть», не работает. Мы аккуратно чистили данные, анализировали распределения по датам и сегментам, сопоставляли их с target rate и только после этого формировали финальную выборку. Уже на этом этапе, за счёт более качественных данных и подбора гиперпараметров, удалось получить ощутимый прирост в сравнении с моделями прошлого поколения, что видно по графику ежемесячного аплифта к метрике Джини по трем базовым моделям.


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

Бизнес, к счастью, поддержал этот настрой — и мы запустили серию довольно смелых архитектурных экспериментов над базовыми моделями ТРС, КТ и БКИ.
Напомним, что в основе нашего подхода лежит обработка event-sequence данных с помощью последовательных архитектур (RNN или encoder-based Transformer), которые выступают в роли feature extractor’ов. Каждая такая модель независимо извлекает представление клиента в своём домене и обучается напрямую на задачу PD — это классический supervised-подход.
Однако в какой-то момент мы начали переосмысливать саму роль этих моделей. Вместо того, чтобы рассматривать их исключительно как независимые классификаторы, мы стали смотреть на них как на инструмент построения качественного векторного пространства клиентов, которое затем используется финальным агрегатором.
Прежде чем переходить к архитектурным изменениям, кратко опишем используемые последовательности.
В зависимости от домена данных используемые нами максимальные длины последовательностей существенно различаются:
БКИ: до 50 событий.
ТРС: до 550 транзакций.
КТ: до 750 транзакций.

Во всех случаях используется окно наблюдений длиной в один год. Мы также пробовали расширять его (например, для БКИ до трёх лет), однако это не дало ожидаемого прироста качества. При этом, после оптимизации обучения и инференса, мы рассматриваем возможность вернуться к этой идее и протестировать более длинные горизонты.
Отдельно отметим, что мы не используем явное кодирование временных промежутков (time gaps) — задача формулируется как event-sequence, где порядок событий уже несёт основной сигнал.
Смена функции потерь
Одним из самых сильных улучшений стала смена функции потерь. Вместо стандартной бинарной кросс-энтропии мы перешли к оптимизации ROC-AUC через pairwise log loss.
Интуитивно идея следующая: модель обучается не просто предсказывать вероятность дефолта, а правильно упорядочивать клиентов — так, чтобы дефолтные клиенты получали более высокий скор, чем недефолтные.
На практике это реализуется следующим образом:
Внутри батча выделяются положительные и отрицательные объекты.
Строятся попарные разности логитов.
Применяется логистическая функция потерь к этим разностям.
Такой подход позволяет напрямую оптимизировать ранжирование и лучше использовать данные, особенно в условиях дисбаланса классов. Этот переход дал один из самых сильных приростов качества за всё время экспериментов и стал нашим текущим бейзлайном.
Hard negative mining
Очевидный следующий шаг по улучшению качества ранжирования это использовать hard negative mining.
Коротко напомним суть подхода: при обучении на pairwise log loss модель получает наибольший сигнал от «сложных» пар — тех случаев, где модель ошибается или не уверена (например, когда недефолтный клиент получает скор выше дефолтного).
Предвкушая высокие аплифты, мы столкнулись с сильным ухудшением качества…
Но потом мы выдвинули гипотезу, что это связано с особенностями пайплайна: для экономии памяти мы разбиваем датасет на чанки, внутри которых формируются батчи. Это снижает потребление памяти примерно в два раза, но ухудшает качество перемешивания данных. В результате «сложные» пары просто не попадают в один батч, и эффект hard mining существенно снижается.
Трансформеры
После успешного внедрения ранжирования мы перешли к попытке заменить базовую RNN-архитектуру на трансформер.
В качестве базовой конфигурации использовался encoder-only трансформер:
размер скрытого пространства — 256;
количество голов внимания — 8;
feed-forward слой — 1024,
глубина — 3 блока.
На вход подавалась последовательность эмбеддингов, дополненная CLS-токеном и позиционным кодированием. Для каждого источника архитектуры немного менялись (но не сильно). В общем виде это выглядит так:

Входе экспериментов мы исследовали различные компоненты:
Добавление CLS-токена (дало базовый прирост).
Подбор глубины (оптимум — 3 блока).
Функции активации (SiLU, GELU, SwiGLU).
Нормализации (лучший результат показал RMSNorm против LayerNorm).
Отдельно отметим, что SiLU и SwiGLU дали наиболее стабильный прирост, что согласуется с наблюдениями из современных архитектур.
Эксперименты с более сложными механизмами внимания
Мы также экспериментировали с более сложными механизмами внимания, включая gated attention из архитектуры Qwen.
В чистом виде этот подход не дал существенного прироста, однако оказался полезным как механизм пулинга. В комбинации с CLS-токеном это позволило получить более информативное представление последовательности.

На графике представлены аплифты разных стратегий агрегирования векторного пространства после энкодера против бейзлайна только на CLS‑токене, где лучший результат — комбинация между Gated attention с CLS.
Обучение проводилось с использованием уже с комбинированной функции потерь, где суммируется бинарная кросс-энтропия и pairwise log loss, так как что-то одно не давало сильных результатов.
Подбор весов между ними осуществлялся экспериментально.
Мы также придерживались современных лучших практик обучения трансформеров, включая аккуратный подбор weight decay в AdamW и использование продвинутых техник регуляризации вместе с грамотным batch_size.
Прунинг весов
После стабилизации архитектуры мы попробовали ещё одно направление — прунинг весов.
Изначально мотивация была инженерной (ускорение и уменьшение модели), однако на практике оказалось, что прунинг можно рассматривать как механизм регуляризации.
Мы исследовали:
unstructured pruning (обнуление малых весов),
pruning attention-head’ов,
частичный pruning feed-forward слоёв.
После этого модель дообучалась.
На практике мы увидели, что:
умеренный прунинг почти не ухудшает качество,
иногда даёт небольшой прирост (за счёт регуляризации),
агрессивный прунинг приводит к деградации.
При этом выигрыш по скорости оказался ограниченным:
Pruning family |
Degree |
OOT uplift |
Unstructured |
10 % |
+0.08% |
Unstructured |
20 % |
+0.27% |
Unstructured |
30 % |
-0.18% |
Unstructured |
50 % |
-1.74% |
Attention heads |
10% |
+0.03% |
Attention heads |
30% |
-0.41% |
Attention heads |
50% |
-3.08% |
FFN |
10 % |
+0.11% |
FFN |
20 % |
-0.36% |
FFN |
40 % |
-2.64% |
Combined |
15% |
-0.22% |
Combined |
30% |
-9.84% |
Перейдем к кульминации
Несмотря на все архитектурные улучшения, трансформер не смог обойти идею ранжирующих RNN Feature extractor’ов. Финальные значения аплифта по Gini для наших моделей:

Анализируя результаты мы пришли к выводу, что ключевое преимущество RNN — способность последовательно накапливать информацию от события к событию. В отличие от трансформеров, которые обрабатывают последовательность более «плоско», RNN естественным образом формируют историческое состояние.
Эта идея перекликается с современными исследованиями, например History Tokenize Transformer.
Однако на текущий момент лучшим решением остаётся:
RNN как feature extractor.
Обучение через ранжирование.
Независимое обучение по доменам.
Именно эта конфигурация даёт наиболее информативные представления для финального агрегатора. Однако мы очень верим и любим технологию трансформеров и продолжим исследовать способы ее применения в нашей задаче. Да, мы пока что не изобрели лампочку, но зато мы теперь знаем 1000 способов как её сделать невозможно!).
Также указанные подходы можно (и нужно!) распространять на прочие домены данных, имеющие природу последовательностей, например, на данные чеков, данные логов действий в мобильном приложении и прочие. О дальнейших результатах наших экспериментов мы обязательно сообщим в следующих публикациях.
Badsanta83
Я вообще ничего не понял. Навалили графиков понятных только вам. Что вы подали модели на вход для обучения? Как разметили датасет? Какая классификация бинарная, многоклассовая? Как распределили классы по каким признакам?
Что вышло в итоге - как работает модель, насколько успешно отшивает платёжеспособных и раздаёт кредиты алкашам в состоянии банкротства?