Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting relax = TRUE for glmnet models fails #82

Open
hfrick opened this issue Feb 3, 2024 · 1 comment
Open

Setting relax = TRUE for glmnet models fails #82

hfrick opened this issue Feb 3, 2024 · 1 comment
Labels
bug an unexpected problem or unintended behavior

Comments

@hfrick
Copy link
Member

hfrick commented Feb 3, 2024

Slightly adapted from this SO post

library(poissonreg)
#> Loading required package: parsnip

set.seed(123)
df <- tibble::tibble(
  y = rpois(1000, lambda = 3),
  x_1 = 2 * y + rnorm(1000),
  x_2 = 0.1 * y + rnorm(1000)
)

# setting `relax` by itself works
mod <- poisson_reg(penalty = 0.5) %>%
  set_engine("glmnet", relax = TRUE) |> 
  fit(y ~ ., data = df) 

# setting `family` by itself works
mod <- poisson_reg(penalty = 0.5) %>%
  set_engine("glmnet", family = "poisson") |> 
  fit(y ~ ., data = df)

# setting both together fails
mod <- poisson_reg(penalty = 0.5) %>%
  set_engine("glmnet", family = "poisson", relax = TRUE) |> 
  fit(y ~ ., data = df)
#> Error in glmnet.path(x, y, weights, lambda, nlambda, lambda.min.ratio, : Invalid family argument; must be either character, function or family object

# glmnet directly works
mod <- glmnet::glmnet(x = as.matrix(df[,2:3]), y = df$y, family = "poisson")
mod <- glmnet::glmnet(x = as.matrix(df[,2:3]), y = df$y, family = "poisson", relax = TRUE)

Created on 2024-02-03 with reprex v2.1.0

@hfrick
Copy link
Member Author

hfrick commented Feb 16, 2024

This affects all glmnet models that we wrap in tidymodels (not just here in poissonreg) where we set relax = TRUE. Here is an example with linear_reg() and main arguments and engines arguments, respectively.

library(parsnip)

mod <- linear_reg(penalty = 0.5, mixture = 1) %>%
  set_engine("glmnet", relax = TRUE) |> 
  fit(mpg ~ ., data = mtcars)
#> Error in `glmnet::glmnet()`:
#> ! Base operators are not defined for quosures. Do you need to unquote
#>   the quosure?
#> 
#> # Bad: myquosure > rhs
#> 
#> # Good: !!myquosure > rhs


mod <- linear_reg(penalty = 0.5) %>%
  set_engine("glmnet", relax = TRUE, maxit = 1000) |> 
  fit(mpg ~ ., data = mtcars)
#> Warning: from glmnet C++ code (error code -63); Convergence for 63th lambda
#> value not reached after maxit=1000 iterations; solutions for larger lambdas
#> returned
#> Error in elnet(xd, is.sparse, y, weights, offset, type.gaussian, alpha, : 'language' object cannot be coerced to type 'integer'

Created on 2024-02-16 with reprex v2.1.0

This is because glmnet::glmnet() calls glmnet::relax.glmnet() with the "regular" fit object (glmnet code snippet).

glmnet::relax.glmnet() uses that fit object to refit without any regularization . That happens via stats::update.default() (glmnet code snippet) which uses eval() to evaluate the call -- but that call contains the arguments as quosures. That is what ultimately breaks eval().

@hfrick hfrick changed the title Specifying multiple engine arguments for glmnet fails Setting relax = TRUE for glmnet models fails Feb 16, 2024
@hfrick hfrick added the bug an unexpected problem or unintended behavior label Jul 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug an unexpected problem or unintended behavior
Projects
None yet
Development

No branches or pull requests

1 participant