本文此案例的完整流程和涉及知识

首先先看数据

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
data = pd.read_csv("creditcard.csv")
data.head()
data.shape


好的,它长这个样子。大致解释一下V1-V28都是一系列的指标(具体是什么不用知道),Amount是交易金额,Class=0表示是正常操作,而=1表示异常操作。

明确目标:检测是否异常,也就是说是一个二分类问题,接着想到用逻辑回归建模。

1.观察数据特征

Class=0的我们不妨称之为负样本,Class=1的称正样本,看一下正负样本的数量。

count_classes = pd.value_counts(data['Class'],sort = True).sort_index()
plt.figure(figsize=(10,6))
count_classes.plot(kind='bar')
plt.title("Fraud class histogram")
plt.xlabel("Class",size=20)
plt.xticks(rotation=0)
plt.ylabel("Number",size=20)


可以看出样本数据严重不均衡,样本类别不均衡将导致样本量少的分类所包含的特征过少,并很难从中提取规律。同时你的学习结果会过度拟合这种不均的结果,通俗来说就是将你的学习结果用到一组分布均匀的数据上,拟合度会很差。
那么怎么解决这个问题呢?有两种办法

采样方式选择

(1)下采样

对这个问题来说,下采样采取的方法就是取正样本中的一部分,使得正样本和负样本数量大致相同。就是让样本变得一样少

(2)过采样

相对的,过采样的做法即再生成更多的负样本数据,使得负样本和正样本一样多。就是让样本变得一样多

2.归一化处理

继续观察数据,我们可以发现Amount这一列数据的浮动差异和V1-V28数据的浮动相比差距很大。在做模型之前要保证特征之间的分布差异是差不多的,否则会对我们的模型产生误导,所以先对Amount做归一化或者标准化做法如下,使用sklearn很方便

#在这里顺便删去了Time列,因为Time列对这个问题没什么帮助
from sklearn.preprocessing import StandardScaler
data['normAmount'] = StandardScaler().fit_transform(data['Amount'].values.reshape(-1, 1))
data = data.drop(['Time','Amount'],axis=1)
data.head()

3.采用下采样处理数据

X = data.loc[:, data.columns != 'Class']
y = data.loc[:, data.columns == 'Class']#y=pd.DataFrame(data.loc[:,'Class'])或y=pd.DataFrame(data.Class)
number_records_fraud = len(data[data.Class == 1])
fraud_indices = np.array(data[data.Class == 1].index)
normal_indices = data[data.Class == 0].indexrandom_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False)
#random.choince从所有正样本索引中随机选择负样本数量的正样本索引,replace=False表示不进行替换
random_normal_indices = np.array(random_normal_indices)
#拿出来后转成array格式
under_sample_indices = np.concatenate([fraud_indices,random_normal_indices])
#合并随机得到的正样本index和负样本
under_sample_data = data.iloc[under_sample_indices,:]
#再用index定位得到数据
X_undersample = under_sample_data.loc[:, under_sample_data.columns != 'Class']
y_undersample = under_sample_data.loc[:, under_sample_data.columns == 'Class']
#X_undersample和y_undersampl即为经过下采样处理后样本
print("正样本占总样本: ", len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data))
print("负样本占总样本 ", len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data))
print("总样本数量", len(under_sample_data))
X_undersample.head(3)
y_undersample.head(3)

得到的结果:

交叉验证

把数据集切分成train(训练集)和test(测试集),通常八二分,再把train等分成3个集合

一.1+2------>3 表示用1和2建立model,用3当作验证集
二.1+3------>2 同理即1和3建model,2当作验证集
三.2+3------>1
这样做的好处如果只做一次操作,假若样本比较简单会造成模型的效率比真实值高,而如果样本存在离群值会使得模型效率比真实偏低。为了权衡两者,这样操作相当于求一个平均值,使得模型的拟合效果更理性
最后的评估效果:分别把用3,2,1的评估结果求平均值
代码实现如下:

from sklearn.model_selection import train_test_split
#sklearn中已经废弃cross_validation,将其中的内容整合到model_selection中将sklearn.cross_validation 替换为 sklearn.model_selectionX_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)
#随机切分,random_state=0类似设置随机数种子,test_size就是测试集比例,我这里设置为0.3即0.7训练集,0.3测试集print("原始样本训练集:", len(X_train))
print("原始样本测试集: ", len(X_test))
print("原始样本总数:", len(X_train)+len(X_test))#对下采样数据也进行切分
X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample,y_undersample,test_size = 0.3,random_state = 0)
print("")
print("下采样样本训练集: ", len(X_train_undersample))
print("下采样样本测试集: ", len(X_test_undersample))
print("下采样样本总数:", len(X_train_undersample)+len(X_test_undersample))

#Recall = TP/(TP+FN)通过召回率评估模型
#TP(true positives)FP(false positives)FN(false negatives)TN(true negatives)
from sklearn.linear_model import LogisticRegression#引入逻辑回归模型
from sklearn.model_selection import KFold, cross_val_score
#KFlod指做几倍的交叉验证,cross_val_score为交叉验证评估结果
from sklearn.metrics import confusion_matrix,recall_score,classification_report
#confusion_matrix混淆矩阵

关于Recall的解释这篇文章讲的很清楚

正则化惩罚项

假设有两组权重参数A和B,它们的RECALL值相同,但是A这组的方差远大于B,那么A比B更容易出现** 过拟合(在训练集效果良好但在测试集变现差)**的情况。所以为了得到B这样的模型,引入正则化惩罚项。即把目标函数变成 损失函数+正则化惩罚项
正则化惩罚项分两种:
L1:

L2:

def printing_Kfold_scores(x_train_data,y_train_data):#fold.split(y_train_data)
c_param_range = [0.01,0.1,1,10,100]
#正则化惩罚力度候选
results_table = pd.DataFrame(index = range(len(c_param_range),2), columns = ['C_parameter','Mean recall score'])
results_table['C_parameter'] = c_param_range# the k-fold will give 2 lists: train_indices = indices[0], test_indices = indices[1]
j = 0
for c_param in c_param_range:#找出最合适的正则化惩罚力度print('-------------------------------------------')print('C parameter: ', c_param)print('-------------------------------------------')print('')recall_accs = []for iteration, indices in enumerate(fold.split(y_train_data),start=1):lr = LogisticRegression(C = c_param, penalty = 'l1',solver='liblinear')#C是惩罚力度,penalty是选择l1还是l2惩罚,solver可选参数:{‘liblinear’, ‘sag’, ‘saga’,‘newton-cg’, ‘lbfgs’}lr.fit(x_train_data.iloc[indices[0],:],y_train_data.iloc[indices[0],:].values.ravel())#lr.fit:训练lr模型,传入dataframe的X和转变成一行的yy_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values)#lr.predict:用验证样本集进行预测recall_acc = recall_score(y_train_data.iloc[indices[1],:].values,y_pred_undersample)#recall_score:传入结果集,和predict的结果得到评估结果recall_accs.append(recall_acc)print('Iteration ', iteration,': recall score = ', recall_acc)results_table.loc[j,'Mean recall score'] = np.mean(recall_accs)j += 1print('')print('Mean recall score ', np.mean(recall_accs))print('')best_c = results_table.loc[np.argmax(np.array(results_table['Mean recall score']))]['C_parameter']print('*********************************************************************************')
print('Best model to choose from cross validation is with C parameter = ', best_c)
print('*********************************************************************************')
return best_c
best_c = printing_Kfold_scores(X_train_undersample,y_train_undersample)

具体迭代过程就不看了,感兴趣的可以复制过去跑一下,最终得到结果如下

用下采样训练的模型画混淆矩阵

def plot_confusion_matrix(cm, classes,title='Confusion matrix',cmap=plt.cm.Blues):plt.imshow(cm, interpolation='nearest', cmap=cmap,aspect='auto')plt.title(title)plt.colorbar()tick_marks = np.arange(len(classes))plt.xticks(tick_marks, classes, rotation=0)plt.yticks(tick_marks, classes)thresh = cm.max() / 2.for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):plt.text(j, i, cm[i, j],horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")plt.tight_layout()plt.ylabel('True label')plt.xlabel('Predicted label')import itertools
lr = LogisticRegression(C = best_c, penalty = 'l2')
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred_undersample = lr.predict(X_test_undersample.values)cnf_matrix = confusion_matrix(y_test_undersample,y_pred_undersample)
np.set_printoptions(precision=2)print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names, title='Confusion matrix')
plt.show()

这个是用模型拟合下采样测试集结果,我这个由于matplotlib库版本问题数据有点错位。
不过可以看出TP=138,TN=9,FP=9,FN看不太清不过和TP差不多
RECALL值有0.863

再用模型拟合原数据的测试集画混淆矩阵

lr = LogisticRegression(C = best_c, penalty = 'l1',solver='liblinear')
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred = lr.predict(X_test.values)# Compute confusion matrix
cnf_matrix = confusion_matrix(y_test,y_pred)
np.set_printoptions(precision=2)print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))# Plot non-normalized confusion matrix
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names, title='Confusion matrix')
plt.show()


RECALL值满意需求,但是还是存在问题。FP这类有8000多个,也就是说** 原本正常被当初异常即“误杀”的样本有8000多个,会使得精度降低**

4.对比下采样和直接拿原始数据训练模型

best_c = printing_Kfold_scores(X_train,y_train)
#用原始数据训练,找最佳的正则化惩罚项
lr = LogisticRegression(C = best_c, penalty = 'l2')
lr.fit(X_train,y_train.values.ravel())
y_pred_undersample = lr.predict(X_test.values)# Compute confusion matrix
cnf_matrix = confusion_matrix(y_test,y_pred_undersample)
np.set_printoptions(precision=2)print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))# Plot non-normalized confusion matrix
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names, title='Confusion matrix')
plt.show()

可以看到结果很不理想,RECALL值很低,所以样本不均的情况下不做处理做出的模型通常很差。

5.逻辑回归阈值对结果的影响

lr = LogisticRegression(C = 0.01, penalty = 'l1',solver='liblinear')
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred_undersample_proba = lr.predict_proba(X_test_undersample.values)
#lr.predict_proba 预测出一个概率值thresholds = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]
#指定一系列阈值
plt.figure(figsize=(12,10))j = 1
for i in thresholds:y_test_predictions_high_recall = y_pred_undersample_proba[:,1] > iplt.subplot(3,3,j)j += 1cnf_matrix = confusion_matrix(y_test_undersample,y_test_predictions_high_recall)np.set_printoptions(precision=2)print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))# Plot non-normalized confusion matrixclass_names = [0,1]plot_confusion_matrix(cnf_matrix, classes=class_names,title='Threshold >= %s'%i)
#右上角是误杀的,左下角是没被揪出来的异常

原来默认是概率大于0.5就认为是异常,这个阈值可以自己设定,阈值越大即表示越严格。
可以看出不同阈值对结果的影响,RECALL是一个递减的过程,精度逐渐增大


所以阈值的选取通常根据实际要求合理选取,好的模型RECALL和精度都要保证尽量高。

Kaggle经典案例—信用卡诈骗检测的完整流程(学习笔记)相关推荐

  1. ML之LoRBaggingRF:依次利用Bagging、RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测——模型融合

    ML之LoR&Bagging&RF:依次利用Bagging.RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测--模型融合 目录 输出结果 设计思路 核心代码 ...

  2. ML之LoRBaggingRF:依次利用LoR、Bagging、RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测——优化baseline模型

    ML之LoR&Bagging&RF:依次利用LoR.Bagging.RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测--优化baseline模型 目录 模型优 ...

  3. ML之LoRBaggingRF:依次利用LoR、Bagging、RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测(最全)

    ML之LoR&Bagging&RF:依次利用LoR.Bagging.RF算法对泰坦尼克号数据集 (Kaggle经典案例)获救人员进行二分类预测 目录 输出结果 设计思路 核心代码 输出 ...

  4. ML之LoRBaggingRF:依次利用LoR、Bagging、RF算法对titanic(泰坦尼克号)数据集 (Kaggle经典案例)获救人员进行二分类预测(最全)

    ML之LoR&Bagging&RF:依次利用LoR.Bagging.RF算法对titanic(泰坦尼克号)数据集 (Kaggle经典案例)获救人员进行二分类预测 目录 输出结果 设计思 ...

  5. 论文《基于深度学习的表面缺陷检测方法综述》学习笔记

    <基于深度学习的表面缺陷检测方法综述>学习笔记 前段时间完成了<基于图像的零部件缺陷识别系统设计>毕业课程设计,过程中收获了很多,老师也分享了很多论文,在此记录一下学习的收获. ...

  6. 用 Kaggle 经典案例教你用 CNN 做图像分类!

    我们来看一个 Kaggle 上比较经典的一个图像分类的比赛 CIFAR( CIFAR-10 - Object Recognition in Images ),这个比赛现在已经关闭了,但不妨碍我们来去通 ...

  7. kaggle经典案例:爱彼迎租房数据探索

    公众号:尤而小屋 作者:Peter 编辑:Peter 大家好,我是Peter~ Airbnb是AirBed and Breakfast ( "Air-b-n-b" )的缩写,中文名 ...

  8. 全球模具经典案例|SPC软件在开模流程中的应用

    一.精密结构及模具制造成本 董明珠2016年央视财经论坛暨中国上市公司峰会的演讲,多次提及格力集团自主研发的工业设备和模具,称中国2025需要企业更多的创新能力提高核心竞争力,而非简单的贴牌赚钱.模具 ...

  9. 2021最新版RabbitMQ完整教程学习笔记

    文章目录 一.中间件 1. 什么是中间件 2. 中间件技术及架构的概述 3. 基于消息中间件的分布式系统的架构 4. 消息队列协议 5. 消息队列持久化 6. 消息的分发策略 7. 消息队列高可用和高 ...

  10. 熬了几个大夜,学完一套985博士总结的「卷积神经网络、目标检测、OpenCV」学习笔记(20G高清/PPT/代码)...

    AI 显然是最近几年非常火的一个新技术方向,从几年前大家认识到 AI 的能力,到现在产业里已经在普遍的探讨 AI 如何落地了. 我们可以预言未来在很多的领域,很多的行业,AI 都会在里边起到重要的作用 ...

最新文章

  1. Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo
  2. java web问题
  3. Eclipse插件安装的三种方式
  4. zabbix监控mysql的性能_zabbix2.4.2实战监控mysql5.6性能
  5. mixin network_【译文】Mixin——以最高的安全性满足所有区块链资产的交易需求
  6. python函数被调用才能执行吗_python3x函数在不被调用的情况下运行
  7. python os.walk_Python os.walk() 简介
  8. Momentum, RMSprob and Adam
  9. ArcGIS+Fragstats软件进行景观格局指数分析(附练习数据下载)
  10. asymptotic notation and recursion
  11. 信息流项目计划和思路
  12. Windows10重装系统教程(超详细)
  13. 如何快速合并多个TXT文件
  14. LC-3 机器语言 指令集
  15. 实现jquery双击图片放大
  16. 关于python教学
  17. 李丽云为什么选择肖志军?
  18. 解决微信浏览器video标签自动播放视频失效
  19. 无创脑刺激对不同神经和神经精神疾病睡眠障碍的影响
  20. cmd 连接 远程数据库

热门文章

  1. Idea主菜单栏不见了怎么找回
  2. 数据结构与算法(陈越版)第一讲 基本概念
  3. 将多个文件合并为一个文件
  4. 【算法-LeetCode】121. 买卖股票的最佳时机(动态规划;贪心)
  5. mysql排序order by asc | desc
  6. 四级,六级报名网站很卡怎么办?
  7. MIPS中的异常处理和系统调用
  8. Win10安装Deepin双系统找不到启动项
  9. Linpack的编译和安装
  10. 上半年要完成的博客占坑77