這是一道kaggle上的題目。html
咱們都知道信用卡,可以透支一大筆錢來供本身消費,正由於這一點,不法分子就利用信用卡進一特性來實施欺詐行爲。銀行爲了可以檢測出這一欺詐行爲,經過機器學習模型進行智能識別,提早凍結該帳戶,避免形成銀行的損失。那麼咱們應該經過什麼方式來提升這種識別精度呢!這就是今天要說的主題,多模型融合預測。使用到的模型算法有:KNN、SVM、Logistic Regression(LR)、Random Forest。python
我會講到如何使用多模型進行融合計算(模型集成)、模型評估、超參數調節、K折交叉驗證等,力求可以講得清楚,但願你們經過這篇博文可以瞭解到一個完整的機器學習算法究竟是怎樣的,若有講得不到位亦或是錯誤的地方,望告知!git
如下咱們正式開始介紹。github
數據集下載:https://v2.fangcloud.com/share/a63342d8bd816c43f281dab455算法
GitHub完整代碼bootstrap
GitHub完整代碼:數組
咱們先從概念着手,這是咱們的地基,要建起高樓大廈,首先地基要穩。微信
那麼多模型融合存在着多種實現方法:Bagging思想、Stacking、Adaboost。框架
Bagging是bootstrap aggregating。Bagging思想就是從整體樣本當中隨機取一部分樣本進行訓練,經過屢次這樣的結果,進行投票亦或求取平均值做爲結果輸出,這就極大可能的避免了很差的樣本數據,從而提升準確度。由於有些是很差的樣本,至關於噪聲,模型學入噪聲後會使準確度不高。一句話歸納就是:羣衆的力量是偉大的,集體智慧是驚人的。dom
而反觀多模型,其實也是同樣的,利用多個模型的結果進行投票亦或求取均值做爲最終的輸出,用的就是Bagging的思想。
stacking是一種分層模型集成框架。以兩層爲例,第一層由多個基學習器組成,其輸入爲原始訓練集,第二層的模型則是以第一層基學習器的輸出做爲訓練集進行再訓練,從而獲得完整的stacking模型。若是是多層次的話,以此類推。一句話歸納:站在巨人的肩膀上,能看得更遠。
所謂的AdaBoost的核心思想實際上是,既然找一個強分類器不容易,那麼咱們乾脆就不找了吧!咱們能夠去找多個弱分類器,這是比較容易實現的一件事情,而後再集成這些弱分類器就有可能達到強分類器的效果了,其中這裏的弱分類器真的是很弱,你只須要構建一個比瞎猜的效果好一點點的分類器就能夠了。一句話歸納:堅守一萬小時定律,努力學習。
首先拉取數據到python中。
將數據劃分紅訓練集和測試集,訓練集因爲分類極度不平衡,因此採起下采樣工做,使分類比例達到一致。
將訓練集送入模型中訓練,同時以K折交叉驗證方法來進行超參數調節,哪一組超參數表現好,就選擇哪一組超參數。
尋找到超參數後,用一樣的方法尋找決策邊界,至此模型訓練完成。
使用模型集成預測測試集,並使用ROC曲線分析法,獲得模型的評估指標。
啥都不說,先上代碼,這裏須要說明的就是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)
先回答什麼是數據下采樣:
數據下采樣:數據集中正樣本和負樣本的比例嚴重失調,這會給模型的學習帶來很大的困擾,例如,正樣本有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函數以下,因爲代碼顯示效果不行,因此以圖代替,文章開頭已有源代碼連接,註解已寫得很清楚,不需重複贅述:
#用不一樣的模型進行訓練 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曲線:評估模型好壞的方式,已有人解釋很是清楚,此處再也不贅述,欲瞭解請點擊:
接下來就是真正的模型訓練函數:
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
徑向基函數(RBF)作SVM的核函數。
欲想了解核函數:http://www.javashuo.com/article/p-fctewcoy-bo.html
# 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
多項式(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
邏輯迴歸模型
# 邏輯迴歸當中的正則化強度 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
隨機森林模型,欲知超參數含義請點擊:
http://www.javashuo.com/article/p-nxbasnll-kw.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')
在具備兩個類的統計分類問題中,決策邊界或決策表面是超曲面,其將基礎向量空間劃分爲兩個集合,一個集合。 分類器將決策邊界一側的全部點分類爲屬於一個類,而將另外一側的全部點分類爲屬於另外一個類。
因此這一步咱們要作的就是根據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函數爲,與前面尋找超參數大體相同:
尋找到最優的超參數和決策邊界後,就能夠正式開始訓練各個模型了。
# 最優參數建模 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]
使用以前劃分的測試集運用以上訓練出來的模型進行預測,預測使用的是模型集成的投票機制。
咱們先來看看預測的代碼:
模型集成投票代碼:
使用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)
數據集下載:https://v2.fangcloud.com/share/a63342d8bd816c43f281dab455
.
.
.
歡迎添加微信交流!請備註「機器學習」。