XGBoost实战2--数据预测保险赔偿

news2025/1/11 19:45:21

一、概述

本次实战基于给出的数据进行保险预测。数据集:Allstate Claims Severity | Kaggle

给出的训练数据是116列(cat1-cat116)的离散数据和14列(con1-con14)的连续数据。数据集中的每一行表示一个保险索赔。必须预测‘loss’列的值。

 二、导入包

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pyecharts.charts import Bar
import pyecharts.options as opts
from scipy import stats
import seaborn as sns
import xgboost as xgb
from sklearn.metrics import mean_absolute_error, mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer

三、查看数据

1、 info查看数据类型

train_data = pd.read_csv('./allstate-claims-severity/train.csv')
test_data = pd.read_csv('./allstate-claims-severity/test.csv')
print(train_data.info())

2、head查看数据前5条信息

 print(train_data.head())

3、shape查看数据大小

print(train_data.shape)

4、查看数据列名

print('前20列名:', list(train_data.columns[:20]))
print('后20列名:', list(train_data.columns[-20:]))

5、describe查看数据统计量信息

print(train_data.describe())

6、查看数据是否有空值

print(pd.isnull(train_data).values.any())  # False表示没有缺失值

pandas的any方法 

7、统计离散型和连续型变量的数量

cat_features = list(train_data.select_dtypes(include=['object']).columns)
print('离散型特征有{}个,它们是:{}'.format(len(cat_features), cat_features))
cont_features = [cont for cont in list(train_data.select_dtypes(include=['float64']).columns) if cont not in ['loss']]
print('连续型特征有{}个,它们是:{}'.format(len(cont_features), cont_features))

 pandas的selectdtypes方法 

8、离散型特征

(1)统计每一类离散型数据的数目

cat_uniques = {}
for cat in cat_features:
    cat_uniques[cat] = len(list(train_data[cat].unique()))
cat_uniques_df = pd.DataFrame({'cat_name':list(cat_uniques.keys()),
                               'unique_values': list(cat_uniques.values())})
print(cat_uniques_df)
data = cat_uniques_df['unique_values'].value_counts().to_dict()
bar = Bar()
bar.add_xaxis(list(data.keys()))
bar.add_yaxis('', list(data.values()))
bar.set_global_opts(title_opts=opts.TitleOpts(title='离散特征值分布情况', pos_left='center'),
                    xaxis_opts=opts.AxisOpts(name='离散特征中的\n不同值的数目'),
                    yaxis_opts=opts.AxisOpts(name='具有X个不同值的\n分类特征的数量', is_show=True, splitline_opts=opts.SplitLineOpts(is_show=True))
                    )
bar.render('a.html')

正如我们所看到的,大部分的分类特征(72/116)是二值的,其中有一个具有326个值的特征。

(2)列举了10类离散型特征分布情况

fig, ax = plt.subplots(2, 5, figsize=(16, 9))
for i in range(2):
    for j in range(5):
        cat = cat_features[5*i+j]
        data = train_data[cat].value_counts().to_dict()
        ax[i][j].bar(list(data.keys()), list(data.values()), width=0.5)
        ax[i][j].set_xlabel(cat)
plt.savefig('./g.png')

9、连续型特征

(1)绘制连续值特征分布图

train_data[cont_features].hist(bins=50, figsize=(16, 12))
plt.savefig('./d.png', dpi=300)

(2)特征之间的相关性

plt.subplots(figsize=(16, 9))
corr_data = train_data[cont_features].corr()
sns.heatmap(corr_data, annot=True)
plt.savefig('./e.png', dpi=300)

(3) 统计连续特征与loss的相关性值,并按降序排列,绘制图

cont_features.append('loss')
res = train_data[cont_features].corr()['loss'].apply(lambda x: round(x, 4)).to_dict()
print(list(res.keys()))
bar2 = Bar()
bar2.add_xaxis(list(res.keys())[:-1])
bar2.add_yaxis('', list(res.values())[:-1], label_opts=opts.LabelOpts(formatter='{c}'))
bar2.set_global_opts(xaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_inside=True),  # 设置刻度线朝里还是外
                                              axislabel_opts=opts.LabelOpts(interval=0)))  # 解决pyechart x轴标签隔一个展示一个的问题
bar2.render('f.html')

 10、绘制loss值

plt.figure(figsize=(16, 8))
plt.plot(train_data['id'], train_data['loss'])
print('train_data[\'id\']的个数', len(train_data['id']))
plt.title('Loss values per id')
plt.xlabel('id')
plt.ylabel('loss')
plt.legend()
plt.savefig('./b.png', dpi=300)
# plt.show()

11、loss的偏度

偏度:度量了实值随机变量的均值分布的不对称性,下面让我们来计算一下loss的偏度。

# scipy.stats 统计指标
skew = stats.mstats.skew(train_data['loss']).data
print(skew)
after_transform_skew = stats.mstats.skew(np.log(train_data['loss'])).data
print(after_transform_skew)
# 两种loss分布对比
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(16, 5)
ax1.hist(train_data['loss'], bins=50)
ax1.set_title('Train Loss target histogram')
ax1.grid(True)
ax2.hist(np.log(train_data['loss']), bins=50, color='g')
ax2.set_title('Train Log Loss target histogram')
ax2.grid(True)
plt.savefig('./c.png', dpi=300)
# plt.show()

四、数据预处理--处理训练集和测试集

1、训练集

(1)增加log_loss作为训练集中的预测值y

train_data['log_loss'] = np.log(train_data['loss'])
train_y = train_data['log_loss']

(2)选出特征作为训练集中的特征x

features = [x for x in train_data.columns if x not in ['id', 'loss', 'log_loss']]
train_x = train_data[features]

(3)将离散型转换为数值型

# 将目标列,转换为 category 类型;然后,转换为整形的编码
for c in range(len(cat_features)):
    train_x[cat_features[c]] = train_x[cat_features[c]].astype('category').cat.codes
print(train_x)

2、测试集

(1)选出特征作为测试集中的特征x

features_test = [x for x in test_data.columns if x not in ['id']]
test_x = test_data[features]

(2)将离散型转换为数值型

# 将目标列,转换为 category 类型;然后,转换为整形的编码
for c in range(len(cat_features)):
    test_x[cat_features[c]] = test_x[cat_features[c]].astype('category').cat.codes
print(test_x)

五、建立模型

1、XGBoost 参数

booster : gbtree, 用什么方法进行结点分裂。梯度提升树来进行结点分裂。
objective : multi softmax, 使用的损失函数,softmax 是多分类问题
num_class : 10, 类别数,与 multi softmax 并用
gamma : 损失下降多少才进行分裂
max_depth : 12, 构建树的深度, 越大越容易过拟合
lambda : 2, 控制模型复杂度的权重值的L2正则化项参数,参数越大。模型越不容易过拟合。
subsample : 0.7 , 随机采样训练样本,取70%的数据训练
colsample_bytree : 0.7, 生成树时进行的列采样
min_child_weight : 3, 孩子节点中最小的样本权重和,如果一个叶子结点的样本权重和小于 min_child_weight 则拆分过程结果
slient : 0, 设置成 1 则没有运行信息输出,最好是设置为0
eta : 0.007, 如同学习率。前面的树都不变了,新加入一棵树后对结果的影响占比
seed : 1000
Thread : 7, cup 线程数

2、建立xgboost模型

(1)划分数据集并将数据类型转换成库可以使用的底层格

x_train, x_test, y_train, y_test = train_test_split(train_x, train_y, test_size=0.2, random_state=14)
print(x_test)
dtrain = xgb.DMatrix(x_train, y_train)
d_test = xgb.DMatrix(x_test, y_test)

(2) xgboost的CV建模

step1:初始参数

xgb_params = {
    'seed': 0,
    'eta': 0.1,
    'colsample_bytree': 0.5,
    'silent': 1,
    'subsample': 0.5,
    'objective': 'reg:squarederror',
    'max_depth': 5,
    'min_child_weight': 3
}

step2:定义计算损失值的函数

评估策略:e的次幂,用来评估。
结果衡量方法:使用平均绝对误差来衡量,mean_absolute_error(np.exp(y), np.exp(yhat))。

def xg_eval_mae(y_hat, dtrain):
    y = dtrain.get_label()
    return 'mae', mean_absolute_error(np.exp(y), np.exp(y_hat))

step3:CV建模

# feval:评估策略
bst_cv1 = xgb.cv(xgb_params, dtrain, num_boost_round=50, nfold=3, seed=0,
                 feval=xg_eval_mae, maximize=False, early_stopping_rounds=10)
print('CV score:', bst_cv1.iloc[-1, :]['test-mae-mean'])
plt.figure()
bst_cv1[['train-mae-mean', 'test-mae-mean']].plot()
plt.savefig('./h.png', dpi=300)

(3)修改num_boost_round参数

上面建立的树模型为50, 我们设置为100对比下结果。

bst_cv2 = xgb.cv(xgb_params, dtrain, num_boost_round=100, nfold=3, seed=0,
                 feval=xg_eval_mae, maximize=False, early_stopping_rounds=10)
print ('CV score:', bst_cv1.iloc[-1, :]['test-mae-mean'])

绘图100个数树模型下的结果

fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(16, 4)
ax1.set_title('100 rounds of training')
ax1.set_xlabel('Rounds')
ax1.set_ylabel('Loss')
ax1.grid(True)
ax1.plot(bst_cv2[['train-mae-mean', 'test-mae-mean']])
ax1.legend(['Training Loss', 'Test Loss'])
ax2.set_title('60 last rounds of training')
ax2.set_xlabel('Rounds')
ax2.set_ylabel('Loss')
ax2.grid(True)
ax2.plot(bst_cv2.iloc[40:][['train-mae-mean', 'test-mae-mean']])
ax2.legend(['Training Loss', 'Test Loss'])
plt.savefig('./i.png', dpi=300)

我们把树模型的数量增加到了100。效果不是很明显。看最后的60次。我们可以看到 测试集仅比训练集高那么一丁点。存在一丁点的过拟合。
不过我们的CV score更低了。接下来,我们改变其他参数。

(4)输出当前模型下测试集的预测值

改变参数之前,需要输出当前模型下测试集的预测值,以观察模型结果有无提升。

step1:数据类型转换成库可以使用的底层格式。

dtest_x = xgb.DMatrix(test_x)

step2:用XGBoost自身的库来实现(使用train)

model = xgb.train(xgb_params, dtrain, num_boost_round=50)
test_predict = model.predict(d_test)
mse = mean_squared_error(y_test, test_predict)
print(mse)

step3:可输出真实的预测值

test_y = model.predict(dtest_x)
print(test_y[1], len(test_y))

调优前的MSE为0.321。 

2、xgboost参数调节

step1:选择一组初始参数

衡量标准

def mae_score(y_true, y_pred):
    return mean_absolute_error(np.exp(y_true), np.exp(y_pred))
mae_scorer = make_scorer(mae_score, greater_is_better=False)

step2:改变 max_depth 和 min_child_weight,其他参数不变

params = {
    'seed': 0,
    'eta': 0.1,
    'colsample_bytree': 0.5,
    'silent': 1,
    'subsample': 0.5,
    'objective': 'reg:squarederror',
    # 'max_depth': 5,
    # 'min_child_weight': 3,
    'num_boost_round': 50,
}
cv_params = {'max_depth': list(range(4, 9)), 'min_child_weight': list((1, 3, 6))}
model = xgb.XGBRegressor(**params)
grid = GridSearchCV(estimator=model, param_grid=cv_params, scoring=mae_scorer, cv=5, verbose=1, n_jobs=4)
grid.fit(x_train, y_train)
test_predict = grid.predict(x_test)
mse = mean_squared_error(y_test, test_predict)
test_y = grid.predict(test_x)
print(grid.best_params_)
print(mse)
print(grid.best_score_)

 改变 max_depth 和 min_child_weight后,MSE:0.321-->0.296。

step3:调节 gamma 降低模型过拟合风险

params = {
    'seed': 0,
    'eta': 0.1,
    'colsample_bytree': 0.5,
    'silent': 1,
    'subsample': 0.5,
    'objective': 'reg:squarederror',
    'max_depth': 8,
    'min_child_weight': 3,
    'num_boost_round': 50,
}
cv_params = {'gamma': [0.1 * i for i in range(0, 5)]}
model = xgb.XGBRegressor(**params)
grid = GridSearchCV(estimator=model, param_grid=cv_params, scoring=mae_scorer, cv=5, verbose=1, n_jobs=4)
grid.fit(x_train, y_train)
test_predict = grid.predict(x_test)
mse = mean_squared_error(y_test, test_predict)
test_y = grid.predict(test_x)
print(grid.best_params_)
print(mse)
print(grid.best_score_)

调节gamma后,MSE:0.296-->0.297。 

Step 4: 调节样本采样方式 subsample 和 colsample_bytree

params = {
    'seed': 0,
    'eta': 0.1,
    # 'colsample_bytree': 0.5,
    'silent': 1,
    # 'subsample': 0.5,
    'objective': 'reg:squarederror',
    'max_depth': 8,
    'min_child_weight': 3,
    'num_boost_round': 50,
    'gamma': 0.1
}
cv_params = {'subsample': [0.1 * i for i in range(6, 9)],
             'colsample_bytree': [0.1 * i for i in range(6, 9)]}
model = xgb.XGBRegressor(**params)
grid = GridSearchCV(estimator=model, param_grid=cv_params, scoring=mae_scorer, cv=5, verbose=1, n_jobs=4)
grid.fit(x_train, y_train)
test_predict = grid.predict(x_test)
mse = mean_squared_error(y_test, test_predict)
test_y = grid.predict(test_x)
print(grid.best_params_)
print(mse)
print(grid.best_score_)

 调节样本采样方式 subsample 和 colsample_bytree,MSE:0.297-->0.296。

step5:减小学习率并增大树个数

params = {
    'seed': 0,
    # 'eta': 0.1,
    'colsample_bytree': 0.6,
    'silent': 1,
    'subsample': 0.7,
    'objective': 'reg:squarederror',
    'max_depth': 8,
    'min_child_weight': 3,
    'num_boost_round': 100,
    'gamma': 0.1
}
cv_params = {'eta': [0.5, 0.4, 0.3, 0.2, 0.1, 0.075, 0.05, 0.04, 0.03]}
model = xgb.XGBRegressor(**params)
grid = GridSearchCV(estimator=model, param_grid=cv_params, scoring=mae_scorer, cv=5, verbose=1, n_jobs=4)
grid.fit(x_train, y_train)
test_predict = grid.predict(x_test)
mse = mean_squared_error(y_test, test_predict)
test_y = grid.predict(test_x)
print(grid.best_params_)
print(mse)
print(grid.best_score_)

减小学习率并增大树个数,由于eta没变,MSE:不变。 

 六、总结

通过GridSerchCV调节参数,找打了一组最优参数,并切该参数下的模型结果最优,MSE最低,从调优前0.321的降到0.296。

最优参数:

best_params = {'max_depth' : 8,

                        'min_child_weight' : 3,

                        'gamma' : 0.1,

                        'colsample'_bytree : 0.6,

                        'subsample' : 0.7}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jina AI @Slush 上海 地表最酷科技创新大会来啦!

地表最酷的科技创新大会 S 创上海 2023 The Final Slush Shanghai 即将在 9 月 22 - 23 日空降上海 Jina AI 受邀参与本次大会,并带来好玩的互动! 多种门票限时限量派送中 还在犹豫什么!! 就等你啦~ 什么是 S 创 2023 上海大会 本…

vulnhub靶机Thoth-Tech

下载地址:https://download.vulnhub.com/thothtech/Thoth-Tech.ova 主机发现 arp-scan -l 目标:192.168.21.148 端口扫描 nmap --min-rate 10000 -p- 192.168.21.148 服务扫描 nmap -sV -sT -O -p21,22,80 192.168.21.148 漏洞扫描 nmap --scriptvu…

IT技术2222

发布的方式 脚本 ansible 自动化,点点点

Mac电脑报错“托管配置文件格式不正确”的解决方法

本文介绍在Mac电脑中,复制地址链接后出现“托管配置文件格式不正确”这一报错的解决方法。 有时候,我们在把订阅地址粘贴到对应软件中时,会出现托管配置文件格式不正确: invalid mode: redir-host的报错。 出现这种报错,就意味着我…

座舱台架介绍与搭建流程

座舱台架介绍 车载测试中的座舱台架测试包括以下几个方面: 仪表盘:测试仪表盘的显示、功能、光线反射和防眩目性能等。评估仪表盘是否能够提供准确的驾驶信息,并能在各种光照条件下清晰可见。中控屏:测试中控屏的触摸响应、图像…

连接MySQL时报错:Public Key Retrieval is not allowed的解决方法

问题描述: DBeaver 连接 mysql 时报错:Public Key Retrieval is not allowed(不允许公钥检索) 解决方法: 连接设置 -> 驱动属性 -> allowPublicKeyRetrievalfalse(这里的运输公钥检索是默认关闭的&a…

禁用Win10自动更新

第一步,winr,输入 gpedit.msc 并回车,打开【组策略】 第二步,依次点击 管理模板->Windows组件->Windows更新 第三步,双击Windows更新,然后在设置中双击 指定 intranet Microsoft 更新服务位置 第…

融合柯西变异和自适应莱维飞行的布谷鸟优化算法,改进布谷鸟,MATLAB代码

经常有小伙伴后台留言问: 作者改进的算法可不可以用来写论文呀? 回答是:当然可以!且不用加引用! 如果我的文章能帮助到大家写论文,那是作者的荣幸呀! 布谷鸟优化算法是一个非常经典的优化算法&a…

视频怎么制作成gif动画?这个方法试试看

日常生活中我们会接触到这种各样的视频,随着拍摄工具的升级视频的画质越来越清楚体积也就越来越大。想要将这些视频转换成gif动图的时候要怎么操作呢?给大家推荐一款gif动画制作(https://www.gif.cn/)工具,上传视频仅需…

指针-字符串替换

任务描述 从标准输入读入数据,每行中最多包含一个字符串 “_xy_”,且除了字符串“_xy_”外,输入数据中不包括下划线字符,请将输入行中的 “_xy_” 替换为 “_ab_”, 在标准输出上输出替换后的结果;若没有进行过满足条…

Dockerfile RUN

语法 RUN cmd 例如: RUN apt-get update RUN [“executable”, “param1”, “param2”] 例如:RUN [“apt-get”,“update”] 请注意,每个 RUN 指令都会创建一个新的镜像层,因此在 Dockerfile 中使用 RUN 指令时,要注意…

优优嗨聚集团:外卖市场发展红火,外卖代运营服务如何发展

随着外卖市场的飞速发展,外卖代运营服务已成为新的蓝海。本文将对外卖市场的发展趋势以及外卖代运营服务的发展现状和趋势进行分析,以期为相关从业者提供参考。 一、外卖市场发展红火 近年来,外卖市场的发展速度十分惊人。根据艾媒咨询的数据…

基于SSM的车库智能管理平台设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

Zabbix技术分享——如何配置SNMPTrap监控

NMP是一种网络管理协议,SNMPTrap则是基于此协议的一种数据传输方式。在Zabbix监控实践中,SNMP的应用非常广泛,下面我们来看一下如何进行SNMPTrap配置监控。 当我们获取到设备发送过来的trap的时候,需要是从trap信息中获取到Trap …

Echarts 桑基图的详细配置过程

文章目录 桑基图 简介配置步骤简易示例 桑基图 简介 Echarts桑基图(Sankey Diagram)是一种数据可视化图表类型,用于展示流量、能量、资金等在各个节点之间的流动和转化关系。桑基图通过节点和曲线来表示不同元素之间的关系,从而形…

嵌入式单片机上练手的小型图形库

大家好,今天分享一款小型的图形库。 Tiny Graphics Library: http://www.technoblogy.com/show?23OS 这个小型图形库提供点、线和字符绘图命令,用于 ATtiny85 上的 I2C 128x64 OLED 显示器. 它通过避免显示缓冲器来支持RAM有限的处理器&…

【从入门到起飞】JavaAPI—System,Runtime,Object,Objects类

🎊专栏【JavaSE】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🍔System类⭐exit()⭐currentTimeMillis()🎄用…

Linux驱动IO篇——mmap操作

文章目录 前言应用层驱动层 前言 平时我们写Linux驱动和用户空间交互时,都是通过copy_from_user把用户空间传过来的数据进行拷贝,为什么要这么做呢? 因为用户空间是不能直接内核空间数据的,他们映射的是不同的地址空间&#xff0…

java:数组缩减

// 有一个数组{1,2,3,4,5}可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后那个元素当只剩下最后一个元素提示不能继续缩减 import java.util.Scanner; public class suojian {public static void…