數據競賽實戰(4)——交通事故理賠審核

  • 2019 年 11 月 8 日
  • 筆記

前言

1,背景介紹

  在交通摩擦(事故)發生後,理賠員會前往現場勘察、採集信息,這些信息往往影響着車主是否能夠得到保險公司的理賠。訓練集數據包括理賠人員在現場對該事故方採集的36條信息,信息已經被編碼,以及該事故方最終是否獲得理賠。我們的任務是根據這36條信息預測該事故方沒有被理賠的概率

2,任務類型

  入門二元分類模型

3,數據文件說明

train.csv        訓練集     文件大小為15.6MB

test.csv               預測集    文件大小為6.1MB

sample_submit.csv    提交示例      文件大小為1.4MB

4,數據變量說明 

  訓練集中共有200000條樣本,預測集中有80000條樣本。 

5,評估方法

  你的提交結果為每個測試樣本未通過審核的概率,也就是Evaluation為1的概率。評價方法為精度-召回曲線下面積(Precision-Recall AUC),以下簡稱PR-AUC。 

  PR-AUC的取值範圍是0到1。越接近1,說明模型預測的結果越接近真實結果。

5.1  精度和召回的定義和計算方式如下:

  可以參考博文:機器學習筆記:常用評估方法

  首先,我們先從混淆矩陣聊起,混淆矩陣是用來總結一個分類器結果的矩陣,對於K元分類,其實它就是一個 k * k  的表格,用來記錄分類器的預測結果。

  對於最常見的二元分類來說,它的混淆矩陣是 2 * 2的,如下:

  TP = True  Positive =  真陽性;  FP = False  Positive =  假陽性

  FN = False Negative = 假陰性; TN = True  Negative = 真陰性

下面舉個例子

 比如我們一個模型對15個樣本預測,然後結果如下:

預測值:1    1    1    1    1    0    0    0    0    0    1    1    1    0    1

真實值:0    1    1    0    1    1    0    0    1    0    1    0    1    0    0

   上面的就是混淆矩陣,混淆矩陣的這四個數值,經常被用來定義其他的一些度量。

準確度(Accuracy) = (TP+TN) / (TP+TN+FN+TN)

  在上面的例子中,準確度 = (5+4) / 15 = 0.6

精度(precision, 或者PPV, positive predictive value) = TP / (TP + FP)

  在上面的例子中,精度 = 5 / (5+4) = 0.556

召回(recall, 或者敏感度,sensitivity,真陽性率,TPR,True Positive Rate) = TP / (TP + FN)

  在上面的例子中,召回 = 5 / (5+2) = 0.714

特異度(specificity,或者真陰性率,TNR,True Negative Rate) = TN / (TN + FP)

  在上面的例子中,特異度 = 4 / (4+2) = 0.667 

F1-值(F1-score) = 2*TP / (2*TP+FP+FN) 

  在上面的例子中,F1-值 = 2*5 / (2*5+4+2) = 0.625

5.2  精準率Precision,召回率Recall

  精確率(正確率)和召回率是廣泛用於信息檢索和統計學分類領域的兩個度量值,用來評價結果的質量。其中精度是檢索出相關文檔樹與檢索出的文檔總數的比率,衡量的是檢索系統的查准率;召回率是指檢索出的相關文檔數和文檔庫中所有的相關文檔數的比率,衡量的是檢索系統的查全率。

  一般來說,Precsion就是檢索出來的條目(比如:文檔,網頁等)有多少是準確的,Recall就是所有準確的條目有多少被檢索出來了,兩者定義如下:

  精準度(又稱查准率)和召回率(又稱查全率)是一對矛盾的度量。一般來說,查准率高時,查全率往往偏低,而查全率高時,查准率又往往偏低,所以通常只有在一些簡單任務中,才可能使得查准率和查全率都很高。

5.3  PR-AUC的定義如下:

  首先舉個例子:

  比如100個測試樣本,根據我們的模型,我們得到了這100個點是被分為標籤1的概率y1, y2, y3,…y100、

  下面我們需要閾值t,把概率轉化為標籤,如果 y_i 顯然,一個 t 的取值,對應着一組(精度,召回)。我們遍歷 t 所有的取值, 0, y1, y2, y3, … y100, 1。 我們就得到了102組(精度,召回)。

  以召回為X軸,精度為Y軸,我們就可以在XOY坐標系中標出102個坐標點,把這102個點連成線,這個折線就稱為精度召回曲線。曲線與坐標軸圍成的面積就是精度-召回AUC。AUC越接近1,說明模型越好。

   AUC是一種模型分類指標,且僅僅是二分類模型的評價指標。AUC是Area Under Curve(曲線下面積)的簡稱,那麼Curve就是ROC(Receiver Operating  Characteristic),翻譯為“接受者操作特性曲線”。也就是說ROC是一條曲線,AUC是一個面積值。

  ROC曲線應該盡量偏離參考線,越靠近左上越好。

  AUC:ROC曲線下面積,參考面積為0.5,AUC應大於0.5,且偏離越多越好。

5.4  什麼是AUC?

  AUC是ROC曲線所覆蓋的區域面積,顯然,AUC越大,分類器分類效果越好。

  AUC =1 是完美分類器,採用這個預測模型時,不管設定什麼閾值都能得出完美預測。絕大多數預測的場合,不存在完美分類器。

  0.5 < AUC < 1,優於隨機猜測,這個分類器(模型)妥善設置閾值的話,能有預測價值。

  AUC = 0.5 , 和隨機猜想一樣,模型沒有預測價值。

  AUC < 0.5,比隨機猜想還差,但只要總是反預測就行,這樣就由於隨機猜測。

 

  AUC的物理意義:假設分類器的輸出是樣本屬於正類的score(置信度),則AUC的物理意義為:任意一對(正,負)樣本,正樣本的score大於負樣本的score的概率。

  AUC的物理意義正樣本的預測結果大於負樣本的預測結果的概率。所以AUC反應的是分類器對樣本的排序能力。

  另外值得注意的是:AUC對樣本是否均衡並不敏感,這也是不均衡樣本通常採用AUC評價分類器性能的一個原因。

5.5  PR-AUC的計算方法如下:

  第一種方法就是:AUC為ROC曲線下的面積,那我們直接計算面積可得。面積為一個個小的梯形面積之和。計算的精度與閾值的精度有關。

  第二種方法:根據AUC的物理意義,我們計算正樣本score大於負樣本的score的概率。取N* M(N為正樣本數,M為負樣本數)個二元組,比較score,最後得到AUC,時間複雜度為O(N*M)。

  第三種方法:與第二種方法相似,直接計算正樣本score大於負樣本的概率。我們首先把所有樣本按照score排序,依次用rank表示他們,如最大score的樣本,rank = n(n=M+N),其次為 n-1。那麼對於正樣本中rank最大的樣本,rank_max,有M – 1個其他正樣本比他的score小。最後我們得到正樣本大於負樣本的概率的時間複雜度為 O(N+M)

from sklearn.metrics import roc_auc_score  # y_test:實際的標籤, dataset_pred:預測的概率值。  roc_auc_score(y_test, dataset_pred)  

  

  使用sklearn.metrics.average_precision_score

>>> import numpy as np  >>> from sklearn.metrics import average_precision_score  >>> y_true = np.array([0, 0, 1, 1])  >>> y_predict = np.array([0.1, 0.4, 0.35, 0.8])  >>> average_precision_score(y_true, y_predict)  0.791666666  

  

6,完整代碼,請移步小編的GitHub

  傳送門:請點擊我

 

數據預處理

1,觀察數據有沒有缺失值

print(train.info())      <class 'pandas.core.frame.DataFrame'>  RangeIndex: 10000 entries, 0 to 9999  Data columns (total 7 columns):  city          10000 non-null int64  hour          10000 non-null int64  is_workday    10000 non-null int64  weather       10000 non-null int64  temp_1        10000 non-null float64  temp_2        10000 non-null float64  wind          10000 non-null int64  dtypes: float64(2), int64(5)  memory usage: 547.0 KB  None  

  我們可以看到,共有10000個觀測值,沒有缺失值。

2,觀察每個變量的基礎描述信息

print(train.describe())                     city          hour      ...             temp_2          wind  count  10000.000000  10000.000000      ...       10000.000000  10000.000000  mean       0.499800     11.527500      ...          15.321230      1.248600  std        0.500025      6.909777      ...          11.308986      1.095773  min        0.000000      0.000000      ...         -15.600000      0.000000  25%        0.000000      6.000000      ...           5.800000      0.000000  50%        0.000000     12.000000      ...          16.000000      1.000000  75%        1.000000     18.000000      ...          24.800000      2.000000  max        1.000000     23.000000      ...          46.800000      7.000000    [8 rows x 7 columns]  

  通過觀察可以得出一些猜測,如城市0 和城市1基本可以排除南方城市;整個觀測記錄時間跨度較長,還可能包含了一個長假期數據等等。

3,查看相關係數

  (為了方便查看,絕對值低於0.2的就用nan替代)

    corr = feature_data.corr()      corr[np.abs(corr) < 0.2] = np.nan      print(corr)                  city  hour  is_workday  weather    temp_1    temp_2  wind  city         1.0   NaN         NaN      NaN       NaN       NaN   NaN  hour         NaN   1.0         NaN      NaN       NaN       NaN   NaN  is_workday   NaN   NaN         1.0      NaN       NaN       NaN   NaN  weather      NaN   NaN         NaN      1.0       NaN       NaN   NaN  temp_1       NaN   NaN         NaN      NaN  1.000000  0.987357   NaN  temp_2       NaN   NaN         NaN      NaN  0.987357  1.000000   NaN  wind         NaN   NaN         NaN      NaN       NaN       NaN   1.0  

  從相關性角度來看,用車的時間和當時的氣溫對借取數量y有較強的關係;氣溫和體感氣溫顯強正相關(共線性),這個和常識一致。

模型訓練及其結果展示

1,標杆模型:LASSO邏輯回歸模型

  該模型預測結果結果的PR-AUC為:0.714644

# -*- coding: utf-8 -*-    import pandas as pd  from sklearn.linear_model import LogisticRegression    # 讀取數據  train = pd.read_csv("train.csv")  test = pd.read_csv("test.csv")  submit = pd.read_csv("sample_submit.csv")    # 刪除id  train.drop('CaseId', axis=1, inplace=True)  test.drop('CaseId', axis=1, inplace=True)    # 取出訓練集的y  y_train = train.pop('Evaluation')    # 建立LASSO邏輯回歸模型  clf = LogisticRegression(penalty='l1', C=1.0, random_state=0)  clf.fit(train, y_train)  y_pred = clf.predict_proba(test)[:, 1]    # 輸出預測結果至my_LASSO_prediction.csv  submit['Evaluation'] = y_pred  submit.to_csv('my_LASSO_prediction.csv', index=False)  

  

2,標杆模型:隨機森林分類模型

  該模型預測結果的PR-AUC為:0.850897

# -*- coding: utf-8 -*-  import pandas as pd  from sklearn.ensemble import RandomForestClassifier    # 讀取數據  train = pd.read_csv("train.csv")  test = pd.read_csv("test.csv")  submit = pd.read_csv("sample_submit.csv")    # 刪除id  train.drop('CaseId', axis=1, inplace=True)  test.drop('CaseId', axis=1, inplace=True)    # 取出訓練集的y  y_train = train.pop('Evaluation')    # 建立隨機森林模型  clf = RandomForestClassifier(n_estimators=100, random_state=0)  clf.fit(train, y_train)  y_pred = clf.predict_proba(test)[:, 1]    # 輸出預測結果至my_RF_prediction.csv  submit['Evaluation'] = y_pred  submit.to_csv('my_RF_prediction.csv', index=False)  

  我提交的結果:

   這裡我嘗試了使用隨機森林進行關鍵特徵提取,然後對關鍵特徵進行模型訓練,發現效果不是很好,所以這裡就不貼特徵提取的代碼了。如果有需求,請參考我之前的博客。

KMeans 算法與交通事故理賠審核預測

  K-Means 是基於劃分的聚類方法,他是數據挖掘十大算法之一。基於劃分的方法是將樣本集組成的矢量空間劃分成為多個區域,每個區域都存在一個樣本中心,通過建立映射關係,可以將所有樣本分類到其相應的中心。

1,經典的K-Means聚類算法步驟

  • 1,初始化聚類中心
  • 2,分配樣本到相近的聚類集合
  • 3,根據步驟2的結果,更新聚類中心
  • 4,若達到最大迭代步數或兩次迭代差小於設定的閾值則算法結束,否則重複步驟2.

  經典的K-means算法在初始化聚類中心時採用的時隨機採樣的方式,不能保證得到期望的聚類結果,可以選擇重複訓練多個模型,選取其中表現最好的,但是有沒有更好的方法呢?David Arthur提出的 K-means++算法能夠有效地產生初始化的聚類中心。

  首先隨機初始化一個聚類中心C1,然後通過迭代計算最大概率值X,將其加入到中心點中,重複該過程,直到選擇K個中心。

2,快速了解數據情況

  顯示數據簡略信息,可以看到每列有多少非空的值,以及每列數據對應的數據類型。

  本文數據對應的結果如下:

<class 'pandas.core.frame.DataFrame'>  RangeIndex: 200000 entries, 0 to 199999  Data columns (total 37 columns):  Q1            200000 non-null int64  Q2            200000 non-null int64  Q3            200000 non-null int64  Q4            200000 non-null int64  Q5            200000 non-null int64  Q6            200000 non-null int64  Q7            200000 non-null int64  Q8            200000 non-null int64  Q9            200000 non-null int64  Q10           200000 non-null int64  Q11           200000 non-null int64  Q12           200000 non-null int64  Q13           200000 non-null int64  Q14           200000 non-null int64  Q15           200000 non-null int64  Q16           200000 non-null int64  Q17           200000 non-null int64  Q18           200000 non-null int64  Q19           200000 non-null int64  Q20           200000 non-null int64  Q21           200000 non-null int64  Q22           200000 non-null int64  Q23           200000 non-null int64  Q24           200000 non-null int64  Q25           200000 non-null int64  Q26           200000 non-null int64  Q27           200000 non-null int64  Q28           200000 non-null int64  Q29           200000 non-null int64  Q30           200000 non-null int64  Q31           200000 non-null int64  Q32           200000 non-null int64  Q33           200000 non-null int64  Q34           200000 non-null int64  Q35           200000 non-null int64  Q36           200000 non-null int64  Evaluation    200000 non-null int64  dtypes: int64(37)  memory usage: 56.5 MB  None  

  想要了解特徵之間的相關性,可計算相關係數矩陣,然後可對某個特徵來排序

 

   排序後結果如下:

Evaluation    1.000000  Q28           0.410700  Q30           0.324421  Q36           0.302709  Q35           0.224996  Q34           0.152743  Q32           0.049397  Q21           0.034897  Q33           0.032248  Q13           0.023603  Q8            0.021922  Q19           0.019694  Q20           0.013903  Q4            0.011626  Q27           0.004262  Q23           0.002898  Q7            0.001143  Q31          -0.000036  Q14          -0.000669  Q29          -0.002014  Q10          -0.002711  Q12          -0.005287  Q1           -0.006511  Q16          -0.007184  Q18          -0.007643  Q26          -0.008188  Q11          -0.009252  Q24          -0.010891  Q22          -0.011821  Q25          -0.012660  Q6           -0.016072  Q2           -0.018307  Q15          -0.019570  Q9           -0.021261  Q5           -0.023893  Q3           -0.026349  Q17          -0.028461  Name: Evaluation, dtype: float64  

  

3,使用K-Means訓練模型

  KMeans():n_clusters指要預測的有幾個類;init指初始化中心的方法,默認使用的是k-means++方法,而非經典的K-means方法的隨機採樣初始化,當然你可以設置為random使用隨機初始化;n_jobs指定使用CPU核心數,-1為使用全部CPU。

  完整的代碼如下:

import pandas as pd    traindata = pd.read_csv(r'data/train.csv')  testdata = pd.read_csv(r'data/test.csv')    # 去掉沒有意義的一列  traindata.drop('CaseId', axis=1, inplace=True)  testdata.drop('CaseId', axis=1, inplace=True)    # head() 默認顯示前5行數據,可指定顯示多行  # 例如 head(50)顯示前50行  # 查看每類有多少空值  # res = traindata.isnull().sum()  # 顯示數據簡略信息,可以每列有多少非空的值,以及每列數據對應的數據類型  # res = traindata.info()    # 以圖的形式,快速了解數據  # ~hist():繪製直方圖,參數figsize可指定輸出圖片的尺寸。  # traindata.hist(figsize=(20, 20))    # # 想要了解特徵之間的相關性,可計算相關係數矩陣,然後可對某個特徵來排序  # corr_matrix = traindata.corr()  # # ascending=False 表示降序排列  # corr_matrix = corr_matrix['Evaluation'].sort_values(ascending=False)  # print(corr_matrix)    # 從訓練集中分類標籤  y = traindata['Evaluation']  traindata.drop('Evaluation', axis=1, inplace=True)    from sklearn.cluster import KMeans    clf = KMeans(n_clusters=2, init='k-means++', n_jobs=-1)  clf.fit(traindata, y)  y_pred = clf.predict(testdata)    # 保存預測的結果  submitData = pd.read_csv(r'data/sample_submit.csv')  submitData['Evaluation'] = y_pred  submitData.to_csv("KMeans.csv", index=False)  

  結果如下:0.485968

   K-means算法是數據挖掘的十大經典算法之一,但實際中如果想要得到滿意的效果,還是非常難的,這裡做一個嘗試,確實是不行的。

 4,自己使用XGBoost訓練

  直接訓練,代碼如下:

import pandas as pd  import numpy as np  from sklearn.model_selection import train_test_split  import xgboost as xgb  from sklearn.metrics import accuracy_score    traindata = pd.read_csv(r'data/train.csv')  testdata = pd.read_csv(r'data/test.csv')    # 去掉沒有意義的一列  traindata.drop('CaseId', axis=1, inplace=True)  testdata.drop('CaseId', axis=1, inplace=True)    # 從訓練集中分類標籤  trainlabel = traindata['Evaluation']  traindata.drop('Evaluation', axis=1, inplace=True)    traindata1, testdata1, trainlabel1 = traindata.values, testdata.values, trainlabel.values  # 數據集分割  X_train, X_test, y_train, y_test = train_test_split(traindata1, trainlabel1,                                                      test_size=0.3, random_state=123457)  # 訓練模型  model = xgb.XGBClassifier(max_depth=5,                            learning_rate=0.1,                            gamma=0.1,                            n_estimators=160,                            silent=True,                            objective='binary:logistic',                            nthread=4,                            seed=27,                            colsample_bytree=0.8)    model.fit(X_train, y_train)    # 對測試集進行預測  y_pred = model.predict(X_test)    # 計算準確率  accuracy = accuracy_score(y_test, y_pred)  print('accuracy:%2.f%%' % (accuracy * 100))    #查看AUC評價標準  # from sklearn import metrics  ##必須二分類才能計算  # print("AUC Score (Train): %f" % metrics.roc_auc_score(y_test, y_pred))    def run_predict():      y_pred_test = model.predict_proba(testdata1)[:, 1]      # 保存預測的結果      submitData = pd.read_csv(r'data/sample_submit.csv')      submitData['Evaluation'] = y_pred_test      submitData.to_csv("xgboost.csv", index=False)      run_predict()  

  結果如下:

   然後對XGBoost進行調參,調參結果如下:

  這裡直接展示了模型的最佳參數:

XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,         colsample_bytree=0.6, gamma=0.3, learning_rate=0.1,         max_delta_step=0, max_depth=6, min_child_weight=4, missing=None,         n_estimators=1000, n_jobs=1, nthread=4, objective='binary:logistic',         random_state=0, reg_alpha=1, reg_lambda=1, scale_pos_weight=1,         seed=27, silent=True, subsample=0.9)  

  然後運行,得到的結果如下:

   當然相比較之前的xgboost,結果提高了一些。

  到目前為止,就做這些嘗試吧,看來xgboost還真是解題利器。有時間的話,繼續嘗試其他算法,那這些簡單的題,目的是繼續嘗試應用自己學到的算法。