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

能否在mlr3pipelines中基于分组执行特征缩放操作?

基于分组在mlr3pipelines中实现变量缩放

问题描述

能否基于分组应用mlr3管道处理?例如,mlr3pipelines文档中提供了基础的变量缩放代码:

library(mlr3)
library(mlr3pipelines)
task = tsk("iris")
pop = po("scalemaxabs")
pop$train(list(task))[[1]]$data()

我们给鸢尾花数据添加month分组列后:

library(mlr3)
library(mlr3pipelines)
task = tsk("iris")
dt = task$data()
dt[, month := c(rep(1, 50), rep(2, 50), rep(3, 50))]
task = as_task_classif(dt, target = "Species", id = "iris")

希望按month列对预测变量单独缩放(类似以下data.table的实现逻辑):

task$data()[, lapply(.SD, function(x) as.vector(scale(x))), .SDcols = names(dt)[2:5], by = month]

是否能在mlr3管道图中完成该操作?

解决方案

完全可以,以下两种方法可以实现分组缩放需求:

方法1:使用内置po("group")处理器

po("group")可以按指定列拆分任务,对每个分组的子任务应用后续管道操作,最后自动合并回原任务结构。示例代码如下:

library(mlr3)
library(mlr3pipelines)

# 创建带分组列的分类任务
task = tsk("iris")
dt = task$data()
dt[, month := c(rep(1, 50), rep(2, 50), rep(3, 50))]
task = as_task_classif(dt, target = "Species", id = "iris")

# 构建分组缩放管道:拆分分组 → 缩放 → 合并分组
pipe = po("group", group_col = "month") %>>% 
  po("scalemaxabs") %>>% 
  po("ungroup")

# 训练管道并获取处理后的任务
processed_task = pipe$train(list(task))[[1]]
processed_task$data()

方法2:自定义分组缩放PipeOp

如果需要更灵活的缩放逻辑(比如使用scale()进行标准化而非scalemaxabs),可以自定义PipeOp结合data.table的分组操作:

library(mlr3)
library(mlr3pipelines)
library(data.table)

# 创建带分组列的分类任务
task = tsk("iris")
dt = task$data()
dt[, month := c(rep(1, 50), rep(2, 50), rep(3, 50))]
task = as_task_classif(dt, target = "Species", id = "iris")

# 自定义分组缩放PipeOp
PipeOpGroupScale = R6::R6Class("PipeOpGroupScale",
  inherit = PipeOpTaskPreproc,
  public = list(
    initialize = function(id = "group_scale", param_vals = list()) {
      super$initialize(id, param_vals = param_vals)
    }
  ),
  private = list(
    .train_task = function(task) {
      dt = task$data()
      # 按month分组对所有特征列执行标准化
      scaled_features = dt[, lapply(.SD, function(x) as.vector(scale(x))), 
                           .SDcols = task$feature_names, by = month]
      # 合并目标列与处理后的特征列
      full_dt = merge(scaled_features, dt[, .(get(task$target_names), month)], 
                      by = c("month", task$feature_names), all = TRUE)
      setnames(full_dt, "V1", task$target_names)
      # 转换回分类任务
      as_task_classif(full_dt, target = task$target_names, id = task$id)
    },
    .predict_task = function(task) {
      # 预测阶段复用训练阶段的分组缩放逻辑
      dt = task$data()
      scaled_features = dt[, lapply(.SD, function(x) as.vector(scale(x))), 
                           .SDcols = task$feature_names, by = month]
      full_dt = merge(scaled_features, dt[, .(get(task$target_names), month)], 
                      by = c("month", task$feature_names), all = TRUE)
      setnames(full_dt, "V1", task$target_names)
      as_task_classif(full_dt, target = task$target_names, id = task$id)
    }
  )
)

# 实例化自定义PipeOp并运行
po_group_scale = PipeOpGroupScale$new()
processed_task = po_group_scale$train(list(task))[[1]]
processed_task$data()

说明:方法1适合使用内置处理器的标准化场景,代码简洁;方法2适合需要自定义缩放逻辑的场景,灵活性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 09:36:10