XGBoost中自定义目标函数未生效及参数报错的问题咨询
问题描述
在XGBoost的sklearn封装XGBClassifier中尝试实现自定义加权二元交叉熵损失函数,遇到以下问题:
- 最初使用
obj参数传入自定义函数时,函数完全未生效——添加的print无输出,故意写错的dtrain.get_labe()也未触发报错 - 改为
objective参数后,报错'numpy.ndarray' object has no attribute 'get_label',原因是自定义函数基于xgb.DMatrix编写,但sklearn的fit方法传入的是numpy数组
对应代码:
def weighted_binary_cross_entropy(dtrain, pred): # assign the value of imbalanced alpha imbalance_alpha = 90 # retrieve data from dtrain matrix print('!!!!') label = dtrain.get_labe() ### BUG intentionally added here # compute the prediction with sigmoid sigmoid_pred = 1.0 / (1.0 + np.exp(-pred)) # gradient grad = -(imbalance_alpha ** label) * (label - sigmoid_pred) hess = (imbalance_alpha ** label) * sigmoid_pred * (1.0 - sigmoid_pred) return grad, hess xgb_test=XGBClassifier(obj=weighted_binary_cross_entropy).fit(X_trainnorm.to_numpy(), y_train.to_frame().to_numpy()) y_pred=xgb.predict(X_testnorm)
解决方案
1. 明确obj与objective的参数差异
XGBoost的sklearn接口中,自定义目标函数必须通过objective参数传入,obj是原生xgb.train接口的参数名,sklearn封装不识别该参数,因此之前用obj时自定义函数根本未被调用,自然不会有输出或报错。
2. 适配sklearn接口的自定义目标函数
sklearn接口的fit方法会自动将输入的numpy数组转换为内部DMatrix,但传给自定义objective函数的第一个参数是numpy数组形式的标签,而非DMatrix对象,第二个参数是模型的原始预测值(未经过sigmoid转换)。修改后的代码如下:
import numpy as np from xgboost import XGBClassifier def weighted_binary_cross_entropy(y_true, y_pred): imbalance_alpha = 90 # y_true为numpy数组,直接使用无需get_label() sigmoid_pred = 1.0 / (1.0 + np.exp(-y_pred)) grad = -(imbalance_alpha ** y_true) * (y_true - sigmoid_pred) hess = (imbalance_alpha ** y_true) * sigmoid_pred * (1.0 - sigmoid_pred) return grad, hess # 使用objective参数传入自定义函数 xgb_test = XGBClassifier(objective=weighted_binary_cross_entropy).fit(X_trainnorm.to_numpy(), y_train.to_numpy().ravel()) y_pred = xgb_test.predict(X_testnorm)
- 关键修正点:
- 函数参数替换为
y_true(numpy数组)和y_pred,移除DMatrix相关的get_label()调用 - 将
y_train.to_frame().to_numpy()改为y_train.to_numpy().ravel(),确保标签为一维数组,符合XGBoost输入要求 - 用
objective参数传入自定义函数
- 函数参数替换为
3. 是否需要手动转换为DMatrix?
不需要手动转换,sklearn接口会自动处理numpy数组到DMatrix的转换。若坚持使用原生接口逻辑,可手动构造DMatrix后调用xgb.train训练,但会脱离sklearn封装,无法使用fit/predict等sklearn风格方法。
内容的提问来源于stack exchange,提问作者horcle_buzz
相关产品推荐
相关产品推荐

