• 数据竞赛实战(4)——交通事故理赔审核


    前言

    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还真是解题利器。有时间的话,继续尝试其他算法,那这些简单的题,目的是继续尝试应用自己学到的算法。

  • 相关阅读:
    物联网和互联网到底有什么区别和联系呢?
    JAVA流程控制
    JAVA运算符
    JAVA中的变量及取值范围
    CSS position 属性
    web中的HTML CSS
    css选择器
    LAST_INSERT_ID
    [方法] 如何做产品规划
    [方法]需求挖掘采集的方法
  • 原文地址:https://www.cnblogs.com/wj-1314/p/10790197.html
Copyright © 2020-2023  润新知