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

在mlr3中用glmnet实现松弛LASSO报错:找不到对象'cv'

解决mlr3中classif.glmnet开启relax选项时"object 'cv' not found"错误

问题背景

将直接使用glmnet包的松弛LASSO回归代码迁移到mlr3框架时,使用classif.cv_glmnet学习器调优lambda可正常运行,但使用classif.glmnet学习器并开启relax选项训练时,出现错误提示object 'cv' not found,关闭relax选项则训练正常。

原代码与错误栈

复现代码

library(mlr3)
library(mlr3learners)
library(glmnet)

# 定义任务
task.sonar <- mlr_tasks$get("sonar")

# 交叉验证调优lambda
learner.sonar.lasso.cv <- lrn("classif.cv_glmnet", alpha = 1, relax = TRUE, gamma = 0, nfolds = 15)
set.seed(1112)
learner.sonar.lasso.cv$train(task.sonar)

# 拟合完整模型(报错代码)
learner.sonar.lasso <- lrn("classif.glmnet", alpha = 1, lambda = learner.sonar.lasso.cv$model$lambda, relax = TRUE, gamma = 0)
learner.sonar.lasso$train(task.sonar)
# Error in eval(call, parent.frame()) : object 'cv' not found

# 关闭relax选项可正常训练
learner.sonar.lasso.2 <- lrn("classif.glmnet", lambda = learner.sonar.lasso.cv$model$lambda, alpha = 1)
learner.sonar.lasso.2$train(task.sonar)

完整错误栈

Fehler in eval(call, parent.frame()) : Objekt 'cv' nicht gefunden
23: eval(call, parent.frame())
22: eval(call, parent.frame())
21: update.default(fit, x = x, lambda = lam0, exclude = exclude, 
        ..., relax = FALSE)
20: update(fit, x = x, lambda = lam0, exclude = exclude, ..., relax = FALSE)
19: update(fit, x = x, lambda = lam0, exclude = exclude, ..., relax = FALSE)
18: relax.glmnet(fit, x = x, y = y, weights = weights, offset = offset, 
        lower.limits = lower.limits, upper.limits = upper.limits, 
        penalty.factor = penalty.factor, check.args = FALSE, ...)
17: (if (cv) glmnet::cv.glmnet else glmnet::glmnet)(x = data, y = target, 
        alpha = 1, lambda = c(0.215936661924212, 0.196753444025244, 
        ...), relax = TRUE, 
        family = "binomial")
16: eval(expr, p)
15: eval(expr, p)
14: eval.parent(expr, n = 1L)
13: invoke(if (cv) glmnet::cv.glmnet else glmnet::glmnet, x = data, 
        y = target, .args = pv)
12: glmnet_invoke(data, target, pv)
11: .__LearnerClassifGlmnet__.train(self = self, private = private, 
        super = super, task = task)
10: get_private(learner)$.train(task)
9: .f(learner = <environment>, task = <environment>)
8: eval(expr, p)
7: eval(expr, p)
6: eval.parent(expr, n = 1L)
5: invoke(.f, .args = .args, .opts = .opts, .seed = .seed, .timeout = .timeout)
4: encapsulate(learner$encapsulate["train"], .f = train_wrapper, 
       .args = list(learner = learner, task = task), .pkgs = learner$packages, 
       .seed = NA_integer_, .timeout = learner$timeout["train"])
3: learner_train(learner, task, train_row_ids = train_row_ids, test_row_ids = test_row_ids, 
       mode = mode)
2: .__Learner__train(self = self, private = private, super = super, 
       task = task, row_ids = row_ids)
1: learner.sonar.lasso$train(task.sonar)

解决方案

方案1:直接复用classif.cv_glmnet的松弛模型

classif.cv_glmnet在开启relax=TRUE时,已经完成了松弛模型的训练,无需再用classif.glmnet重新拟合,可直接使用:

# 从cv训练结果中提取松弛后的完整模型
relaxed_full_model <- learner.sonar.lasso.cv$model$glmnet.fit

# 直接用cv学习器进行预测(自动使用最优lambda对应的松弛模型)
predictions <- learner.sonar.lasso.cv$predict(task.sonar)

方案2:手动调用relax.glmnet封装模型

若必须使用classif.glmnet学习器,可先训练基础模型,再手动调用relax.glmnet获取松弛模型并赋值:

# 先训练不带relax的基础glmnet模型
base_learner <- lrn("classif.glmnet", alpha = 1, lambda = learner.sonar.lasso.cv$model$lambda)
base_learner$train(task.sonar)

# 提取任务的特征和目标变量
x <- as.matrix(task.sonar$data(cols = task.sonar$feature_names))
y <- task.sonar$data(cols = task.sonar$target_names)[[1]]

# 手动调用relax.glmnet生成松弛模型
relaxed_fit <- relax.glmnet(base_learner$model, x = x, y = y, gamma = 0)

# 将松弛模型赋值给原学习器
base_learner$model <- relaxed_fit

# 此时可正常使用该学习器进行预测
predictions_relaxed <- base_learner$predict(task.sonar)

错误原因

从错误栈可知,mlr3learners的classif.glmnet学习器内部调用glmnet_invoke函数时,使用了if (cv) glmnet::cv.glmnet else glmnet::glmnet的分支逻辑,但在调用relax.glmnet时,cv变量不在当前作用域内,导致eval执行时找不到该变量,从而抛出错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:07:53