机器学习xgboost模型,特性重要性输出的依据是什么?
发布于 作者:苏南大叔 来源:程序如此灵动~本文讨探xgboost
的稍稍基础一些的内容:“特征重要性”。对应到数据集里面,就是特征特性features
。对于任何一个模型的预测结果来说,它都是对这些特征进行各种分析得出的结论。这些特征都有一个重要性的说法。谁对结论的影响更大呢?是不是存在着一些影响不重要的特征?
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验文章。测试环境:python@3.12.3
,pandas@2.2.2
,numpy@1.26.4
,xlrd@2.0.1
,openpyxl@3.1.2
,scikit-learn@1.5.0
,xgboost@2.0.3
。
xgboost基模型
基础模型是基于树还是基于线性的,影响了特征重要性的输出依据。而xgboost
的构造函数中,booster
参数表示迭代的模型。它包括:
gbtree
,基于树的模型。gblinear
,基于线性模型。
模型名 | 基于 | 参数booster | .coef_ | .feature_importances_ | plot_importance() |
---|---|---|---|---|---|
gbtree | 树模型 | 默认值 | 不存在 | 存在(越大越重要) | 存在(越大越重要) |
gblinear | 线性模型 | 非默认值 | 存在(越小越重要) | 存在(越大越重要) | 存在(越大越重要) |
使用上面的几种方法都可以得出特征重要性的排序结果。但是,可以看到,排序的结果并不一致。其中,
- 默认的
.feature_importances_
属性和plot_importance(importance_type='gain')
的结果是一致的。 .feature_importances_
属性和.coef_
属性,特性情况下,是可以同时存在的。但是,两者结论相反。
本文的结论就是上面这个表格,后续的文章内容就是对它进行的阐述和解释。
龙套代码
这里的龙套代码还是基于斯坦福大学的泰坦尼克数据集,使用xgboost
模型进行预测。参考文章:
import pandas as pd
df = pd.read_csv("titanic.csv")
df = df.drop('Name', axis=1)
df = pd.get_dummies(df, columns=['Pclass', 'Sex'], drop_first=True)
target = df['Survived']
features = df.drop('Survived', axis=1)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_true = train_test_split(features, target, test_size=0.25, random_state=42)
import xgboost as xgb
model = xgb.XGBClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
注意里面的构造函数xgb.XGBClassifier()
,它隐藏了一个参数booster='gbtree'
。
model = xgb.XGBClassifier()
特征重要性相关属性
xgboost
使用的booster
参数,它拥有两个属性取值,分别是:gbtree
和gblinear
。在这两种情况下,重要性相关属性有着不同的表现:
默认值是gbtree
,它仅仅拥有其中一个属性.feature_importances_
:
model = xgb.XGBClassifier(booster='gbtree')
# ...
print(model.feature_importances_)
print(model.coef_) # Coefficients are not defined for Booster type gbtree
xgboost
使用的booster
改成gblinear
,它拥有两个属性.feature_importances_
和.coef_
:
model = xgb.XGBClassifier(booster='gblinear')
# ...
print(model.feature_importances_)
print(model.coef_) # 依然存在
参考文章:
特征重要性相关属性加工
无论是.feature_importances_
还是.coef_
,返回值仅是个list
数组,并没有直观的表明对应的是哪一个字段。
对于属性.coef_
来说,多数为负数。其数值越小越相关。和feature_importances_
的结论完全相反。
所以需要点特殊的代码加工:
importance_ = pd.Series(model.feature_importances_, index=features.columns).sort_values()
# importance_ = importance_.sort_values(ascending=False)
print(importance_)
# model = xgb.XGBClassifier(booster='gblinear')
coef_ = pd.Series(model.coef_, index=features.columns).sort_values()
# coef_ = coef_.sort_values(ascending=False)
print(coef_)
输出:
Fare -0.000842
Age 0.005639
Parents/Children Aboard 0.019782
Siblings/Spouses Aboard 0.064652
Pclass_2 0.123056
Pclass_3 0.320397
Sex_male 0.467315
dtype: float32
Sex_male -2.795780
Pclass_3 -1.916820
Pclass_2 -0.736201
Siblings/Spouses Aboard -0.386790
Parents/Children Aboard -0.118348
Age -0.033738
Fare 0.005039
dtype: float64
特征重要性相关属性画图
从画图结果上,可以继续验证相关结论。
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"] # 显示中文
plt.rc('axes', unicode_minus=False)
importance_.plot.barh(figsize=(6, 3.5), fontsize=12)
# coef_.plot.barh(figsize=(6, 3.5), fontsize=12, rot=-45)
plt.tight_layout()
plt.show()
重点就是一句话:
# model = xgb.XGBClassifier(booster='gbtree')
# ...
importance_.plot.barh()
# model = xgb.XGBClassifier(booster='gbtree')
# ...
coef_.plot.barh()
plot_importance()
对于xgbooster
来说,还可以直接画图。使用的核心代码是:
from xgboost import plot_importance
plot_importance(model,ax=ax,importance_type='gain')
这个函数的原型里面,参数很多。在本文中,就讨论它的importance_type
这个参数,它表述的是重要性计算的规则。
测试代码
这个plot_importance()
的画图结果是对标.feature_importances_
的。然而,两者的默认结果有较大区别。其主要影响因素是importance_type
参数。
# model = xgb.XGBClassifier(booster='gbtree')
# ...
from xgboost import plot_importance
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"] # 显示中文
plt.rc('axes', unicode_minus=False)
fig,ax = plt.subplots(figsize=(6.5,3.6)) # 纸张大小
plot_importance(model,ax=ax,importance_type='gain') # 必须写ax,否则画图奇怪输出
plt.show()
规则之'weight'【默认】
weight
指的是特征在提升树里出现的次数。也就是在所有树中,某个特征作为分裂节点的次数。这个就是plot_importance()
的默认值,得出的结论和importance_type
差别较大。
plot_importance(model,ax=ax)
规则之'gain'【重点】
gain
指的是在所有树中,某个特征在分裂后带来的平均信息增益。importance_type
改成这个gain
参数后,plot_importance()
的画图结果,就能对标.feature_importances_
属性了。
plot_importance(model,ax=ax,importance_type='gain')
规则之'cover'
cover
指的是与特征相关的记录(observation)的相对数量,待议。
"cover" is the average coverage of splits which use the feature where coverage is defined as the number of samples affected by the split.
plot_importance(model,ax=ax,importance_type='cover')
参考文章
结束语
更多机器学习的文章总结,可以参考苏南大叔的文章。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。