You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用概率而非类别标签训练XGBoost分类器?

如何在XGBoost中使用mixup数据增强的浮点型概率标签训练多分类模型?

我尝试用训练数据集和浮点型概率标签(比如[0,0.6,0.4,0]这种mixup增强生成的软标签)训练XGBoost多分类器,但调用model.fit()时出错——XGBoost的scikit-learn接口默认期望接收类别索引或整数独热标签,而非浮点概率分布。

附测试代码:

import xgboost as xgb
import numpy as np

# 生成随机训练数据
X = np.random.rand(100, 16)

# 生成随机独热标签并转为浮点概率(模拟mixup生成的软标签)
y_one_hot = np.random.randint(0, 4, size=(100,))
y = np.eye(4)[y_one_hot]
y_proba = y / np.sum(y, axis=1, keepdims=True)  # 简化原代码的循环逻辑

# 定义XGBoost分类器
model = xgb.XGBClassifier(objective='multi:softprob', num_class=4)

# 训练时报错:标签格式不符合要求
model.fit(X, y_proba)

# 测试部分(原代码)
X_test = np.random.rand(10, 16)
y_pred_proba = model.predict_proba(X_test)
y_pred = np.argmax(y_pred_proba, axis=1)

解决方案:使用XGBoost原生API+自定义软标签损失函数

XGBoost的scikit-learn接口对标签格式限制严格,而原生API支持自定义目标函数,完美适配mixup的软标签场景。具体步骤如下:

1. 自定义多分类软标签的交叉熵损失与梯度计算

对于软标签(每个样本是类别的概率分布),需要实现基于交叉熵的损失函数,同时计算XGBoost所需的一阶梯度(损失对预测值的导数)和二阶导(梯度的导数)。

2. 使用DMatrix封装数据

DMatrix是XGBoost的原生数据结构,支持直接传入浮点型标签矩阵。

3. 调用原生train方法训练模型

传入自定义目标函数,替代默认的硬标签目标。

修改后的完整代码:

import xgboost as xgb
import numpy as np

# 生成随机训练数据
X = np.random.rand(100, 16)

# 模拟mixup生成的软标签(浮点概率分布)
y_one_hot = np.random.randint(0, 4, size=(100,))
y = np.eye(4)[y_one_hot]
# 手动生成一个mixup样例,替换第一个样本的标签为软概率
y[0] = np.array([0, 0.6, 0.4, 0])
y_proba = y / np.sum(y, axis=1, keepdims=True)

# 自定义多分类软标签的目标函数(交叉熵)
def soft_multiclass_obj(preds, dtrain):
    # preds形状:(n_samples, num_class),是原始的logit输出
    labels = dtrain.get_label().reshape(-1, 4)  # 取出软标签,转为(n_samples,4)
    preds = preds.reshape(-1, 4)
    # 对logit做softmax,得到预测概率
    exp_preds = np.exp(preds)
    probs = exp_preds / np.sum(exp_preds, axis=1, keepdims=True)
    # 计算交叉熵损失的梯度和二阶导
    grad = probs - labels
    hess = probs * (1 - probs)
    # 展平为一维数组返回(XGBoost要求的格式)
    return grad.flatten(), hess.flatten()

# 封装数据为DMatrix,注意标签传入浮点概率矩阵
dtrain = xgb.DMatrix(X, label=y_proba)

# 设置训练参数
params = {
    'max_depth': 3,
    'eta': 0.1,
    'silent': 1,
    'num_class': 4,
    # 这里不需要指定objective,因为用了自定义目标
}

# 训练模型
model = xgb.train(params, dtrain, num_boost_round=100, obj=soft_multiclass_obj)

# 测试预测
X_test = np.random.rand(10, 16)
dtest = xgb.DMatrix(X_test)
y_pred_logit = model.predict(dtest)
y_pred_proba = np.exp(y_pred_logit.reshape(-1,4)) / np.sum(np.exp(y_pred_logit.reshape(-1,4)), axis=1, keepdims=True)
y_pred = np.argmax(y_pred_proba, axis=1)

print("预测类别:", y_pred)
print("预测概率分布:\n", y_pred_proba)

关键说明

  • 自定义目标函数返回的grad和hess必须是一维数组,因此需要对二维的梯度/二阶导矩阵做展平。
  • 原生API的预测结果是logit值,需要手动做softmax转换为概率分布。
  • 若需调整模型复杂度,可修改params中的max_depth、eta等超参数。

内容的提问来源于stack exchange,提问作者Jeff Boker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 16:07:44