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

如何为tidymodels生态下的集成模型设置自定义权重?

自定义权重集成模型构建(基于tidymodels与stacks)

需求概述

我需要构建带自定义权重的集成模型:用tidymodels训练多个子模型后,手动指定各子模型的权重(比如等权重0.5/0.5)。stacks包在自动优化权重上表现出色,但我需要手动控制权重;同时希望最终的集成模型能像stacks输出的对象一样,兼容DALEXtra进行模型解释。

现有实现(stacks自动加权)

以下是用stacks自动生成权重的代码,当前输出的权重不符合自定义需求:

## 加载依赖包
library(tidymodels)
library(stacks)
library(DALEXtra)

# 抽取ames数据集样本
set.seed(1)
df <- ames %>% 
  sample_n(500)

# 数据划分与重采样设置
set.seed(1)
df_splits <- initial_split(df)
df_train <- training(df_splits)
df_test  <- testing(df_splits)

set.seed(1)
df_folds <- vfold_cv(df_train, v = 4)

# 定义两个特征配方
rec_small <- recipe(Sale_Price ~ Gr_Liv_Area, data = df)
rec_big <- recipe(Sale_Price ~ BsmtFin_SF_1 + First_Flr_SF + Second_Flr_SF, data = df)

# 随机森林模型规格
rand_forest_ranger_spec <-
  rand_forest() %>%
  set_engine('ranger') %>%
  set_mode('regression')

# 构建工作流集合
wf_rfs <- 
  workflow_set(
    preproc = list(rec_small, rec_big), 
    models = list(rf = rand_forest_ranger_spec)
  )

# 训练子模型
grid_ctrl <-
  control_grid(
    save_pred = TRUE,
    parallel_over = "everything",
    save_workflow = TRUE
  )

grid_results <-
  wf_rfs %>%
  workflow_map(
    seed = 1503,
    resamples = df_folds,
    control = grid_ctrl
  )

# stacks自动加权集成
df_st <- stacks() %>% add_candidates(grid_results)

set.seed(1)
df_model_st <- df_st %>% blend_predictions()

# 查看自动生成的权重公式
df_model_st$equations$numeric
# 当前输出:-42148.1667470673 + (recipe_1_rf_1_1 * 0.13109783287876) + (recipe_2_rf_1_1 * 1.08833216052151)
# 期望输出:0 + (recipe_1_rf_1_1 * .5) + (recipe_2_rf_1_1 * .5)

模型解释流程(基于stacks模型)

以下是用DALEXtra对stacks集成模型做解释的代码,这是我希望保留的功能:

# 拟合集成模型成员
df_model_st_fitted <- df_model_st %>% fit_members()

# 准备解释用特征与数据
vip_features <- c("Gr_Liv_Area", "BsmtFin_SF_1", "First_Flr_SF", "Second_Flr_SF")
vip_train <- df %>% select(all_of(vip_features))

# 创建模型解释器
explainer_blended_rf <- 
  explain_tidymodels(
    df_model_st_fitted, 
    data = vip_train, 
    y = df$Sale_Price,
    label = "Blended Random Forest",
    verbose = FALSE
  )

# 生成变量重要性图(VIP)
vip_example <- 
  explain_tidymodels(
    df_model_st_fitted, 
    data = vip_train, 
    y = df$Sale_Price,
    label = "Blended RF",
    verbose = FALSE
  ) %>% 
  model_parts() 

plot(vip_example)

# 生成累积局部效应图(AL Plots)
al_rf <- model_profile(
  explainer = explainer_blended_rf,
  type = "accumulated",
  variables = names(vip_train)
)

plot(al_rf) + ggtitle("Accumulated-local profiles")

解决方法

方法1:修改stacks模型的权重

直接修改stacks生成的模型对象中的系数,替换为自定义权重后再拟合成员模型:

# 定义自定义权重(截距为0,两个子模型各0.5)
custom_weights <- c(0, 0.5, 0.5)
names(custom_weights) <- names(df_model_st$coefficients$numeric)

# 更新模型系数
df_model_st$coefficients$numeric <- custom_weights

# 重新拟合成员模型
df_custom_st_fitted <- df_model_st %>% fit_members()

# 验证自定义权重的预测效果
predict(df_custom_st_fitted, df_test)

方法2:手动构建兼容tidymodels的自定义集成模型

如果不想依赖stacks,可以手动构建符合tidymodels规范的集成模型,确保能被DALEXtra识别:

# 1. 预先训练并保存每个子模型的完整拟合对象
wf_small <- wf_rfs$workflow[[1]] %>% fit(df_train)
wf_big <- wf_rfs$workflow[[2]] %>% fit(df_train)

# 2. 定义自定义集成模型的预测函数
custom_ensemble_predict <- function(new_data) {
  pred_small <- predict(wf_small, new_data)$.pred
  pred_big <- predict(wf_big, new_data)$.pred
  # 等权重加权计算最终预测值
  tibble(.pred = 0.5 * pred_small + 0.5 * pred_big)
}

# 3. 包装成parsnip兼容的自定义模型
custom_ensemble_spec <- 
  parsnip::model_spec(
    mode = "regression",
    engine = "custom"
  ) %>%
  parsnip::set_engine(
    engine = "custom",
    model = list(wf_small = wf_small, wf_big = wf_big)
  )

# 注册自定义模型的拟合与预测方法
parsnip::set_model_engine("custom", "regression", "fit") <- function(object, formula, data, ...) {
  object$fit <- list(wf_small = wf_small, wf_big = wf_big)
  object
}

parsnip::set_model_engine("custom", "regression", "predict") <- function(object, new_data, ...) {
  custom_ensemble_predict(new_data)
}

# 拟合自定义集成模型
custom_ensemble_fit <- custom_ensemble_spec %>% fit(Sale_Price ~ ., data = df_train)

# 用DALEXtra进行模型解释
explainer_custom <- 
  explain_tidymodels(
    custom_ensemble_fit, 
    data = vip_train, 
    y = df$Sale_Price,
    label = "Custom Weighted Ensemble",
    verbose = FALSE
  )

# 生成变量重要性图
vip_custom <- model_parts(explainer_custom)
plot(vip_custom)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 14:22:33