用svm预测信用卡诈骗

数据集来源于Kaggle https://www.kaggle.com/mlg-ulb/creditcardfraud, 用于预测信用卡用户是否会落入诈骗组,这里发一个中文版本的存稿

数据初探

首先导入数据

dat = pd.read_csv("E:/study/machine learning/credit card fraud/creditcard.csv")
df = pd.DataFrame(dat)
df.describe()

            Time         V1         V2  ...  Amount  Class  Amount_log
0            0.0  -1.359807  -0.072781  ...  149.62      0    5.008166
1            0.0   1.191857   0.266151  ...    2.69      0    0.993252
2            1.0  -1.358354  -1.340163  ...  378.66      0    5.936665
3            1.0  -0.966272  -0.185226  ...  123.50      0    4.816322
4            2.0  -1.158233   0.877737  ...   69.99      0    4.248495
5            2.0  -0.425966   0.960523  ...    3.67      0    1.302913
6            4.0   1.229658   0.141004  ...    4.99      0    1.609438
7            7.0  -0.644269   1.417964  ...   40.80      0    3.708927
8            7.0  -0.894286   0.286157  ...   93.20      0    4.534855
9            9.0  -0.338262   1.119593  ...    3.68      0    1.305626
10          10.0   1.449044  -1.176339  ...    7.80      0    2.055405
11          10.0   0.384978   0.616109  ...    9.99      0    2.302585
12          10.0   1.249999  -1.221637  ...  121.50      0    4.79...

数据共31列,除去是否落入诈骗组的“Class”组外,另有时间和消费额,以及用于隐藏用户信息、经过PCA处理过的V1至V28,我们首先来看数据在Class组中的分布

plt.figure(figsize=(7,5))
sns.countplot(df['Class'])
plt.title("Fraud and not Fraud Class Count", fontsize=18)
plt.xlabel("Fraud and not Fraud", fontsize=15)
plt.ylabel("Count", fontsize=15)
plt.show()

用svm预测信用卡诈骗_第1张图片
我们可以看到,这是一组明显的不平衡数据集,参与过诈骗的用户量远远少没参与过诈骗的用户,这意味着我们在建模前,首先要对数据集的不平衡性进行处理,否则模型会始终倾向于将用户分入非诈骗组。

我们继续分析另外两个明确定义的变量,下图是经过log处理后的消费额Amount与Class的箱型图,从图中我们可以看到,信用卡诈骗用户的消费额范围更广,且IQR明显高于非诈骗用户,但最高的消费额存在于非诈骗组。

df['Amount_log'] = np.log(df['Amount'] + 0.01) # engineer the data for better visualization
plt.figure(figsize=(7,5))
sns.boxplot(x = "Class", y = "Amount_log", data = df)
plt.show()

用svm预测信用卡诈骗_第2张图片
最后我们分析时间与class的关系,

fraud = df[df["Class"] == 1]
nonfraud = df[df["Class"] == 0]

plt.figure(figsize=(7,20))
plt.subplot(211)
ax1 = sns.scatterplot(x=fraud["Time"],y=fraud["Amount"])
plt.subplot(212)
ax2 = sns.scatterplot(x=nonfraud["Time"],y=nonfraud["Amount"])
plt.show()

用svm预测信用卡诈骗_第3张图片
在不同的时间维度上,诈骗组和非诈骗组的消费额虽都整体偏低,但分布都非常均匀,该图显示时间与是否诈骗没有什么明显的关系。在之后建模时,我们可以考虑删除时间变量。

我们现在再来看看变量之间的相关性

df_corr = df.corr()
plt.figure(figsize=(7,5))
sns.heatmap(df_corr, cmap="YlGnBu")
plt.title('Heatmap correlation')
plt.show()

用svm预测信用卡诈骗_第4张图片
从上图我们可以看出,绝大多数的变量之间都没有相关关系,这也侧面证明了变量也确实经过了PCA,不需要再次进行PCA的处理。

建模

首先,我们需要将数据集分为训练集和测试集两部分

X = df.drop(["Amount_log", "Time", "Class"],axis=1)
y = df["Class"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 12)

处理不平衡数据有多种方法,考虑到训练时间问题(因为我们这里选择的是需要较长训练时间的SVM),这里我们选择undersampling,从多数集中抽样,使诈骗组和非诈骗组中的用户量成为同一个量级

undersampling_train = pd.concat([X_train,y_train],axis=1)
undersampling_train_nonfraud = undersampling_train[undersampling_train['Class']==0].sample(300)
undersampling_train_fraud = undersampling_train[undersampling_train['Class']==1]
undersampling_train_total = pd.concat([undersampling_train_nonfraud,undersampling_train_fraud],axis=0)
undersampling_X = undersampling_train_total.drop("Class",axis=1)
undersampling_y = undersampling_train_total["Class"]

我们选择的方法是SVM

def confusion_matrix_1(CM):
    fig, ax = plot_confusion_matrix(conf_mat=CM)
    plt.title("The Confusion Matrix 1 of Undersampled dataset")
    plt.ylabel("Actual")
    plt.xlabel("Predicted")
    plt.show()
    print("The accuracy is "+str((CM[1,1]+CM[0,0])/(CM[0,0] + CM[0,1]+CM[1,0] + CM[1,1])*100) + " %")
    print("The recall from the confusion matrix is "+ str(CM[1,1]/(CM[1,0] + CM[1,1])*100) +" %")


ss = SVC(kernel="linear")
ss.fit(undersampling_X,undersampling_y)
y_pred = ss.predict(X_test)
cmss = confusion_matrix(y_test, y_pred)
confusion_matrix_1(cmss)
The accuracy is 95.20519086542512 %
The recall from the confusion matrix is 87.09677419354838 %

95%的正确率看起来还不错,但我们在分析信用卡诈骗问题时,更多是用recall来衡量模型的准确度,而87%的recall看起来就有提升的空间了

调参

我们尝试使用GridSearchCV来调整SVM的参数

turned_parameters = [{'kernel':['linear','rbf','poly'],'gamma':['auto'],'C': [1,10,100,1000]}]
svm = GridSearchCV(SVC(), turned_parameters,cv=5,scoring='recall')
svm.fit(undersampling_X, undersampling_y)
print("Best parameters set found on Training dataset:")
print()
print(svm.best_params_)

由GridSearchCV,最合适的参数为{‘C’: 100, ‘gamma’: ‘auto’, ‘kernel’: ‘rbf’},我们使用这组参数来重新对数据集进行建模

{'C': 100, 'gamma': 'auto', 'kernel': 'rbf'}
The accuracy is 82.39796634925986 %
The recall from the confusion matrix is 94.35483870967742 %

用svm预测信用卡诈骗_第5张图片
虽然总的正确率下降,但94%的recall要明显优于原模型,故新模型要更加贴合数据。

你可能感兴趣的:(用svm预测信用卡诈骗)