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

使用mlrMBO做XGBoost超参数贝叶斯优化结果不可复现问题求解

问题根因及修复方案

以下是导致结果无法复现的核心原因及对应修改方案:

  1. XGBoost内部随机性未控制
    仅设置R语言全局种子无法控制XGBoost本身的随机状态,同时nthreads = NULL会调用所有可用CPU核心,多线程并行本身会引入计算误差和随机性。
    修复方式:在xgb.cv参数中添加seed = 1234,固定nthreads = 1(如需多线程可固定为明确数值,如nthreads = 4,不要留空)。
  2. rgenoud优化器种子未固定
    克里金模型选用的优化方式optim.method = "gen"本质是调用rgenoud优化器,该优化器的随机过程不受R全局种子控制,需要显式传入种子参数。
    修复方式:在makeLearner的control参数中添加seed = 1234,对应rgenoud的随机种子设置。
  3. 全局种子设置不一致
    函数内部设置种子时指定了"L'Ecuyer-CMRG"类型,但最后两次调用bayes()函数前仅设置了数值种子,未指定类型,导致种子序列不匹配。
    修复方式:所有set.seed调用统一使用set.seed(1234, kind = "L'Ecuyer-CMRG")。
  4. MBO内部采样随机性未控制
    mlrMBO的infill优化过程自带随机采样步骤,需要在控制对象中显式设置种子。
    修复方式:在创建control对象后添加control$seed = 1234。

修改后可复现的完整代码

db <- read.delim("https://drive.google.com/uc?export=download&id=1JXMUbwAWi8jjRPGQxzC15tUzSIWrPfNH")
db <- as.data.frame(db)
# 贝叶斯优化
library("xgboost")
library("data.table")
library("tidymodels")
library("mlrMBO")
library("skimr")
library("DiceKriging")
library("rgenoud")
library("Matrix")

sparse_matrix <- sparse.model.matrix(outcome ~ .-1, data = db)
labels <- db$outcome
db_xgb <- xgb.DMatrix(data = sparse_matrix, label = labels)

obj.fun <- smoof::makeSingleObjectiveFunction(
  name = "xgbcv", 
  fn = function(x) {
    set.seed(1234, kind = "L'Ecuyer-CMRG")
    xgbcv <- xgb.cv(
      params = list(
        nthreads = 1,
        max_depth = x["max_depth"],
        min_child_weight = x["min_child_weight"],
        eta = x["eta"],
        gamma = x["gamma"],
        max_delta_step = x["max_delta_step"],
        alpha = x["alpha"],
        lambda = x["lambda"],
        booster = "gbtree",
        objective = "binary:logistic",
        eval_metric = "logloss"
      ),
      tree_method = "hist",
      nround = 1000,
      nfold = 5,
      early_stopping_rounds = 50,
      verbose = 0,
      maximize = F,
      data = db_xgb,
      seed = 1234
    )
    min(xgbcv$evaluation_log$test_logloss_mean)
  },
  par.set = makeParamSet(
    makeNumericParam("eta", lower = 0.0001, upper = 0.5),
    makeNumericParam("gamma", lower = 0, upper = 20),
    makeIntegerParam("max_depth", lower = 1, upper = 50),
    makeIntegerParam("min_child_weight", lower = 1, upper = 10),
    makeNumericParam("max_delta_step", lower = 0, upper = 10),
    makeNumericParam("alpha", lower = 0, upper = 10),
    makeNumericParam("lambda", lower = 0, upper = 10)
  ),
  minimize = T
)

bayes <- function(n_design = (10*getNumberOfParameters(obj.fun)), opt_steps = 50) {
  set.seed(1234, kind = "L'Ecuyer-CMRG")
  des <- generateDesign(n = n_design, par.set = getParamSet(obj.fun), fun = lhs::optimumLHS)
  set.seed(1234, kind = "L'Ecuyer-CMRG")
  des$y <- apply(des, 1, obj.fun)
  
  control <- makeMBOControl()
  control <- setMBOControlTermination(control, iters = 50)  
  control <- setMBOControlInfill(control, crit = makeMBOInfillCritEI())
  control$seed <- 1234
  
  set.seed(1234, kind = "L'Ecuyer-CMRG")
  run <- mbo(
    fun = obj.fun, 
    design = des, 
    learner = makeLearner(
      "regr.km", 
      predict.type = "se", 
      covtype = "matern3_2", 
      optim.method = "gen",
      nugget.estim = F, 
      jitter = F, 
      nugget = 1e-22,
      control = list(trace = F, seed = 1234)
    ),
    control = control, 
    show.info = T
  )
  
  optimization_process <- as.data.frame(
    run$opt.path$env$path %>%  
      dplyr::mutate(round = row_number()) %>%
      dplyr::mutate(type = case_when(
        round <= n_design ~ "design",
        TRUE ~ "bayesian optimization"
      ))
  )
  return(list(optimization_process))
}

set.seed(1234, kind = "L'Ecuyer-CMRG")
runs <- bayes()
bayes_1 <- as.data.frame(runs[[1]])

set.seed(1234, kind = "L'Ecuyer-CMRG")
runs <- bayes()
bayes_2 <- as.data.frame(runs[[1]])

# 验证一致性
all.equal(bayes_1, bayes_2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:57:01