CatBoost道路风险预测学习笔记

下面所学知识经验均来自对kaggle竞赛Predicting Road Accident Riskz中的公开Notebook代码的模仿过程


数据观察(主要用pandas库)

读取数据
  • 读取文件——pd.read_csv(“path”)pd.read_csv
数据分析

注意kaggle比赛中,数据已经备好了,从赛者可专注于模型的建立和学习
一下较为常用的用粗体表示

  • df.columns 查看列 df.columns
  • 数据DataFrame的信息——df.info()df.info()输出列名、以及对于列名的数据大小、空值情况、以及对应的数据类型
  • df.shape查看数据的形状 df.shape
  • 数据DataFrame的前五行——df.head()df.head()在nb中会自动展示,或者要对比可以print,or display

EDA

探索性数据分析(Exploratory Data Analysis,简称EDA)是数据科学中的关键步骤,旨在熟悉数据集、揭示变量间的关系并指导后续处理。通过读取数据、数据汇总、总览、缺失值和异常值分析,以及特征分析,我们可以深入了解数据的结构和质量。

目标分布
  • plt.figure()的作用创建画布
  • sns.histplot()的参数和功能是什么?bin箱子的数目,kde是否加一条拟合分布的曲线

参考两个教程民间教程官方教程

关联热力图
  • 筛选出数值列df.select_dtypes(include=["int64","float64"])

  • df.corr()用来计算各列之间的相关系数的(可以自定义方法用method参数来指定)。这用来做作为 sns.heatmap()的输入参数极为方便

参考民间教程

  • sns.heatmap()

参考两个教程民间教程官方教程


CatBoost Model

介绍(擅长处理类别特征)

CatBoost的全称是Categorical Boosting,它是一种由俄罗斯搜索巨头Yandex开发的梯度提升算法库,特别擅长处理类别型特征。

CatBoost的名称来源于其核心功能,即处理类别型特征(Categorical Features)和梯度提升(Gradient Boosting)。与其他梯度提升算法如XGBoost和LightGBM相比,CatBoost在处理类别型特征方面具有显著优势。

CatBoost的特点

  1. 类别型特征处理:CatBoost使用独特的编码方法来处理类别型特征,降低过拟合风险。(无需对这些特征(分类特征)进行One-Hot编码
  2. 克服梯度偏差:CatBoost采用排序提升的概念,防止目标泄漏和过度拟合。
  3. 高效实现:支持GPU加速和多GPU训练,提升计算效率。
  4. 鲁棒性:减少对大量超参数调整的需求,降低过度拟合的机会。
    CatBoost的应用

CatBoost在多个领域中表现出色,包括金融风控、推荐系统和生物医学等。例如,在信用卡欺诈检测、商品推荐和基因表达数据分析中,CatBoost能够有效处理类别型特征和缺失值,构建精准的预测模型。

总之,CatBoost作为一种专为类别型特征优化的梯度提升算法,凭借其独特的处理策略和高效的实现,迅速成为业界广受欢迎的GBDT框架。

详细介绍解释参考数据STUDIO, 2022CatBoost深度解析官方 CatBoost

分类特征(前面对数值类型的特征进行了关联性的分析)

dtype一般是bool或者object

  • 作者做了一个操作,将bool转化为str,也变成了object对象。关于选择bool值时,df.select_dtypes(include=)进行优化

  • 关于具体转化格式的函数方法,作者使用的是df.astype()

可参考转化类型

关于from sklearn.model_selection import train_test_split, cross_val_score

  • train_test_split这个函数十分常用在从训练集分割出验证集时。

参考民间教程官方教程

模型构建

使用的是catboost库中的,CatBoostRegressor模型,记得安装

1
2
3
conda activate your_env

conda install catboost
模型参数选择
  1. iterations 迭代次数(定义了训练过程中提升树的数量)
  2. learning_rate 学习率(控制每一步梯度提升时模型权重更新的幅度,而迭代)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
params = {     
'iterations': 1000, # 迭代次数
'learning_rate': 0.1, # 学习率
'depth': 6, # 树的深度
'cat_features': cat_features, # 分类特征
'random_seed': 42, # 随机种子
'loss_function': 'RMSE', # 损失函数
'verbose': 100, # 每100次迭代打印一次信息
'early_stopping_rounds': 50, # 早停轮数
"task_type": "GPU", # 启用 GPU
"devices": "0" # 指定 GPU 设备
}

Catboost_model = CatBoostRegressor(**params) Catboost_model.fit(X, y, eval_set=(X_val, y_val)) # eval_set 用于监控模型在验证集上的性能 没有则不会显示性能表现
  1. 损失函数(二元分类Logloss;回归RMSE(均方根误差) or MAE(平均绝对误差;多分类采用Multiclass损失;不平衡数据集(QueryCrossentropy)
  2. GPU加速,加快训练速度
  • model.fit() 模型训练,输入X,以及对应的y标签即可。
模型评估
1
2
3
4
5
6
7
8
# Make predictions on validation set
y_pred = Catboost_model.predict(X_val) # Calculate RMSE
val_rmse = mean_squared_error(y_val, y_pred) print(f"Validation RMSE: {val_rmse:.4f}")

# Cross-validation
cv_scores = cross_val_score(Catboost_model, X, y, cv=5, scoring='neg_mean_squared_error')
cv_rmse = np.sqrt(-cv_scores)
print(f"Cross-validation RMSE: {cv_rmse.mean():.4f} (+/- {cv_rmse.std() * 2:.4f})")

这段代码实现了交叉验证(Cross-validation)过程,用于评估CatBoost模型的性能。具体解释如下:

  1. 第一行代码cv_scores = cross_val_score(Catboost_model, X, y, cv=5, scoring='neg_mean_squared_error')
  • 使用cross_val_score函数执行5折交叉验证
  • 参数Catboost_model是已经定义好的CatBoost模型
  • X是特征数据,y是目标变量
  • cv=5表示将数据集分成5个部分进行交叉验证
  • scoring='neg_mean_squared_error'表示使用负均方误差作为评分指标(负值是因为scikit-learn中大多数评分函数追求最大化)
  1. 第二行代码cv_rmse = np.sqrt(-cv_scores)
  • 将负均方误差转换为均方根误差(RMSE)
  • 首先取负值(因为原始得分是负数),然后开平方
  • 得到的cv_rmse是一个包含5个元素的数组,每个元素对应一折验证的RMSE(均方根误差)
  1. 第三行代码print(f"Cross-validation RMSE: {cv_rmse.mean():.4f} (+/- {cv_rmse.std() * 2:.4f})")
  • 输出交叉验证的平均RMSE和标准差
  • .mean()计算5折RMSE的平均值
  • .std() * 2计算2倍标准差,表示模型性能的置信区间范围
  • :.4f表示保留4位小数 这段代码的主要目的是通过交叉验证来评估模型的泛化能力,避免过拟合问题,并提供模型性能的可靠估计。
  • mean_squared_error() 计算两列的均方根误差
  • cross_val_score()

参考教程民间教程官方文档中文官方

重要性分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Feature Importance

feature_importance = Catboost_model.get_feature_importance()  # index类型

#print(feature_importance)

feature_names = X.columns # ndarray类型

#print(feature_names)

importance_df = pd.DataFrame({

    'feature': feature_names,

    'importance': feature_importance

}).sort_values('importance', ascending=False) # 按重要性降序排序



print("\nTop 10 Most Important Features:")

print(importance_df.head(10))

这里直接用catboost_model.get_feature_importance()方法。

  • sort_values() 函数,他是一个排序函数

参考民间教程

1
2
3
4
5
6
7
8
9
10
11
# Detailed feature importance plot

plt.figure()

sns.barplot(data=importance_df.head(10), x='importance', y='feature', palette='viridis')

plt.title('Top 10 Most Important Features')

plt.xlabel('Importance Score')

plt.show()

sns.barplot()函数功能,支持df的输入,指定对于xy的列名即可

可视化结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Plot actual vs predicted values

plt.scatter(y_val, y_pred, alpha=0.1, marker='.', s=5)
# 画出对应的散点图,x为实际,y为预测。所有的散点越靠近完美对角线,就意味着预测效果越好
plt.plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'r--', lw=2)
# 第一个参数代表x范围,第二个参数是y的范围,此时默认x=y 画出完美预测线,对角线。

plt.xlabel('Actual Values')

plt.ylabel('Predicted Values')

plt.title('Actual vs Predicted Values')

plt.show()

提交结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Prepare test data (excluding the id column for prediction)

test_features = test_ds.drop('id', axis=1)

# Make predictions on test set
test_predictions = Catboost_model.predict(test_features)

# Create submission file

submission = pd.DataFrame({
    'id': test_ds['id'],
    'accident_risk': test_predictions
})


# Save submission file
submission.to_csv('submission.csv', index=False)
print(f"Submission shape: {submission.shape}")
print("\nFirst 5 rows of submission:")
display(submission.head())