1. 程式人生 > >通俗易懂--信用卡欺詐預測案例講解(算法+案例)

通俗易懂--信用卡欺詐預測案例講解(算法+案例)

spl 合計 report 顯示效果 基函數 election ase ensemble ges

1.信用卡欺詐預測案例

這是一道kaggle上的題目。

我們都知道信用卡,能夠透支一大筆錢來供自己消費,正因為這一點,不法分子就利用信用卡進一特性來實施欺詐行為。銀行為了能夠檢測出這一欺詐行為,通過機器學習模型進行智能識別,提前凍結該賬戶,避免造成銀行的損失。那麽我們應該通過什麽方式來提高這種識別精度呢!這就是今天要說的主題,多模型融合預測。使用到的模型算法有:KNN、SVM、Logistic Regression(LR)、Random Forest

我會講到如何使用多模型進行融合計算(模型集成)、模型評估、超參數調節、K折交叉驗證等,力求能夠講得清楚,希望大家通過這篇博文能夠了解到一個完整的機器學習算法到底是怎樣的,如有講得不到位亦或是錯誤的地方,望告知!

以下我們正式開始介紹。

數據集下載:https://v2.fangcloud.com/share/a63342d8bd816c43f281dab455

GitHub完整代碼

GitHub完整代碼:

2.模型集成(model ensemble)

我們先從概念著手,這是我們的地基,要建起高樓大廈,首先地基要穩。

  • 多模型:分類問題是以多個模型計算出的結果進行投票決定最終答案,線性問題以多個模型計算出來的結果求取均值作為預測數值。

那麽多模型融合存在著多種實現方法:Bagging思想、Stacking、Adaboost。

2.1Bagging

Bagging是bootstrap aggregating。Bagging思想就是從總體樣本當中隨機取一部分樣本進行訓練,通過多次這樣的結果,進行投票亦或求取平均值作為結果輸出,這就極大可能的避免了不好的樣本數據,從而提高準確度。因為有些是不好的樣本,相當於噪聲,模型學入噪聲後會使準確度不高。一句話概括就是:群眾的力量是偉大的,集體智慧是驚人的。

而反觀多模型,其實也是一樣的,利用多個模型的結果進行投票亦或求取均值作為最終的輸出,用的就是Bagging的思想。

2.2Stacking

stacking是一種分層模型集成框架。以兩層為例,第一層由多個基學習器組成,其輸入為原始訓練集,第二層的模型則是以第一層基學習器的輸出作為訓練集進行再訓練,從而得到完整的stacking模型。如果是多層次的話,以此類推。一句話概括:站在巨人的肩膀上,能看得更遠。

技術分享圖片

2.3Adaboost

所謂的AdaBoost的核心思想其實是,既然找一個強分類器不容易,那麽我們幹脆就不找了吧!我們可以去找多個弱分類器,這是比較容易實現的一件事情,然後再集成這些弱分類器就有可能達到強分類器的效果了,其中這裏的弱分類器真的是很弱,你只需要構建一個比瞎猜的效果好一點點的分類器就可以了。一句話概括:堅守一萬小時定律,努力學習。

2.4圖解模型集成

技術分享圖片

3.案例總流程

技術分享圖片

  1. 首先拉取數據到python中。

  2. 將數據劃分成訓練集和測試集,訓練集由於分類極度不平衡,所以采取下采樣工作,使分類比例達到一致。

  3. 將訓練集送入模型中訓練,同時以K折交叉驗證方法來進行超參數調節,哪一組超參數表現好,就選擇哪一組超參數。

  4. 尋找到超參數後,用同樣的方法尋找決策邊界,至此模型訓練完成。

  5. 使用模型集成預測測試集,並使用ROC曲線分析法,得到模型的評估指標。

4.初始化工作

啥都不說,先上代碼,這裏需要說明的就是sklearn.model_selection這個類庫,因為老版本和新版本的區別還是很大的,如果巡行報錯,嘗試著升級sklearn庫。

# 數據讀取與計算
import pandas as  pd
import matplotlib.pyplot as plt
import numpy as np

# 數據預處理與模型選擇
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.metrics import confusion_matrix, precision_recall_curve, auc, roc_auc_score, roc_curve, recall_score, classification_report
import itertools

# 隨機森林與SVM
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from scipy import stats

import warnings
warnings.filterwarnings("ignore")

# 一些基本參數設定
mode = 2        #投票個數閾值
ratio = 1       #負樣本倍率
iteration1 = 1  #總流程循環次數
show_best_c = True  #是否顯示最優超參數
show_bdry = True    #是否顯示決策邊界

##讀取數據,刪除無用的時間特征。
data=pd.read_csv(‘creditcard.csv‘)
data.drop(‘Time‘,axis=1,inplace=True)

5.數據下采樣

先回答什麽是數據下采樣:

數據下采樣:數據集中正樣本和負樣本的比例嚴重失調,這會給模型的學習帶來很大的困擾,例如,正樣本有100個,而負樣本只有1個,模型只是看到了正樣本,而學習不到負樣本,這回造成模型對負樣本的預測能力幾乎為0。所以為了避免這種數據傾斜,處理數據使得正樣本和負樣本的數量基本均等,這樣的模型泛化能力才會高。

反觀數據上采樣也是一樣的,只不過是基準樣本不一樣而已。

這裏的數據處理采用下標的方式,較容易運算。

#欺詐類的樣本下標
fraud_indices=np.array(data[data.Class==1].index)
#進行隨機排列
np.random.shuffle(fraud_indices)

#獲取正常樣本下標
normal_indices=np.array(data[data.Class==0].index)
np.random.shuffle(normal_indices)


#劃分訓練集和測試集
train_normal_indices, train_fraud_indices, test_normal_indices
    ,test_fraud_indices = split_train_test(normal_indices,fraud_indices)

##合並測試集
test_indices=np.concatenate([test_normal_indices,test_fraud_indices])

#通過下標選取測試集數據,[表示選取行,表示選取列]
test_data=data.iloc[test_indices,:]
x_test=test_data.ix[:,test_data.columns != ‘Class‘]
y_test=test_data.ix[:,test_data.columns == ‘Class‘]

#數據下采樣,調用下采樣函數 getTrainingSample
x_train_undersample,y_train_undersample,train_normal_pos=getTrainingSample(
train_fraud_indices,train_normal_indices,data,0,ratio)

getTrainingSample函數如下,由於代碼顯示效果不行,所以以圖代替,文章開頭已有源代碼鏈接,註解已寫得很清楚,不需重復贅述:

技術分享圖片

6.模型訓練

6.1KNN

#用不同的模型進行訓練
models_dict = {‘knn‘ : knn_module, ‘svm_rbf‘: svm_rbf_module, ‘svm_poly‘: svm_poly_module,
‘lr‘: lr_module, ‘rf‘: rf_module}

#knn中取不同的k值(超參數)
c_param_range_knn=[3,5,7,9]
#自定義cross_validation_recall,使用循環找出最適合的超參數。
best_c_knn=cross_validation_recall(x,y, c_param_range_knn,models_dict, ‘knn‘)

cross_validation_recall函數如下:

技術分享圖片

這裏有幾個概念需要解釋一下,以防大家看不懂。

  • K折交叉驗證:K折交叉驗證(k-fold cross-validation)首先將所有數據分割成K個子樣本,不重復的選取其中一個子樣本作為測試集,其他K-1個樣本用來訓練。共重復K次,平均K次的結果或者使用其它指標,最終得到一個單一估測。

    這個方法的優勢在於,保證每個子樣本都參與訓練且都被測試,降低泛化誤差。其中,10折交叉驗證是最常用的。

  • ROC曲線:評估模型好壞的方式,已有人解釋非常清楚,此處不再贅述,欲了解請點擊:

    https://www.cnblogs.com/gatherstars/p/6084696.html

接下來就是真正的模型訓練函數:

def knn_module(x,y,indices, c_param, bdry=None):
    #超參數賦值
    knn=KNeighborsClassifier(n_neighbors=c_param)
    #ravel把數組變平
    knn.fit(x.iloc[indices[0],:], y.iloc[indices[0],:].values.ravel())
    y_pred_undersample = knn.predict(x.iloc[indices[1],:].values)
    
    return y_pred_undersample

模型評估,計算召回率和auc值:

#計算召回率和auc
#y_t是真實值,y_p是預測值
def compute_recall_and_auc(y_t, y_p):
    #混淆矩陣 https://www.cnblogs.com/zhixingheyi/p/8097782.html
    #  https://blog.csdn.net/xierhacker/article/details/70903617
    cnf_matrix=confusion_matrix(y_t,y_p)
    #設置numpy的打印精度
    np.set_printoptions(precision=2)
    recall_score = cnf_matrix[0,0]/(cnf_matrix[1,0]+cnf_matrix[0,0])
    
    #Roc曲線
    # https://www.cnblogs.com/gatherstars/p/6084696.html
    fpr, tpr,thresholds = roc_curve(y_t,y_p)
    roc_auc= auc(fpr,tpr)
    return recall_score , roc_auc

6.2 SVM-RBF

徑向基函數(RBF)做SVM的核函數。

欲想了解核函數:https://blog.csdn.net/v_JULY_v/article/details/7624837#commentBox

# SVM-RBF中不同的參數
c_param_range_svm_rbf=[0.01,0.1,1,10,100]
best_c_svm_rbf = cross_validation_recall(x,y,c_param_range_svm_rbf, models_dict, ‘svm_rbf‘)

def svm_rbf_module(x, y, indices, c_param, bdry= 0.5):
    svm_rbf = SVC(C=c_param, probability=True)
    svm_rbf.fit(x.iloc[indices[0],:], y.iloc[indices[0],:].values.ravel())
    y_pred_undersample = svm_rbf.predict_proba(x.iloc[indices[1],:].values)[:,1] >= bdry#True/Flase
    return y_pred_undersample

6.3 SVM-POLY

多項式(POLY)做SVM的核函數。

技術分享圖片

訓練函數為:

def svm_poly_module(x,y, indices, c_param, bdry=0.5):
    svm_poly=SVC(C=c_param[0], kernel=‘poly‘, degree= c_param[1], probability=True)
    svm_poly.fit(x.iloc[indices[0],:], y.iloc[indices[0],:].values.ravel())
    y_pred_undersample = svm_poly.predict_proba(x.iloc[indices[1],:].values)[:,1] >= bdry
    return y_pred_undersample

6.4 Logistic Regression

邏輯回歸模型

# 邏輯回歸當中的正則化強度
c_param_range_lr=[0.01,0.1,1,10,100]
best_c_lr = cross_validation_recall(x,y, c_param_range_lr, models_dict, ‘lr‘)

def lr_module(x,y, indices, c_param, bdry=0.5):
    # penalty懲罰系數
    lr = LogisticRegression(C=c_param,penalty=‘11‘)
    lr.fit(X.iloc[indices[0],:], y.iloc[indices[0],:].values.ravel())
    y_pred_undersample= lr.predict_proba(X.iloc[indices[1],:].values)[:,1]>=bdry
    return y_pred_undersample

6.5 Random Forest

隨機森林模型,欲知超參數含義請點擊:

https://www.cnblogs.com/harvey888/p/6512312.html

# 隨機森林裏調參
c_param_range_rf = [2,5,10,15,20]
best_c_rf= cross_validation_recall(X, y, c_param_range_rf, models_dict, ‘rf‘)

技術分享圖片

6.6決策邊界

在具有兩個類的統計分類問題中,決策邊界或決策表面是超曲面,其將基礎向量空間劃分為兩個集合,一個集合。 分類器將決策邊界一側的所有點分類為屬於一個類,而將另一側的所有點分類為屬於另一個類。

所以這一步我們要做的就是根據AUC值找出模型最好的決策邊界值,也就是概率值。大於這一概率值為正樣本,反之為負樣本。

# 交叉驗證確定合適的決策邊界閾值
fold = KFold(4,shuffle=True)

# 定義各個模型的計算公式
def lr_bdry_module(recall_acc, roc_auc):
    return 0.9*recall_acc+0.1*roc_auc
def svm_rbf_bdry_module(recall_acc, roc_auc):
    return recall_acc*roc_auc
def svm_poly_bdry_module(recall_acc, roc_auc):
    return recall_acc*roc_auc
def rf_bdry_module(recall_acc, roc_auc):
    return 0.5*recall_acc+0.5*roc_auc
bdry_dict = {‘lr‘: lr_bdry_module,‘svm_rbf‘: svm_rbf_bdry_module,
             ‘svm_poly‘: svm_poly_bdry_module, ‘rf‘: rf_bdry_module}

# decision_boundary是一個計算決策邊界的函數
best_bdry_svm_rbf= decision_boundary(x, y, fold, best_c_svm_rbf, bdry_dict, models_dict, ‘svm_rbf‘)
best_bdry_svm_poly = decision_boundary(x, y, fold, best_c_svm_poly, bdry_dict, models_dict,                         ‘svm_poly‘)
best_bdry_lr = decision_boundary(x, y, fold, best_c_lr, bdry_dict, models_dict, ‘lr‘)
best_bdry_rf = decision_boundary(x, y, fold, best_c_rf, bdry_dict, models_dict, ‘rf‘)
best_bdry = [0.5, best_bdry_svm_rbf, best_bdry_svm_poly, best_bdry_lr, best_bdry_rf]

decision_boundary函數為,與前面尋找超參數大致相同:

技術分享圖片

6.7 模型建模

尋找到最優的超參數和決策邊界後,就可以正式開始訓練各個模型了。

# 最優參數建模
knn = KNeighborsClassifier(n_neighbors = int(best_c_knn))
knn.fit(x.values, y.values.ravel())

svm_rbf = SVC(C=best_c_svm_rbf, probability = True)
svm_rbf.fit(x.values, y.values.ravel())

svm_poly = SVC(C=best_c_svm_poly[0], kernel = ‘poly‘, degree = best_c_svm_poly[1], probability = True)
svm_poly.fit(x.values, y.values.ravel())

lr = LogisticRegression(C = best_c_lr, penalty =‘l1‘, warm_start = False)
lr.fit(x.values, y.values.ravel())

rf = RandomForestClassifier(n_jobs=-1, n_estimators = 100, criterion = ‘entropy‘, 
max_features = ‘auto‘, max_depth = None, 
min_samples_split  = int(best_c_rf), random_state=0)
rf.fit(x.values, y.values.ravel())

models = [knn,svm_rbf,svm_poly, lr, rf]

7.結果

7.1預測

使用之前劃分的測試集運用以上訓練出來的模型進行預測,預測使用的是模型集成的投票機制。

我們先來看看預測的代碼:

技術分享圖片

模型集成投票代碼:

技術分享圖片

7.2模型評估

使用AUC進行模型評估,預測部分代碼已經記錄有相關指標數據,只要計算平均得分就可以。

#計算平均得分
mean_recall_score = np.mean(recall_score_list)
std_recall_score = np.std(recall_score_list)?

mean_auc= np.mean(auc_list)
std_auc = np.std(auc_list)

8.完整代碼

數據集下載:https://v2.fangcloud.com/share/a63342d8bd816c43f281dab455

GitHub完整代碼

.

.

.

技術分享圖片

歡迎添加微信交流!請備註“機器學習”。

通俗易懂--信用卡欺詐預測案例講解(算法+案例)