基于孤立森林的信用卡欺诈 Python 实战案例,最佳参数选择可视化等

Posted 我爱Python数据挖掘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于孤立森林的信用卡欺诈 Python 实战案例,最佳参数选择可视化等相关的知识,希望对你有一定的参考价值。

大家好,信用卡欺诈在金融风控领域是非常常见的,在信用卡欺诈数据集上,使用IsolationForest默认的参数,Top1000准确率为19%左右,优化参数后提高到27%左右,提升幅度非常大,异常检测模型的评估,由于黑白样本极度不平衡,使用准确率评估就不合适了。

本文通过信用卡欺诈交易的数据进行检测,提高我们对于这个模型参数优化和评估方式,我相信你会有一个更清晰的认识。

孤立森林最重要的三个参数:

n_estimators:iTree的个数,指定该森林中生成的随机树数量,默认为100

max_samples:用来训练随机数的样本数量,即子采样的大小,默认每次采样256个,整数为个数,小数为占全集的比例

max_features : 构建每个子树的特征数,整数位个数,小数为占全特征的比例,指定从总样本X中抽取来训练每棵树iTree的属性的数量,默认只使用1个特征

本文涉及的数据也只是30w不到,如果数据继续上升到百万,千万,上亿等规模,可能学习的情况完全不同,等后面研究了跟大家分享。

一、数据介绍

数据来自于kaggle上的一个信用卡欺诈检测比赛,数据质量高,正负样本比例非常悬殊,很典型的异常检测数据集,在这个数据集上来测试一下各种异常检测手段的效果。当然,可能换个数据集结果就会有很大不同,结果仅供参考。

注意点

提供完整代码、资料、技术交流,目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友
方式、添加微信号:dkl88191,备注:来自CSDN
方式、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

1、数据集介绍

信用卡欺诈是指故意使用伪造、作废的信用卡,冒用他人的信用卡骗取财物,或用本人信用卡进行恶意透支的行为,信用卡欺诈形式分为3种:失卡冒用、假冒申请、伪造信用卡。欺诈案件中,有60%以上是伪造信用卡诈骗,其特点是团伙性质,从盗取卡资料、制造假卡、贩卖假卡,到用假卡作案,牟取暴利。而信用卡欺诈检测是银行减少损失的重要手段。

该数据集包含欧洲持卡人于 2013 年 9 月通过信用卡进行的交易信息。此数据集显示的是两天内发生的交易,在 284807 笔交易中,存在 492 起欺诈,数据集高度不平衡,正类(欺诈)仅占所有交易的 0.172%。原数据集已做脱敏处理和PCA处理,匿名变量V1, V2, …V28 是 PCA 获得的主成分,唯一未经过 PCA 处理的变量是 Time 和 Amount。Time 是每笔交易与数据集中第一笔交易之间的间隔,单位为秒;Amount 是交易金额。Class 是分类变量,在发生欺诈时为1,否则为0。项目要求根据现有数据集建立分类模型,对信用卡欺诈行为进行检测。

**注:**PCA - “Principal Component Analysis” - 主成分分析,用于提取数据集的"主成分"特征,即对数据集进行降维处理。

2、数据来源

数据集 Credit Card Fraud Detection 由比利时布鲁塞尔自由大学(ULB) - Worldline and the Machine Learning Group 提供。可从Kaggle上下载:https://www.kaggle.com/mlg-ulb/creditcardfraud

二、孤立森林参数

我们使用sklearn中的孤立森林,进行参数调节讲解,一般任务默认参数即可,算法API地址:

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html#sklearn.ensemble.IsolationForest

1、基本用法

sklearn.ensemble.IsolationForest(
              *, 
              n_estimators=100, 
              max_samples='auto', 
              contamination='auto', 
              max_features=1.0, 
              bootstrap=False, 
              n_jobs=None, 
              random_state=None, 
              verbose=0, 
              warm_start=False
)

2、参数详解

n_estimators : int, optional (default=100)

iTree的个数,指定该森林中生成的随机树数量,默认为100个

max_samples : int or float, optional (default=”auto”)

如果设置的是一个int常数,那么就会从总样本X拉取max_samples个样本来生成一棵树iTree

如果设置的是一个float浮点数,那么就会从总样本X拉取max_samples * X.shape[0]个样本,X.shape[0]表示总样本个数

如果设置的是"auto",则max_samples=min(256, n_samples),n_samples即总样本的数量,如果max_samples值比提供的总样本数量还大的话,所有的样本都会用来构造数,意思就是没有采样了,构造的n_estimators棵iTree使用的样本都是一样的,即所有的样本

contamination : float in (0., 0.5), optional (default=0.1)

取值范围为(0., 0.5),表示异常数据占给定的数据集的比例,数据集中污染的数量,其实就是训练数据中异常数据的数量,比如数据集异常数据的比例。定义该参数值的作用是在决策函数中定义阈值。如果设置为’auto’,则决策函数的阈值就和论文中定义的一样

max_features : int or float, optional (default=1.0)

构建每个子树的特征数,整数位个数,小数为占全特征的比例,指定从总样本X中抽取来训练每棵树iTree的属性的数量,默认只使用一个属性

如果设置为int整数,则抽取max_features个属性

如果是float浮点数,则抽取max_features * X.shape[1]个属性

bootstrap : boolean, optional (default=False)
采样是有放回还是无放回,如果为True,则各个树可放回地对训练数据进行采样。如果为False,则执行不放回的采样。

**n_jobs 😗*int or None, optional (default=None)
在运行fit()和predict()函数时并行运行的作业数量。除了在joblib.parallel_backend上下文的情况下,None表示为1。设置为-1则表示使用所有可用的处理器

random_state : int, RandomState instance or None, optional (default=None)

每次训练的随机性

如果设置为int常数,则该random_state参数值是用于随机数生成器的种子

如果设置为RandomState实例,则该random_state就是一个随机数生成器

如果设置为None,该随机数生成器就是使用在np.random中的RandomState实例

verbose : int, optional (default=0)

训练中打印日志的详细程度,数值越大越详细

warm_start : bool, optional (default=False)
当设置为True时,重用上一次调用的结果去fit,添加更多的树到上一次的森林1集合中;否则就fit一整个新的森林

3、属 性

base_estimator_:构建子分类器的模板

estimators_:子分类器的列表,存储了所有的树

estimators_:features_list of ndarray The subset of drawn features for each base estimator.

estimators_features_:每个树所选用的特征

max_samples_:构建树时抽取的样本数

n_features_:构建树时使用的特征数量

n_features_in_:_同上,也是特征数量,替代_n_features_

feature_names_in_:所使用的特征名称

4、方 法

fit(X[, y, sample_weight]):训练模型

decision_function(X):返回平均异常分数

predict(X):预测模型返回1或者-1

fit_predict(X[, y]):训练-预测模型一起完成

get_params([deep]):获取分类器的参数

score_samples(X):返回原来的论文里面的分数形式

set_params(**params):设置分类器的参数

三、算法应用测试

1、数据读取

# 工作空间设置
import os 
import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest

os.chdir('/Users/wuzhengxiang/Documents/DataSets/CreditCardFraudDetection')
os.getcwd()


# 数据读取
data = pd.read_csv('creditcard.csv')

# 查看 0 - 1 个数
print(data.Class.value_counts())
0    284315
1       492
Name: Class, dtype: int64

num_nonfraud = np.sum(data['Class'] == 0)
num_fraud = np.sum(data['Class'] == 1)
plt.bar(['Fraud', 'non-fraud'], [num_fraud, num_nonfraud], color='red')
plt.show()


#简单的特征工程
data['Hour'] = data["Time"].apply(lambda x : divmod(x, 3600)[0])
X = data.drop(['Time','Class'],axis=1)
Y = data.Class

2、使用默认参数

# 模型训练
iforest = IsolationForest()
#fit_predict 函数 训练和预测一起 可以得到模型是否异常的判断,-1为异常,1为正常
data['label'] = iforest.fit_predict(X) 
# 预测 decision_function 可以得出 异常评分
data['scores'] = iforest.decision_function(X)  
# TopN准确率评估
n = 1000
df =  data.sort_values(by='scores',ascending=True)
df = df.head(n)
rate = df[df['Class']==1].shape[0]/n
print('Top的准确率为:'.format(n,rate))
Top1000的准确率为:0.187

我们可以看到,在默认情况下,准确率为0.187,我们看看看默认参数都是啥

iforest.get_params()
'bootstrap': False,
 'contamination': 'auto',
 'max_features': 1.0,
 'max_samples': 'auto',
 'n_estimators': 100,
 'n_jobs': None,
 'random_state': None,
 'verbose': 0,
 'warm_start': False

接下来我们就要进行参数的评估与调整,看看模型的极限有多少

3、n_estimators对准确率的影响

n_estimators是指我们需要构建多少颗树,默认值是100,我们从10-500开始测试,看看什么区间的准确率会提高。

n_est = list(range(10,500,10))
rates = []
for i in n_est:
    # 模型训练
    iforest = IsolationForest(n_estimators=i, 
                              max_samples=256,  
                              contamination=0.02, 
                              max_features=5,  
                              random_state=1
                              )
    #fit_predict 函数 训练和预测一起 可以得到模型是否异常的判断,-1为异常,1为正常
    data['label'] = iforest.fit_predict(X) 
    # 预测 decision_function 可以得出 异常评分
    data['scores'] = iforest.decision_function(X)  
    # TopN准确率评估
    n = 1000
    df =  data.sort_values(by='scores',ascending=True)
    df = df.head(n)
    rate = df[df['Class']==1].shape[0]/n
    print('Top的准确率为:'.format(n,rate))
    rates.append(rate)
print(n_est)
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490]
print(rates)
[0.114, 0.179, 0.18, 0.184, 0.178, 0.189, 0.194, 0.197, 0.185, 0.192, 0.189, 0.19, 0.193, 0.208, 0.207, 0.192, 0.197, 0.195, 0.197, 0.196, 0.202, 0.207, 0.207, 0.197, 0.195, 0.196, 0.192, 0.195, 0.191, 0.191, 0.191, 0.188, 0.183, 0.182, 0.183, 0.184, 0.185, 0.184, 0.184, 0.184, 0.183, 0.184, 0.183, 0.184, 0.183, 0.186, 0.185, 0.184, 0.185]
import matplotlib.pyplot as plt
plt.plot(n_est,rates, linestyle='--', marker='.',color='c',markerfacecolor='red')
plt.show()

我们可以看到,树的棵树,超过200,准确率就开始下降,到300左右,维持在一个比较低的水平了,不下降不上升,因此,树的棵树,并不是越多越好

4、max_features对准确率的影响

max_features是指每次构建树时候,抽取的特征个数,我们从1开始,本数据集有30个特征,那我们就做30次评估。

features = list(range(1,X.shape[1]+1))
rates = []
for i in features:
    # 模型训练
    iforest = IsolationForest(n_estimators=100, 
                              max_samples = 256,  
                              contamination=0.02, 
                              max_features=i,  
                              random_state=1
                              )
    #fit_predict 函数 训练和预测一起 可以得到模型是否异常的判断,-1为异常,1为正常
    data['label'] = iforest.fit_predict(X) 
    # 预测 decision_function 可以得出 异常评分
    data['scores'] = iforest.decision_function(X)  
    # TopN准确率评估
    n = 1000
    df =  data.sort_values(by='scores',ascending=True)
    df = df.head(n)
    rate = df[df['Class']==1].shape[0]/n
    print('Top的准确率为:'.format(n,rate))
    rates.append(rate)
    
print(features)    

print(rates)

import matplotlib.pyplot as plt
plt.plot(features,rates, linestyle='--', marker='.',color='c',markerfacecolor='red')
plt.title('max_features and TopN Acc')
plt.show()

可以看到,特征最多的时候,准确率最高,但是理论上不大可能,我们研究随机森林的时候知道,特征最大的时候,模型的相关性很高,融合准确率反而低。那为什么会出现这种情况呢,我推测是每次抽取的样本数过少的原因,我们把样本数加大在看看。max_samples = 1200

features = list(range(1,X.shape[1]+1))
rates = []
for i in features:
    # 模型训练
    iforest = IsolationForest(n_estimators=100, 
                              max_samples = 1200,  
                              contamination=0.02, 
                              max_features=i,  
                              random_state=1
                              )
    #fit_predict 函数 训练和预测一起 可以得到模型是否异常的判断,-1为异常,1为正常
    data['label'] = iforest.fit_predict(X) 
    # 预测 decision_function 可以得出 异常评分
    data['scores'] = iforest.decision_function(X)  
    # TopN准确率评估
    n = 1000
    df =  data.sort_values(by='scores',ascending=True)
    df = df.head(n)
    rate = df[df['Class']==1].shape[0]/n
    print('Top的准确率为:'.format(n,rate))
    rates.append(rate)
    
print(features)    
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
print(rates)
[0.198, 0.195, 0.188, 0.191, 0.192, 0.185, 0.184, 0.161, 0.158, 0.166, 0.209, 0.183, 0.174, 0.169, 0.164, 0.154, 0.167, 0.17, 0.183, 0.149, 0.186, 0.18, 0.183, 0.195, 0.187, 0.157, 0.191, 0.189, 0.146, 0.23]
import matplotlib.pyplot as plt
plt.plot(features,rates, linestyle='--', marker='.',color='c',markerfacecolor='red')
plt.title('max_samples and TopN Acc')
plt.show()

可以看到,样本数加大后,准确率和特征树就不会有这么极端的情况了,基本上在7左右能取到一个较好的值了。

证明我们的猜想是对的,大家可以继续加大样本量进行测试。

5、max_samples对准确率的影响

max_samples 这个是每次抽取样本的个数,默认256,相对于我们的28w样本,是杯水车薪,但是即使这样,也是有非常好的准确率了。

这个参数是最难测试的,需要涉及到几个数量级的波动,几百,几千,几万,十几万等,我们从小的开始进行测试,看看与默认值同一个数量级的情况下,准确率的变化。

samples = list(range(16,2066,16))
rates = []
for i in samples:
    # 模型训练
    iforest = IsolationForest(n_estimators=100, 
                              max_samples= i,  
                              contamination=0.02, 
                              max_features=5,  
                              random_state=1
                              )
    #fit_predict 函数 训练和预测一起 可以得到模型是否异常的判断,-1为异常,1为正常
    data['label'] = iforest.fit_predict(X) 
    # 预测 decision_function 可以得出 异常评分
    data['scores'] = iforest.decision_function(X)  
    # TopN准确率评估
    n = 1000
    df =  data.sort_values(by='scores',ascending=True)
    df = df.head(n)
    rate = df[df['Class']==1].shape[0]/n
    print('Top的准确率为:'.format(n,rate))
    rates.append(rate)
    
print(samples)   
[16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, 336, 352, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 528, 544, 560, 576, 592, 608, 624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848, 864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1040, 1056, 1072, 1088, 1104, 1120, 1136, 1152, 1168, 1184, 1200, 1216, 1232, 1248, 1264, 1280, 1296, 1312, 1328, 1344, 1360, 1376, 1392, 1408, 1424, 1440以上是关于基于孤立森林的信用卡欺诈 Python 实战案例,最佳参数选择可视化等的主要内容,如果未能解决你的问题,请参考以下文章

机器学习实战分享:用 Python 进行信用卡欺诈检测

异常检测怎么做,试试孤立随机森林算法(附代码)

通过python扩展spark mllib 算法包(e.g.基于spark使用孤立森林进行异常检测)

python数据分析案例实战——融360客户贷款风险预测(信用卡)

通俗易懂--信用卡欺诈预测案例讲解(算法+案例)

通过python扩展spark mllib 算法包(e.g.基于spark使用孤立森林进行异常检测)