funcml

funcml provides a machine learning framework for R. The package also includes native interpretability helpers for permutation importance, partial dependence, ICE, ALE, local surrogate explanations, SHAP, interaction strength, greedy breakdown profiles, and global surrogate models.

It also exposes native ensemble learners through model = "stacking" and model = "superlearner".

The package is intentionally opinionated. It is not designed to compete feature for feature with broader frameworks such as tidymodels, mlr3, or caret. Instead, funcml focuses on a compact and explicit framework for users who want to fit, compare, tune, interpret, and estimate models through one coherent interface, with formula syntax as the main model-specification surface.

This design comes with a deliberate tradeoff:

Users who need broader preprocessing orchestration or specialized resampling designs should use a more complete framework.

Learner coverage currently includes:

fit_obj <- fit(mpg ~ wt + hp, data = mtcars, model = "ranger")

permute_obj <- interpret(fit_obj, mtcars, method = "permute", nsim = 5)
pdp_obj <- interpret(fit_obj, mtcars, method = "pdp", features = "wt")
ale_obj <- interpret(fit_obj, mtcars, method = "ale", features = "wt")
local_obj <- interpret(fit_obj, mtcars, method = "local_model", newdata = mtcars[1, , drop = FALSE], k = 2)
shap_obj <- interpret(fit_obj, mtcars, method = "shap", newdata = mtcars[1, , drop = FALSE], nsim = 20)
profile_obj <- interpret(fit_obj, mtcars, method = "profile", newdata = mtcars[1, , drop = FALSE])
surrogate_obj <- interpret(fit_obj, mtcars, method = "surrogate")
eval_obj <- evaluate(mpg ~ wt + hp, data = mtcars, model = "glm", resampling = cv(5))
eval_obj
#> <funcml_eval> model: glm | task: regression
#>   metric   mean     sd n std_error conf_level conf_low conf_high
#> 1   rmse 2.6832 1.0347 5    0.4627       0.95   1.3984    3.9680
#> 2    mae 2.1913 0.8367 5    0.3742       0.95   1.1525    3.2302
#> 3    mse 8.0560 5.5846 5    2.4975       0.95   1.1219   14.9902
#> 4  medae 1.9705 0.9344 5    0.4179       0.95   0.8102    3.1307
#> 5   mape 0.1150 0.0567 5    0.0254       0.95   0.0446    0.1855
#> 6    rsq 0.1750 1.2412 5    0.5551       0.95  -1.3661    1.7162
tune_grid <- expand.grid(intercept = c(TRUE, FALSE))

tune_obj <- tune(mpg ~ wt + hp, data = mtcars, model = "glm", grid = tune_grid, search = "random", n_evals = 1, resampling = cv(v = 3, seed = 1), seed = 1)

tune_obj
#> <funcml_tune> metric=rmse direction=min search=random
#> Best:
#>   intercept   mean     sd n std_error conf_level conf_low conf_high
#> 1      TRUE 2.7726 0.9774 3    0.5643       0.95   0.3445    5.2007

Nested CV is available through outer_resampling. The inner resampling argument still selects the best configuration, and the outer resampling loop provides an unbiased estimate of tuned model-selection performance.

nested_tune_obj <- tune(
  mpg ~ wt + hp,
  data = mtcars,
  model = "glm",
  grid = tune_grid,
  resampling = cv(v = 3, seed = 1),
  outer_resampling = cv(v = 4, seed = 2),
  metric = "rmse",
  seed = 1
)
nested_tune_obj
#> <funcml_tune> metric=rmse direction=min search=grid
#> Best:
#>   intercept   mean     sd n std_error conf_level conf_low conf_high
#> 1      TRUE 2.7726 0.9774 3    0.5643       0.95   0.3445    5.2007
#> Nested resampling:
#>   metric   mean     sd n std_error conf_level conf_low conf_high
#> 1   rmse 2.8862 1.0851 4    0.5425       0.95   1.1596    4.6128
interaction_obj <- interpret(fit_obj, mtcars, method = "interaction")
plot(interaction_obj)
learners()
#>  [1] "glm"          "rpart"        "glmnet"       "ranger"       "nnet"        
#>  [6] "mlp"          "densemlp"     "e1071_svm"    "randomForest" "gbm"         
#> [11] "C50"          "kknn"         "earth"        "gam"          "naivebayes"  
#> [16] "fda"          "adaboost"     "pls"          "ctree"        "cforest"     
#> [21] "lda"          "qda"          "lightgbm"     "bart"         "xgboost"     
#> [26] "fastgbm"      "stacking"     "superlearner"
plot(permute_obj)

plot(pdp_obj)

plot(ale_obj)

plot(local_obj)

plot(shap_obj, kind = "waterfall")

plot(profile_obj)

plot(surrogate_obj)