分类案例:XGB中的样本不均衡问题

参数设置

分类问题中经常会存在样本不平衡的现象,XGB 中存在着调节样本不平衡的参数 scale_pos_weight 通常我们在参数中输入的是负样本量与正样本量之比 \frac{sum\left( negative\,\,instances \right)}{sum\left( positive\,\,instances \right)}

分类案例

创建不平衡数据集
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")


结果分析和建议

  1. 原始数据集中负样本量与正样本量之比是10:1,在依次对比模型参数scale_pos_weight的值为1,5,10后发现,模型在测试集上的准确率、AUC面积和召回率都有所提高,说明该参数的确使XGBoost模型对不平衡数据具有很好的处理能力。
  2. 本质上来说,scale_pos_weight参数是通过调节预测的概率值来调节,大家可以通过查看bst.predict(Xtest)返回的结果来观察概率受到了怎样的影响。因此,当我们只关心预测出的结果是否准确,AUC面积或者召回率是否足够好,我们就可以使用scale_pos_weight参数来帮助我们。
  3. 然而xgboost除了可以做分类和回归,还有其他的多种功能,在一些需要使用精确概率的领域(比如排序ranking),我们希望能够保持概率原有的模样,而提升模型的效果。这种时候,我们就无法使用scale_pos_weight来帮助我们。
  4. 如果我们只在意模型的整表现,则使用AUC作为模型评估指标,使用scale_pos_weight来处理样本不平衡问题,如果我们在意预测出正确的概率,那我们就无法通过调节scale_pos_weight来减轻样本不平衡问题带来的影响,这种时候,我们需要考虑另一个参数:max_delta_step。这个参数被称之为是“树的权重估计中允许的单次最大增量”,既可以考虑成是影响估计的参数。如果我们在处理样本不均衡问题,并且十分在意得到正确的预测概率,则可以设置max_delta_step参数为一个有限的数(比如1)来帮助收敛。max_delta_step参数通常不进行使用,二分类下的样本不均衡问题时是这个参数唯一的用途。   

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉淀体育生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值