Ваша карта когда-нибудь была отклонена из-за подозрительной активности? Это попытка ИИ избежать убытков в размере 117 млн долларов США, вызванных мошенничеством, как в 2020 году. Такие ситуации смущают клиентов, и их следует избегать, но ослабление критериев ИИ позволит увеличить число случаев мошенничества. Вот почему важно правильно обучать и тестировать машину с правильным классификатором и данными. И это то, что мы постараемся сделать где.

Получение данных

Все данные доступны на Kaggle, а переменные содержат только числовые входные переменные, которые являются результатом преобразования PCA. Транзакции в наборе данных относятся к европейским держателям карт в сентябре 2013 года.

Полный код доступен на Google Colab.

И не менее важны библиотеки.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scikitplot as skplt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.metrics import classification_report
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix
from sklearn.metrics import plot_confusion_matrix
from imblearn.under_sampling import RandomUnderSampler
sns.set_style('dark')

Исследовательский анализ

Каждый исследовательский анализ начинается с первых записей во фрейме данных.

df.head()

Мы можем ясно видеть влияние PCA на записи. Сумма и время не были частью PCA, сохраняя свое первоначальное значение. Столбец Класс представляет собой двоичное целое, где 0 соответствует мошенническим транзакциям, а 1 — обычным транзакциям.

Другой важной частью советника является статистическая часть.

df.describe()

Здесь мы видим, что переменные, прошедшие преобразование PCA, не имеют явного расхождения.

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

Мы также должны проверить недостающие значения.

df.isnull().sum()
Time      0 
V1        0 
V2        0 
V3        0 
V4        0 
V5        0 
V6        0 
V7        0 
V8        0 
V9        0 
V10       0 
V11       0 
V12       0 
V13       0 
V14       0 
V15       0 
V16       0 
V17       0 
V18       0 
V19       0 
V20       0 
V21       0 
V22       0 
V23       0 
V24       0 
V25       0 
V26       0 
V27       0 
V28       0 
Amount    0 
Class     0 
dtype: int64

Хорошо! Там нет пропущенных значений, так что это не будет проблемой.

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

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

Также может быть связь между Time и типом транзакции. Итак, давайте проверим.

Кажется, что нет никакой связи, но всегда стоит проверить.

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

Мы видим различное распределение для обоих классов, что, вероятно, способствует обучению модели.

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

Перед запуском модели машинного обучения необходимо сделать некоторые вещи.

Стандартизируйте Time и Amount

Этот шаг заключается в удалении выбросов из тех столбцов с StandardScaler..

df_clean = df.copy()
df_clean['std_amount'] = StandardScaler().fit_transform(df_clean['Amount'].values.reshape(-1, 1))
df_clean['std_time'] = StandardScaler().fit_transform(df_clean['Time'].values.reshape(-1, 1))
df_clean.drop(['Time', 'Amount'], axis=1, inplace=True)

Разделить поезд и тест

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

X =df_clean.drop('Class', axis=1)
y = df.Class
X_train, X_test, y_train, y_test = train_test_split(X,y,stratify=y,shuffle=True)

Балансировка данных

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

rus = RandomUnderSampler()
X_rus, y_rus = rus.fit_sample(X_train, y_train)

Модель машинного обучения

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

Логистическая регрессия

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

log_model = LogisticRegression()
log_model.fit(X_rus, y_rus)
y_pred_log = log_model.predict(X_test)
y_proba_log = log_model.predict_proba(X_test)

Древо решений

Дерево решений — это алгоритм, который проверяет атрибуты в древовидной структуре.

from sklearn.tree import DecisionTreeClassifier
tree_model = DecisionTreeClassifier(max_depth=4, criterion="entropy")
tree_model.fit(X_rus, y_rus)
y_pred_tree = tree_model.predict(X_test)

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

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

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

print("Logistic Regression\n")
print("Classification Report:\n", classification_report(y_test, y_pred_log, digits=4))
print("Acuracy: {:.4f}\n".format(accuracy_score(y_test, y_pred_log)))
print("AUC: {:.4f}\n".format(roc_auc_score(y_test, y_pred_log)))
print("Decision Tree")
print("Classification Report:\n", classification_report(y_test, y_pred_tree, digits=4))
print("Accuracy: {:.4f}\n".format(accuracy_score(y_test, y_pred_tree)))
print("AUC: {:.4f}\n".format(roc_auc_score(y_test, y_pred_tree)))

Вывод

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