sofasofa——交通事故理赔审核

一、简介

1.背景介绍

在交通摩擦(事故)发生后,理赔员会前往现场勘察、采集信息,这些信息往往影响着车主是否能够得到保险公司的理赔。训练集数据包括理赔人员在现场对该事故方采集的36条信息,信息已经被编码,以及该事故方最终是否获得理赔。我们的任务是根据这36条信息预测该事故方没有被理赔的概率。

2.数据

  • 数据文件
    train.csv 训练集,文件大小 15.6mb
    test.csv 预测集, 文件大小 6.1mb
    sample_submit.csv 提交示例 文件大小 1.4mb
    训练集中共有200000条样本,预测集中有80000条样本。
  • 数据下载
    下载链接:http://sofasofa.io/competition.php?id=2#c1跳转

3.变量说明

变量名释义
CaseId案例编号,没有实际意义
Q1理赔员现场勘察采集的信息,Q1代表第一个问题的信息。信息被编码成数字,数字的大小不代表真实的关系。
Qk同上,Qk代表第k个问题的信息。一共36个问题。
Evaluation表示最终审核结果。0表示授予理赔,1表示未通过理赔审核。在test.csv中,这是需要被预测的标签。

4.评价方法

  1. 提交结果为每个测试样本未通过审核的概率,也就是Evaluation为1的概率。评价方法为精度-召回曲线下面积(Precision-Recall AUC),以下简称PR-AUC。
  2. PR-AUC的取值范围是0到1。越接近1,说明模型预测的结果越接近真实结果。

二、标杆模型

  • 官方给了两个标杆模型:
    http://sofasofa.io/benchmarks.php?id=2跳转

1.LASSO逻辑回归模型(Python)

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)
  • 该模型预测结果的PR-AUC为:0.714644

2.随机森林分类模型(Python)

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)
  • 该模型预测结果的PR-AUC为:0.850897

3.总结

因为该比赛的评价方法是通过计算PR-AUC进行比较。根据给出的两个不同的模型和其PR-AUC值,可以知道随机森林分类模型的PR-AUC是两个模型里最低的,所以我们直接对随机森林分类模型进行处理。

三、基础准备

1.混淆矩阵

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.PR-AUC的定义

在这里插入图片描述

3.PR-AUC的计算方法

  • 使用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

四、数据预处理

1.缺失值

代码:

print(train.info())

结果:
在这里插入图片描述
可以看到结果图最后一行返回的是“None”,也就是说没有缺失值!

  • 若是有缺失值,可以用下面这行代码进行剔除:
dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

更多关于缺失值的操作:https://blog.csdn.net/qq_41780234/article/details/102794601传送门

2.观察变量信息

代码:

print(train.describe())

结果:
在这里插入图片描述

3.相关系数查看

代码:

#导入numpy库	
#补充在在最开始导入库的版块里
import numpy as np

#格式:corr=文件名.corr
#0.2只是我的建议范围,波动范围在0.0~1.0
corr = train.corr()
corr[np.abs(corr) < 0.2] = np.nan		#绝对值低于0.2的就用nan替代
print(corr)

结果:
在这里插入图片描述
之所以选择0.2是因为:0.2-0.4弱正相关;0.4-0.6算中等相关;0.6-0.8达到强正相关。可以看出不同变量之间的关联不大。

4.重复值

代码:

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

train = pd.read_csv(r"E:\my code\train.csv")
test = pd.read_csv(r"E:\my code\test.csv")
submit = pd.read_csv(r"E:\my code\sample_submit.csv")

# 去掉没有意义的一列
train.drop('CaseId', axis=1, inplace=True)

train.drop_duplicates(subset=None,keep='first',inplace=True)
print(train)

结果:
在这里插入图片描述

五、随机森林模型调参

1.交叉验证

数据集上实现一个分类森林,用随机森林训练并进行交叉验证:

#导入必要的包
from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split,GridSearchCV,cross_val_score
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取数据
train = pd.read_csv(r"E:\my code\train.csv")
test = pd.read_csv(r"E:\my code\test.csv")
submit = pd.read_csv(r"E:\my code\sample_submit.csv")

#导入数据集
data = load_digits()
x = data.data
y = data.target

RF = RandomForestClassifier(random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('交叉验证得分: %.4f'%score)

结果:
交叉验证的得分为0.9460
在这里插入图片描述

2.选择criterion参数

这个参数只有两个参数 ‘entropy’(熵) 和 ‘gini’(基尼系数)可选,虽然但是,一般默认为gini

代码:

RF = RandomForestClassifier(random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('基尼系数得分: %.4f'%score)
RF = RandomForestClassifier(criterion = 'entropy',random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('熵得分: %.4f'%score)

结果:
在这里插入图片描述

3.选择n_estimators的最佳值

代码:

###调n_estimators参数
ScoreAll = []
for i in range(10,200,10):
    DT = RandomForestClassifier(n_estimators = i,random_state = 66) #,criterion = 'entropy'
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [150.0.94990999]
在这里插入图片描述
在这里插入图片描述

4.缩小n_estimators最优值范围

代码:

###进一步缩小范围,调n_estimators参数
ScoreAll = []
for i in range(100,160):
    DT = RandomForestClassifier(n_estimators = i,random_state = 66)   #criterion = 'entropy',
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [151.0.95102421];可以看到,151为得分最高点,我们暂定n_estimators为151。
在这里插入图片描述
在这里插入图片描述

5.选择max_depth最优值

代码:

###粗调max_depth参数
ScoreAll = []
for i in range(10,30,3):
    DT = RandomForestClassifier(n_estimators = 151,random_state = 66,max_depth =i ) #,criterion = 'entropy'
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [19.0.95102421]
在这里插入图片描述
在这里插入图片描述

6.缩小max_depth最优值的范围

转折点在19,但是19之后一直没有变化,可以说明就算不限制,所有树的最大深度也就是19左右,因为是以步长为3搜索的,所以还需要进行下一步搜索一下19附近的值。

(1)第一次缩范围:调节步长
代码:

ScoreAll = []
for i in range(10,30,1):                        #把步长调为1
    DT = RandomForestClassifier(n_estimators = 151,random_state = 66,max_depth =i ) #,criterion = 'entropy'
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
在这里插入图片描述
在这里插入图片描述

(2)第二次缩范围:调节范围

代码:

ScoreAll = []
for i in range(15,20,1):
    DT = RandomForestClassifier(n_estimators = 151,random_state = 66,max_depth =i ) #,criterion = 'entropy'
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [17.0.95102421];精细搜索之后发现,17这个值就是转折点,所以暂定max_depth = 17。
在这里插入图片描述
在这里插入图片描述

7.选择min_samples_split的最佳参数

因为min_samples_split最小值就是2,所以直接从2开始调起。

代码:

###调min_samples_split参数
ScoreAll = []
for i in range(2,10):
    RF = RandomForestClassifier(n_estimators = 151,random_state = 66,max_depth =17,min_samples_split = i ) #,criterion = 'entropy'
    score = cross_val_score(RF,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [2. 0.95102421];可以看到,随着min_samples_split增大,模型得分下降,说明没有出现过拟合现象,min_samples_split暂定2。
在这里插入图片描述
在这里插入图片描述

8.选择min_samples_leaf的最佳参数

代码:

###调min_samples_leaf参数
ScoreAll = []
for i in range(1,15,2):
    DT = RandomForestClassifier(n_estimators = 151,random_state = 66,max_depth =17,min_samples_leaf = i,min_samples_split = 2 ) 
    score = cross_val_score(DT,data.data,data.target,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

结果:
最优参数以及最高得分: [1. 0.95102421]
在这里插入图片描述
在这里插入图片描述

9.max_features的调参

代码:

#调max_features参数
param_grid = {
    'max_features':np.arange(0.1, 1)}

rfc = RandomForestClassifier(random_state=66,n_estimators = 151,max_depth = 17,min_samples_leaf =1 ,min_samples_split =2 )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)

结果:
{‘max_features’: 0.1}
0.9526877715704531
在这里插入图片描述

10.最佳参数汇总

参数最优值
n_estimators151
max_depth17
min_samples_split2
min_samples_leaf1
max_features0.1

六、最优参数附近进行小范围网格搜索

因为手动调参时,这些参数可能会相互影响,导致得到的参数还不是最优的。所以在最优参数附近进行小范围的网格搜索,排出相互影响的因素。

但这次的数据量巨大,不需要网格搜索,且耗时巨长,博主跑了一个下午都没出结果,遂决定放弃。

七、随机森林的最终结果

代码:

#导入必要的包
from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split,GridSearchCV,cross_val_score
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取数据
train = pd.read_csv(r"E:\my code\train.csv")
test = pd.read_csv(r"E:\my code\test.csv")
submit = pd.read_csv(r"E:\my code\sample_submit.csv")

#导入数据集
data = load_digits()
x = data.data
y = data.target

# 删除id
train.drop('CaseId', axis=1, inplace=True)
test.drop('CaseId', axis=1, inplace=True)

# 取出训练集的y
y_train = train.pop('Evaluation')

# 建立随机森林模型
clf = RandomForestClassifier(random_state=66,n_estimators = 151,max_depth = 17,min_samples_leaf =1 ,min_samples_split =2 )
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_prediction3.csv', index=False)

结果:
结果不尽人意,比标杆模型的auc还低 QAQ
在这里插入图片描述

八、Xgboost模型优化

1.特征工程——整体相关性分析

from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split,GridSearchCV,cross_val_score
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sn


# 读取数据
train = pd.read_csv(r"E:\my code\train.csv")
test = pd.read_csv(r"E:\my code\test.csv")
submit = pd.read_csv(r"E:\my code\sample_submit.csv")

sn.heatmap(train.corr())
plt.show()

在这里插入图片描述
放大右下角:
在这里插入图片描述

2.最后的模型

代码:

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"E:\my code\train.csv")
testdata = pd.read_csv(r"E:\my code\test.csv")
submitdata = pd.read_csv(r"E:\my code\sample_submit.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,
                          min_child_weight=4,
                          gamma=0.5,
                          n_estimators=5000,
                          silent=True,
                          objective='binary:logistic',
                          nthread=4,
                          seed=27,
                          scale_pos_weight=1,
                          subsample=0.9,
                          colsample_bytree=0.6,
                          reg_alpha=10,
                         colsample_bylevel=1,
                         base_score=0.5,
                          )

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"E:\my code\sample_submit.csv")
    submitData['Evaluation'] = y_pred_test
    submitData.to_csv("xgboost9.csv", index=False)

run_predict()

多次调整后:
在这里插入图片描述
在这里插入图片描述
= =

九、参考文章

  1. https://blog.csdn.net/u013044310/article/details/104045284跳转
  2. https://www.cnblogs.com/wj-1314/p/10790197.html跳转
  3. https://www.jianshu.com/p/de1df23bee31跳转

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值