2
$\begingroup$

I am playing with xgboost and callbacks in xgb.train. The code below raises an error: "Error in predict(env$model, dval) : argument "env" is missing, with no default"

Can someone explain me what's wrong about that code? Many thanks!

library(xgboost)

# Example data
data(iris)
iris$Species <- as.numeric(iris$Species) - 1

set.seed(123)
train_idx <- sample(1:nrow(iris), 100)
dtrain <- xgb.DMatrix(as.matrix(iris[train_idx, 1:4]), label = iris$Species[train_idx])
dval   <- xgb.DMatrix(as.matrix(iris[-train_idx, 1:4]), label = iris$Species[-train_idx])

# Custom callback for logging RMSE and MAE
metric_logger <- function(dval) {
  
  # closure to store metrics
  history <- data.frame(iter = integer(), rmse = numeric(), mae = numeric())
  
  # callback function
  cb <- function(env) {
    preds <- predict(env$model, dval)
    labels <- getinfo(dval, "label")
    
    rmse <- sqrt(mean((preds - labels)^2))
    mae  <- mean(abs(preds - labels))
    
    history <<- rbind(history, data.frame(iter = env$iteration, rmse = rmse, mae = mae))
    
    cat(sprintf("[%d] val_rmse=%.5f val_mae=%.5f\n", env$iteration, rmse, mae))
  }
  
  # ⚡ required for XGBoost 2.0.3.1
  attr(cb, "name") <- "metric_logger"
  
  return(cb)
}

# Create the callback
cb_metrics <- metric_logger(dval)

# Train with callback
bst <- xgb.train(
  params    = list(objective = "reg:squarederror"),
  data      = dtrain,
  nrounds   = 20,
  callbacks = list(cb_metrics)
)
```
$\endgroup$

1 Answer 1

2
$\begingroup$

I found the solution:

metric_logger is not correct. I made two changes:

  • env=parent.frame()
  • env$bst

corrected version:

metric_logger <- function(dval) {
  
  # closure to store metrics
  history <- data.frame(iter = integer(), rmse = numeric(), mae = numeric())
  
  # callback function
  cb <- function(env=parent.frame()) {
    preds <- predict(env$bst, dval)
    labels <- getinfo(dval, "label")
    
    rmse <- sqrt(mean((preds - labels)^2))
    mae  <- mean(abs(preds - labels))
    
    history <<- rbind(history, data.frame(iter = env$iteration, rmse = rmse, mae = mae))
    
    cat(sprintf("[%d] val_rmse=%.5f val_mae=%.5f\n", env$iteration, rmse, mae))
  }
  
  # ⚡ required for XGBoost 2.0.3.1
  attr(cb, "name") <- "metric_logger"
  
  return(cb)
}

Now it works!

$\endgroup$
1
  • 1
    $\begingroup$ Nice work ! (+1) x 2 $\endgroup$ Commented Jan 15 at 14:19

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.