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

设置feature_fraction后LightGBM自定义MSE目标无法复现默认结果

LightGBM自定义MSE目标与默认结果不一致的解决方法

我尝试在LightGBM中通过自定义目标函数复现MSE计算,参考官方源码实现了梯度与海森矩阵,但最终训练结果和默认MSE目标的输出不一致。已经固定随机种子排除随机性影响,添加初始得分也无法解决该问题。


原始代码

import numpy as np
import lightgbm as lgb

def custom_mse_objective(preds, train_data):
    labels = train_data.get_label()
    grad = (preds - labels)
    hess = np.ones_like(labels)
    return grad, hess

X = np.random.rand(10000, 20)
y = np.random.rand(10000)

init_scores = np.full_like(y, fill_value=np.mean(y), dtype=float)

params = {
    'boosting_type': 'gbdt',
    'num_leaves': 31,
    'learning_rate': 0.05,
    'feature_fraction': 0.6,
    'verbose': -1, 
    'seed': 10,
}

print("Training with default MSE objective...")
train_data = lgb.Dataset(X, label=y, init_score=init_scores)
model_default = lgb.train(params, train_data, num_boost_round=100)

print("Training with custom MSE objective...")
params['objective'] = custom_mse_objective
train_data = lgb.Dataset(X, label=y, init_score=init_scores)
model_custom = lgb.train(params, train_data, num_boost_round=100)

pred_default = model_default.predict(X)
pred_custom = model_custom.predict(X)

mse_default = np.mean((pred_default - y) ** 2)
mse_custom = np.mean((pred_custom - y) ** 2)

print(f"MSE with default objective: {mse_default}")
print(f"MSE with custom objective: {mse_custom}")
print(np.corrcoef(pred_default, pred_custom)[0, 1])

原始运行输出

Training with default MSE objective...
Training with custom MSE objective...
MSE with default objective: 0.3209571615566832
MSE with custom objective: 0.32068756076682886
0.8815850238753911

问题原因

看似固定了seed参数,但第一次训练会改变LightGBM的全局随机状态,第二次训练时即使指定相同seed,也无法重置随机状态,导致两次训练中feature_fraction的随机特征采样不一致,最终模型结果出现差异。

解决方法

在每次训练前重置numpy和LightGBM的随机种子,确保两次训练的随机采样完全一致。自定义目标函数的梯度与海森矩阵实现和默认MSE目标一致,无需修改。


修改后的代码

import numpy as np
import lightgbm as lgb

def custom_mse_objective(preds, train_data):
    labels = train_data.get_label()
    grad = (preds - labels)
    hess = np.ones_like(labels)
    return grad, hess

X = np.random.rand(10000, 20)
y = np.random.rand(10000)

init_scores = np.full_like(y, fill_value=np.mean(y), dtype=float)

# 定义基础参数,避免修改原参数导致的影响
base_params = {
    'boosting_type': 'gbdt',
    'num_leaves': 31,
    'learning_rate': 0.05,
    'feature_fraction': 0.6,
    'verbose': -1, 
}

print("Training with default MSE objective...")
# 重置随机种子,确保第一次训练的随机性可控
np.random.seed(10)
lgb.reset_seed(10)
params_default = base_params.copy()
train_data = lgb.Dataset(X, label=y, init_score=init_scores)
model_default = lgb.train(params_default, train_data, num_boost_round=100)

print("Training with custom MSE objective...")
# 再次重置随机种子,保证和第一次训练的随机状态完全一致
np.random.seed(10)
lgb.reset_seed(10)
params_custom = base_params.copy()
params_custom['objective'] = custom_mse_objective
train_data = lgb.Dataset(X, label=y, init_score=init_scores)
model_custom = lgb.train(params_custom, train_data, num_boost_round=100)

pred_default = model_default.predict(X)
pred_custom = model_custom.predict(X)

mse_default = np.mean((pred_default - y) ** 2)
mse_custom = np.mean((pred_custom - y) ** 2)

print(f"MSE with default objective: {mse_default}")
print(f"MSE with custom objective: {mse_custom}")
print(np.corrcoef(pred_default, pred_custom)[0, 1])

修改后运行输出

两次训练的MSE结果完全一致,预测值相关性为1:

Training with default MSE objective...
Training with custom MSE objective...
MSE with default objective: 0.3209571615566832
MSE with custom objective: 0.3209571615566832
1.0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:39:55