XGBoost 與 信用卡詐騙數據集

在Github 上面找到了一個信用卡詐騙數據集:

https://github.com/georgymh/ml-fraud-detection

數據源於 kaggle 的信用卡詐騙數據。

其中給出了三種大方法,分別是神經網絡,kmeans,以及邏輯迴歸。

但是今天我想要用XGBoost 試一試。

import sklearn as sk 
import xgboost as xgb 
import numpy as np 
import pandas as pd 
from sklearn.model_selection import train_test_split # 功能:數據集按比例切分爲訓練集和測試集
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.preprocessing import scale # 數據集標準化
import matplotlib.pyplot as plt
from pandas_ml import ConfusionMatrix # 引入混淆矩陣
# https://github.com/pandas-ml/pandas-ml/

df = pd.read_csv('creditcard.csv', low_memory=False)

X = df.iloc[:,:-1] # 基於位置的純整數索引
y = df['Class'] # 類別
X_scaled = scale(X) # 標準化

train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.35 ,random_state = 12) 

dtrain = xgb.DMatrix(train_X, label = train_y)
dtest = xgb.DMatrix(test_X, label = test_y)

param = {                          
    # --------------- Tree Booster 參數  --------------- 
    'eta':0.3,                     # 每個循環的學習步長,就是sklearn的learning_rate
    'booster':'gbtree',            # gbtree使用基於樹的模型進行提升計算,gblinear使用線性模型進行提升計算
    'max_depth':5,                 # 每棵樹的最大深度,默認6
    'silent':1,                    # 默認0,而1表示靜默模式開啓,不會輸出任何信息
    # ---------------------------------------------------------------------
    'num_class':2,                 # 類別個數,記得改!
    # ---------------------------------------------------------------------
    'min_child_weight':1.0,        # 決定最小葉子節點樣本權重和
    # 'max_leaf_nodes':            # 樹上最大的節點或葉子的數量。 可以替代max_depth的作用。
    'scale_pos_weight':1.0,        # 調節正負樣本不均衡問題
    'gamma':0.1,                   # 這個參數的值越大,算法越保守,默認0
    'max_delta_step':0,            # 這參數限制每棵樹權重改變的最大步長。0意味着沒有約束。
    'subsample':1.0,               # 控制對於每棵樹,隨機採樣的比例。 
                                   # 減小這個參數的值,算法會更加保守,避免過擬合。
                                   # 如果這個值設置得過小,它可能會導致欠擬合。一般0.5-1
    'colsample_bytree':1.0,        # 用來控制每棵隨機採樣的列數的佔比(每一列是一個特徵)。一般0.5-1
    'colsample_bylevel':1.0,       # 控制樹的每一級的每一次分裂,對列數的採樣的佔比。
    # 'scale_pos_weight':1,          # 在各類別樣本十分不平衡時,把這個參數設定爲一個正值,可以使算法更快收斂
    # --------------- Linear Booster 參數 ---------------
    # 'lambda_bias':0,             # 在偏置上的L2正則
    # 'lambda':1,                  # 權重的L2正則化項。默認1
    # 'alpha':1,                   # 權重的L1正則化項。默認1
    # --------------- Task 參數 ---------------
    'objective':'multi:softprob',   # 定義學習任務及相應的學習目標
            
    #'objective':'reg:linear',      # 線性迴歸
    #'objective':'reg:logistic',    # 邏輯迴歸
    #'objective':'binary:logistic', # 二分類的邏輯迴歸問題,輸出爲概率
    #'objective':'binary:logitraw', # 二分類的邏輯迴歸問題,輸出結果爲 wTx,wTx指機器學習線性模型f(x)=wTx+b
    #'objective':'count:poisson'    # 計數問題的poisson迴歸,輸出結果爲poisson分佈
    #'objective':'multi:softmax'    # 讓XGBoost採用softmax目標函數處理多分類問題,同時需要設置參數num_class
    #'objective':'multi:softprob'   # 和softmax一樣,但是輸出的是ndata * nclass的向量,
                                    # 可以將該向量reshape成ndata行nclass列的矩陣。
                                    # 每行數據表示樣本所屬於每個類別的概率。
                
    'base_score':0.5,               # 所有實例的初始預測評分, global bias
    # 'eval_metric'
    'seed':0                        # 默認爲0
}
num_round = 20  # 循環次數

bst = xgb.train(param, dtrain, num_round) # 參數 + 訓練集 + 循環次數
preds = bst.predict(dtest) # 對測試集作出預測
print("訓練完成")

best_preds = np.asarray([np.argmax(line) for line in preds]) # np.argmax(line) 返回沿着line軸的最大值的索引
                                                             # np.asarray 將列表轉換爲數組

# 精確度(Precision):
# P = TP/(TP+FP) ;  反映了被分類器判定的正例中真正的正例樣本的比重
print("精確度(Precision):", precision_score(test_y, best_preds, average='macro')) # 97.32%
print("召回率(Recall):", recall_score(test_y, best_preds, average='macro')) # 90.34%

predicted_y = np.array(best_preds)
right_y = np.array(test_y)

# 混淆矩陣的每一列代表了預測類別,
# 每一列的總數表示預測爲該類別的數據的數目;
# 每一行代表了數據的真實歸屬類別,
# 每一行的數據總數表示該類別的數據實例的數目。
confusion_matrix = ConfusionMatrix(right_y, predicted_y)
# print("Confusion matrix:\n%s" % confusion_matrix)
# confusion_matrix.plot(normalized=True)
# plt.show()
confusion_matrix.print_stats()

'''
population: 99683
P: 176
N: 99507
PositiveTest: 150
NegativeTest: 99533
TP: 142
TN: 99499
FP: 8
FN: 34
TPR: 0.806818181818
TNR: 0.999919603646
PPV: 0.946666666667
NPV: 0.99965840475
FPR: 8.03963540253e-05
FDR: 0.0533333333333
FNR: 0.193181818182
ACC: 0.999578664366
F1_score: 0.871165644172
MCC: 0.87374835762
informedness: 0.806737785464
markedness: 0.946325071417
prevalence: 0.00176559694231
LRP: 10035.5071023
LRN: 0.193197350544
DOR: 51944.3308824
FOR: 0.000341595249817
'''

講道理註釋已經很清楚了,最後的結果也不差。

進一步的問題在於,如何使用類似 SKlearn 中的 balance 參數,讓少數的詐騙1和大多數的非詐騙0均衡一下,讓1的學習權重更重。

這樣的後果就是 False Negative 值降低,但是False Positive 值急劇增高。關鍵看採用哪種策略吧。


目前的研究在於這個

'scale_pos_weight':1.0,        # 調節正負樣本不均衡問題

這個參數是 XGBoost 的 SKlearn API中的,如果直接使用XGBoost好像就沒有這個參數?當然也可能是我不明白。反正目前的參數是不錯的。


相對的,在 Github 中的程序有一個線性迴歸的例子就帶有這個 balance 參數,效果很奇妙...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章