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

posted @ 2019-11-08 15:19 战争热诚 阅读(...) 评论(...) 编辑 收藏