銀行評判用戶的信用考量規避信用卡詐騙數組
數據共有 31 個特徵, 爲了安全起見數據已經向了模糊化處理沒法讀出真實信息目標安全
其中數據中的 class 特徵標識爲是否正經常使用戶 (0 表明正常, 1 表明異常)app
本質依舊是一個分類問題, 0/1 的問題判斷是否爲信用卡詐騙用戶dom
而在數據中 class 已經進行標識, 並且此次的樣本數據的兩項結果是極度的不均衡機器學習
既正經常使用戶的樣本數量是遠遠大於異常數據的.函數
不均衡的數據處理方式能夠進行 下采樣, 或者上採樣學習
▨ 下采樣 - 對多的數據進行消減到和少的數據同樣少測試
▨ 上採樣 - 對少的數據進行填充到和多的數據同樣多spa
1 import pandas as pd 2 import matplotlib.pyplot as plt 3 import numpy as np
count_classes = pd.value_counts(data['Class'], sort = True).sort_index() # 某一列的查詢按照數據排序 count_classes.plot(kind = 'bar') # 條形圖 plt.title("Fraud class histogram") # 標題 plt.xlabel("Class") # x 軸 plt.ylabel("Frequency") # y 軸
能夠看出正經常使用戶多達28w, 而異常樣本大概有幾百個左右, 3d
機器學習的常規認知是對較大的特徵數值基於更大的影響, 所以當特徵的的取值大小之間的不一樣,
會致使認爲較大數值的特徵比較小數值特徵的影響更大, 所以須要對數據特徵進行歸一化處理
好比都限制在取值在 0-1 之間這樣機器學習會將全部的特徵按照統一的標準進行考量
from sklearn.preprocessing import StandardScaler data['normAmount'] = StandardScaler().fit_transform(data['Amount'].reshape(-1, 1)) data = data.drop(['Time','Amount'],axis=1) data.head()
引用 sklearn 模塊進行預處理操做
reshape 方法進行維度的重處理
取值 (-1, 1) 中的 -1 表示系統自動判斷, 後面是提供參考值 ( 好比原來是 2,3 的維度, 你輸入 (-1,1) 則表示轉換爲 ( 6,1 ), 系統對 -1 進行自動計算 )
而後生成的新特徵填充到樣本數據中, 刪除掉轉換前的特徵, 以及沒有用的特徵
fit_transform 對數據進行歸一化處理, 具體流程爲先擬合後進行歸一處理
下采樣的方法爲將多的那類數據樣本降和少的那類同樣的少
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 from sklearn.metrics import recall_score # 召回率計算 from sklearn.metrics import classification_report
X = data.ix[:, data.columns != 'Class'] # 除了 "Class" 列的其餘列的全部數據 y = data.ix[:, data.columns == 'Class'] # "Class" 列的數據 number_records_fraud = len(data[data.Class == 1]) # 全部的異常(class == 1)的數據的個數 fraud_indices = np.array(data[data.Class == 1].index) # 全部的異常(class == 1)的數據的索引 normal_indices = data[data.Class == 0].index # 全部的正常(class == 0)數據的索引 # np 的隨機模塊進行選擇 參數:( 被選容器(正常數據), 個數(異常數據個數), 是否代替(不代替) ) random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace = False) random_normal_indices = np.array(random_normal_indices) # 拼接數組 under_sample_indices = np.concatenate([fraud_indices,random_normal_indices]) # 下采樣以後的數據 under_sample_data = data.iloc[under_sample_indices,:] # X , y X_undersample = under_sample_data.ix[:, under_sample_data.columns != 'Class'] y_undersample = under_sample_data.ix[:, under_sample_data.columns == 'Class']
將異常數據的個數計算出來後, 而後在政策數據集中隨機篩選出異常數據集個數的數據, 而後組合爲新的數據集
從而保證異常數據集和正常數據集爲 1:1 比例
# Showing ratio print("Percentage of normal transactions: ", len(under_sample_data[under_sample_data.Class == 0])/len(under_sample_data)) print("Percentage of fraud transactions: ", len(under_sample_data[under_sample_data.Class == 1])/len(under_sample_data)) print("Total number of transactions in resampled data: ", len(under_sample_data))
數據集在最開始的時候會劃分爲 訓練集 和 測試集
訓練集用於建模, 測試集用於對模型進行驗證
而建模階段訓練集一般會進行 n 等分, 而後彼此再次劃分 訓練集和測試集
目的是爲了獲取正確的參數, 從而須要進行屢次的訓練集和測試集的互換從而交叉驗證
from sklearn.model_selection import train_test_split # 原始數據集切分數據 - 0.3 的測試集, 0.7 的訓練集 , 設定隨機參數 X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0) # print("Number transactions train dataset: ", len(X_train)) print("Number transactions test dataset: ", len(X_test)) print("Total number of transactions: ", len(X_train)+len(X_test)) # 下采樣數據集切分數據 - 0.3 的測試集, 0.7 的訓練集 , 設定隨機參數 X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample ,y_undersample ,test_size = 0.3 ,random_state = 0) print("") print("Number transactions train dataset: ", len(X_train_undersample)) print("Number transactions test dataset: ", len(X_test_undersample)) print("Total number of transactions: ", len(X_train_undersample)+len(X_test_undersample))
一般的評估方法中可使用精度計算
精度計算的評估方法很大程度取決於樣本數據自己的狀況
尤爲是不對稱的數據中會形成精度計算的極大不許確性
如圖所示, 如1000 數據中 990 數據爲正樣本數據, 則計算出的結果則爲 99.9% 則負樣本預測不出來. 實則無用
根據目標來指定標準, 好比 1000數據中的異常數據爲 10 , 目標則是找出異常數據
則根據檢測出的異常數據於原有的異常數據進行比對來判斷計算 recall 值
兩個維度, 1 是否符合預期 (P/N) , 2 判斷是否正確 (T/F)
Recall = TP/(TP+FN)
在不一樣的模型中可能存在最終的 Recall 都同樣的狀況, 若是 Recall 相同的是否能夠理解爲兩個模型效果相同?
可是模型本質可能仍是存在不一樣, 所以須要在另外一個維度進行分析, 圖示的 A 和 B 的參數可見實際上是不一樣的
A 的浮動明顯很大, B 的浮動小不少, 浮動過大多是過擬合的問題致使, 而此時引入一個懲罰概念進行篩選
對浮動過大的進行懲罰更大, 由此進行區分, 懲罰方式能夠選擇 L1/L2 等, 具體的原酸都是加入一個值進行區分
而懲罰粒度也能夠限制從 0.1 ,1,10,100 不等, 而這個粒度則須要交叉驗證進行選擇, 既比對參數
def printing_Kfold_scores(x_train_data,y_train_data): fold = KFold(5,shuffle=False) # 劃分爲 5 等分, 即 5次交叉驗證, shuffle 不洗牌 # 默認的懲罰粒度參數容器 c_param_range = [0.01,0.1,1,10,100] # 展現用 results_table = pd.DataFrame(index = range(len(c_param_range),2), columns = ['C_parameter','Mean recall score']) results_table['C_parameter'] = c_param_range # the k-fold will give 2 lists: train_indices = indices[0], test_indices = indices[1] j = 0 for c_param in c_param_range: # 循環每一個待選參數 print('-------------------------------------------') print('C parameter: ', c_param) print('-------------------------------------------') print('') recall_accs = [] for iteration, indices in enumerate(fold.split(x_train_data)): # 交叉驗證 # 創建邏輯迴歸模型實例化, 傳入懲罰項粒度, 以及懲罰模式 能夠選擇 l1 或者 l2 # solver='liblinear' 是爲了不 FutureWarning 提示 lr = LogisticRegression(C = c_param, penalty = 'l1',solver='liblinear') # 訓練模型 lr.fit(x_train_data.iloc[indices[0],:],y_train_data.iloc[indices[0],:].values.ravel()) # 預測 y_pred_undersample = lr.predict(x_train_data.iloc[indices[1],:].values) # 計算召回率 recall_acc = recall_score(y_train_data.iloc[indices[1],:].values,y_pred_undersample) recall_accs.append(recall_acc) print('Iteration ', iteration,': recall score = ', recall_acc) # 計算均值展現 results_table.loc[j,'Mean recall score'] = np.mean(recall_accs) j += 1 print('') print('Mean recall score ', np.mean(recall_accs)) print('') best_c = results_table.loc[results_table['Mean recall score'].values.argmax()]['C_parameter'] # 打印最好的選擇 print('*********************************************************************************') print('Best model to choose from cross validation is with C parameter = ', best_c) print('*********************************************************************************') return best_c
best_c = printing_Kfold_scores(X_train_undersample,y_train_undersample)
打印結果對比能夠看出 通過了5次不洗牌的交叉驗證後, 爲 0.01 的 recall 值最高, 爲最優參數
------------------------------------------- C parameter: 0.01 ------------------------------------------- Iteration 0 : recall score = 0.958904109589041 Iteration 1 : recall score = 0.9178082191780822 Iteration 2 : recall score = 1.0 Iteration 3 : recall score = 0.9594594594594594 Iteration 4 : recall score = 0.9848484848484849 Mean recall score 0.9642040546150135 ------------------------------------------- C parameter: 0.1 ------------------------------------------- Iteration 0 : recall score = 0.8493150684931506 Iteration 1 : recall score = 0.863013698630137 Iteration 2 : recall score = 0.9152542372881356 Iteration 3 : recall score = 0.918918918918919 Iteration 4 : recall score = 0.8939393939393939 Mean recall score 0.8880882634539471 ------------------------------------------- C parameter: 1 ------------------------------------------- Iteration 0 : recall score = 0.863013698630137 Iteration 1 : recall score = 0.863013698630137 Iteration 2 : recall score = 0.9661016949152542 Iteration 3 : recall score = 0.9459459459459459 Iteration 4 : recall score = 0.9090909090909091 Mean recall score 0.9094331894424765 ------------------------------------------- C parameter: 10 ------------------------------------------- Iteration 0 : recall score = 0.863013698630137 Iteration 1 : recall score = 0.863013698630137 Iteration 2 : recall score = 0.9830508474576272 Iteration 3 : recall score = 0.9324324324324325 Iteration 4 : recall score = 0.9242424242424242 Mean recall score 0.9131506202785514 ------------------------------------------- C parameter: 100 ------------------------------------------- Iteration 0 : recall score = 0.863013698630137 Iteration 1 : recall score = 0.863013698630137 Iteration 2 : recall score = 0.9830508474576272 Iteration 3 : recall score = 0.9324324324324325 Iteration 4 : recall score = 0.9242424242424242 Mean recall score 0.9131506202785514 ********************************************************************************* Best model to choose from cross validation is with C parameter = 0.01 *********************************************************************************
best_c = printing_Kfold_scores(X_train,y_train)
------------------------------------------- C parameter: 0.01 ------------------------------------------- Iteration 0 : recall score = 0.4925373134328358 Iteration 1 : recall score = 0.6027397260273972 Iteration 2 : recall score = 0.6833333333333333 Iteration 3 : recall score = 0.5692307692307692 Iteration 4 : recall score = 0.45 Mean recall score 0.5595682284048672 ------------------------------------------- C parameter: 0.1 ------------------------------------------- Iteration 0 : recall score = 0.5671641791044776 Iteration 1 : recall score = 0.6164383561643836 Iteration 2 : recall score = 0.6833333333333333 Iteration 3 : recall score = 0.5846153846153846 Iteration 4 : recall score = 0.525 Mean recall score 0.5953102506435158 ------------------------------------------- C parameter: 1 ------------------------------------------- Iteration 0 : recall score = 0.5522388059701493 Iteration 1 : recall score = 0.6164383561643836 Iteration 2 : recall score = 0.7166666666666667 Iteration 3 : recall score = 0.6153846153846154 Iteration 4 : recall score = 0.5625 Mean recall score 0.612645688837163 ------------------------------------------- C parameter: 10 ------------------------------------------- Iteration 0 : recall score = 0.5522388059701493 Iteration 1 : recall score = 0.6164383561643836 Iteration 2 : recall score = 0.7333333333333333 Iteration 3 : recall score = 0.6153846153846154 Iteration 4 : recall score = 0.575 Mean recall score 0.6184790221704963 ------------------------------------------- C parameter: 100 ------------------------------------------- Iteration 0 : recall score = 0.5522388059701493 Iteration 1 : recall score = 0.6164383561643836 Iteration 2 : recall score = 0.7333333333333333 Iteration 3 : recall score = 0.6153846153846154 Iteration 4 : recall score = 0.575 Mean recall score 0.6184790221704963 ********************************************************************************* Best model to choose from cross validation is with C parameter = 10.0 *********************************************************************************
能夠看出在不均衡的數據中的計算recall 值是至關糟糕
只有 0.61 和 通過下采樣的計算 0.91 相差甚遠
混淆矩陣用來更直觀的平面展現模型的狀況以方便評估
這裏再拉回來以前的評估方法公式回憶一下
Recall = TP/(TP+FN)
def plot_confusion_matrix(cm, classes, title='Confusion matrix', cmap=plt.cm.Blues): """ This function prints and plots the confusion matrix. """ 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')
import itertools lr = LogisticRegression(C = best_c, penalty = 'l1',solver='liblinear') lr.fit(X_train_undersample,y_train_undersample.values.ravel()) y_pred_undersample = lr.predict(X_test_undersample.values) # Compute confusion matrix cnf_matrix = confusion_matrix(y_test_undersample,y_pred_undersample) np.set_printoptions(precision=2) print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1])) # Plot non-normalized confusion matrix class_names = [0,1] plt.figure() plot_confusion_matrix(cnf_matrix , classes=class_names , title='Confusion matrix') plt.show()
以上是在下采樣的數據集上進行的測試, 還須要在原始的數據集上進行測試才行
而在全量數據集的在進行判斷纔看是否精準才能夠判斷模型的可行性
lr = LogisticRegression(C = best_c, penalty = 'l1',solver='liblinear') lr.fit(X_train_undersample,y_train_undersample.values.ravel()) y_pred = lr.predict(X_test.values) # Compute confusion matrix cnf_matrix = confusion_matrix(y_test,y_pred) np.set_printoptions(precision=2) print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1])) # Plot non-normalized confusion matrix class_names = [0,1] plt.figure() plot_confusion_matrix(cnf_matrix , classes=class_names , title='Confusion matrix') plt.show()
經過測試結果就能夠看出異常了, TP ( 正例判對 ) 問題不大
可是 問題是 FP ( 正例判錯 ) 高達到 8000 就明顯說不過去了 - 判斷正經常使用戶爲詐騙犯, 誤殺
這個的數據異常確實不會影響到 recall 的計算
由於 recall 值和 TP 和 FN ( 反例正判 ) 有關
所以這個的結果會對精度有必定的影響, 這也是下采樣的弊端
在默認的迴歸模型中的閾值爲 0.5 , 即比例徹底均分的判斷,
而閾值調整提高則可讓檢測更加嚴格, 反之更加容易經過
應用於此實例中則爲
0.99 ---- 不像是個詐騙犯的要死的程度是不會認爲這人是詐騙犯
0.01 ----- 特麼稍微有點異常動做你就是個詐騙犯了
lr = LogisticRegression(C = 0.01, penalty = 'l1',solver='liblinear') lr.fit(X_train_undersample,y_train_undersample.values.ravel()) y_pred_undersample_proba = lr.predict_proba(X_test_undersample.values) # 此函數產出的是機率值 thresholds = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9] plt.figure(figsize=(10,10)) j = 1 for i in thresholds: y_test_predictions_high_recall = y_pred_undersample_proba[:,1] > i plt.subplot(3,3,j) j += 1 # Compute confusion matrix cnf_matrix = confusion_matrix(y_test_undersample,y_test_predictions_high_recall) np.set_printoptions(precision=2) print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1])) # Plot non-normalized confusion matrix class_names = [0,1] plot_confusion_matrix(cnf_matrix , classes=class_names , title='Threshold >= %s'%i)
可見在 0.1 時 ,recall 值很高, 可是 精度很低, 由於將全部的都預測成了詐騙犯, 所以錯殺不少
可是在 0.9 時 ,recall 值很低, 錯殺問題解決了. 沒法檢測到的卻不少了.
因而可知, 結合實際考慮以後, 大概在 0.5 - 0.7 之間的較爲合適,
固然通常也會提供數據要求誤殺率不能高於多少, 精度要大於多少, recall 要大於多少之類的, 再結合模型進行適當的選擇
過 ( 上 ) 採樣的方法爲將少的那類數據樣本增長的和多的那類同樣的多
不一樣於sklearn模塊, imblearn 是須要額外本身手動安裝的包 pip install imblearn
import pandas as pd from imblearn.over_sampling import SMOTE from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import confusion_matrix from sklearn.model_selection import train_test_split
credit_cards=pd.read_csv('creditcard.csv') columns=credit_cards.columns # 去掉最後一行沒用的數據 features_columns=columns.delete(len(columns)-1) features=credit_cards[features_columns] labels=credit_cards['Class']
拆分訓練集和測試集
features_train, features_test, labels_train, labels_test = train_test_split(features, labels, test_size=0.2, random_state=0)
過採樣數據處理
oversampler=SMOTE(random_state=0) # 指定每次生成數據相同, random_state=0 os_features,os_labels=oversampler.fit_sample(features_train,labels_train) # 那訓練集進行數據的生成, 不要動測試集
能夠看出數據進行了填充
計算最優參數
os_features = pd.DataFrame(os_features) os_labels = pd.DataFrame(os_labels) best_c = printing_Kfold_scores(os_features,os_labels)
------------------------------------------- C parameter: 0.01 ------------------------------------------- Iteration 1 : recall score = 0.890322580645 Iteration 2 : recall score = 0.894736842105 Iteration 3 : recall score = 0.968861347792 Iteration 4 : recall score = 0.957595541926 Iteration 5 : recall score = 0.958430881173 Mean recall score 0.933989438728 ------------------------------------------- C parameter: 0.1 ------------------------------------------- Iteration 1 : recall score = 0.890322580645 Iteration 2 : recall score = 0.894736842105 Iteration 3 : recall score = 0.970410534469 Iteration 4 : recall score = 0.959980655302 Iteration 5 : recall score = 0.960178498807 Mean recall score 0.935125822266 ------------------------------------------- C parameter: 1 ------------------------------------------- Iteration 1 : recall score = 0.890322580645 Iteration 2 : recall score = 0.894736842105 Iteration 3 : recall score = 0.970454796946 Iteration 4 : recall score = 0.96014552489 Iteration 5 : recall score = 0.960596168431 Mean recall score 0.935251182603 ------------------------------------------- C parameter: 10 ------------------------------------------- Iteration 1 : recall score = 0.890322580645 Iteration 2 : recall score = 0.894736842105 Iteration 3 : recall score = 0.97065397809 Iteration 4 : recall score = 0.960343368396 Iteration 5 : recall score = 0.960530220596 Mean recall score 0.935317397966 ------------------------------------------- C parameter: 100 ------------------------------------------- Iteration 1 : recall score = 0.890322580645 Iteration 2 : recall score = 0.894736842105 Iteration 3 : recall score = 0.970543321899 Iteration 4 : recall score = 0.960211472725 Iteration 5 : recall score = 0.960903924995 Mean recall score 0.935343628474 ********************************************************************************* Best model to choose from cross validation is with C parameter = 100.0 *********************************************************************************
能夠看出 100 爲最優選擇
繼續計算混淆矩陣
lr = LogisticRegression(C = best_c, penalty = 'l1') lr.fit(os_features,os_labels.values.ravel()) y_pred = lr.predict(features_test.values) # Compute confusion matrix cnf_matrix = confusion_matrix(labels_test,y_pred) np.set_printoptions(precision=2) print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1])) # Plot non-normalized confusion matrix class_names = [0,1] plt.figure() plot_confusion_matrix(cnf_matrix , classes=class_names , title='Confusion matrix') plt.show()
由結果能夠看出.
儘管 Recall 值相對較低, 不以下采樣的高
可是 誤殺的程度要低不少. 只有 517 個, 比起下采樣的 8000個要好不少
而精度固然也是 過採樣 更好一些
觀察數據的特徵 - 標準化處理/特徵工程
觀察數據的分佈 - 是否均衡 - 不均衡的話怎麼處理 - 下采樣/過採樣
下采樣和過採樣的選擇問題
優先仍是選擇過採樣. 儘管下采樣的 Recall 更高
可是數據量越大對於模型的穩定性是越高的, 由此也更可靠.
所以比起削減數據. 增長數據是更好的選擇
交叉驗證計算 Recall 比對選擇最合適的參數
邏輯迴歸中的閾值選擇
根據混淆矩陣, 計算 TP / FP / TN / FN / Recall / 精度