常见的数据分析用例 —— 信用卡交易欺诈检测

news2024/9/19 7:39:29

文章目录

  • 引言
  • 数据集
  • 分析
    • 1. 读入数据并快速浏览
    • 2.计算欺诈交易占数据集中交易总数的百分比
    • 3. 类别不平衡对模型的影响
      • 3.1 总体思路
        • (1)数据的划分
        • (2)训练模型
        • (3)测试模型
        • (4)解决不平衡问题
      • 3.2 为什么要解决不平衡问题
    • 4. 处理不平衡数据集
    • 5. 训练和评估模型
      • 5.1 回到原始数据,制定规则
        • 5.1.1 代码
      • 5.1.2 结果分析
        • 混淆矩阵
        • 分类报告
      • 结论
      • 5.2 逻辑回归模型(未使用SMOTE)和逻辑回归模型(使用SMOTE)
        • 代码及结果
          • 混淆矩阵
          • 分类报告
    • 6. 进一步
    • 7. 随机森林模型
    • 8. 模型应用
      • 误报处理
      • 漏报处理

引言

数据分析在银行中的应用有如下:
投资风险分析
客户终身价值预测
客户细分
客户流失率预测
个性化营销
客户情绪分析
虚拟助理和聊天机器人
……
这里是一个常见的数据分析用例

欺诈检测是为识别和防止欺诈活动以及财务损失而采取的一种主动措施
一般的做法有:

  • 统计学:统计参数计算、回归、概率分布、数据匹配;
  • 人工智能:数据挖掘、机器学习、深度学习

机器学习是欺诈检测的重要支柱,其工具包提供了两种方法:

  • 监督方法:K-近邻、逻辑回归、支持向量机、决策树、随机森林、时间序列分析、神经网络等。
  • 无监督方法:聚类分析、链接分析、自组织地图、主成分分析、异常识别等。

目前没有通用的机器学习算法用于欺诈检测。相反,对于现实世界的数据科学用例,通常会选择几种方法,通过测试比较,选择最佳的。

数据集

Credit Card Fraud Detection | Kaggle数据集:
https://www.kaggle.com/mlg-ulb/creditcardfraud

该数据集是Kaggle信用卡欺诈检测数据集的一个修改样本,持卡人拥有信用卡的交易情况

下载以后保存在Jupyter notebook默认目录下
在这里插入图片描述

分析

1. 读入数据并快速浏览

import pandas as pd

creditcard_data = pd.read_csv('creditcard.csv', index_col=0)
print(creditcard_data.info())
print('\n')
pd.options.display.max_columns = len(creditcard_data)
print(creditcard_data.head(3))

结果如下:

<class 'pandas.core.frame.DataFrame'>
Index: 284807 entries, 0.0 to 172792.0
Data columns (total 30 columns):
 #   Column  Non-Null Count   Dtype  
---  ------  --------------   -----  
 0   V1      284807 non-null  float64
 1   V2      284807 non-null  float64
 2   V3      284807 non-null  float64
 3   V4      284807 non-null  float64
 4   V5      284807 non-null  float64
 5   V6      284807 non-null  float64
 6   V7      284807 non-null  float64
 7   V8      284807 non-null  float64
 8   V9      284807 non-null  float64
 9   V10     284807 non-null  float64
 10  V11     284807 non-null  float64
 11  V12     284807 non-null  float64
 12  V13     284807 non-null  float64
 13  V14     284807 non-null  float64
 14  V15     284807 non-null  float64
 15  V16     284807 non-null  float64
 16  V17     284807 non-null  float64
 17  V18     284807 non-null  float64
 18  V19     284807 non-null  float64
 19  V20     284807 non-null  float64
 20  V21     284807 non-null  float64
 21  V22     284807 non-null  float64
 22  V23     284807 non-null  float64
 23  V24     284807 non-null  float64
 24  V25     284807 non-null  float64
 25  V26     284807 non-null  float64
 26  V27     284807 non-null  float64
 27  V28     284807 non-null  float64
 28  Amount  284807 non-null  float64
 29  Class   284807 non-null  int64  
dtypes: float64(29), int64(1)
memory usage: 67.4 MB
None


            V1        V2        V3        V4        V5        V6        V7  \
Time                                                                         
0.0  -1.359807 -0.072781  2.536347  1.378155 -0.338321  0.462388  0.239599   
0.0   1.191857  0.266151  0.166480  0.448154  0.060018 -0.082361 -0.078803   
1.0  -1.358354 -1.340163  1.773209  0.379780 -0.503198  1.800499  0.791461   

            V8        V9       V10       V11       V12       V13       V14  \
Time                                                                         
0.0   0.098698  0.363787  0.090794 -0.551600 -0.617801 -0.991390 -0.311169   
0.0   0.085102 -0.255425 -0.166974  1.612727  1.065235  0.489095 -0.143772   
1.0   0.247676 -1.514654  0.207643  0.624501  0.066084  0.717293 -0.165946   

           V15       V16       V17       V18       V19       V20       V21  \
Time                                                                         
0.0   1.468177 -0.470401  0.207971  0.025791  0.403993  0.251412 -0.018307   
0.0   0.635558  0.463917 -0.114805 -0.183361 -0.145783 -0.069083 -0.225775   
1.0   2.345865 -2.890083  1.109969 -0.121359 -2.261857  0.524980  0.247998   

           V22       V23       V24       V25       V26       V27       V28  \
Time                                                                         
0.0   0.277838 -0.110474  0.066928  0.128539 -0.189115  0.133558 -0.021053   
0.0  -0.638672  0.101288 -0.339846  0.167170  0.125895 -0.008983  0.014724   
1.0   0.771679  0.909412 -0.689281 -0.327642 -0.139097 -0.055353 -0.059752   

      Amount  Class  
Time                 
0.0   149.62      0  
0.0     2.69      0  
1.0   378.66      0  

这个数据集共有284807条记录。
数据集包含30个列,其中29个列是float64类型(浮点数),1个列是int64类型(整数)。
每一列的数据都是非空的(没有缺失值)。

通过creditcard_data.head(3),我们查看数据集的前3行:
Time:表示交易时间。
V1 到 V28:这些是经过PCA(主成分分析)转换后的特征
Amount:表示交易金额。
Class:目标变量,表示交易是否为欺诈(1表示欺诈,0表示正常)。

数据集非常大且没有缺失值,适合进行机器学习模型的训练。

通过初步的浏览,我们对数据有了一个基本的了解,可以进一步进行数据分析和建模工作。

2.计算欺诈交易占数据集中交易总数的百分比

# 计算欺诈交易数量
fraud_count = creditcard_data[creditcard_data['Class'] == 1].shape[0]
# 计算总交易数量
total_count = creditcard_data.shape[0]
# 计算百分比
fraud_percentage = (fraud_count / total_count) * 100
# 打印结果
print(f'欺诈交易占总交易数的百分比: {fraud_percentage:.2f}%')

结果如下:
在这里插入图片描述

使用条件筛选creditcard_data[creditcard_data[‘Class’] == 1]获取所有标记为欺诈交易的数据,然后使用shape[0]计算行数(即欺诈交易的数量)。

欺诈案件总归占少数,隐藏在真实的交易中。
创建一个图表,将欺诈与非欺诈的数据点可视化

import matplotlib.pyplot as plt
import numpy as np

# prep_data(df)从数据集中提取特征和标签
def prep_data(df):
    X = df.iloc[:, 1:28]  #选择第1列到第28列的数据作为特征
    X = np.array(X).astype(float) #将数据框转换为numpy数组,并将数据类型转换为float(浮点数)
    y = df.iloc[:, 29] #选择第29列的数据作为标签(目标变量)(1表示欺诈,0表示正常)
    y = np.array(y).astype(float) #标签转换为numpy数组
    return X, y

def plot_data(X, y):
    plt.scatter(X[y==0, 0], X[y==0, 1], label='Class #0', alpha=0.5, linewidth=0.15)
    plt.scatter(X[y==1, 0], X[y==1, 1], label='Class #1', alpha=0.5, linewidth=0.15, c='r')
    plt.legend()
    return plt.show()

X, y = prep_data(creditcard_data)

plot_data(X, y)

结果如下:
在这里插入图片描述

欺诈性交易的比例非常低,类别不平衡

3. 类别不平衡对模型的影响

3.1 总体思路

数据集是信用卡交易记录,我们想通过这个数据找出哪些交易是欺诈行为,哪些是正常的交易。

我们希望建立一个聪明的模型,帮助我们准确地识别哪些交易是欺诈行为。

可以分为几个简单的步骤:

(1)数据的划分

首先,我们把数据分成两部分:一部分用于训练模型,另一部分用于测试模型。打个比方,用历年真题来学习,用今年的考试题来测试学习效果。

(2)训练模型

这里我们打算使用“逻辑回归”的数学方法来训练我们的模型。让这个模型会学到哪些交易看起来像是欺诈,哪些交易看起来是正常的。

(3)测试模型

训练好模型后,用测试数据来检查模型的表现。我们会得到一个结果表,显示模型预测的和实际的结果对比。比如,模型认为某些交易是欺诈,但实际上它们不是;或者模型认为某些交易是正常的,但实际上它们是欺诈。

(4)解决不平衡问题

我们的数据里,正常交易很多,欺诈交易很少。为了让模型更好地识别欺诈交易,我们使用了一种叫做SMOTE的方法。这个方法会“制造”一些假的欺诈交易,让数据看起来更平衡,就像我们在班级里增加一些假人,让男女比例更均匀。
也就是说用 SMOTE 来重新平衡数据,它不只是创建观察值的精确副本,而是使用欺诈交易的最近邻居的特征来创建新的、合成的样本,这些样本与少数人类别中的现有观察值相当相似

3.2 为什么要解决不平衡问题

在训练模型时,希望模型能更好地学习到如何识别每一类数据。

如果数据非常不平衡,比如正常交易很多,欺诈交易很少,模型会倾向于只学习正常交易,而忽略了欺诈交易。

打个比方,假设你在班级里玩一个游戏,老师给你看10张卡片,其中9张是苹果,1张是橙子。然后老师让你猜下一张卡片是什么。你很可能会猜是苹果,因为苹果的卡片太多了。如果这个时候老师给你多一些橙子的卡片,比如让你看到5张苹果和5张橙子,那么你在猜下一张卡片时,就会更认真地考虑两种可能性。

对于模型来说也是这样,如果我们的数据里正常交易很多,欺诈交易很少,模型在训练过程中会主要学习到正常交易的特征,而不会很好地学习到欺诈交易的特征。

结果就是模型会更倾向于预测所有的交易都是正常的,

解决方法——让数据平衡:

为了让模型更好地学习到两类交易的特征,我们可以使用一些技术手段,比如SMOTE。这种方法会“制造”一些假的欺诈交易,让数据看起来更平衡。

这样模型在训练过程中会看到更多的欺诈交易,更好地理解每一类数据的特征,从而更准确地识别出欺诈交易

这样,在预测时就会更准确地判断哪些交易是正常的,哪些是欺诈的。
就像你在玩卡片游戏时,看到的苹果和橙子数量差不多,你在猜下一张卡片时就会更准确一样。

4. 处理不平衡数据集

让我们把SMOTE应用于该信用卡数据,提供了更多的少数类别的观察结果
SMOTE首先识别数据集中属于少数类的样本。
对于每个少数类样本,SMOTE会在其最近邻样本中随机选择一个样本。
在这两个样本之间随机插值,生成一个新的合成样本。
通过上述步骤生成足够多的合成样本,使得少数类样本数量与多数类样本数量接近或相等。

from imblearn.over_sampling import SMOTE

# 实例化SMOTE对象
method = SMOTE()

# 对数据进行过采样
X_resampled, y_resampled = method.fit_resample(X, y)

# 可视化过采样后的数据
plot_data(X_resampled, y_resampled)

# 打印过采样前后的记录数量
print(f'原始数据集记录数量: {X.shape[0]}')
print(f'过采样后数据集记录数量: {X_resampled.shape[0]}')

# 打印过采样前后的类别分布
print(f'原始数据集类别分布:\n{pd.Series(y).value_counts()}')
print(f'过采样后数据集类别分布:\n{pd.Series(y_resampled).value_counts()}')

结果如下:
在这里插入图片描述
原始数据集有284807条记录,其中284315条是正常交易(类别0),492条是欺诈交易(类别1)。
过采样后数据集有568630条记录,其中正常交易仍然是284315条,但欺诈交易增加到了284315条,使得类别更加平衡。

为了更好地看到这种方法的结果,这里将其与原始数据进行比较:

def compare_plot(X, y, X_resampled, y_resampled, method):
    f, (ax1, ax2) = plt.subplots(1, 2)
    c0 = ax1.scatter(X[y==0, 0], X[y==0, 1], label='Class #0',alpha=0.5)
    c1 = ax1.scatter(X[y==1, 0], X[y==1, 1], label='Class #1',alpha=0.5, c='r')
    ax1.set_title('Original set')
    ax2.scatter(X_resampled[y_resampled==0, 0], X_resampled[y_resampled==0, 1], label='Class #0', alpha=.5)
    ax2.scatter(X_resampled[y_resampled==1, 0], X_resampled[y_resampled==1, 1], label='Class #1', alpha=.5,c='r')
    ax2.set_title(method)
    plt.figlegend((c0, c1), ('Class #0', 'Class #1'), loc='lower center', ncol=2, labelspacing=0.)
    plt.tight_layout(pad=3)
    return plt.show()

print(f'Original set:\n'
      f'{pd.Series(y).value_counts()}\n\n'
      f'SMOTE:\n'
      f'{pd.Series(y_resampled).value_counts()}\n')

compare_plot(X, y, X_resampled, y_resampled, method='SMOTE')

结果如下:
在这里插入图片描述
原始数据集类别分布:
0.0 284315
1.0 492
Name: count, dtype: int64
过采样后数据集类别分布:
0.0 284315
1.0 284315
Name: count, dtype: int64
SMOTE方法平衡了数据,少数群体现在与多数群体的规模相等

5. 训练和评估模型

在平衡了数据集之后,下一步训练和评估机器学习模型,以确保模型能够更准确地识别少数类(这里是欺诈交易)
这里用两种方法作对比:制定规则来识别欺诈交易,用机器学习模型来识别欺诈交易

5.1 回到原始数据,制定规则

基于原始数据,制定一些规则来识别欺诈行为,
基于对数据的观察和分析,定义一些特定的阈值来检测异常交易
例如,可以根据特征的平均值和标准差来设置阈值。

计算特征均值:
使用creditcard_data.groupby(‘Class’).mean().round(3)[[‘V1’, ‘V3’]]来计算特征V1和V3在不同类别(正常交易和欺诈交易)中的平均值。

print(creditcard_data.groupby('Class').mean().round(3)[['V1', 'V3']])

结果为:
在这里插入图片描述
从输出可以看到,正常交易(Class 0)和欺诈交易(Class 1)在特征V1和V3上的平均值有显著差异。
对于正常交易(Class 0),特征V1和V3的平均值分别是0.008和0.012。
对于欺诈交易(Class 1),特征V1和V3的平均值分别是-4.772和-7.033。
这表明,欺诈交易的这两个特征值明显低于正常交易。

例如,可以制定一个规则:
如果交易的V1值小于-3并且V3值小于-5,则认为该交易是欺诈行为。
这是因为在欺诈交易中,V1和V3的平均值都显著低于正常交易。
为了评估这种方法的性能,我们将把标记的欺诈案例与实际案例进行比较

5.1.1 代码

定义规则:如果交易的V1值小于-3并且V3值小于-5,则认为该交易是欺诈行为。
使用该规则标记数据集中每一条交易是否为欺诈。

import pandas as pd

# 读取数据集
creditcard_data = pd.read_csv('creditcard.csv', index_col=0)

# 计算特征均值
mean_values = creditcard_data.groupby('Class').mean().round(3)[['V1', 'V3']]
print(mean_values)

# 制定规则:V1 < -3 和 V3 < -5
def rule_based_detection(row):
    if row['V1'] < -3 and row['V3'] < -5:
        return 1  # 标记为欺诈
    else:
        return 0  # 标记为正常

# 应用规则
creditcard_data['Predicted_Class'] = creditcard_data.apply(rule_based_detection, axis=1)

# 计算混淆矩阵和分类报告
from sklearn.metrics import confusion_matrix, classification_report

y_true = creditcard_data['Class']
y_pred = creditcard_data['Predicted_Class']

print("Confusion Matrix:")
print(confusion_matrix(y_true, y_pred))
print("\nClassification Report:")
print(classification_report(y_true, y_pred))

运行结果为
在这里插入图片描述

5.1.2 结果分析

计算混淆矩阵和分类报告
计算实际标签(Class)和预测标签(Predicted_Class)之间的混淆矩阵和分类报告,评估规则的性能。

混淆矩阵

Confusion Matrix:
[[283089 1226]
[ 322 170]]
283089个正常交易被正确分类为正常交易(真阴性)。
1226个正常交易被错误分类为欺诈交易(假阳性)。
322个欺诈交易被错误分类为正常交易(假阴性)。
170个欺诈交易被正确分类为欺诈交易(真阳性)。

分类报告

Precision(精确率):
类0(正常交易):精确率是1.00,表示所有被预测为正常交易的样本中,实际是正常交易的比例是100%。
换句话说,模型对正常交易的预测非常准确,没有将正常交易误判为欺诈交易。
类1(欺诈交易):精确率是0.12,表示所有被预测为欺诈交易的样本中,实际是欺诈交易的比例是12%。
这意味着在所有被标记为欺诈交易的样本中,只有12%是真正的欺诈交易,正常交易很大可能被误识别为欺诈交易。

Recall(召回率):
类0(正常交易):召回率是1.00,表示所有实际为正常交易的样本中,正确被预测为正常交易的比例是100%。
模型能够识别出所有的正常交易,没有漏掉任何正常交易。
类1(欺诈交易):召回率是0.35,表示所有实际为欺诈交易的样本中,正确被预测为欺诈交易的比例是35%。
在所有实际的欺诈交易中,只有35%被模型正确识别为欺诈交易,其余65%被误识别为正常交易。也就是说,很多欺诈交易会被误识别为正常交易。

打个比方:
假设有100个样本,模型预测有20个是欺诈交易(类1),但实际上只有2个是欺诈交易,其余18个是正常交易。模型预测80个是正常交易(类0),其中实际有78个是正常交易,其余2个是欺诈交易。
精确率(类1):
预测为欺诈的20个样本中,只有2个是实际欺诈,所以精确率 = 2/20 = 0.10。
召回率(类1):
实际为欺诈的4个样本中,只有2个被正确识别,所以召回率 = 2/4 = 0.50。

F1-score:
类0(正常交易):F1-score是1.00,是精确率和召回率的调和平均数。
类1(欺诈交易):F1-score是0.18,表示模型对欺诈交易的分类效果较差。

F1-score 同时考虑了精确率和召回率两个方面,是精确率(Precision)和召回率(Recall)的调和平均数,用来衡量模型在分类任务中的性能。F1-score 适用于不平衡数据集。
F1-score = 2 × Precision × Recall Precision + Recall \text{F1-score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} F1-score=2×Precision+RecallPrecision×Recall
类0(正常交易):
精确率(Precision) 和 召回率(Recall) 都是1.00。 因此,F1-score 也是1.00。
这表明模型对正常交易的分类效果非常好,能够准确且全面地识别正常交易,没有误分类和漏分类的情况。

类1(欺诈交易):
精确率(Precision) 是0.12,表示所有被预测为欺诈交易的样本中,实际是欺诈交易的比例。
召回率(Recall) 是0.35,表示所有实际为欺诈交易的样本中,正确被预测为欺诈交易的比例。
F1-score 为 0.18
F1-score = 2 × 0.12 × 0.35 0.12 + 0.35 = 2 × 0.042 0.47 ≈ 0.18 \text{F1-score} = 2 \times \frac{0.12 \times 0.35}{0.12 + 0.35} = 2 \times \frac{0.042}{0.47} \approx 0.18 F1-score=2×0.12+0.350.12×0.35=2×0.470.0420.18
表示模型对欺诈交易的分类效果较差。误报率较高(精确率低),漏报率也较高(召回率低)

Accuracy(准确率), 正确分类的样本数占总样本数的比例
Accuracy = TP + TN TP + TN + FP + FN \text{Accuracy} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}} Accuracy=TP+TN+FP+FNTP+TN
混淆矩阵:
TN(True Negative):283089 - 正常交易被正确分类为正常交易
FP(False Positive):1226 - 正常交易被错误分类为欺诈交易
FN(False Negative):322 - 欺诈交易被错误分类为正常交易
TP(True Positive):170 - 欺诈交易被正确分类为欺诈交易
模型在所有样本中有99%的样本被正确分类,很高的准确率,但在不平衡数据集中,准确率并不能全面反映模型的性能,特别是对少数类(如欺诈交易)的识别能力。

支持度(Support)分类的样本数量,正常交易远多于欺诈交易,数据集极度不平衡
类0(正常交易)的样本数是284315。
类1(欺诈交易)的样本数是492。
高准确率主要是由于模型对正常交易的高识别率(几乎所有正常交易都被正确分类)
然而,模型对欺诈交易的识别效果较差,这可以从较低的类1(欺诈交易)的精确率、召回率和F1-score中看出。

Macro avg,宏平均,不同类别的指标的简单平均值。
精确率、召回率和F1-score分别是0.56、0.67和0.59。
简单平均,它反映了每个类别的指标对等的重要性。对于不平衡的数据集,少数类(如欺诈交易)的表现对这个值有较大影响

Weighted avg,加权平均,考虑了类别的样本数量,占主导地位的多数类(如正常交易)的指标。因此,即使欺诈交易的表现较差,由于正常交易占多数,整体的加权平均值仍然很高。
精确率、召回率和F1-score分别是1.00、0.99和1.00

结论

基于原始数据,制定一些规则来识别欺诈行为,检测效果不佳。

5.2 逻辑回归模型(未使用SMOTE)和逻辑回归模型(使用SMOTE)

代码及结果
import numpy as np
import pandas as pd
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
from imblearn.pipeline import Pipeline

# 读取数据集
creditcard_data = pd.read_csv('creditcard.csv', index_col=0)
print(f"Original dataset size: {creditcard_data.shape[0]}")

# 平衡数据集
X, y = creditcard_data.iloc[:, 1:28], creditcard_data.iloc[:, 29]
smote = SMOTE()
X_resampled, y_resampled = smote.fit_resample(X, y)
print(f"Resampled dataset size: {X_resampled.shape[0]}")

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
print(f"Training set size: {X_train.shape[0]}")
print(f"Test set size: {X_test.shape[0]}")

# 训练逻辑回归模型并评估
lr = LogisticRegression()
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print("Logistic Regression (without SMOTE):")
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
print(confusion_matrix(y_test, predictions))
print(classification_report(y_test, predictions))

# 结合SMOTE和逻辑回归
pipeline = Pipeline([('SMOTE', smote), ('Logistic Regression', lr)])
pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)
print("Logistic Regression with SMOTE:")
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
print(confusion_matrix(y_test, predictions))
print(classification_report(y_test, predictions))

结果如下:
在这里插入图片描述
数据集划分:
原始数据集被划分为训练集和测试集,其中 X_train 和 y_train 用于训练模型,X_test 和 y_test 用于评估模型。
train_test_split(X, y, test_size=0.3, random_state=0) 将 70% 的数据用作训练集,30% 的数据用作测试集。

模型训练和评估:
训练逻辑回归模型时,使用的是 X_train 和 y_train。
在测试集上进行预测,并生成混淆矩阵和分类报告时,使用的是 X_test 和 y_test。

测试集中,正常交易的样本数为 85296,欺诈交易的样本数为 147。
分类报告反映的是模型在测试集上的性能评估结果

混淆矩阵

Logistic Regression(未使用SMOTE)

Logistic Regression (without SMOTE):
Flagged Fraud      0     1
Actual Fraud              
0              85284    12
1                 58    89
[[85284    12]
 [   58    89]]

85284:正常交易正确分类(真负例)
12:正常交易误分类为欺诈交易(假阳性)
58:欺诈交易误分类为正常交易(假阴性)
89:欺诈交易正确分类(真阳性)

Logistic Regression with SMOTE(使用SMOTE)

Logistic Regression with SMOTE:
Flagged Fraud      0     1
Actual Fraud              
0              83101  2195
1                 12    135
[[83101  2195]
 [   12   135]]

83101:正常交易正确分类(真负例)
2195:正常交易误分类为欺诈交易(假阳性)
12:欺诈交易误分类为正常交易(假阴性)
135:欺诈交易正确分类(真阳性)

分类报告

Logistic Regression(未使用SMOTE)

              precision    recall  f1-score   support

           0       1.00      1.00      1.00     85296
           1       0.88      0.61      0.72       147

    accuracy                           1.00     85443
   macro avg       0.94      0.80      0.86     85443
weighted avg       1.00      1.00      1.00     85443

正常交易(类0):精确率、召回率和F1-score都为1.00。
欺诈交易(类1):精确率为0.88,召回率为0.61,F1-score为0.72,模型在识别欺诈交易时漏报较多,但误报较少。

Logistic Regression(使用SMOTE)

              precision    recall  f1-score   support

           0       1.00      0.97      0.99     85296
           1       0.06      0.92      0.11       147

    accuracy                           0.97     85443
   macro avg       0.53      0.95      0.55     85443
weighted avg       1.00      0.97      0.99     85443

正常交易(类0):精确率仍然为1.00,但召回率下降到0.97,F1-score为0.99。
欺诈交易(类1):精确率下降到0.06,但召回率显著提高到0.92,F1-score为0.11。能识别大部分欺诈交易,但误报较多。

未使用SMOTE:模型对正常交易的识别效果非常好,但召回率较低,对欺诈交易的识别较差。
使用SMOTE:模型对欺诈交易的识别效果显著提高,召回率达到0.92,但精确率大幅下降,误报增多。

6. 进一步

可以看到,逻辑回归模型在处理欺诈检测问题上,比简单的阈值设定规则(例如V1 < -3 和 V3 < -5)能更好地识别欺诈交易。

为了提高逻辑回归模型的准确性,可以调整一些算法参数(如正则化参数),也可以考虑使用k-fold交叉验证而不是简单地将数据集分成训练集和测试集,交叉验证通过多次分割和训练数据集,减少了因数据分割随机性带来的误差,可以更好地评估模型的性能并选择最佳的模型参数,提高模型的稳定性和泛化能力。

也可以尝试不同的SMOTE参数,找到平衡精确率和召回率的最佳参数,如 sampling_strategy 和 k_neighbors,以找到最佳的参数组合,当欺诈记录在数据集中非常分散时,SMOTE可能会引入偏见,因为生成的合成样本可能不代表实际的欺诈模式,所以使用SMOTE会引入偏见问题。

还可以尝试一些其他的机器学习算法(如如随机森林、XGBoost),找到平衡精确率和召回率的最佳方案,从而在实际应用中更有效地识别欺诈交易

7. 随机森林模型

混淆矩阵和分类报告,显示该模型在正常交易数量远远多于欺诈交易的情况下,欺诈检测表现是比较理想的

import pandas as pd
import numpy as np
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, roc_curve
from imblearn.pipeline import Pipeline
import matplotlib.pyplot as plt
import joblib

# 数据预处理函数
def prep_data(df):
    X = df.iloc[:, 1:28]
    y = df.iloc[:, 29]
    return np.array(X).astype(float), np.array(y).astype(float)

# 读取数据集
creditcard_data = pd.read_csv('creditcard.csv', index_col=0)

# 数据预处理
X, y = prep_data(creditcard_data)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建并训练随机森林模型的管道
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('smote', SMOTE()),
    ('randomforestclassifier', RandomForestClassifier(random_state=42))
])

# 训练模型
pipeline.fit(X_train, y_train)

# 预测测试集
y_pred = pipeline.predict(X_test)

# 打印混淆矩阵和分类报告
print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))
print("\nClassification Report:")
print(classification_report(y_test, y_pred))

# 保存模型
joblib.dump(pipeline, 'random_forest_fraud_model.pkl')
print("Model saved as random_forest_fraud_model.pkl")

结果如下
在这里插入图片描述

8. 模型应用

关于模型的应用,需要结合实际情况优化方案,粗略的思路,例如:
目前看起来有了一个好用的模型,以后有新的交易数据进来,先把这些数据按照之前训练集的标准整理好,数据格式和特征都和训练时一致,加载模型,把整理好的数据交给模型,让它来判断哪些交易是正常的,哪些可能是欺诈的。

模型会给出一个判断结果,比如:
1 表示欺诈交易
0 表示正常交易
以下是未经运行的示例

误报处理

对于模型标记为欺诈的交易(但可能是正常交易),引入人工审核,比如,设立团队对这些交易进行复查,处理被误报的正常交易

漏报处理

对于模型没有标记为欺诈的交易(但实际上可能是欺诈交易),需要降低漏报率
例如,提高模型阈值
让模型输出每笔交易是欺诈的概率,根据业务需求调整判断标准(阈值),比如当概率大于0.5时标记为欺诈。

再如,组合多个模型提高判断的准确性
使用多个不同的模型,并取大家的综合结果
也可以进一步更新和优化训练模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1937604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知迪科技发布了全新软件产品

近日&#xff0c;知迪科技发布了全新软件产品——Vehicle Bus Tool-Trace Version免费版。该软件产品能高效的离线分析汽车总线数据&#xff0c;并拥有一大亮点功能&#xff1a;Ethernet通信离线文件基于ARXML文件的信号级解析&#xff0c;具体操作如下&#xff1a; 1、新建一…

git修改提交姓名

git config --global user.name “新用户名” git config --global user.email “新邮箱地址” 修改提交的用户名 git config --global user.name “yu***”

java转义文本中的HTML字符为安全的字

java转义文本中的HTML字符为安全的字 &#xff0c;以下字符被转义&#xff1a;替换为 (&apos; doesnt work in HTML4) " 替换为 &quot; & 替换为 &amp; < 替换为 < > 替换为 >1.先添加hutool依赖到pom <dependency><groupId>cn…

Docker安装笔记

1. Mac安装Docker 1.1 Docker安装包下载 1.1.1 阿里云 对于10.10.3以下的用户 推荐使用 对于10.10.3以上的用户 推荐使用 1.1.2 官网下载 系统和芯片选择适合自己的安装包 1.2 镜像加速 【推荐】阿里镜像 登陆后&#xff0c;左侧菜单选中镜像加速器就可以看到你的专属地…

阿尔泰科技利用485模块搭建自动灌溉系统实现远程控制

自动灌溉系统又叫土壤墒情监控系统&#xff0c;土壤墒情监控系统主要实现固定站无人值守情况下的土壤墒情数据的自动采集和无线传输&#xff0c;数据在监控中心自动接收入库&#xff1b;可以实现24小时连续在线监控并将监控数据通过有线、无线等传输方式实时传输到监控中心生成…

怎样在 PostgreSQL 中实现数据的异地备份?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中实现数据的异地备份&#xff1f;一、异地备份的重要性二、PostgreSQL 中的备份方…

Docker的安装【虚拟机】

Docker的安装【虚拟机】 准备环节【可跳过】 # 进入yum.repos.d目录&#xff0c;保留base.repo 和 CentOs-Base.repo&#xff0c;其余删除 cd /etc/yum.repos.d/ ----------------------------------------------------- # 现将base.repo 和 CentOs-Base.repo 存放至bak包中 …

SQL执行流程、SQL执行计划、SQL优化

select查询语句 select查询语句中join连接是如何工作的&#xff1f; 1、INNER JOIN 返回两个表中的匹配行。 2、LEFT JOIN 返回左表中的所有记录以及右表中的匹配记录。 3、RIGHT JOIN 返回右表中的所有记录以及左表中的匹配记录。 4、FULL OUTER JOIN 返回左侧或右侧表中有匹…

深度洞察市场需求,Vatee万腾平台定制化解决方案引领潮流

在当今这个日新月异的商业环境中&#xff0c;深刻理解并精准把握市场需求&#xff0c;已成为企业生存与发展的核心要义。Vatee万腾平台&#xff0c;作为行业内的佼佼者&#xff0c;凭借其卓越的定制化解决方案能力&#xff0c;正引领着市场潮流&#xff0c;为企业客户量身打造数…

【BUG】已解决:AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

已解决&#xff1a;AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ 目录 已解决&#xff1a;AttributeError: ‘DataFrame‘ object has no attribute ‘append‘ 【常见模块错误】 错误原因&#xff1a; 解决办法&#xff1a; 欢迎来到英杰社区https:/…

Linux—KVM虚拟化中(虚拟机克隆,快照,还原,删除)等应用实例

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…

【数据结构初阶】顺序表三道经典算法题(详解+图例)

Hello&#xff01;很高兴又见到你了~~~ 看看今天要学点什么来充实大脑吧—— 目录 1、移除元素 【思路图解】 【总结】 2、删除有序数组中的重复项 【思路图解】 【总结】 3、合并两个有序数组 【思路图解】 【总结】 至此结束&#xff0c;Show Time&#xff01; 1、…

加拿大上市药品查询-加拿大药品数据库

在加拿大&#xff0c;药品的安全性、有效性和质量是受到严格监管的。根据《食品药品法案》的规定&#xff0c;所有药品制造商必须提供充分的科学证据&#xff0c;证明其产品的安全性和有效性。为此&#xff0c;加拿大卫生部建立了一个全面的药品数据库 &#xff08;DPD) &#…

Websocket自动消息回复服务端工具

点击下载《Websocket自动消息回复服务端工具》 1. 前言 在进行Websocket开发时&#xff0c;前端小伙伴通常是和后端开发人员同步进行项目开发&#xff0c;经常会遇到后端开发人员接口还没开发完&#xff0c;也没有可以调试的环境&#xff0c;只能按照接口文档进行“脑回路开发…

深入探究理解大型语言模型参数和内存需求

概述 大型语言模型 取得了显著进步。GPT-4、谷歌的 Gemini 和 Claude 3 等模型在功能和应用方面树立了新标准。这些模型不仅增强了文本生成和翻译&#xff0c;还在多模态处理方面开辟了新天地&#xff0c;将文本、图像、音频和视频输入结合起来&#xff0c;提供更全面的 AI 解…

昇思25天学习打卡营第20天|Diffusion扩散模型

Mindspore框架利用扩散模型DDPM生成高分辨率图像&#xff08;生成高保真图像项目实践&#xff09; Mindspore框架利用扩散模型DDPM生成高分辨率图像|&#xff08;一&#xff09;关于denoising diffusion probabilistic model &#xff08;DDPM&#xff09;模型Mindspore框架利…

GitHub CLI 发布 2.53.0

gh 是 GitHub 官方的命令行客户端工具&#xff0c;在此推荐给每一位在参与、想参与到 GitHub 上开源项目的小伙伴。体验异常舒适&#xff01; 常用的命令包括有&#xff1a; 登陆认证 gh auth login克隆代码仓库 gh repo clone linuxsuren/api-testing创建 Fork 仓库 gh repo f…

Java面试八股之Redis Stream的实现原理及应用场景

Redis Stream的实现原理及应用场景 Redis Stream是一种在Redis 5.0版本中引入的数据结构&#xff0c;它主要用于实现高效的消息队列服务。下面我将详细解释其实现原理以及一些常见的应用场景。 实现原理 1. 结构组成&#xff1a; - Redis Stream由一个或多个消息组成&#xf…

《无所不能的JavaScript · 异步编程》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

数据库:编程(打开、操作、关闭)

一、需要的头文件 sqlite3.h 二、编译过程 gcc xxx -lsqlite3 三、编程框架 打开数据库 》读写数据库(增&#xff0c;删&#xff0c;改&#xff0c;查) 》关闭数据库 3.1 打开数据库&#xff1a; sqlite3_open int sqlite3_open(char * path,sqlite3 ** db); 功能&…