SVM_信用卡欺诈

信用卡欺诈问题

  • 概述
  • 实现过程
    • SVM介绍
    • 数据源下载
    • 代码实现
    • 代码解释
  • 总结

概述

初衷是因为引用卡欺诈问题相对与其他机器学习问题略有不同,因为二分类数据量差距过大,导致以往的评价方法对其不适用,如下图的284807 笔交易中只有492笔是欺诈行为,如果用以为的准确率评价几乎都在99%以上,但是这并不能说明模型好,因为即使漏掉1个欺诈交易都是损失很大的,所以这篇里引入了召回率和精确率,进行综合评价,详细步骤如下:

  • 对数据源中不比较的字段进行删减,对数值型数据进行规范化,因为没有测试集数据,所以进行数据划分。
  • 数据建模使用的是LinearSVR,因为LinearSVC 对线性分类做了优化,对于数据量大的线性可分问题,使用 LinearSVC 的效率要高于 SVC。这里我们是假设特征是线性可分的(线性可分就可以理解成用一条线能把两个类别分开),当然也可以使用逻辑回归、决策树、或者是把核函数设置为rbf(高斯核函数)进行尝试。

实现过程

SVM介绍

model = svm.SVC(kernel=‘rbf’, C=1.0, gamma=‘auto’) 

kernel代表核函数的选择,它有四种选择,只不过默认是 rbf,即高斯核函数。linear:线性核函数poly:多项式核函数rbf:高斯核函数(默认)sigmoid:sigmoid 核函数这四种函数代表不同的映射方式。

此外引用一位知乎题主的回答,我觉得比较实用:
作者:Jason Gu
链接:https://www.zhihu.com/question/21883548/answer/19693213

  1. Linear核:主要用于线性可分的情形。参数少,速度快,对于一般数据,分类效果已经很理想了。
  2. RBF核:主要用于线性不可分的情形。参数多,分类结果非常依赖于参数。有很多人是通过训练数据的交叉验证来寻找合适的参数,不过这个过程比较耗时。我个人的体会是:使用libsvm,默认参数,RBF核比Linear核效果稍差。通过进行大量参数的尝试,一般能找到比linear核更好的效果。至于到底该采用哪种核,要根据具体问题,有的数据是线性可分的,有的不可分,需要多尝试不同核不同参数。如果特征的提取的好,包含的信息量足够大,很多问题都是线性可分的。当然,如果有足够的时间去寻找RBF核参数,应该能达到更好的效果。

此外,sigmoid一般用于处理神经网络,pold虽然可以处理非线性问题,但是训练时间比较长。

数据源下载

数据源
链接:https://pan.baidu.com/s/14F8WuX0ZJntdB_r1EC08HA 提取码:58gp

说明:Class=0 为正常(非欺诈),Class=1 代表欺诈。

代码实现

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import svm
from sklearn.metrics import confusion_matrix, precision_recall_curve
import warnings
import itertools
warnings.filterwarnings('ignore')

# 混淆矩阵可视化
def plot_confusion_matrix(cm, classes, normalize = False, title = 'Confusion matrix"', cmap = plt.cm.Blues) :
    plt.figure()
    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')
    plt.show()

# 显示模型评估结果
def show_metrics():
    tp = cm[1,1]
    fn = cm[1,0]
    fp = cm[0,1]
    tn = cm[0,0]
    print('精确率: {:.3f}'.format(tp/(tp+fp)))
    print('召回率: {:.3f}'.format(tp/(tp+fn)))
    print('F1值: {:.3f}'.format(2*(((tp/(tp+fp))*(tp/(tp+fn)))/((tp/(tp+fp))+(tp/(tp+fn))))))

# 绘制精确率-召回率曲线
def plot_precision_recall():
    plt.step(recall, precision, color = 'b', alpha = 0.2, where = 'post')
    plt.fill_between(recall, precision, step ='post', alpha = 0.2, color = 'b')
    plt.plot(recall, precision, linewidth=2)
    plt.xlim([0.0,1])
    plt.ylim([0.0,1.05])
    plt.xlabel('召回率')
    plt.ylabel('精确率')
    plt.title('精确率-召回率 曲线')
    plt.show();
     
data = pd.read_csv('./creditcard.csv')
data['Amount_Norm'] = StandardScaler().fit_transform(data['Amount'].values.reshape(-1,1))
y = np.array(data.Class.tolist())
data = data.drop(['Time','Amount','Class'],axis=1)
X = np.array(data.as_matrix())#DataFrame的形式,这个时候要记得转换成数组
train_x, test_x, train_y, test_y = train_test_split (X, y, test_size = 0.1, random_state = 33)
#创建SVM模型
model = svm.LinearSVC()
model.fit(train_x,train_y)
prediction=model.predict(test_x)
cm = confusion_matrix(test_y, prediction)
show_metrics()
# 设置plt正确显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
# 绘制类别分布

class_names = [0,1]
# 显示混淆矩阵
plot_confusion_matrix(cm, classes = class_names, title = '逻辑回归 混淆矩阵')

score_y = model.decision_function(test_x)
precision, recall, thresholds = precision_recall_curve(test_y, score_y)
plot_precision_recall()

结果:
精确率: 0.843
召回率: 0.717
F1值: 0.775
SVM_信用卡欺诈_第1张图片
SVM_信用卡欺诈_第2张图片

代码解释

  1. 可以把混淆矩阵理解成对测试集做预测后给的一个反馈,有4种可能:
    tp:判断是,结果对;
    tn:判断是,结果错
    fn:判断不是,结果错;
    fp:判断不是,结果对
  2. 精确率: P = TP/ (TP+FP),你可以理解成预测欺诈的准确率,预测成功的所有情况中,欺诈的情况占多大的比例
  3. 召回率 R = TP/ (TP+FN),也称为查全率。就是所有的欺诈情况中,你查出来的占多少
  4. plot_precision_recall用于测试精确率和召回率的一个动态关系,可以看到两者成反比,一般召回率越高,精确率越低,比如你认为所有的交易都是欺诈交易,那么召回率可以达到100%,但是准确率就会很低。

总结

信用卡欺诈问题总体来说是一个二分类问题,其特点在于类别数据比差距过大,评价指标不能仅使用metrics.accuracy_score(prediction,test_y))。建模实现分类的方法有很多,以及各个模型下还有参数调整情况,可以尝试使用弱分类器组成Adaboost、还有将随机森林与GridSearchCV结合找出最优解,可以下次写一下实现方法,逻辑回归也是一个比较实用的方法但是经测试训练时间较快,但是效果略差于SVM。

你可能感兴趣的:(笔记,python,机器学习,人工智能,可视化)