Если вы проходили какую-либо курсовую работу по машинному обучению, вы, вероятно, оттачивали свои навыки на некоторых довольно чистых наборах данных. Может быть, ирис или MNIST. Это отличные наборы данных для обучения, но как только вас выпустят в дикую природу, чтобы практиковать науку о данных в реальном мире, вы быстро обнаружите, что данные никогда не бывают такими чистыми.
Существуют отсутствующие значения, недопустимые значения, несогласованные методы сбора и множество других потенциальных проблем. Тот, с которым я лично сталкивался чаще всего, — это дисбаланс.
В задачах классификации несбалансированный набор данных — это набор, в котором один или несколько классов сильно представлены по отношению к другому классу (классам).
Вы видите, что это всплывает во многих приложениях. Большую часть своей карьеры я провел в области профилактического обслуживания в авиационной сфере, и (к счастью) те отказы, которые я пытался предсказать, случаются примерно раз в 250 000 полетов.
Это крайний пример, поэтому сегодня мы сосредоточимся на чем-то более простом: обнаружении мошенничества с кредитными картами.
Введение данных
Мы будем использовать этот пример набора данных для мошеннических транзакций по кредитным картам. Вы можете скачать его с kaggle, если хотите следовать!
Детали данных не очень важны. На самом деле функции этого конкретного набора данных являются выходными данными PCA, поэтому в любом случае обсуждать эти функции не так уж интересно. В дополнение к результатам этого процесса PCA набор данных также включает сумму в долларах, связанную с каждой транзакцией, последовательный индекс времени в секундах и двоичный флаг, указывающий на наличие или отсутствие мошенничества. Мы мало что знаем об этом временном индексе, но потенциально он может быть полезен, учитывая разработку некоторых функций.
А пока просто помните, что у нас есть эта сумма в долларах; это будет важно позже!
Для наших целей наиболее важным атрибутом данных является то, что из 284 807 строк данных только 0,173% строк являются случаями мошенничества.
Это определенно квалифицируется как дисбаланс классов и делает моделирование и прогнозирование мошеннического поведения немного сложным.
Но давайте попробуем!
Примечание о показателях производительности
Как правило, в сфере несбалансированных данных есть несколько ценных показателей производительности, которые можно использовать, чтобы дать вам представление о производительности модели. Возможно, в следующей статье мы поговорим о таких вещах, как показатели f_beta.
Часто выбор метрики сильно зависит от приложения и последствий, связанных с ложными/истинными положительными/отрицательными результатами. Один размер не подходит всем, и поэтому быть специалистом по данным так весело!
В контексте мошенничества с кредитными картами нас не очень впечатлит модель, дающая высокую оценку точности. Поскольку набор данных настолько сильно несбалансирован, будет огромное количество истинных отрицательных значений, завышающих этот показатель. Но мы не очень заинтересованы в том, чтобы точно предсказывать, когда транзакции по кредитным картам не являются мошенническими. Мы создаем ценность для бизнеса, точно прогнозируя наличие мошенничества, а не его отсутствие.
На данный момент мы собираемся использовать оценку отзыва в качестве основного показателя производительности нашей модели. Отзыв — это мера того, сколько положительных случаев точно предсказывается моделью. В нашем конкретном случае использования более высокий показатель отзыва означает, что мы обнаружили больше случаев мошенничества.
Фактически, мы собираемся расширить понятие отзыва, включив в него финансовые затраты, связанные с нашей классификацией. Помните, ранее мы упоминали, что каждая строка нашего набора данных включает сумму в долларах, связанную с транзакцией? Мы учтем это при оценке эффективности и назовем это «финансовым отзывом». Мы рассмотрим более подробно ниже.
Подготовка к моделированию
Для начала давайте прочитаем наши данные и разделим их на наборы для обучения и тестирования:
Если вы раньше не использовали аргумент stratify
в train_test_split
, он станет вашим лучшим другом при работе с несбалансированными данными. Я рекомендую вам ознакомиться с документацией sklearn по стратификации в целом, но для наших целей все, что делает этот аргумент, — это гарантирует, что мы поддерживаем эквивалентную пропорцию нашей переменной ответа как в наших обучающих, так и в тестовых наборах.
Если бы мы не передали этот аргумент train_test_split
, доля случаев мошенничества была бы совершенно случайной между нашим набором поездов и тестов. Мы могли бы получить двойную пропорцию в нашем наборе поездов, что создало бы плохо работающую модель. Мы хотим, чтобы примерно 0,173% (наша глобальная доля мошенничества) наших транзакций были мошенническими как в обучающем, так и в тестовом наборах.
Базовая модель
Далее мы создадим и обучим базовую модель логистической регрессии, которая будет служить в качестве основы. Но прежде чем мы это сделаем, давайте создадим небольшую функцию, которая будет включать сумму каждой транзакции в долларах в нашу оценку производительности.
Мы заботимся о подсчете случаев мошенничества, которые мы должным образом классифицируем, но мы также заботимся (возможно, гораздо больше) о том, чтобы свести к минимуму потери долларов в результате мошенничества. Это «финансовый отзыв», о котором мы говорили ранее. Давайте создадим небольшую функцию для суммирования суммы мошенничества в долларах, которую мы правильно идентифицируем, в дополнение к необработанным подсчетам:
Теперь, когда мы выяснили наши функции оценки, давайте обучим нашу базовую модель и оценим ее производительность:
Наша базовая модель обеспечивает отзыв 59% и финансовый отзыв 61%, что на самом деле лучше, чем я ожидал. Это определенно нехорошо, но с чего-то надо начинать! Держу пари, мы можем сделать лучше…
Улучшение модели: веса классов
То, как мы настраиваем нашу базовую модель, рассматривает оба наших класса как одинаково важные. Модель не знает, что мы больше заботимся о положительных случаях (мошенничество), чем о отрицательных случаях (отсутствие мошенничества).
Мы могли бы погрузиться в целую дискуссию о функциях затрат и о том, как мы собираемся обновлять наши, но это выходит за рамки текущих задач. Если вам нужна (суперматематическая) дискуссия на эту тему, ознакомьтесь с этой статьей.
К счастью, API sklearn позволяет очень легко сообщить модели о наших предпочтениях для правильной идентификации мошенничества: аргумент class_weight
.
При использовании class_weight
модель ожидает словарь с ключом для каждого класса, где значением является вес этого класса. У нас есть два класса, и для примера предположим, что мошеннические дела в 10 раз важнее. В этом случае мы бы передали class_weight
словарь следующим образом:
fraud_class_weights = {0:1, 1:10}
Но sklearn API делает этот процесс еще проще. Аргумент class_weight
также может принимать значение 'balanced'
. Все, что нужно сделать, это создать словарь, в котором веса пропорциональны распределению классов в данных, используя следующее уравнение:
len(X_train) / (2 * numpy.bincount(y_train))
Применяя приведенное выше уравнение к нашим данным, мы оцениваем, что положительный случай на самом деле примерно в 575 раз важнее, чем отрицательный.
Когда мы поместим этот новый аргумент в нашу модель логистической регрессии, она будет гораздо больше сосредоточена на правильной классификации наших мошеннических транзакций. Это именно тот результат, который мы ищем!
Давайте настроим его, а затем исследуем производительность:
Это простое изменение повышает показатель отзыва до 90% и финансовый отзыв до 93%! Теперь мы гораздо более чувствительны к мошенничеству и точно выявляем гораздо больше случаев мошенничества, чем при использовании базовой модели.
Заключение
Использование class_weight
в вашей модели определенно поможет вам получить более релевантную производительность от вашей модели. Кроме того, его достаточно легко настроить, поэтому всегда стоит хотя бы попробовать.
Это слишком упрощенный подход к решению этой проблемы, но очевидно, что это мощный инструмент для обработки несбалансированных данных. Есть много других тем для обсуждения в этой области, так что следите за будущими статьями!