金融反欺诈项目

构建信用卡反欺诈预测模型

本项目需解决的问题

本项目通过利用信用卡的历史交易数据,进行机器学习,构建信用卡反欺诈预测模型,提前发现客户信用卡被盗刷的事件。

1.项目背景

数据集包含由欧洲持卡人于2013年9月使用信用卡进行交易的数据。此数据集显示两天内发生的交易,其中284,807笔交易中有492笔被盗刷。数据集非常不平衡,
积极的类(被盗刷)占所有交易的0.172%。

它只包含作为PCA转换结果的数字输入变量。不幸的是,由于保密问题,我们无法提供有关数据的原始功能和更多背景信息。特征V1,V2,… V28是使用PCA
获得的主要组件,没有用PCA转换的唯一特征是“时间”和“量”。特征’时间’包含数据集中每个事务和第一个事务之间经过的秒数。特征“金额”是交易金额,此特
征可用于实例依赖的成本认知学习。特征’类’是响应变量,如果发生被盗刷,则取值1,否则为0。
以上取自Kaggle官网对本数据集部分介绍(谷歌翻译),关于数据集更多介绍请参考《Credit Card Fraud Detection》。

2.场景解析(算法选择)

  1. 首先,我们拿到的数据是持卡人两天内的信用卡交易数据,这份数据包含很多维度,要解决的问题是预测持卡人是否会发生信用卡被盗刷。信用卡持卡人是否会发生被盗刷只有两种可能,发生被盗刷或不发生被盗刷。又因为这份数据是打标好的(字段Class是目标列),也就是说它是一个监督学习的场景。于是,我们判定信用卡持卡人是否会发生被盗刷是一个二元分类问题,意味着可以通过二分类相关的算法来找到具体的解决办法,本项目选用的算法是逻辑斯蒂回归(Logistic Regression)。
  2. 分析数据:数据是结构化数据 ,不需要做特征抽象。特征V1至V28是经过PCA处理,而特征Time和Amount的数据规格与其他特征差别较大,需要对其做特征缩放,将特征缩放至同一个规格。在数据质量方面 ,没有出现乱码或空字符的数据,可以确定字段Class为目标列,其他列为特征列。
  3. 这份数据是全部打标好的数据,可以通过交叉验证的方法对训练集生成的模型进行评估。70%的数据进行训练,30%的数据进行预测和评估。
    现对该业务场景进行总结如下:
    1. 根据历史记录数据学习并对信用卡持卡人是否会发生被盗刷进行预测,二分类监督学习场景,选择逻辑斯蒂回归(Logistic Regression)算法。
    1. 数据为结构化数据,不需要做特征抽象,但需要做特征缩放。

3.项目代码实现

1数据获取与解析

  • 导包
import numpy as np
import pandas as pd
from pandas import Series,DataFrame

import matplotlib.pyplot as plt
%matplotlib inline

from imblearn.over_sampling import SMOTE
  • 导入数据
credit = pd.read_csv('creditcard.csv')
credit.tail()

Time	V1	V2	V3	V4	V5	V6	V7	V8	V9	...	V21	V22	V23	V24	V25	V26	V27	V28	Amount	Class
284802	172786.0	-11.881118	10.071785	-9.834783	-2.066656	-5.364473	-2.606837	-4.918215	7.305334	1.914428	...	0.213454	0.111864	1.014480	-0.509348	1.436807	0.250034	0.943651	0.823731	0.77	0
284803	172787.0	-0.732789	-0.055080	2.035030	-0.738589	0.868229	1.058415	0.024330	0.294869	0.584800	...	0.214205	0.924384	0.012463	-1.016226	-0.606624	-0.395255	0.068472	-0.053527	24.79	0
284804	172788.0	1.919565	-0.301254	-3.249640	-0.557828	2.630515	3.031260	-0.296827	0.708417	0.432454	...	0.232045	0.578229	-0.037501	0.640134	0.265745	-0.087371	0.004455	-0.026561	67.88	0
284805	172788.0	-0.240440	0.530483	0.702510	0.689799	-0.377961	0.623708	-0.686180	0.679145	0.392087	...	0.265245	0.800049	-0.163298	0.123205	-0.569159	0.546668	0.108821	0.104533	10.00	0
284806	172792.0	-0.533413	-0.189733	0.703337	-0.506271	-0.012546	-0.649617	1.577006	-0.414650	0.486180	...	0.261057	0.643078	0.376777	0.008797	-0.473649	-0.818267	-0.002415	0.013649	217.00	0
5 rows × 31 columns

从上面可以看出,数据为结构化数据,不需要抽特征转化,但特征Time和Amount的数据规格和其他特征不一样,需要对其做特征做特征缩放
表明此数据有28万行,31列

credit.shape
out:(284807, 31)

说明数据类型只有float64和int64,且无缺失值,方便后续处理

credit.dtypes
credit.isnull().any()

2.特征工程

counts = credit.Class.value_counts()
# 查看总数据中正负例的数目, 1代表被倒刷的次数
0    284315
1       492
Name: Class, dtype: int64
  • 画图直观的观察正负例的数目
plt.figure(figsize=(10,8))
ax = plt.subplot(1,2,1)
counts.plot(kind='pie', autopct='%.4f%%', ax=ax)
# plt.axis('equal')

# 画柱状图
ax = plt.subplot(1,2,2)
counts.plot(kind='bar')

正负例图形展示.png
通过上面的图和数据可知,存在492例盗刷,占总样本的0.17%,由此可知,这是一个明显的数据类别不平衡问题,稍后我们采用过采样(增加数据)的方法对这种问题进行处理。

  • 特征转换,将时间从单位每秒化为单位每小时
# 7201秒 --> ?个小时
# 使用divmod
divmod(7201, 3600)
out: (2, 1)
# 使用map修改已有的列:Time
credit.Time = credit.Time.map(lambda x: divmod(x, 3600)[0])
credit.tail()
# 查看Time列更改了吗?
  • 特征选择
    先画一个特征的直方图(hist)
# 比较直观的方法.
# 通过画图比较.
cond0 = credit['Class'] == 0
cond1 = credit['Class'] == 1
# V1中0类的数据
v1_0 = credit['V1'][cond0]
v1_1 = credit['V1'][cond1]

v1_0.plot(kind='hist', density=True, bins=500)
v1_1.plot(kind='hist', density=True, bins=50)

特征V1的直方图.png

credit.columns

out:Index(['Time', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10',
       'V11', 'V12', 'V13', 'V14', 'V15', 'V16', 'V17', 'V18', 'V19', 'V20',
       'V21', 'V22', 'V23', 'V24', 'V25', 'V26', 'V27', 'V28', 'Amount',
       'Class'],
      dtype='object')
cols = ['Time', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10',
       'V11', 'V12', 'V13', 'V14', 'V15', 'V16', 'V17', 'V18', 'V19', 'V20',
       'V21', 'V22', 'V23', 'V24', 'V25', 'V26', 'V27', 'V28', 'Amount']
cond0 = credit['Class'] == 0
cond1 = credit['Class'] == 1
#  研究所有特征的分布情况
plt.figure(figsize=(10, 30* 6))

for i, col in enumerate(cols):
    v1_0 = credit[col][cond0]
    v1_1 = credit[col][cond1]
    
    ax = plt.subplot(30,1, i+1)
    v1_0.plot(kind='hist', density=True, bins=500, ax=ax)
    v1_1.plot(kind='hist', density=True, bins=50, ax=ax)
    ax.set_title(col)

上面的for循环会画出所有cols的特征直方图太大就不展示了
上图是不同变量在信用卡被盗刷和信用卡正常的不同分布情况,我们将选择在不同信用卡状态下的分布有明显区别的变量。因此剔除变量V8、V13 、V15 、V20、V21 、V22、 V23 、V24 、V25 、V26 、V27 和V28变量。

  • 剔除不明显的特征
# V8、V13 、V15 、V20 、V21 、V22、 V23 、V24 、V25 、V26 、V27 和V28变量
cols = ['V8', 'V13', 'V15', 'V20', 'V21' , 'V22', 'V23', 'V24', 'V25', 'V26', 'V27', 'V28']
credit.drop(columns=cols, inplace=True)
credit.shape

out:(284807, 19)
  • 特征缩放
    Amount
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值