参数设置
分类问题中经常会存在样本不平衡的现象,XGB
中存在着调节样本不平衡的参数
scale_pos_weight
,
通常我们在参数中输入的是负样本量与正样本量之比
分类案例
创建不平衡数据集
import numpy as np
import xgboost as xgb
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split as TTS
from sklearn.metrics import accuracy_score as accuracy, recall_score as recall, roc_auc_score as auc
class_1 = 500 # 类别1有500个样本
class_2 = 50 # 类别2只有50个
centers = [[0.0, 0.0], [2.0, 2.0]] # 设定两个类别的中心
clusters_std = [1.5, 0.5] # 设定两个类别的方差,通常来说,样本量比较大的类别会更加松散
X, y = make_blobs(n_samples=[class_1, class_2],
centers=centers,
cluster_std=clusters_std,
random_state=0, shuffle=False)
Xtrain, Xtest, Ytrain, Ytest = TTS(X,y,test_size=0.3,random_state=420)
(y == 1).sum() / y.shape[0]
XGBoost建模
dtrain = xgb.DMatrix(Xtrain,Ytrain)
dtest = xgb.DMatrix(Xtest,Ytest)
param= {'silent':True,'objective':'binary:logistic',"eta":0.1,"scale_pos_weight":1}
num_round = 100
bst = xgb.train(param, dtrain, num_round)
preds = bst.predict(dtest)
上面的preds返回的是样本的分类概率,可以通过下面设置阈值的方式生成样本被预测的类别。
#自己设定阈值
ypred = preds.copy()
ypred[preds > 0.5] = 1
ypred[ypred != 1] = 0
调参评估
# 参数设置
scale_pos_weight = [1,5,10]
names = ["negative vs positive: 1",
"negative vs positive: 5",
"negative vs positive: 10"]
for name,i in zip(names,scale_pos_weight):
param={'silent':True,'objective':'binary:logistic',"eta":0.1,"scale_pos_weight":i,'verbosity':0}
clf = xgb.train(param, dtrain, num_round)
preds = clf.predict(dtest)
ypred = preds.copy()
ypred[preds > 0.5] = 1
ypred[ypred != 1] = 0
print(name)
print("\tAccuracy:{}".format(accuracy(Ytest,ypred)))
print("\tRecall:{}".format(recall(Ytest,ypred)))
print("\tAUC:{}".format(auc(Ytest,preds)))
print("\t")
# 也可以使用不同的阈值
for name,i in zip(names,scale_pos_weight):
for thres in [0.3,0.5,0.7,0.9]:
param= {'silent':True,'objective':'binary:logistic',"eta":0.1,"scale_pos_weight":i,'verbosity':0}
clf = xgb.train(param, dtrain, num_round)
preds = clf.predict(dtest)
ypred = preds.copy()
ypred[preds > thres] = 1
ypred[ypred != 1] = 0
print("{},thresholds:{}".format(name,thres))
print("\tAccuracy:{}".format(accuracy(Ytest,ypred)))
print("\tRecall:{}".format(recall(Ytest,ypred)))
print("\tAUC:{}".format(auc(Ytest,preds)))
print("\t")
结果分析和建议
- 原始数据集中负样本量与正样本量之比是10:1,在依次对比模型参数scale_pos_weight的值为1,5,10后发现,模型在测试集上的准确率、AUC面积和召回率都有所提高,说明该参数的确使XGBoost模型对不平衡数据具有很好的处理能力。
- 本质上来说,scale_pos_weight参数是通过调节预测的概率值来调节,大家可以通过查看bst.predict(Xtest)返回的结果来观察概率受到了怎样的影响。因此,当我们只关心预测出的结果是否准确,AUC面积或者召回率是否足够好,我们就可以使用scale_pos_weight参数来帮助我们。
- 然而xgboost除了可以做分类和回归,还有其他的多种功能,在一些需要使用精确概率的领域(比如排序ranking),我们希望能够保持概率原有的模样,而提升模型的效果。这种时候,我们就无法使用scale_pos_weight来帮助我们。
- 如果我们只在意模型的整表现,则使用AUC作为模型评估指标,使用scale_pos_weight来处理样本不平衡问题,如果我们在意预测出正确的概率,那我们就无法通过调节scale_pos_weight来减轻样本不平衡问题带来的影响,这种时候,我们需要考虑另一个参数:max_delta_step。这个参数被称之为是“树的权重估计中允许的单次最大增量”,既可以考虑成是影响估计的参数。如果我们在处理样本不均衡问题,并且十分在意得到正确的预测概率,则可以设置max_delta_step参数为一个有限的数(比如1)来帮助收敛。max_delta_step参数通常不进行使用,二分类下的样本不均衡问题时是这个参数唯一的用途。