Глубокое обучение (DL) произвело революцию в ряде областей за последнее десятилетие, от компьютерного зрения до естественного языка и обработки речи. В Feedzai большинство наборов данных, с которыми мы работаем, включают не неструктурированные данные, такие как изображения, естественный язык или звук, а табличные данные - таблицы, где строки представляют собой отдельные транзакции, каждая из которых помечена как мошенничество или нет. мошенничество, а столбцы - это атрибуты, такие как сумма, продавец или час дня. Глубокое обучение не так популярно для табличных данных, как для неструктурированных, но сообщество DL развивается быстрыми темпами, с огромным количеством опубликованных научных статей и большим количеством ресурсов, вложенных в исследования некоторыми из крупнейших технологические компании. Можем ли мы каким-то образом извлечь из этого пользу для улучшения наших моделей обнаружения мошенничества?

Типичный случай транзакции: табличные данные

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

Последние три транзакции являются мошенническими и действительно кажутся подозрительными: три транзакции по 200 долларов США с одной и той же карты на трех разных веб-сайтах за 3 минуты. Однако, если мы передадим набор данных с этими функциями классификатору, каждая транзакция будет рассматриваться независимо. Модель, обученная на этом фиктивном наборе данных, не смогла понять, что подозрительная активность здесь возникает из-за того, что одна и та же карта произвела три платежа на разных веб-сайтах за очень короткое время; он, вероятно (ошибочно) узнает, что эти три транзакции являются мошенническими, потому что 200,00 долларов США - это особенно рискованная сумма, хотя это, скорее всего, не так.

Обычно наша система обнаружения мошенничества обрабатывает это, обогащая каждую транзакцию или строку в таблице профилями: новыми столбцами, которые содержат прошлую информацию о объектах, участвующих в транзакции. В зависимости от варианта использования эти объекты могут включать не только кредитные карты, но также продавцов, электронные письма или идентификаторы устройств - любое поле, история которого с течением времени может помочь нам обнаружить мошенничество. Эти профили обычно включают агрегаты по скользящим окнам продолжительностью X минут, дней или даже месяцев; некоторые примеры:

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

В нашем фиктивном примере подсчет количества транзакций и суммы транзакции на карту за 5-минутные окна будет выглядеть следующим образом:

После добавления этих новых столбцов расширенный набор данных может выглядеть так:

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

Рекуррентные нейронные сети

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

  • даже с возможностью AutoML в Feedzai требуется время, чтобы вычислить сотни профилей перед обучением модели, и
  • в производстве, поддержание и обновление профилей и связанного состояния потребляет много памяти.

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

Как это работает

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

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

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

Существует несколько вариантов RNN, включая LSTM и GRU; мы в основном использовали ГРУ, так как их немного легче обучить, а результаты примерно такие же. На рисунке ниже показано, как это работает, когда мы обучаем модель на исторических данных.

  1. Мы начинаем с вектора состояния, инициализированного нулем для каждой карты.
  2. Затем мы берем последовательность транзакций карты, пропускаем ее через RNN и для каждой транзакции прогнозируем, является ли она мошеннической или законной, и обновляем состояние, которое передается следующей транзакции.
  3. Делаем это не с одной, а с партией карточек.
  4. После того, как у нас есть прогнозы для всех транзакций для карт в пакете, мы сравниваем их с метками и вычисляем убыток для каждой транзакции - показатель того, насколько наши прогнозы не соответствуют правильным меткам - и корректируем модель с помощью Стохастического градиентного спуска. .
  5. Промойте и повторите - продолжайте делать это с разными партиями карточек и наблюдайте, как модель со временем улучшается.

Обратите внимание, что каждая карта представляет собой отдельную последовательность со своим собственным вектором состояния, развивающимся с течением времени, но обучаемые блоки в модели (блоки, которые мы постепенно корректируем, чтобы уменьшить среднюю ошибку в процессе обучения) являются общими для последовательностей и шагов в каждой последовательности:

  • блок «Ячейка ГРУ», синий - блок, который создает новый вектор состояния для карты, учитывая ее предыдущий вектор состояния и входящую транзакцию;
  • блок «классификатор» оранжевого цвета - блок, который производит прогноз на основе вектора состояния и транзакции.

Мы пропустили большую часть деталей, но на самом деле каждый из этих двух блоков представляет собой нейронную сеть. Звучит сложно? Больше нет - с такими инструментами, как TensorFlow, Keras и PyTorch, это на самом деле легко реализовать. Большинство этих фреймворков предлагают реализации для ряда вариантов RNN.

Но можем ли мы использовать это в режиме реального времени?

Может показаться, что это невозможно использовать в режиме реального времени, учитывая задержку и ограничения памяти. В конце концов, чтобы получить прогноз для сотой транзакции карты, нам нужно будет скормить модели всю последовательность из 100 транзакций - и это число может стать намного больше! Уловка здесь в том, что информация, которую мы храним о последовательности, полностью закодирована в ее векторе состояния. Если мы храним в памяти таблицу с самым последним состоянием для каждой кредитной карты, при поступлении новой транзакции нам просто нужно:

  1. Получить текущее состояние для данного номера карты из памяти.
  2. Загрузите текущую транзакцию и состояние, которое мы только что получили, в ячейку GRU, получив новое состояние для этого номера карты.
  3. Передайте новое состояние последнему блоку, чтобы получить прогноз.
  4. Обновите таблицу состояний, указав новое состояние для данной карты.

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

Забрать

До сих пор в каждом случае мы пробовали похожие модели RNN, они превосходили наши предыдущие лучшие модели (Random Forests, XGBoost или LightGBM). В таблице ниже показаны улучшения отзыва транзакций при частоте ложных срабатываний 1% (общий базовый показатель) для двух разных наборов данных. Например, в наборе данных 1 это улучшение позволит сэкономить около 1 миллиона долларов США на мошенничестве в год. Эти модели не нуждались в особой настройке, поэтому мы ожидаем, что результаты можно было бы даже улучшить, если бы гиперпараметры были более тщательно оптимизированы.

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

Следующие шаги

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

Эта работа была выполнена в сотрудничестве с Марианой Алмейда и Бернардо Бранко.