1 建模目的

信用卡欺诈检测,又叫异常检测。异常检测无非就是正常和异常,这是一个二分类任务,显然正常的占绝大部分,异常的只占很少的比例,我们要检测的就是这些异常的。利用信用卡历史数据进行建模,构建反欺诈模型,预测新的信用卡被盗刷的可能性。

2 数据集介绍

数据集包含由欧洲人于2013年9月使用信用卡进行交易的数据。此数据集显示两天内发生的交易,其中284807笔交易中有492笔被盗刷。数据集非常不平衡,正例(被盗刷)占所有交易的0.172%。,这是因为由于保密问题,我们无法提供有关数据的原始功能和更多背景信息。特征V1,V2,… V28是使用PCA获得的主要组件,没有用PCA转换的唯一特征是“Class”和“Amount”。特征’Time’包含数据集中每个刷卡时间和第一次刷卡时间之间经过的秒数。特征’Class’是响应变量,如果发生被盗刷,则取值1,否则为0。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
import seaborn as sns
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
data = pd.read_csv("creditcard.csv")
data.head()
Time V1 V2 V3 V4 V5 V6 V7 V8 V9 ... V21 V22 V23 V24 V25 V26 V27 V28 Amount Class
0 0.0 -1.359807 -0.072781 2.536347 1.378155 -0.338321 0.462388 0.239599 0.098698 0.363787 ... -0.018307 0.277838 -0.110474 0.066928 0.128539 -0.189115 0.133558 -0.021053 149.62 0
1 0.0 1.191857 0.266151 0.166480 0.448154 0.060018 -0.082361 -0.078803 0.085102 -0.255425 ... -0.225775 -0.638672 0.101288 -0.339846 0.167170 0.125895 -0.008983 0.014724 2.69 0
2 1.0 -1.358354 -1.340163 1.773209 0.379780 -0.503198 1.800499 0.791461 0.247676 -1.514654 ... 0.247998 0.771679 0.909412 -0.689281 -0.327642 -0.139097 -0.055353 -0.059752 378.66 0
3 1.0 -0.966272 -0.185226 1.792993 -0.863291 -0.010309 1.247203 0.237609 0.377436 -1.387024 ... -0.108300 0.005274 -0.190321 -1.175575 0.647376 -0.221929 0.062723 0.061458 123.50 0
4 2.0 -1.158233 0.877737 1.548718 0.403034 -0.407193 0.095921 0.592941 -0.270533 0.817739 ... -0.009431 0.798278 -0.137458 0.141267 -0.206010 0.502292 0.219422 0.215153 69.99 0

5 rows × 31 columns

data.shape
(284807, 31)
data.isnull().sum()
Time      0
V1        0
V2        0
V3        0
V4        0
V5        0
V6        0
V7        0
V8        0
V9        0
V10       0
V11       0
V12       0
V13       0
V14       0
V15       0
V16       0
V17       0
V18       0
V19       0
V20       0
V21       0
V22       0
V23       0
V24       0
V25       0
V26       0
V27       0
V28       0
Amount    0
Class     0
dtype: int64

此数据集无缺失值。

3 探索性分析

3.1 交易时间分布

f, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(16,4))bins = 50ax1.hist(data["Time"][data["Class"]== 1], bins = bins,facecolor='pink',alpha=0.75)
ax1.set_title('Fraud')ax2.hist(data["Time"][data["Class"] == 0], bins = bins,facecolor= '#ADD8E6',alpha=0.75)
ax2.set_title('Normal')plt.xlabel('Time')
plt.ylabel('Number of Transactions')
plt.show()

可以看到,欺诈交易的时间离散度高,出现2个峰值迹象;正常交易分布聚集度明显,可以看到在两个时间段里,用户交易频率高。

3.2 交易金额分布

f, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(16,4))bins = 50ax1.hist(data["Amount"][data["Class"]== 1], bins = bins,facecolor='#4682B4',alpha=0.75)
ax1.set_title('Fraud')ax2.hist(data["Amount"][data["Class"] == 0], bins = bins,facecolor='#FF8C00',alpha=0.75)
ax2.set_title('Normal')plt.xlabel('Amount')
plt.ylabel('Number of Transactions')
plt.yscale('log')
plt.show()

信用卡被盗刷交易的金额比信用卡正常用户交易的金额小,这说明信用卡盗刷者为了不引起信用卡卡主的注意,更偏向选择小金额消费。

3.3 查看数据标签分布

count_classes = pd.value_counts(data['Class'], sort = True).sort_index()
count_classes.plot(kind = 'bar')
plt.title("Fraud class histogram")
plt.xlabel("Class")
plt.ylabel("Frequency")
data.groupby('Class').size()
Class
0    284315
1       492
dtype: int64

可以看到0样本的个数远远多于1样本的个数,出现样本分布不均衡的情况。

4 数据预处理

4.1特征缩放

在对样本处理之前,需要先处理下数据,对数据规格较大的amount列做归一化处理,使其均值为0,方差为1,使不同维度的特征对模型的重要程度相同。

from sklearn.preprocessing import StandardScaler
normAmount= StandardScaler().fit_transform(data['Amount'].values.reshape(-1, 1))
normTime= StandardScaler().fit_transform(data['Time'].values.reshape(-1, 1))
data.insert(1,'normAmount',normAmount)
data.insert(2,'normTime',normTime)
data = data.drop(['Time','Amount'],axis=1)
data.head()
normAmount normTime V1 V2 V3 V4 V5 V6 V7 V8 ... V20 V21 V22 V23 V24 V25 V26 V27 V28 Class
0 0.244964 -1.996583 -1.359807 -0.072781 2.536347 1.378155 -0.338321 0.462388 0.239599 0.098698 ... 0.251412 -0.018307 0.277838 -0.110474 0.066928 0.128539 -0.189115 0.133558 -0.021053 0
1 -0.342475 -1.996583 1.191857 0.266151 0.166480 0.448154 0.060018 -0.082361 -0.078803 0.085102 ... -0.069083 -0.225775 -0.638672 0.101288 -0.339846 0.167170 0.125895 -0.008983 0.014724 0
2 1.160686 -1.996562 -1.358354 -1.340163 1.773209 0.379780 -0.503198 1.800499 0.791461 0.247676 ... 0.524980 0.247998 0.771679 0.909412 -0.689281 -0.327642 -0.139097 -0.055353 -0.059752 0
3 0.140534 -1.996562 -0.966272 -0.185226 1.792993 -0.863291 -0.010309 1.247203 0.237609 0.377436 ... -0.208038 -0.108300 0.005274 -0.190321 -1.175575 0.647376 -0.221929 0.062723 0.061458 0
4 -0.073403 -1.996541 -1.158233 0.877737 1.548718 0.403034 -0.407193 0.095921 0.592941 -0.270533 ... 0.408542 -0.009431 0.798278 -0.137458 0.141267 -0.206010 0.502292 0.219422 0.215153 0

5 rows × 31 columns

4.2 特征选择

利用GBDT梯度提升决策树进行特征重要性排序

columns = data.columns
features_columns = columns.delete(len(columns) - 1)features = data[features_columns]
labels = data['Class']
# The labels are in the last column ('Class'). Simply remove it to obtain features columns
from sklearn.ensemble import GradientBoostingClassifier
gbdt = GradientBoostingClassifier()
gbdt.fit(features, labels)
GradientBoostingClassifier()
# 找到重要特征
feature_importances = gbdt.feature_importances_
# 重要特征下标排序
# argsort返回的排序之后的下标
inds = feature_importances.argsort()[::-1]
# 重要特征降序排列
data.columns[inds]
Index(['V17', 'V14', 'V26', 'V8', 'V10', 'normTime', 'V12', 'V7', 'V20', 'V27','V4', 'V16', 'V18', 'V21', 'V23', 'V24', 'V9', 'V6', 'V11', 'V25','V15', 'V1', 'V13', 'V3', 'V2', 'V28', 'V5', 'V19', 'V22','normAmount'],dtype='object')
plt.figure(figsize=(15,9))
plt.bar(np.arange(30), feature_importances[inds])
_ = plt.xticks(np.arange(30), data.columns[inds])

根据上图可以发现,v9,v1,v6,v11,v25,v15,v13,v3,v2,v28,v5,v19,v22,normAmount列可以删除

data.drop(columns=['V9', 'V1', 'V6', 'V11', 'V25','V15', 'V13', 'V3', 'V2', 'V28', 'V5', 'V19', 'V22', 'normAmount'], inplace=True)

4.3 样本不均衡处理

  • 下采样处理,让正常样本和异常样本一样少。
  • 过采样处理,让异常样本和正常样本一样多。

这两种方案的效果如何?下面我们首先采用下采样对数据进行处理。

下采样处理

X = data.iloc[:, data.columns != 'Class']
y = data.iloc[:, data.columns == 'Class']# 少数异常数据类所对应的索引值
number_records_fraud = len(data[data.Class == 1])
fraud_indices = np.array(data[data.Class == 1].index)#正常交易数据的索引值
normal_indices = data[data.Class == 0].index#从正常交易的数据中随机取出和异常数据数目一样多的数据
random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False)
random_normal_indices = np.array(random_normal_indices)# 将0样本和1样本的索引合并,形成新的数据集
under_sample_indices = np.concatenate([fraud_indices,random_normal_indices])# 下采样数据集
under_sample_data = data.iloc[under_sample_indices,:]X_undersample = under_sample_data.iloc[:, under_sample_data.columns != 'Class']
y_undersample = under_sample_data.iloc[:, under_sample_data.columns == 'Class']# 0样本和1样本的个数
print("Percentage of normal transactions: ", len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data))
print("Percentage of fraud transactions: ", len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data))
print("Total number of transactions in resampled data: ", len(under_sample_data))
Percentage of normal transactions:  0.5
Percentage of fraud transactions:  0.5
Total number of transactions in resampled data:  984

4.4 数据切分

对下采样数据进行切分是为了训练模型时使用,并且对原始数据进行一定比例的切分,以备测试时使用,不选用下采样数据测试是因为下采样样本数据较少,不具有原始数据的分布特征。

 from sklearn.model_selection import train_test_split# Whole dataset
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)print("Number transactions train dataset: ", len(X_train))
print("Number transactions test dataset: ", len(X_test))
print("Total number of transactions: ", len(X_train)+len(X_test))# Undersampled dataset
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("Number transactions train dataset: ", len(X_train_undersample))
print("Number transactions test dataset: ", len(X_test_undersample))
print("Total number of transactions: ", len(X_train_undersample)+len(X_test_undersample))
Number transactions train dataset:  199364
Number transactions test dataset:  85443
Total number of transactions:  284807Number transactions train dataset:  688
Number transactions test dataset:  296
Total number of transactions:  984

5 逻辑回归建模

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold,cross_val_score
from sklearn.metrics import confusion_matrix,recall_score,classification_report

5.1 模型选择

使用同一个算法,当使用不同的参数时,也会产生不同的模型,这就涉及到模型的选择问题,一般而言,应该选择泛化误差最小的模型,但是我们事先不知道新样本是未知的,通过使用一个测试集来测试对新样本的判别能力,然后以测试集上的测试误差作为泛化误差的近似,常用的有k折交叉验证,
它的基本思路是首先将原始数据按照8:2的比例切分成训练集和测试集,然后再在训练集上进行切分,即训练数据分成K组(K-Fold),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型。这K个模型分别在验证集中评估结果,将求得的MSE(Mean Squared Error)加和平均就得到交叉验证误差,作为评价当前参数下模型的好坏。再用测试集在最终选择的模型上测试,用来评估模最终模型的泛化能力。

这里仅对正则化惩罚力度进行调参实验,正则化的意义是防止过拟合,所谓过拟合,指的是模型在训练集上表现的很好,但是在交叉验证集合测试集上表现较差,也就是说模型对未知样本的预测表现一般。正则化是指去限制参数的空间,减少特征的数量,控制模型的复杂度。参数选择l1正则化范式,比较适合模型的特征非常多,同时希望将一些不重要的特征系数归零,从而让模型系数更加稀疏,权重值更低。

def printing_Kfold_scores(x_train_data,y_train_data):fold = KFold(5,shuffle=False) # 会得到一个可迭代对象(可以用 for 循环遍历取出),可以遍历5次,每次遍历出来的会是一个2值列表,# 存放每一次的训练集和验证集的索引# 不同的正则化惩罚力度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#循环遍历不同的参数j = 0for 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):# enumerate 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中# iteration 表示第几次循环,indices 是一个列表里面有两个元素,indices[0]表示训练集索引,indices[1] 表示验证集索引lr = LogisticRegression(C = c_param, penalty='l1', solver='liblinear',max_iter=10000)#使用训练数据拟合模型,x和y的索引都为0lr.fit(x_train_data.iloc[indices[0],:],y_train_data.iloc[indices[0],:].values.ravel())# Predict values using the test indices in the training data#建立好模型后,预测模型结果,使用验证集y_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values)# Calculate the recall score and append it to a list for recall scores representing the current c_parameter#对预测结果进行评估,recall_score需要传入真实值和预测值recall_acc = recall_score(y_train_data.iloc[indices[1],:].values,y_pred_undersample)recall_accs.append(recall_acc)print('Iteration ', iteration,': recall score = ', recall_acc)# The mean value of those recall scores is the metric we want to save and get hold of.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[results_table['Mean recall score'].astype('float').idxmax()]['C_parameter'] # Finally, we can check which C parameter is the best amongst the chosen.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)
-------------------------------------------
C parameter:  0.01
-------------------------------------------Iteration  1 : recall score =  0.958904109589041
Iteration  2 : recall score =  0.9178082191780822
Iteration  3 : recall score =  1.0
Iteration  4 : recall score =  0.972972972972973
Iteration  5 : recall score =  0.9545454545454546Mean recall score  0.96084615125711-------------------------------------------
C parameter:  0.1
-------------------------------------------Iteration  1 : recall score =  0.8356164383561644
Iteration  2 : recall score =  0.863013698630137
Iteration  3 : recall score =  0.9322033898305084
Iteration  4 : recall score =  0.9324324324324325
Iteration  5 : recall score =  0.8787878787878788Mean recall score  0.8884107676074242-------------------------------------------
C parameter:  1
-------------------------------------------Iteration  1 : recall score =  0.8493150684931506
Iteration  2 : recall score =  0.863013698630137
Iteration  3 : recall score =  0.9661016949152542
Iteration  4 : recall score =  0.9459459459459459
Iteration  5 : recall score =  0.8939393939393939Mean recall score  0.9036631603847762-------------------------------------------
C parameter:  10
-------------------------------------------Iteration  1 : recall score =  0.8493150684931506
Iteration  2 : recall score =  0.863013698630137
Iteration  3 : recall score =  0.9661016949152542
Iteration  4 : recall score =  0.9459459459459459
Iteration  5 : recall score =  0.8939393939393939Mean recall score  0.9036631603847762-------------------------------------------
C parameter:  100
-------------------------------------------Iteration  1 : recall score =  0.8493150684931506
Iteration  2 : recall score =  0.863013698630137
Iteration  3 : recall score =  0.9661016949152542
Iteration  4 : recall score =  0.9459459459459459
Iteration  5 : recall score =  0.8939393939393939Mean recall score  0.9036631603847762*********************************************************************************
Best model to choose from cross validation is with C parameter =  0.01
*********************************************************************************

通过交叉验证,效果最好的模型参数为0.01

5.2 模型评估

混淆矩阵

混淆矩阵是统计真实值和实际值的分布情况,来计算用来评价模型好坏的指标,比如recall值,准确率等 二分类预测的混淆矩阵中,行向量为观测的实际类别,列向量为预测类别值。其中(TP True Positive)为真正,表示实际值为 1 预测值也为 1,FN (False Negative)为假负,表示实际值为 1 预测值为 0,FP (False Positive)为假正,表示实际值为 0,预测值为 1,TN (True Negative)为真负,表示实际值为 0,预测值也为 0。

评价指标

  • 准确率:TP/(FP+TP),表示分类器预测为正例的所有样本中真正为正例的样本的比重。
  • 召回率(recall值):TP/(TP+FN) ,反映了被正确预测的正例的样本占总的正例样本的比重。
  • 精确率:TP/(TP+FP),反映了真正为正例的样本占预测为正例的样本的比重。
  • F1score:2(精确率+召回率)/(精确率+召回率)

ROC曲线 :对于二分类的模型,很多时候并不是给出每个样本预测为哪一类,而是给出其中一类的概率预测,需要选取一个阈值,当这个预测大于这个阈值时,我们将该观测预测为这一类,否则为另一类。而 ROC 曲线通过阈值从 0 到 1 移动,获得多对 FPR=FP/ (TN+FP)和 TPR=TP/ (FN+TP),且当样本出现不均衡的时候,ROC曲线具有不变形,所以选用ROC曲线来比较不同分类器分类效果。

  • 纵轴表示TPR=TP/(FN+TP)(真正例率),表示在所有正例中,预测出来的正例样本有多少。
  • 横轴表示FPR=FP/(TN+FP)(假正例率)表示在所有负例中,被预测为正例的样本有多少。
    显然我们希望TPR越大越好,FPR越小越好。
  • AUC表示ROC曲线下的面积,不同的模型对应的ROC曲线中,AUC值大的模型性能自然相对较好。

下面来定义混淆矩阵的画法,代码如下

def plot_confusion_matrix(cm, classes,title='Confusion matrix',cmap=plt.cm.Blues):"""This function prints and plots the confusion matrix."""plt.imshow(cm, interpolation='nearest', cmap=cmap)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='l1', solver='liblinear')
lr.fit(X_train_undersample,y_train_undersample.values.ravel())
y_pred_undersample = lr.predict(X_test_undersample.values)# Compute confusion matrix
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]))# 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 metric in the testing dataset:  0.9319727891156463

可以看到得到的召回率的值为0.9319727891156463,可以看到分类效果是比较好的,但是这里是用下采样的数据集进行建模,并且测试集采用的也是下采样的数据。

计算指标

from sklearn.metrics import f1_score,precision_score,recall_score,auc,roc_auc_score,accuracy_score,roc_curve
def metrics_score(y_test,y_pred):Accuracy=accuracy_score(y_test,y_pred)Recall=recall_score(y_test,y_pred)Pre=precision_score(y_test,y_pred)F1_score=f1_score(y_test,y_pred)AUC=roc_auc_score(y_test,y_pred)return Accuracy,Recall,Pre,F1_score,AUC
#计算指标得分
y_pred_undersample = lr.predict(X_test_undersample.values)
Accuracy,Recall,Pre,F1_score,AUC=metrics_score(y_test_undersample,y_pred_undersample)
print('准确率:%.2f|召回率:%.2f|精确率:%.2f|F1_score:%.2f|AUC:%.2f'%(Accuracy,Recall,Pre,F1_score,AUC))
准确率:0.89|召回率:0.93|精确率:0.85|F1_score:0.89|AUC:0.89
#ROC曲线图
y_pred_proba=lr.predict_proba(X_test_undersample.values)
fpr, tpr, thresholds = roc_curve(y_test_undersample,y_pred_proba[:,1])
plt.plot(fpr,tpr,label='AUC = %0.2f'% AUC)
plt.legend(loc='lower right')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.plot([0,1],[0,1],'r--')
plt.show()

只在小规模的数据集进行测试,不具有代表性,所以我们在测试时应该采用原始数据集进行测试,代码如下

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 metric in the testing dataset:  0.9183673469387755

#计算指标得分
Accuracy,Recall,Pre,F1_score,AUC=metrics_score(y_test,y_pred)
print('准确率:%.2f|召回率:%.2f|精确率:%.2f|F1_score:%.2f|AUC:%.2f'%(Accuracy,Recall,Pre,F1_score,AUC))
准确率:0.90|召回率:0.92|精确率:0.01|F1_score:0.03|AUC:0.91

可以看到召回率=135/(135+12)=0.9183673469387755较高,准确率0.90也比较高,但是精确率较低,这是因为误抓的样本10624比较多,并且还给我们增加了工作量,根据实际业务需求,后续肯定要对这些异常样本做一些处理,比如冻结账号、电话询问等。这是用下采样处理数据所存在的问题。

6 模型改进-过采样处理

在采用下采样的方案中,可以看到召回率较高的同时,误抓的样本也非常多。于是采用过采样处理方案看效果是否会好一些。

smote算法

SMOTE(Synthetic Minority Oversampling Technique),合成少数类过采样技术.它是基于随机过采样算法的一种改进方案,由于随机过采样采取简单复制样本的策略来增加少数类样本,这样容易产生模型过拟合的问题,即使得模型学习到的信息过于特别(Specific)而不够泛化(General),SMOTE算法的基本思想是对少数类样本进行分析并根据少数类样本人工合成新样本添加到数据集中,具体如下图所示,算法流程如下。

(1)对于少数类中每一个样本x,以欧氏距离为标准计算它到少数类样本集中所有样本的距离,得到其k近邻。

(2)根据样本不平衡比例设置一个采样比例以确定采样倍率N,对于每一个少数类样本x,从其k近邻中随机选择若干个样本,假设选择的近邻为xn。

(3)对于每一个随机选出的近邻xnx_nxn​,分别与原样本按照如下的公式构建新的样本。
xnew=x+rand(0,1)∗(xn−x)x_{new}=x+rand(0,1)*(x_n-x)xnew​=x+rand(0,1)∗(xn​−x)

import pandas as pd
from imblearn.over_sampling import SMOTE  # pip  install imblearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
columns = data.columns
features_columns = columns.delete(len(columns) - 1)
features = data[features_columns]
labels = data['Class']

划分训练集和测试集

features_train, features_test, labels_train, labels_test = train_test_split(features, labels, test_size=0.2, random_state=0)

smote算法生成过采样数据

oversampler = SMOTE(random_state=0)
os_features,os_labels = oversampler.fit_resample(features_train,labels_train) # OS  oversampler
print('过采样后label为1的数据为:',len(os_labels[os_labels==1]))
过采样后label为1的数据为: 227454

k折交叉验证选择最优参数

os_features = pd.DataFrame(os_features)
os_labels = pd.DataFrame(os_labels)
os_features = pd.DataFrame(os_features)
os_labels = pd.DataFrame(os_labels)
best_c = printing_Kfold_scores(os_features, os_labels)
-------------------------------------------
C parameter:  0.01
-------------------------------------------Iteration  1 : recall score =  0.9161290322580645
Iteration  2 : recall score =  0.9078947368421053
Iteration  3 : recall score =  0.9026004204935266
Iteration  4 : recall score =  0.8831844011386993
Iteration  5 : recall score =  0.8844923665380684Mean recall score  0.8988601914540928-------------------------------------------
C parameter:  0.1
-------------------------------------------Iteration  1 : recall score =  0.9161290322580645
Iteration  2 : recall score =  0.9078947368421053
Iteration  3 : recall score =  0.9032200951643244
Iteration  4 : recall score =  0.8835251316208879
Iteration  5 : recall score =  0.8848880535496423Mean recall score  0.8991314098870049-------------------------------------------
C parameter:  1
-------------------------------------------Iteration  1 : recall score =  0.9161290322580645
Iteration  2 : recall score =  0.9078947368421053
Iteration  3 : recall score =  0.9033528825937811
Iteration  4 : recall score =  0.8837889229619371
Iteration  5 : recall score =  0.8849320187731504Mean recall score  0.8992195186858076-------------------------------------------
C parameter:  10
-------------------------------------------Iteration  1 : recall score =  0.9161290322580645
Iteration  2 : recall score =  0.9078947368421053
Iteration  3 : recall score =  0.9033528825937811
Iteration  4 : recall score =  0.8837009925149207
Iteration  5 : recall score =  0.8849540013849045Mean recall score  0.8992063291187552-------------------------------------------
C parameter:  100
-------------------------------------------Iteration  1 : recall score =  0.9161290322580645
Iteration  2 : recall score =  0.9078947368421053
Iteration  3 : recall score =  0.9033307513555383
Iteration  4 : recall score =  0.8838658621030765
Iteration  5 : recall score =  0.8849540013849045Mean recall score  0.8992348767887378*********************************************************************************
Best model to choose from cross validation is with C parameter =  100.0
*********************************************************************************

使用过采样数据训练模型,并用测试集测试

lr = LogisticRegression(C = best_c, penalty = 'l1', solver='liblinear')
lr.fit(os_features,os_labels.values.ravel())
y_pred = lr.predict(features_test.values)# Compute confusion matrix
cnf_matrix = confusion_matrix(labels_test,y_pred)
np.set_printoptions(precision=2)Accuracy,Recall,Pre,F1_score,AUC=metrics_score(labels_test,y_pred)
print('准确率:%.2f|召回率:%.2f|精确率:%.2f|F1_score:%.2f|AUC:%.2f'%(Accuracy,Recall,Pre,F1_score,AUC))# Plot non-normalized confusion matrix
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=class_names, title='Confusion matrix')
plt.show()#ROC曲线图
y_pred_proba=lr.predict_proba(features_test.values)
fpr, tpr, thresholds = roc_curve(labels_test,y_pred_proba[:,1])
plt.plot(fpr,tpr,label='AUC = %0.2f'% AUC)
plt.legend(loc='lower right')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.plot([0,1],[0,1],'r--')
plt.show()
准确率:0.97|召回率:0.93|精确率:0.06|F1_score:0.11|AUC:0.95

可以看到过采样对比下采样,在准确率,召回率和精确率上都有提高,虽然过采样的准确率和召回率都很高,但是精确率还是非常低,也就是误抓的样本偏多,尽管过采样比欠采样的效果要好,但是此模型的选择方面还有待进一步优化。

7 随机森林建模

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
clf_RF=RandomForestClassifier(n_estimators=10,random_state=123)#构建分类随机森林分类器
clf_RF.fit(os_features,os_labels.values.ravel())#交叉验证
scores_RF=cross_val_score(clf_RF,os_features,os_labels.values.ravel())
print('RandomForestClassifier交叉验证准确率为:'+str(scores_RF.mean()))
RandomForestClassifier交叉验证准确率为:0.9997933645851017
# 生成混淆矩阵
cnf_matrix_RF= confusion_matrix(labels_test,y_RFpred)
np.set_printoptions(precision=2)
Accuracy,Recall,Pre,F1_score,AUC=metrics_score(labels_test,y_RFpred)
print('准确率:%.3f|召回率:%.2f|精确率:%.2f|F1_score:%.2f|AUC:%.2f'%(Accuracy,Recall,Pre,F1_score,AUC))
#画混淆矩阵
class_names = [0,1]
plt.figure(figsize=(6,6))
plot_confusion_matrix(cnf_matrix_RF,classes=class_names,title='Confusion matrix')
plt.show()
准确率:0.999|召回率:0.83|精确率:0.84|F1_score:0.84|AUC:0.92

在过采样处理下,随机森林虽然召回率(0.83)没有逻辑回归模型的召回率(0.93)高,但是精确率却有很大提升,也就是说针对后续的欺诈行为,可能会去冻结顾客的银行卡帐户,或者打电话向这些怀疑对象要一些额外资料如信用卡银行对账单,用以核对部分卡号等措施,那为了尽可能少的去打扰到“无辜”客户,所以选择随机森林模型对信用卡欺诈预测效果会更好一些。

信用卡欺诈检测建模分析相关推荐

  1. 大数据分析实战-信用卡欺诈检测(五)-逻辑回归模型

    大数据分析实战-信用卡欺诈检测(一) 大数据分析实战-信用卡欺诈检测(二)-下采样方案和交叉验证 大数据分析实战-信用卡欺诈检测(三)- 模型评估 大数据分析实战-信用卡欺诈检测(四)-正则化惩罚 逻 ...

  2. 信用卡欺诈检测python_Python机器学习实战:信用卡欺诈检测

    原标题:Python机器学习实战:信用卡欺诈检测 本文作者:唐宇迪 ,文末有彩蛋!本期送书python! 故事背景:原始数据为个人交易记录,但是考虑数据本身的隐私性,已经对原始数据进行了类似PCA的处 ...

  3. 毕业设计 - 题目:基于大数据的信用卡欺诈检测

    文章目录 0 简介 1 数据集 2 分析流程 3 数据预览 3.1 数据浏览 3.1.1 查看数据分布 4 数据规范化 4.1 amount特征缩放并去除time字段 4.2 解决样本不均衡问题 5 ...

  4. qiuzitao机器学习(六):信用卡欺诈检测项目

    机器学习实战–信用卡欺诈检测项目 学校大三校企合作的课程设计项目 一.任务基础 拿到的信用卡数据集是由欧洲人于2013年9月使用信用卡进行交易的数据.此数据集显示两天内发生的交易,其中284807笔交 ...

  5. 【机器学习】信用卡欺诈检测 (下采样、SMOTE过采样、集成学习、Pytorch)

    2022.4.17 补充 视频:[参考:6-01 信用卡交易欺诈数据检测 _哔哩哔哩_bilibili] [参考:机器学习/Kaggle/信用卡欺诈检测/Tommy/数据不平衡.ipynb · mya ...

  6. python之逻辑回归项目实战——信用卡欺诈检测

    信用卡欺诈检测 1.项目介绍 2.项目背景 3.分析项目 4.数据读取与分析 4.1 加载数据 4.2 查看数据的标签分布 5.数据预处理 5.1 特征标准化 5.2. 使用下采样解决样本数据不均衡 ...

  7. 大数据分析实战-信用卡欺诈检测(四)-正则化惩罚

    大数据分析实战-信用卡欺诈检测(一) 大数据分析实战-信用卡欺诈检测(二)-下采样方案和交叉验证 大数据分析实战-信用卡欺诈检测(三)- 模型评估 文章目录 正则化惩罚 正则化惩罚 正则化惩罚,这个名 ...

  8. 大数据分析实战-信用卡欺诈检测(三)- 模型评估

    大数据分析实战-信用卡欺诈检测(二)-下采样方案和交叉验证 大数据分析实战-信用卡欺诈检测(一) 文章目录 模型评估方法 模型评估方法 接下来,没错,还没到实际建模任务,还需要考虑模型的评估方法,为什 ...

  9. 大数据分析实战-信用卡欺诈检测(二)-下采样方案和交叉验证

    第一部分已经写到这里了,看完第一部分再看这一部分:大数据分析实战-信用卡欺诈检测 文章目录 下采样方案 交叉验证 下采样方案 下采样方案的实现过程比较简单,只需要对正常样本进行采样,得到与异常样本一样 ...

  10. 机器学习项目实战----信用卡欺诈检测(二)

    六.混淆矩阵: 混淆矩阵是由一个坐标系组成的,有x轴以及y轴,在x轴里面有0和1,在y轴里面有0和1.x轴表达的是预测的值,y轴表达的是真实的值.可以对比真实值与预测值之间的差异,可以计算当前模型衡量 ...

最新文章

  1. cvReleaseImage出错
  2. sqlite to mysql_SqliteToMysql官方版
  3. JScript 和 VBscript访问网络上的打印设备
  4. P2038 无线网络发射器选址
  5. 理解Linux系统中的load average
  6. Ta还没有分享呢,过段时间再来看看吧~ 解决办法
  7. 网页设计Web尺寸规范
  8. IP地址被屏蔽怎么解决
  9. office表格怎么冻结前两行_冻结Excel表格中多行或多列的方法
  10. 【Arduino】一天入门Arduino语言 教程
  11. linux下lamealsa进行音频流操作(一)lame知识介绍
  12. 这台计算机上没有安装驱动程序,电脑打印机显示没有安装驱动怎么办啊
  13. 基于51单片机十字路口交通信号灯(启动按键+绿灯同亮报警)
  14. DCT变换和DFT变换
  15. 如何制作linux iso镜像
  16. ASP.Net中常见的文件类型
  17. 2021年江苏一级计算机报名时间,江苏2021年3月计算机一级报名时间安排
  18. [转摘]必须学好C++么?
  19. 电脑黑屏提示missing operating system怎么办
  20. 南极区域点坐标单位由decimal degrees到meter转换

热门文章

  1. java代码生成流程图,赶紧收藏!
  2. java web 基础知识 流程图
  3. 【转载】GIS概念解析:大地高 | 海拔 | 正高 | 正常高
  4. 【自学笔记】三维copula的构建与分布函数的求解
  5. 使用Spine软件制作骨骼动画供Cocos2d-x使用
  6. 代码雨和N个本地磁盘的制作
  7. 新华三杯考前突击---Day1---物联网技术篇
  8. mac 开启android 模拟器,折腾mac的经验积累 2:mac上如何玩安卓模拟器
  9. 使用易宝支付接口实现java网上支付功能。
  10. 为什么CSDN登陆是明文传输账户密码