Kaggle竞赛——森林覆盖类型分类

目录

  • 1. 竞赛简要
  • 2. 数据分析
    • 2.1 特征类型统计
    • 2.2 四个荒野区域数据分析
    • 2.3 连续特征分析
    • 2.4 离散特征分析
    • 2.5 特征相关性热图
    • 2.6 特征间的散点关系图
  • 3. 特征工程
    • 3.1 特征组合
    • 3.2 连续特征标准化
  • 4. 模型搭建
    • 4.1 模型定义
    • 4.2 绘制混淆矩阵和ROC曲线
    • 4.3 模型对比与选择
  • 5. 测试集分类
    • 5.1 特征重要性排名
    • 5.2 测试集分类
  • 6. 参考文献

1. 竞赛简要

本次竞赛的数据集包含训练集和测试集,数据集的研究区域包含位于科罗拉多州北部罗斯福国家森林的四个荒野区域,这些区域受人为干扰影响最小,每个观测样本的区域大小为 30m x 30m。其中,训练集大小有15120个样本,测试集有565892个样本。共56个特征,7种类别(用数字1-7表示),第一列为样本Id列,最后一列Cover_Type为标签列,详细数据信息见竞赛地址。代码的最终评分为0.78729,竞赛所需的数据集和代码已经打包上传到Gitee,点击直达。

2. 数据分析

2.1 特征类型统计

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_reportimport warnings
warnings.filterwarnings('ignore')# 数据集研究区域位于科罗拉多州北部罗斯福国家森林的四个荒野区域, 每个观测值是一个 30m x 30m 的区域
train = pd.read_csv("D:/Desktop/kaggle数据集/forest-cover/train.csv")
# 删除ID列
train.drop("Id", axis=1, inplace=True)
#------------------------------------------------------------------------------------------------------------#
# 统计数据类别数量(特征中没有非数值变量)
#    分类特征(唯一值数量小于25,也可以是其他值,视情况而定),例:特征列 [1, 2, 2, 3, 3] 的唯一值(1, 2, 3)
#    连续特征(‘Id’列不计入)
#------------------------------------------------------------------------------------------------------------#
discrete_features = [col for col in train.columns if len(train[col].unique()) < 25]
continuous_features = [feature for feature in train.columns if feature not in discrete_features]
print("Number of discrete features : ",len(discrete_features))
print("Number of continuous features: ", len(continuous_features))print("离散型特征: ",discrete_features)
print("连续型特征:", continuous_features)# 重命名一些较长的特征,否则绘图时容易重叠
continuous_features_labels = ["Elevation", "Aspect", "Slope", "Horz_Dist_To_Hydrology", "Vert_Dist_To_Hydrology", "Horz_Dist_To_Roadways", "Hillshade 9am",  "Hillshade Noon", "Hillshade 3pm", "Horz_Dist_To_Fire_Points"]
Number of discrete features :  45
Number of continuous features:  10
离散型特征:  ['Wilderness_Area1', 'Wilderness_Area2', 'Wilderness_Area3', 'Wilderness_Area4', 'Soil_Type1', 'Soil_Type2', 'Soil_Type3', 'Soil_Type4', 'Soil_Type5', 'Soil_Type6', 'Soil_Type7', 'Soil_Type8', 'Soil_Type9', 'Soil_Type10', 'Soil_Type11', 'Soil_Type12', 'Soil_Type13', 'Soil_Type14', 'Soil_Type15', 'Soil_Type16', 'Soil_Type17', 'Soil_Type18', 'Soil_Type19', 'Soil_Type20', 'Soil_Type21', 'Soil_Type22', 'Soil_Type23', 'Soil_Type24', 'Soil_Type25', 'Soil_Type26', 'Soil_Type27', 'Soil_Type28', 'Soil_Type29', 'Soil_Type30', 'Soil_Type31', 'Soil_Type32', 'Soil_Type33', 'Soil_Type34', 'Soil_Type35', 'Soil_Type36', 'Soil_Type37', 'Soil_Type38', 'Soil_Type39', 'Soil_Type40', 'Cover_Type']
连续型特征: ['Elevation', 'Aspect', 'Slope', 'Horizontal_Distance_To_Hydrology', 'Vertical_Distance_To_Hydrology', 'Horizontal_Distance_To_Roadways', 'Hillshade_9am', 'Hillshade_Noon', 'Hillshade_3pm', 'Horizontal_Distance_To_Fire_Points']

其中,45个离散特征包含40个土壤类型特征、4个荒野区域特征和一个森林覆盖类型特征。

2.2 四个荒野区域数据分析

cover_type_counts = np.array(train.groupby(["Cover_Type"]).size())
cover_type_counts
array([2160, 2160, 2160, 2160, 2160, 2160, 2160], dtype=int64)

可以发现,7种森林覆盖类型的总数都相同。


四个荒野区域:

  1. Rawah Wilderness Area
  2. Neota Wilderness Area
  3. Comanche Peak Wilderness Area
  4. Cache la Poudre Wilderness Area
area_1_counts = np.array(train.groupby(["Cover_Type"]).sum()["Wilderness_Area1"])
area_2_counts = np.asarray(train.groupby(["Cover_Type"]).sum()["Wilderness_Area2"])
area_3_counts = np.asarray(train.groupby(["Cover_Type"]).sum()["Wilderness_Area3"])
area_4_counts = np.asarray(train.groupby(["Cover_Type"]).sum()["Wilderness_Area4"])
print(f"区域1森林覆盖类型统计:{area_1_counts}")
区域1森林覆盖类型统计:[1062 1134    0    0  856    0  545]
print("区域1所有土地类型总计:{}".format(train['Wilderness_Area1'].sum()))
print("区域2所有土地类型总计:{}".format(train['Wilderness_Area2'].sum()))
print("区域3所有土地类型总计:{}".format(train['Wilderness_Area3'].sum()))
print("区域4所有土地类型总计:{}".format(train['Wilderness_Area4'].sum()))
区域1所有森林类型总计:3597
区域2所有森林类型总计:499
区域3所有森林类型总计:6349
区域4所有森林类型总计:4675

绘制每个区域上的土地类型分布情况:

area_counts = np.zeros((4, 7))  
area_counts[0] = np.array(train.groupby(["Cover_Type"]).sum()["Wilderness_Area1"])
area_counts[1] = np.array(train.groupby(["Cover_Type"]).sum()["Wilderness_Area2"])
area_counts[2] = np.array(train.groupby(["Cover_Type"]).sum()["Wilderness_Area3"])
area_counts[3] = np.array(train.groupby(["Cover_Type"]).sum()["Wilderness_Area4"])# 初始化底部位置
bottoms = np.zeros(4) 
for i in range(7):  # width用于控制条形的宽度plt.bar(range(1,5), area_counts[:, i], width=0.5, bottom=bottoms, label=f"Type {i + 1}")# 更新底部位置bottoms += area_counts[:, i] 
# 动态设置 y 轴的范围
plt.ylim([0, np.max(bottoms) + 1000]) 
plt.legend(ncol=2)
plt.xlabel("Wilderness Areas")
plt.ylabel("Total Number")
plt.title("Forest Cover Types in each Wilderness Area")
plt.xticks(range(1,5), ['Area 1', 'Area 2', 'Area 3', 'Area 4']);
plt.tight_layout()

在这里插入图片描述

2.3 连续特征分析

查看不同土地类型相对于每个连续变量的分布

fig, axs = plt.subplots(10, 2, figsize=(14,40))
for i in range(len(continuous_features)):#--------------------------------------------------------------------------------------------------------## kdeplot 用于绘制核密度估计图(可视化连续变量的概率密度分布)# 纵坐标为概率密度:概率密度并不是直接表示概率,而是表示在某个小区间内找到随机变量的可能性,# 通过计算相应区间的积分来获得,而不是直接从概率密度函数中读取#--------------------------------------------------------------------------------------------------------#sns.kdeplot(data=train, x=continuous_features[i], hue='Cover_Type', palette='turbo', fill=True, ax=axs[i][0])sns.boxplot(data=train, x='Cover_Type', y=continuous_features[i],  palette='turbo', fliersize=2, ax=axs[i][1])axs[i][0].set_xlabel(continuous_features_labels[i], fontsize=14)axs[i][1].set_ylabel(continuous_features_labels[i], fontsize=14)axs[i][1].set_xlabel('Cover Type', fontsize=14)axs[i][0].set_ylabel('Density', fontsize=14)
# 调整子图布局,wspace=0.4:表示子图之间的水平间距是子图宽度的40%
plt.subplots_adjust(wspace=0.4, hspace=0.3)

运行结果(图太长,截取局部):
在这里插入图片描述由箱线图可知:海拔(Elevation)特征对土地类型的划分较为明显,例如土地类型7都分布海拔3000m以上,土地类型4都分布再海拔2500m以下。Horizontal_Distance_To_Roadways也在一定程度上分离了覆盖类型,类型4都分布在水平范围2000m以内,而类型1,2,7在4000m内分布较为均匀。


绘制连续特征数值分布:
fig, ax = plt.subplots(nrows=5, ncols=2, figsize=(14, 20))
for i, feature in enumerate(continuous_features):sns.histplot(data=train, x=feature, kde=True, ax=ax[i//2,i%2])

运行结果(图太长,截取局部):
在这里插入图片描述

2.4 离散特征分析

查看不同土地类型的土壤类型分布情况(共 40 种不同土壤类型),根据分布情况分析各覆盖类型中以哪些土壤类型为主。

fig, axs = plt.subplots(4,2, figsize=(14, 18))
soil_data = [soil_1, soil_2, soil_3, soil_4, soil_5, soil_6, soil_7]
for i in range(7):sns.barplot(x=list(range(1,41)), y=soil_data[i], ax=axs[i//2][i%2], palette='coolwarm')
axs[3][1].axis('off')axs[0][0].set_title('Cover Type 1 (Spruce/Fir)')
axs[0][1].set_title('Cover Type 2 (Lodgepole Pine)')
axs[1][0].set_title('Cover Type 3 (Ponderosa Pine)')
axs[1][1].set_title('Cover Type 4 (Cottonwood/Willow)')
axs[2][0].set_title('Cover Type 5 (Aspen)')
axs[2][1].set_title('Cover Type 6 (Douglas Fir)')
axs[3][0].set_title('Cover Type 7 (Krummholz)')for i in range(4):for j in range(2):# 设置横坐标值的字体大小axs[i][j].set_xticklabels(labels=list(range(1,41)), fontsize=7.5)axs[i][j].set_xlabel('Soil Type')axs[i][j].set_ylabel('Total Number')# 旋转刻度标签axs[i][j].tick_params(axis='x', rotation=45)  
plt.subplots_adjust(wspace=0.2, hspace=0.45)

运行结果(图太长,截取局部):
在这里插入图片描述

2.5 特征相关性热图

plt.figure(figsize=(8,7))
corr = train[continuous_features].corr()
sns.heatmap(corr, xticklabels=continuous_features_labels, yticklabels=continuous_features_labels, linewidths=0.5, annot=True);

在这里插入图片描述
由图可知,特征Hillshade 9amHillshade 3pm之间具有极强的相关性, Horizontal_Distance_To_HydrologyVertical_Distance_To_Hydrology之间的相关性也较高。后续的特征工程重点分析这几个特征。此外,Hillshade在不同时间段的预测值、海拔与道路/火点距离之间的相关性也较高。

注:特征之间的强相关性会导致多重共线性,多重共线性会使回归模型的系数估计不可靠,影响其解释性和预测能力。特别是在具有高度相关性的自变量之间,模型很难准确估计每个自变量对因变量的独立贡献。但是由于测试数据比训练数据大得多,根据现有的特征得出的结论可能不完善,因此一些强相关的特征继续保留。

下面将使用散点图详细分析哪些特征适合组合。

2.6 特征间的散点关系图

#--------------------------------------------------------------------------------------------------------------------------------#
# 绘制连续变量之间的分布关系
# jointplot:用于绘制两个变量之间的关系,同时显示这些变量的分布情况(边际图)
# height=5: 设置绘图的高度(单位是英寸)
# s=3: 设置散点的大小
#--------------------------------------------------------------------------------------------------------------------------------#
sns.jointplot(data=train, x="Horizontal_Distance_To_Hydrology", y="Vertical_Distance_To_Hydrology", hue="Cover_Type", palette='turbo', height=5, s=3);

在这里插入图片描述
由图知,Vertical_Distance_To_HydrologyHorizontal_Distance_To_Hydrology之间存在较强的正相关关系。这与相关性系数0.65相符。

  • Horizontal_Distance_To_Hydrology:到最近的地表水体的水平距离
  • Vertical_Distance_To_Hydrology:到最近的地表水体的垂直距离

后续的特征工程可以根据这两个特征计算出距离地表水的实际距离,将两个特征作为直角三角形的两条直角边,计算得出的斜边 C C C即为实际距离,计算公式:
C = V 2 + H 2 C=\sqrt{V^2+H^2} C=V2+H2

sns.jointplot(data=train, x="Horizontal_Distance_To_Roadways", y="Elevation", hue="Cover_Type", palette='turbo', height=5, s=3);
sns.jointplot(data=train, x="Horizontal_Distance_To_Fire_Points", y="Horizontal_Distance_To_Roadways", hue="Cover_Type", palette='turbo', height=5, s=3);

在这里插入图片描述

以上结果表明,特征之间整体相关性不强,但是单独以每种森林覆盖类型来看, 存在一些类型的观测值沿正斜率线分布,可以对特征进行加减(有助于捕捉更多的潜在模式和关系)组合

sns.jointplot(data=train, x="Vertical_Distance_To_Hydrology", y="Elevation", hue="Cover_Type", palette='turbo', height=5, s=3);

在这里插入图片描述
ElevationVertical_Distance_To_Hydrology之间的相关性系数为0.12(几乎没有相关性),但是以每种森林覆盖类型来看, 每种类型对应的两个特征的值沿正斜率线分布(即正相关)。可以将两个特征相加或相减,有助于按土地类型对数据进行分层。此外,相加时具有现实解释意义,即距离实际观测地点最近的地表水的海拔。

3. 特征工程

3.1 特征组合

# 特征组合:通过距离最近地表水的垂直距离和水平距离计算实际直线距离
train['Actual_Distance_To_Hydrology'] = (train['Vertical_Distance_To_Hydrology']**2 + train['Horizontal_Distance_To_Hydrology']**2)**0.5train['Elevation_Plus_Vertical_Hydrology'] = train['Elevation'] + train['Vertical_Distance_To_Hydrology']
train['Elevation_Minus_Vertical_Hydrology'] = train['Elevation'] - train['Vertical_Distance_To_Hydrology']# 特征 Hillshade_9am 和 Hillshade_3pm 之间具有极强的负相关性,Hillshade_3pm和Hillshade_Noon有较(0.61)强正相关性,因此对三个特征进行组合
train['Hillshade'] = train['Hillshade_9am'] + train['Hillshade_3pm'] + train['Hillshade_Noon']train['Elevation_Plus_Horizontal_Roadways'] = train['Elevation'] +train['Horizontal_Distance_To_Roadways']
train['Elevation_Minus_Horizontal_Roadways'] = train['Elevation'] - train['Horizontal_Distance_To_Roadways']train['Fire_Points_Plus_Roadways'] = train['Horizontal_Distance_To_Fire_Points'] + train['Horizontal_Distance_To_Roadways']
train['Fire_Points_Minus_Roadways'] = train['Horizontal_Distance_To_Fire_Points'] - train['Horizontal_Distance_To_Roadways']

划分训练集与验证集:

X = train.drop('Cover_Type', axis=1)
y = train['Cover_Type']
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2)

在新数据集中检索连续特征:

discrete_features = [col for col in X.columns if len(X[col].unique()) < 25]
continuous_features = [feature for feature in X.columns if feature not in discrete_features]
print("Number of discrete features : ",len(discrete_features))
print("Number of continuous features: ", len(continuous_features))
print("离散型特征: ",discrete_features)
print("连续型特征:", continuous_features)
Number of discrete features :  44
Number of continuous features:  18
离散型特征:  ['Wilderness_Area1', 'Wilderness_Area2', 'Wilderness_Area3', 'Wilderness_Area4', 'Soil_Type1', 'Soil_Type2', 'Soil_Type3', 'Soil_Type4', 'Soil_Type5', 'Soil_Type6', 'Soil_Type7', 'Soil_Type8', 'Soil_Type9', 'Soil_Type10', 'Soil_Type11', 'Soil_Type12', 'Soil_Type13', 'Soil_Type14', 'Soil_Type15', 'Soil_Type16', 'Soil_Type17', 'Soil_Type18', 'Soil_Type19', 'Soil_Type20', 'Soil_Type21', 'Soil_Type22', 'Soil_Type23', 'Soil_Type24', 'Soil_Type25', 'Soil_Type26', 'Soil_Type27', 'Soil_Type28', 'Soil_Type29', 'Soil_Type30', 'Soil_Type31', 'Soil_Type32', 'Soil_Type33', 'Soil_Type34', 'Soil_Type35', 'Soil_Type36', 'Soil_Type37', 'Soil_Type38', 'Soil_Type39', 'Soil_Type40']
连续型特征: ['Elevation', 'Aspect', 'Slope', 'Horizontal_Distance_To_Hydrology', 'Vertical_Distance_To_Hydrology', 'Horizontal_Distance_To_Roadways', 'Hillshade_9am', 'Hillshade_Noon', 'Hillshade_3pm', 'Horizontal_Distance_To_Fire_Points', 'Actual_Distance_To_Hydrology', 'Elevation_Plus_Vertical_Hydrology', 'Elevation_Minus_Vertical_Hydrology', 'Hillshade', 'Elevation_Plus_Horizontal_Roadways', 'Elevation_Minus_Horizontal_Roadways', 'Fire_Points_Plus_Roadways', 'Fire_Points_Minus_Roadways']

3.2 连续特征标准化

将特征的均值调整为 0,标准差调整为 1,使得数据符合标准正态分布(均值为 0,方差为 1)。

注:训练集和验证集不能一起标准化,因为这会导致模型在训练时“看到”验证集的信息(数据泄露)。会导致模型在验证集上的表现过于乐观。应先在训练集上拟合标准化器,并使用该标准化器对训练集和验证集进行单独转换(保证训练和验证集使用相同的标准进行缩放)。这样可以确保模型在验证集上的表现能够真实反映其泛化能力。

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# 计算 X_train 中指定的连续变量的均值和标准差,scaler 会存储这些特征的均值和标准差
scaler.fit(X_train[continuous_features])X_train_scaled = X_train.copy()
X_valid_scaled = X_valid.copy()# 标准化处理
X_train_scaled[continuous_features] = scaler.transform(X_train_scaled[continuous_features])
X_valid_scaled[continuous_features] = scaler.transform(X_valid_scaled[continuous_features])

4. 模型搭建

4.1 模型定义

定义超参数优化函数和模型函数:

import optuna
from xgboost import XGBClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.model_selection import cross_val_score"""
定义超参数优化函数
Params:objective:待优化的评估函数
Returns:params:最佳超参数组合
"""
def tune(objective, X_train, y_train):# 创建了一个 Optuna 的 Study 对象,用于管理一次超参数优化的过程# direction='maximize' 表示优化的目标是最大化目标函数的返回值(返回值是负的均方根误差)study = optuna.create_study(direction='maximize')# 使用 study 对象的 optimize 方法来执行优化过程# n_trials=10:指进行优化的试验次数study.optimize(lambda trial: objective(trial, X_train, y_train), n_trials=10)params = study.best_params# 获取经过优化后的最佳得分((目标函数的返回值))best_score = study.best_valueprint(f"Best score: {best_score} \nOptimized parameters: {params}")return params

注:XGBClassifier 要求类标签必须是从 0 开始的连续整数(标签需减1),而 ExtraTreesClassifier 没有要求。

"""
XGBoost分类模型
Params:trial:是由 Optuna 库提供的对象,用于在超参数优化过程中管理参数的提议和跟踪
Returns:score:交叉验证评分
"""
def xgb_objective(trial, X_train, y_train):_n_estimators = trial.suggest_categorical("n_estimators", [50, 100, 200, 400, 500, 800])_max_depth = trial.suggest_int("max_depth", 1, 20)_learning_rate = trial.suggest_float("learning_rate", 0.01, 1)xgboost = XGBClassifier(n_estimators=_n_estimators,max_depth=_max_depth, learning_rate=_learning_rate,)score = cross_val_score(xgboost, X_train, y_train-1, cv=10, scoring="accuracy").mean()return score"""
极端随机树分类模型
Params:trial:是由 Optuna 库提供的对象,用于在超参数优化过程中管理参数的提议和跟踪
Returns:score:交叉验证评分
"""
def etc_objective(trial, X_train, y_train):_n_estimators = trial.suggest_categorical("n_estimators", [50, 100, 200, 400, 500, 800])_max_depth = trial.suggest_int("max_depth", 1, 20)extra = ExtraTreesClassifier(n_estimators=_n_estimators,max_depth=_max_depth, )score = cross_val_score(extra, X_train, y_train, cv=10, scoring="accuracy").mean()return score

执行XGBoost模型的超参数优化过程:

import time
start_time = time.time()
xgb_params = tune(xgb_objective, X_train_scaled, y_train)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Running time: {elapsed_time:.2f} seconds")
Best score: 0.8761569906144686 
Optimized parameters: {'n_estimators': 100, 'max_depth': 8, 'learning_rate': 0.3587540957081757}
Running time: 178.71 seconds

在验证集上测试准确率:

xgboost =  XGBClassifier(**xgb_params, random_state=9)
xgboost.fit(X_train_scaled, y_train-1)
score = xgboost.score(X_valid_scaled, y_valid-1)
print("XGBoost准确率:{}".format(score))
XGBoost准确率:0.8806216931216931

打印分类报告:

# 打印各类别的分类报告
y_pred_xgb = xgboost.predict(X_valid_scaled)
print("XGBoost分类报告:")
print(classification_report(y_valid, y_pred_xgb+1, target_names=[str(i) for i in range(1, 8)], digits=3))
XGBoost分类报告:precision    recall  f1-score   support1      0.779     0.777     0.778       4002      0.807     0.716     0.759       4443      0.904     0.846     0.874       4544      0.944     0.985     0.964       4615      0.901     0.962     0.931       4256      0.864     0.903     0.883       4357      0.947     0.973     0.960       405accuracy                          0.881      3024macro avg      0.878     0.880     0.878      3024
weighted avg      0.879     0.881     0.879      3024

经模型挑选后,为减少代码运行时间,准确率较差的模型和方案已注释,如下:

# 未标准化的数据集,已得出结论,先注释
# start_time = time.time()
# xgb1_params = tune(xgb_objective, X_train, y_train)
# end_time = time.time()
# elapsed_time = end_time - start_time
# print(f"Running time: {elapsed_time:.2f} seconds")
# etc_params = tune(etc_objective, X_train_scaled, y_train)
# etc =  ExtraTreesClassifier(**etc_params, random_state=1)
# etc.fit(X_train_scaled, y_train)
# score = etc.score(X_valid_scaled, y_valid)
# print("ExtraTree准确率:{}".format(score))
# 打印各类别的分类报告
# y_pred_etc = etc.predict(X_valid_scaled)
# print("ExtraTree分类报告:")
# print(classification_report(y_valid, y_pred_etc, target_names=[str(i) for i in range(1, 8)], digits=3))

4.2 绘制混淆矩阵和ROC曲线

绘制XGBoost分类器的混淆矩阵:

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, roc_curve, aucconf_matrix = confusion_matrix(y_valid, y_pred_xgb+1)sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',xticklabels=range(1, 8), yticklabels=range(1,8))
plt.ylabel('True')
plt.xlabel('Predicted')
plt.title('Confusion Matrix');

在这里插入图片描述
横轴为预测类别,纵轴为实际类别。对标线上的值表示模型正确预测的样本数量,非对角线上的值表示模型错误预测的样本数量。对角线(1, 1)中的值311表示实际类别为1的样本中有311条被正确预测为类别1。


绘制XGBoost分类器的ROC曲线:

# 样本被预测为各个类别的概率
y_pred_proba = xgboost.predict_proba(X_valid_scaled)
# 以类别(1-7)为键值存储每个类的fpr和tpr(fpr[i]的大小与阈值数组大小相等)
fpr = {}
tpr = {}
roc_auc = {}# 计算ROC曲线和AUC
for i in range(1, 8): #--------------------------------------------------------------------------------------------------------------## roc_curve用于计算 FPR 和 TPR,参数:实际标签(布尔数组)和预测概率。返回值:# fpr[i]:类别 i 的假阳性率# tpr[i]:类别 i 的真阳性率#_:阈值数组# i-1:列索引从0开始#--------------------------------------------------------------------------------------------------------------#fpr[i], tpr[i], k = roc_curve(y_valid == i, y_pred_proba[:, i-1])  roc_auc[i] = auc(fpr[i], tpr[i])# 绘制所有类别的ROC曲线
for i in range(1, 8):  # 类别从1到7plt.plot(fpr[i], tpr[i], label='Type {} (AUC = {:.3})'.format(i, roc_auc[i]))plt.plot([0, 1], [0, 1], 'k--')  # 对角线
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend(loc='lower right');

在这里插入图片描述

4.3 模型对比与选择

model_score = pd.DataFrame({'Classifier':['XGBoost', 'ExtraTrees'],'Validation Set Accuracy':[0.880, 0.874],'Validation Set Precision':[0.879,0.873],'Validation Set Recall':[0.881,0.874],'Validation Set F1 score':[0.879, 0.872]
})
model_score


比较发现,XGBoost的模型分类效果更佳。确定XGBoost模型后,对比是否需要数据标准化处理。

model_score = pd.DataFrame({'Classifier':['XGBoost', 'XGBoost'],'数据标准化':['标准化','未标准化'],'Best score':[0.876,0.878],'Running time(s)':[178, 260]
})
model_score

在这里插入图片描述
对比可知,在最佳评分相差不大的情况下,标准化后的数据集能极大提高代码的运行时间,因此确定最佳分类方案为XGBoost+数据标准化

5. 测试集分类

使用xgboost模型在全部原始训练集上进行训练。由于测试数据比训练数据大得多,且初始的训练集和验证集只划分过一次,泛化性不强,需在原始训练集上进行完整训练,以保证其泛化性。首先对测试集进行标准化处理:

scaler = StandardScaler()
scaler.fit(X[continuous_features])X_scaled = X.copy()
X_scaled[continuous_features] = scaler.transform(X_scaled[continuous_features])best_model = XGBClassifier(**xgb_params)
best_model.fit(X_scaled, y-1)

5.1 特征重要性排名

feature_importance = pd.DataFrame({'Feature': X.columns,'Importance': best_model.feature_importances_
})# 按照重要性排序
feature_importance = feature_importance.sort_values(by='Importance', ascending=False)
top_features = feature_importance.head(20)# 绘制条形图
plt.figure(figsize=(10, 5))
barplot = sns.barplot(x='Importance', y='Feature', data=top_features, palette='viridis')
plt.title('Top 20 Feature Importance')
plt.xlabel('Importance Score')
plt.ylabel('Features')# 标注数值
for index, row in enumerate(top_features.itertuples()):barplot.text(row.Importance, index, f"  {row.Importance:.3f}", color='black', ha="left", va="center")

在这里插入图片描述
由图可知,构造的特征Elevation_Minus_vertical_Hydrology对样本分类的重要性较高。这表明,特征工程构造的特征能较大程度上影响模型的分类决策。

5.2 测试集分类

使用同样的特征工程方法对测试集特征进行处理:

test = pd.read_csv('D:/Desktop/kaggle数据集/forest-cover/test.csv')
Id = test['Id']
test.drop(["Id"], axis=1, inplace=True)test['Actual_Distance_To_Hydrology'] = (test['Vertical_Distance_To_Hydrology']**2 + test['Horizontal_Distance_To_Hydrology']**2)**0.5test['Elevation_Plus_Vertical_Hydrology'] = test['Elevation'] + test['Vertical_Distance_To_Hydrology']
test['Elevation_Minus_Vertical_Hydrology'] = test['Elevation'] - test['Vertical_Distance_To_Hydrology']# 特征 Hillshade_9am 和 Hillshade_3pm 之间具有极强的负相关性,Hillshade_3pm和Hillshade_Noon有较(0.61)强正相关性,因此对三个特征进行组合
test['Hillshade'] = test['Hillshade_9am'] + test['Hillshade_3pm'] + test['Hillshade_Noon']test['Elevation_Plus_Horizontal_Roadways'] = test['Elevation'] +test['Horizontal_Distance_To_Roadways']
test['Elevation_Minus_Horizontal_Roadways'] = test['Elevation'] - test['Horizontal_Distance_To_Roadways']test['Fire_Points_Plus_Roadways'] = test['Horizontal_Distance_To_Fire_Points'] + test['Horizontal_Distance_To_Roadways']
test['Fire_Points_Minus_Roadways'] = test['Horizontal_Distance_To_Fire_Points'] - test['Horizontal_Distance_To_Roadways']

生成提交文件:

test_scaled = test.copy()
test_scaled[continuous_features] = scaler.transform(test_scaled[continuous_features])
pred = best_model.predict(test_scaled)
submission = pd.DataFrame({'Id': Id,'Cover_Type': pred+1})
# submission.to_csv('/kaggle/working/submission.csv', index=False)
print('Submission file created!')

6. 参考文献

[1] Forest Cover Type: 0.81031 (Top 6%) w/ ExtraTrees
[2] Multivariate Classification w/ExtraTreesClassifier

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python爬虫案例——selenium爬取淘宝商品信息,实现翻页抓取(14)

文章目录 1、任务目标2、网页分析3、代码编写3.1 代码分析3.2 完整代码1、任务目标 目标网站:淘宝(https://www.taobao.com/) 任务要求:通过selenium实现自动化抓取 淘宝美食 板块下的所有商品信息,并实现翻页抓取,最后以csv格式将数据保存至本地;如: 2、网页分析 首先…

Qt-系统文件相关介绍使用(61)

目录 描述 输⼊输出设备类 打开/读/写/关闭 使用 先初始化&#xff0c;创建出大致的样貌 输入框设置 绑定槽函数 保存文件 打开文件 提取文件属性 描述 在C/C Linux 中我们都接触过关于文件的操作&#xff0c;当然 Qt 也会有对应的文件操作的 ⽂件操作是应⽤程序必不…

wpf grid 的用法

WPF中的Grid是一种布局控件&#xff0c;可用于将子控件按照行和列的方式排列。 以下是Grid控件的用法&#xff1a; 在XAML文件中&#xff0c;添加一个Grid控件&#xff1a; <Grid> </Grid>在Grid控件中&#xff0c;添加行和列定义&#xff1a; <Grid><…

Spring Cloud-Nacos版 学习理解

注册中心 Nacos 下载安装包 bin目录输入 cmd 进入命令行&#xff0c;输入startup.cmd -m standalone 启动 浏览器输入 http://127.0.0.1:8848/nacos/index.html&#xff0c;进入启动页面 账号密码均默认nacos 服务提供者 NacosProvider、服务调用者 NacosConsumer 服务提…

第五届计算机、大数据与人工智能国际会议(ICCBD+AI 2024)

第五届计算机、大数据与人工智能国际会议&#xff08;ICCBDAI 2024&#xff09;将于2024年11月1日-3日在江西景德镇召开。本届会议由景德镇陶瓷大学主办&#xff0c;西安交通大学、暨南大学、南京邮电大学、长沙学院、景德镇学院、ELSP&#xff08;爱迩思出版社&#xff09;、E…

Python Django 数据库优化与性能调优

Python Django 数据库优化与性能调优 Django 是一个非常流行的 Python Web 框架&#xff0c;它的 ORM&#xff08;对象关系映射&#xff09;允许开发者以简单且直观的方式操作数据库。然而&#xff0c;随着数据量的增长&#xff0c;数据库操作的效率可能会成为瓶颈&#xff0c…

使用 PyTorch 构建 LSTM 股票价格预测模型

目录 引言准备工作1. 训练模型&#xff08;train.py&#xff09;2. 模型定义&#xff08;model.py&#xff09;3. 测试模型和可视化&#xff08;test.py&#xff09;使用说明模型调整结论 引言 在金融领域&#xff0c;股票价格预测是一个重要且具有挑战性的任务。随着深度学习…

Linux文件操作基础

目录 Linux文件操作基础 引入 回顾C语言文件操作 系统调用接口 open函数 read函数和write函数 close函数 模拟C语言接口 文件描述符 如何理解Linux下一切皆文件 文本读写与二进制读写 Linux文件操作基础 引入 在Linux第一章提到过&#xff0c;在Linux中&#xff0…

快速创建一个vue项目并运行

前期准备工作: 1.安装node 2.安装npm 3.设置淘宝镜像 4.全局安装webpack 5.webpack 4.X 开始&#xff0c;需要安装 webpack-cli 依赖 6.全局安装vue-cli 正文开始: 1.创建项目 ,回车 vue init webpack vue-svg > Project name vue-demo 项目名称 回车 > Pro…

电脑桌面自己变成了英文Desktop,怎么改回中文

目录 前言找到Desktop查看位置查找目标修改文件名为桌面重启电脑 或 重启 Windows 资源管理器CtrlShiftEsc 打开任务管理器找到 Windows 资源管理器重启 Windows 资源管理器 查看修改结果 前言 许多人在使用电脑的时候发现&#xff0c;我们经常使用的桌面&#xff0c;不知道因为…

安卓流式布局实现记录

效果图&#xff1a; 1、导入第三方控件 implementation com.google.android:flexbox:1.1.0 2、布局中使用 <com.google.android.flexbox.FlexboxLayoutandroid:id"id/baggageFl"android:layout_width"match_parent"android:layout_height"wrap_co…

震惊!原来贡献开源代码这么简单,分分钟上手!

文章目录 前言一、什么是 Fork 和 PR&#xff1f;1. Fork&#xff08;分叉&#xff09;2. PR&#xff08;Pull Request&#xff0c;拉取请求&#xff09; 二、两种常见的贡献代码方式1. Fork 后通过 PR 提交代码2. 直接在项目分支中修改 三、如何 Fork 和发起 Pull Request&…

高效车辆管理:SpringBoot实现指南

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理车辆管理系统的相关信息成为必然。开发合适…

蜗牛兼职网的设计与实现(论文+源码)_kaic

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c…

Unity开发Hololens项目

Unity打包Hololens设备 目录Visual Studio2019 / Visual Studio2022 远端部署设置Visual Studio2019 / Visual Studio2022 USB部署设置Hololens设备如何查找自身IPHololens设备门户Unity工程内的打包设置 目录 记录下自己做MR相关&#xff1a;Unity和HoloLens设备的历程。 Vi…

智能家居的“眼睛”:计算机视觉如何让家更智能

引言 在不远的未来&#xff0c;当我们走进家门&#xff0c;灯光自动亮起&#xff0c;空调已经调至最舒适的温度&#xff0c;甚至音乐也播放着我们最喜欢的歌曲。 这一切&#xff0c;都得益于智能家居系统的发展。而在这个系统中&#xff0c;计算机视觉技术扮演着至关重要的角色…

opencv 图像BGR三通道分离 split 与 合并 merge -python 实现

图像BGR三通道分离 split 与 合并 merge 会在图像预处理和图像增强中使用。 具体代码如下&#xff1a; #-*-coding:utf-8-*- # date:2021-03-21 # Author: DataBall - XIAN 1、将彩色图片 BGR 三通道分离&#xff08;注意观察 B、G、R 单通道图像素的明暗&#xff09;2、将3个…

Java知识巩固(六)

什么是可变长参数&#xff1f; 从 Java5 开始&#xff0c;Java 支持定义可变长参数&#xff0c;所谓可变长参数就是允许在调用方法时传入不定长度的参数。就比如下面这个方法就可以接受 0 个或者多个参数。 public static void method1(String... args) {//...... } 另外&am…

python 作业1

任务1: python为主的工作是很少的 学习的python的优势在于制作工具&#xff0c;制作合适的工具可以提高我们在工作中的工作效率的工具 提高我们的竞争优势。 任务2: 不换行 换行 任务3: 安装pycharm 进入相应网站Download PyCharm: The Python IDE for data science and we…

分享一套SpringBoot+Vue民宿(预约)系统

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue民宿(预约)系统&#xff0c;分享下嘿嘿。 项目介绍 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c…