介绍
从食品配送应用到在线服装店,互联网让我们可以随时随地轻松购买任何想要的东西,而且使用信用卡购物非常方便。信用卡有很多用处,它让我们免去了每次去任何地方都要随身携带大量现金的不便,还让我们可以提前购买,然后分期付款。
根据 Statista 的数据,2014 年至 2020 年,全球交易数量从每年 1950 亿笔增加到 4680 亿笔。
考虑到世界各地每天都会发生数十亿笔交易,而且人们通过手机应用程序、网上商店和数字钱包使用信用卡的次数比以往任何时候都多,不难想象有些欺诈者正在寻找使用他人姓名和金钱进行购买的方法。
在这种情况下,信用卡公司能够识别欺诈交易非常重要,以避免向客户收取他们未购买的商品的费用,这就是为什么我开发了一个机器学习分类模型来教计算机如何识别模式,从而判断交易是真实的还是欺诈的。
对于这个项目,我使用了 Python 的 scikit-learn 库并测试了四种不同的分类算法,以确定哪一种算法能够通过我们的数据集取得最佳结果。
机器学习
简而言之,机器学习是人工智能的一个分支,它专注于使用数据和算法来教计算机模仿人类的学习方式,并通过经验和执行任务逐步提高其准确性。
机器学习是数据科学的重要组成部分,它使用静态方法并训练算法来根据一些输入数据执行预测和分类等任务,从而使算法能够对数据中的模式做出估计。
Scikit-Learn
Scikit-learn是一个 Python 的开源机器学习库,它为分类、回归、聚类、降维、数据预处理、比较、验证和不同算法的参数选择提供了简单有效的工具。
分类算法
对于这个项目,我使用了四种不同的分类算法来执行识别构成欺诈交易的模式的任务。我使用了决策树分类器,这是一种简单的算法,用于通过学习从数据特征推断出的简单决策规则来预测某个目标变量的值。
我还使用了随机森林分类器、Ada Boost 分类器和梯度提升分类器,这些算法基于集成方法,将多个基础估计器的预测结合起来,以提高单个估计器的稳健性。例如,随机森林分类器基于数百棵随机决策树的构建,以获得最终结果。
我将在下面留下 Scikit-Learn 在线文档的链接,您可以在其中阅读并获得有关分类器的深入解释、它们的工作原理以及它们背后的数学原理。
信用卡欺诈检测项目开发
该项目使用Python语言在Jupyter Notebook中开发,并发布在[GitHub](https://github.com/luuisotorres/Credit-Card-Fraud-Detection/blob/main/Credit Card Fraud Detection.ipynb)和Kaggle上。
当然,第一步是导入开发所需的所有库
# 用于探索、处理和可视化数据的库
将 pandas 导入为 pd、将 numpy 导入为 np、将 matplotlib.pyplot 导入为 plt、将 seaborn 导入为 sns、将 plotly.express 导入为 px# Sklearn 的预处理库从 sklearn.preprocessing 导入 StandardScaler# 导入训练和测试数据分割从 sklearn.model_selection 导入 train_test_split# Sklearn 的指标来评估我们的模型从 sklearn.metrics 导入准确度分数、精度分数、混淆矩阵、召回率分数、f1_score# 分类器从 sklearn.ensemble 导入 RandomForestClassifier从 sklearn.ensemble 导入 AdaBoostClassifier从 sklearn.ensemble 导入 GradientBoostingClassifier从 sklearn.tree 导入 DecisionTreeClassifier# 将主题样式和调色板设置为 seabornsns.set_theme(context ='notebook',style ='darkgrid',palette ='muted')a
理解数据集
然后我使用 pandas.read_csv() 方法获取我们的数据并使用 df.head() 查看数据框。
该项目使用的数据集是信用卡欺诈检测数据集,可在 Kaggle 上找到,其中包含欧洲客户在 2013 年 9 月两天内进行的信用卡交易。它有 284,807 笔交易和 30 个变量。
变量 time 包含数据集中每笔交易与第一笔交易之间相隔的秒数。Amount 包含每笔交易的价值,最后,我们有一个 class,它是一个二进制特征,可以告诉我们某笔交易是真实的还是欺诈的。
我们还有其他特征 V1、V2、…V28,它们是PCA 转换的数值输入结果,由于其机密性质,其内容无法显示。
在探索分析过程中,可以看到数据集仅包含数字输入,不存在空值。我使用 describe() 方法对金额特征进行了分析。
# 金额统计
df.Amount.describe(). round ( 2 )
可以看出,75% 的交易金额低于 77.16 欧元,最高交易金额为 25,691.16 欧元,远高于平均金额 88.35 欧元。让我们在散点图上绘制金额,看看这些值在数据集中的分布情况。
# 金额分布
fig = px.scatter( df , x = '金额' , y =df.index, color = df.Class,
title = '金额值分布' )
fig.update_layout(xaxis_title= '交易金额(欧元)' ,
yaxis_title= '交易' )
fig.show( 'png' )
看起来大多数交易都是真实的,用蓝点表示。我们还可以看到所有高价值交易实际上都是真实的,没有超过 5,000.00 欧元的明显欺诈交易。
然而,在散点图上很难看出任何欺诈交易,这些交易应该用黄点表示,而我所能看到的只是左侧所有蓝色后面的一些小黄色。这给我们留下了一个问题:实际上有多少交易是欺诈?
我使用 plotly 绘制了一个饼图来查看我们的类别在数据集中的分布情况,下面是我得到的结果。
# 可视化类别分布
fig = px.pie(df.Class, values = df.Class.value_counts(),
names=[ 'Genuine' , 'Fraud' ], title= '数据集中的欺诈 x 真实交易' )
fig.show( 'png' )
df.Class.value_counts().Class .value_counts ()
好吧,难怪在散点图上很难看出欺诈交易。只有 0.17% 的交易是欺诈交易!在 284,807 笔交易中,有 492 笔是欺诈交易。我们在这里需要解决的类别不平衡问题非常严重。
让我们尝试获取更多有关欺诈交易的信息。
df.query("Class ==1").Amount.describe()查询(“Class ==1” )。 Amount.describe ()
最高欺诈金额为 2,125.87 欧元,平均欺诈金额约为 122.21 欧元。让我们再次将这些值绘制在散点图上。
# 欺诈交易金额分布
fig = px.scatter(df.query( "Class==1" ), x = 'Amount' , y =df.query( "Class==1" ).index,
title = '欺诈金额分布' )
fig.update_layout(xaxis_title= '交易金额(欧元)' ,
yaxis_title= '交易' )
fig.show( 'png' )
准备数据
时间变量对于这个项目没有任何用处,所以我将其从数据框中删除。
df = df.drop(columns = [ '时间' ], axis = 1 )
完成后,我将数据集分为独立变量(X)和目标变量(y)。
X = df.drop(columns=['Class'], axis=1)
y = df.Class
# 可视化目标变量类
y
# 可视化独立变量
X
完成之后,就该将数据分成训练集和测试集了。我将它们分成 70% 用于训练,30% 用于测试。
train_x, test_x, train_y,test_y = train_test_split(X, y, test_size= .3, random_state = 123.3 , random_state = 123
print ( 'X 训练规模:' , train_x.shape)
print ( 'X 测试规模:' , test_x.shape)
print ( 'X 测试比例' , "%s%%" % round (( len (test_x) / ( len (train_x) + len (test_x))) * 100 ))
print ( 'Y 训练规模:' , train_y.shape)
print ( 'Y 测试规模:' , test_y.shape)
print ( 'Y 测试比例' , "%s%%" % round (( len (test_y) / ( len (train_y) + len (test_y))) * 100 )))
我们现在有 199,364 笔交易用于训练,85,443 笔交易用于测试。
之后,我使用 StandardScaler 对金额值进行归一化,因为这些值与数据集中的其他特征相比差异太大。让所有变量都处于相似的规模非常重要,否则算法会将更大的重要性归因于规模最大的变量,这最终会导致算法出现偏差并对我们的结果产生负面影响。我们不希望出现这种情况!
StandardScaler 实际上非常简单,它通过减去平均值然后将值除以标准差来标准化特征。
为了避免数据泄漏效应,在每个训练和测试集上分别应用 StandardScaler 非常重要!
# 在训练集上缩放数据
scaler = StandardScaler()
train_x[ 'Amount' ] = scaler.fit_transform(train_x.Amount.values.reshape(-1,1))
train_x
# 在测试集上缩放数据
scaler = StandardScaler()
test_x[ 'Amount' ] = scaler.fit_transform(test_x.Amount.values.reshape(-1,1))
test_x
之后,我们开始处理数据不平衡的问题。我使用 imblearn 库应用 SMOTE 来对欺诈数据进行过度采样,这意味着我通过基于数据集中已有的欺诈行为合成生成更多欺诈交易来增加欺诈交易的总数。
只需记住,这就是欺诈交易和真实交易在数据集中的分布方式。
y.value_counts() # 0 = 真实交易 | 1 = 欺诈# 0 = 真实交易 | 1 = 欺诈
然后我在训练集上应用了 SMOTE
从imblearn.over_sampling导入SMOTE
train_x, train_y = SMOTE().fit_resample(train_x,train_y) # 重塑数据
并计算 train_y 集上的值
train_y.value_counts().值计数()
现在,我们在训练集中实现了真实交易和欺诈交易各占一半的平衡。请注意,我只在训练集中应用了过采样,而测试集则保持原样,保持其原始比例,我这样做是因为测试集必须完全代表现实。
应用分类器
好吧,完成所有这些工作后,让我们看看算法能够多好地预测训练集上的欺诈交易。
# 应用随机森林分类器
random_forest = RandomForestClassifier(n_estimators = 100, random_state = 123)
random_forest.fit(train_x,train_y)
y_predictions_rf = random_forest.predict(test_x)
# 应用决策树分类器
decision_tree = DecisionTreeClassifier(random_state = 123)
decision_tree.fit(train_x,train_y)
y_predictions_dt = decision_tree.predict(test_x)
# 应用 Ada Boost 分类器
ada_boost = AdaBoostClassifier(n_estimators = 100, random_state = 123)
ada_boost.fit(train_x,train_y)
y_predictions_ab = ada_boost.predict(test_x)
# 应用梯度提升分类器
gradient_boosting = GradientBoostingClassifier(n_estimators = 100,random_state = 123)
gradient_boosting.fit(train_x,train_y)
y_prediction_gb = gradient_boosting.predict(test_x)
在评估我们的模型表现之前,我将简要讨论一下分类算法的评估指标
分类模型的评估指标
在处理分类模型时,我们可以使用一些评估指标来了解模型的效率。
这些评估指标之一是混淆矩阵,它是预测结果与数据集的实际值相比的总结。对于二元分类问题,混淆矩阵如下所示:
TP 代表 True Positive,它显示模型对正类的正确预测。
FP 是 False Positive 的缩写,它表示模型对正类的预测不正确。
FN 代表“假阴性”,它表示模型对负类的预测不正确。
TN 代表真阴性,它显示模型对阴性类别的正确预测。
除了混淆矩阵之外,我们还有一些其他相关指标。它们是:
准确性
准确度只是告诉我们正确预测的比例。计算方法如下:
精确
准确率告诉我们模型正确预测阳性的频率。计算方法如下:
记起
召回率,也可以称为敏感度,可以告诉我们模型对我们想要预测的类别的预测效果如何。计算方法如下:
F1 分数
最后,F1 分数是准确率和召回率的调和平均值。计算方法如下:
随机森林分数
让我们看看随机森林的指标及其混淆矩阵
# 打印随机森林的评估指标 metrics
= [[ 'Accuracy' ,(accuracy_score(test_y, y_predictions_rf))],
[ 'Precision' ,precision_score(test_y, y_predictions_rf)],
[ 'Recall' , recall_score(test_y, y_predictions_rf)],
[ 'F1_score' ,f1_score(test_y, y_predictions_rf)]]
metrics_df = pd.DataFrame(metrics, columns = [ 'Metrics' , 'Results' ])
metrics_df
随机森林的混淆矩阵对于随机森林
fusion_matrix_rf = chaos_matrix(test_y, y_predictions_rf)
# 可视化
plt.figure(figsize=(10,7))
ax = plt.subplot()
sns.heatmap(confusion_matrix_rf, annot=True, fmt = 'g' , ax = ax)
ax.set_xlabel( '预测值' )
ax.set_ylabel( '实际值' )
ax.set_title( '混淆矩阵 - 随机森林' )
ax.xaxis.set_ticklabels([ '真正' , '欺诈' ])
ax.yaxis.set_ticklabels([ '真正' , '欺诈' ])
plt.show()
决策树评分
Ada Boost 分数
梯度提升分数
让我们看看测试集中有多少欺诈交易和真实交易,以便将这些值与上面的混淆矩阵中的值进行比较。
# 计算测试集上有多少欺诈交易和多少真实交易
test_y.value_counts()
正确预测欺诈交易数量最多的模型是 Ada Boost 分类器,它正确识别了 160 起欺诈交易中的 147 起,召回率为 91.87%,是所有其他算法中最高的。请记住,召回率告诉我们我们的模型预测我们想要预测的类别的准确程度。
结论
当我们使用机器学习模型时,我们必须始终清楚地知道我们想要从该模型中获得什么。
在这个项目中,我们的目标是在发生欺诈交易时检测出来,而表现最好的模型是 Ada Boost 分类器,其召回率为 91.87%,正确检测出 160 笔欺诈交易中的 147 笔。然而,值得注意的是,Ada Boost 分类器的误报率最高,有 1,321 笔真实交易被错误地标记为欺诈,占所有真实交易的 1.54%。
真正的购买被错误地识别为欺诈可能会带来问题。
在这种情况下,有必要了解业务并提出一些问题,例如:
- 假阳性的结果有多便宜?
- 我们是应该保留在检测欺诈方面表现最佳的 Ada Boost 分类器,同时检测出大量误报,还是应该使用随机森林分类器,后者在识别欺诈方面也表现得相当不错(82.50% 的召回率)并减少了误报的数量(0.02% 的真实交易被标记为欺诈)。但这也意味着更多的欺诈者逍遥法外,客户被错误收费……
,我们的目标是在发生欺诈交易时检测出来,而表现最好的模型是 Ada Boost 分类器,其召回率为 91.87%,正确检测出 160 笔欺诈交易中的 147 笔。然而,值得注意的是,Ada Boost 分类器的误报率最高,有 1,321 笔真实交易被错误地标记为欺诈,占所有真实交易的 1.54%。
真正的购买被错误地识别为欺诈可能会带来问题。
在这种情况下,有必要了解业务并提出一些问题,例如:
- 假阳性的结果有多便宜?
- 我们是应该保留在检测欺诈方面表现最佳的 Ada Boost 分类器,同时检测出大量误报,还是应该使用随机森林分类器,后者在识别欺诈方面也表现得相当不错(82.50% 的召回率)并减少了误报的数量(0.02% 的真实交易被标记为欺诈)。但这也意味着更多的欺诈者逍遥法外,客户被错误收费……
这些问题以及对业务运作方式的更深入理解以及我们希望如何使用机器学习来解决问题,对于决策过程至关重要,以选择我们是否愿意处理大量的误报以检测尽可能多的欺诈行为。
博客原文:专业人工智能技术社区