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

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

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

Краткий обзор методов выглядит следующим образом:

а) День 1: базовая модель с использованием классификатора случайного леса (текущая статья)

б) День 2: исправление и очистка данных от асимметрии (найдено здесь)

c) День 3: Разработка и сокращение функций (найдено здесь)

г) День 4: Настройка гиперпараметров (найдено здесь)

д) День 5: Ансамблевые модели (найдено здесь)

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

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

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

Деловой контекст

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

«Наборы данных содержат транзакции, совершенные по кредитным картам в сентябре 2013 года держателями карт из Европы. Этот набор данных представляет транзакции, которые произошли за два дня, где у нас есть 492 мошенничества из 284 807 транзакций. Набор данных сильно несбалансирован, на положительный класс (мошенничество) приходится 0,172% всех транзакций.

Он содержит только числовые входные переменные, которые являются результатом преобразования PCA. К сожалению, из соображений конфиденциальности мы не можем предоставить исходные функции и дополнительную справочную информацию о данных. Признаки V1, V2, … V28 являются основными компонентами, полученными с помощью PCA, единственные признаки, которые не были преобразованы с помощью PCA, — это «Время» и «Количество». Функция «Время» содержит секунды, прошедшие между каждой транзакцией и первой транзакцией в наборе данных. Функция «Сумма» — это сумма транзакции, эту функцию можно использовать, например, для зависимого от затрат обучения. Функция «Класс» — это переменная ответа, которая принимает значение 1 в случае мошенничества и 0 в противном случае».

Теперь, когда у нас есть общее представление о том, что должны означать данные, давайте раскрутим блокнот Jupyter и начнем программировать!

Загрузить данные и проверить визуально

Импортируйте файлы csv как кадр данных pandas, а затем проверьте случайные выборки из набора данных вместе с головой и хвостом (это необходимо для того, чтобы убедиться, что в верхней или нижней части входных файлов нет ничего необычного, например случайных заголовков).

Проверка достоверности данных

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

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

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

Выявление «плохих» столбцов

Далее я собираюсь выяснить, есть ли функции, требующие очистки данных.

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

Рабочий процесс моделирования

Подготовка данных

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

Я установил random_state так, чтобы результаты повторялись. Кроме того, даже для других наборов классификационных данных эффективная практика во время тренировочного теста разделяется на стратификацию в соответствии с распределением классов. Это становится еще более важным для сильно несбалансированных наборов данных, таких как приведенный выше. Обратите внимание, что последний параметр равен stratify = y. Этот параметр указывает методу тестирования поезда, что «во время разделения убедитесь, что соотношение классов остается одинаковым в складках поезда и теста».

Оценка базовой эффективности

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

Выяснилось, что этот набор данных содержит менее 0,2% положительных экземпляров (492 позиции). Если вы визуализируете в виде гистограммы, класс меньшинства будет едва заметен.

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

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

Прогнозное моделирование

Теперь давайте перейдем к веселой части!

Я создал экземпляр случайного лесного классификатора из sklearn, а затем вызвал метод подгонки для данных Train. Обратите внимание, что случайное начальное число было установлено на 42. Вы можете выбрать любое случайное начальное число, но опубликовать его, чтобы другие могли воспроизвести ваши результаты.

Отображение показателей эффективности

Я собираюсь вызвать функцию внутри файла .py, который я собрал для очистки основных блокнотов Jupyter. Это распечатывает отчет о классификации и базовые данные, необходимые для отображения матрицы путаницы.

Как мы интерпретируем отчет о классификации? В несбалансированных наборах данных обычно гораздо полезнее смотреть на метрики только для класса меньшинства (в данном случае 2-я строка, соответствующая Fraud ), а не на общую точность, которая, несмотря на то, что она близка к 100% бесполезно по причинам, изложенным ранее. Давайте также отобразим матрицу путаницы для наглядности:

Интерпретация показателей

На первый взгляд производительность кажется вполне приличной. Из 98 фактических случаев мошенничества наша модель предсказывает, что 78 из них являются мошенничеством, что дает истинное положительное значение (т.е. отзыв) 80%. Точность не так уж плоха и составляет 94%, что означает, что только 6% (в данном случае 5 образцов в правом верхнем углу) мошенничества, предсказанного классификатором, неверны (т.е. ложные срабатывания).

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

F1 = 2*(точность * полнота)/(точность + полнота)

Одним из решений было бы использование обобщенной версии оценки F1, называемой оценкой Fbeta, с бета = 2, чтобы отдать приоритет отзыву над точностью. Но я собираюсь попробовать другой подход. Увидеть ниже!

Обратите внимание, что по умолчанию классификаторы sklearn предполагают, что отсечение вероятности составляет 50% при прогнозировании. Это может быть или не быть тем, чего хочет бизнес, когда вы переходите к производству. Если обнаружение случаев мошенничества более важно за счет допуска нескольких ложных срабатываний, то лучше снизить пороговое значение вероятности до менее 50%.

Но тогда возникает проблема: как мы можем сравнивать производительность модели, если само отсечение вероятности можно настроить так, как мы хотим? Оценки Precision, Recall, F1 зависят от вероятности и не могут быть использованы напрямую.

Пользовательский показатель классификации

Одним из возможных решений является создание пользовательской метрики, например:

В приведенном выше фрагменте кода используется кривая точного отзыва от sklearn, аналогичная ROC. Функция принимает фактические метки и прогнозируемые вероятности вместе с пороговым значением отзыва, которое нас интересует.

Используя Кривую точности воспроизведения, различные точки на кривой для каждого порога вероятности выводятся в списки. Затем значение чуть выше порога отзыва, который мы указали. Вышеупомянутая функция вызывается с использованием следующего фрагмента кода:

Используйте ранее подобранный классификатор для создания вероятностей, а не жестких меток классов. Затем они передаются в нашу функцию. Как видно из выходных данных, точность составляет 88%, когда полнота составляет 85%.

Если бы бизнес вернулся, чтобы проверить нас, мы бы представили модель вместе с выводами. Если бы вы знали, каковы затраты на неверную классификацию для FN и FP, то вы могли бы выяснить компромисс между затратами и выгодами от использования модели по сравнению с тем, что используется в настоящее время.

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

Оставайтесь с нами, чтобы узнать больше!

Большое спасибо hariskrishna tv за сотрудничество в этом проекте! Если вам понравилась эта статья, пожалуйста, проголосуйте. Я рад связаться с читателями на LinkedIn, если у вас есть конкретные вопросы