diff --git a/NAMESPACE b/NAMESPACE index 053a74b1..0d3d793f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -32,6 +32,8 @@ importFrom(R6,R6Class) importFrom(mlr3,LearnerClassif) importFrom(mlr3,LearnerRegr) importFrom(mlr3,mlr_learners) +importFrom(stats,coef) importFrom(stats,predict) importFrom(stats,reformulate) importFrom(utils,bibentry) +importFrom(utils,tail) diff --git a/R/LearnerClassifCVGlmnet.R b/R/LearnerClassifCVGlmnet.R index 84ce5605..78599c63 100644 --- a/R/LearnerClassifCVGlmnet.R +++ b/R/LearnerClassifCVGlmnet.R @@ -79,7 +79,7 @@ LearnerClassifCVGlmnet = R6Class("LearnerClassifCVGlmnet", param_set = ps, predict_types = c("response", "prob"), feature_types = c("logical", "integer", "numeric"), - properties = c("weights", "twoclass", "multiclass", "selected_features"), + properties = c("importance", "selected_features", "weights", "twoclass", "multiclass"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_classif.cv_glmnet" ) @@ -95,6 +95,18 @@ LearnerClassifCVGlmnet = R6Class("LearnerClassifCVGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/LearnerClassifGlmnet.R b/R/LearnerClassifGlmnet.R index ffcfe55c..8c618eaf 100644 --- a/R/LearnerClassifGlmnet.R +++ b/R/LearnerClassifGlmnet.R @@ -89,7 +89,7 @@ LearnerClassifGlmnet = R6Class("LearnerClassifGlmnet", param_set = ps, predict_types = c("response", "prob"), feature_types = c("logical", "integer", "numeric"), - properties = c("weights", "twoclass", "multiclass"), + properties = c("selected_features", "importance", "weights", "twoclass", "multiclass"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_classif.glmnet" ) @@ -105,6 +105,18 @@ LearnerClassifGlmnet = R6Class("LearnerClassifGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/LearnerClassifLogReg.R b/R/LearnerClassifLogReg.R index d25eb485..1fb63273 100644 --- a/R/LearnerClassifLogReg.R +++ b/R/LearnerClassifLogReg.R @@ -53,7 +53,7 @@ LearnerClassifLogReg = R6Class("LearnerClassifLogReg", param_set = ps, predict_types = c("response", "prob"), feature_types = c("logical", "integer", "numeric", "character", "factor", "ordered"), - properties = c("weights", "twoclass", "loglik"), + properties = c("weights", "twoclass", "loglik", "importance"), packages = c("mlr3learners", "stats"), man = "mlr3learners::mlr_learners_classif.log_reg" ) @@ -63,6 +63,15 @@ LearnerClassifLogReg = R6Class("LearnerClassifLogReg", #' Extract the log-likelihood (e.g., via [stats::logLik()] from the fitted model. loglik = function() { extract_loglik(self) + }, + + #' @description + #' Importance scores as \eqn{-log_{10}()}{-log10()} transformed \eqn{p}-values, + #' extracted from [summary()]. + #' Does not work if the model has been fitted on factor features with more than 2 levels. + #' @return Named `numeric()`. + importance = function() { + lin_model_importance(self) } ), diff --git a/R/LearnerClassifMultinom.R b/R/LearnerClassifMultinom.R index df463c53..6f7f6820 100644 --- a/R/LearnerClassifMultinom.R +++ b/R/LearnerClassifMultinom.R @@ -66,6 +66,7 @@ LearnerClassifMultinom = R6Class("LearnerClassifMultinom", if ("weights" %in% task$properties) { pv$weights = task$weights$weight } + if (!is.null(pv$summ)) { pv$summ = as.integer(pv$summ) } diff --git a/R/LearnerRegrCVGlmnet.R b/R/LearnerRegrCVGlmnet.R index 3e4ac1aa..0c880e4d 100644 --- a/R/LearnerRegrCVGlmnet.R +++ b/R/LearnerRegrCVGlmnet.R @@ -79,7 +79,7 @@ LearnerRegrCVGlmnet = R6Class("LearnerRegrCVGlmnet", id = "regr.cv_glmnet", param_set = ps, feature_types = c("logical", "integer", "numeric"), - properties = c("weights", "selected_features"), + properties = c("importance", "selected_features", "weights"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_regr.cv_glmnet" ) @@ -95,6 +95,18 @@ LearnerRegrCVGlmnet = R6Class("LearnerRegrCVGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/LearnerRegrGlmnet.R b/R/LearnerRegrGlmnet.R index e03f4c02..042f40e6 100644 --- a/R/LearnerRegrGlmnet.R +++ b/R/LearnerRegrGlmnet.R @@ -79,7 +79,7 @@ LearnerRegrGlmnet = R6Class("LearnerRegrGlmnet", id = "regr.glmnet", param_set = ps, feature_types = c("logical", "integer", "numeric"), - properties = "weights", + properties = c("weights", "selected_features", "importance"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_regr.glmnet" ) @@ -95,6 +95,18 @@ LearnerRegrGlmnet = R6Class("LearnerRegrGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/LearnerRegrLM.R b/R/LearnerRegrLM.R index bfb7cd8d..2f92fb3f 100644 --- a/R/LearnerRegrLM.R +++ b/R/LearnerRegrLM.R @@ -41,7 +41,7 @@ LearnerRegrLM = R6Class("LearnerRegrLM", param_set = ps, predict_types = c("response", "se"), feature_types = c("logical", "integer", "numeric", "factor", "character"), - properties = c("weights", "loglik"), + properties = c("weights", "loglik", "importance"), packages = c("mlr3learners", "stats"), man = "mlr3learners::mlr_learners_regr.lm" ) @@ -51,6 +51,15 @@ LearnerRegrLM = R6Class("LearnerRegrLM", #' Extract the log-likelihood (e.g., via [stats::logLik()] from the fitted model. loglik = function() { extract_loglik(self) + }, + + #' @description + #' Importance scores as \eqn{-log_{10}()}{-log10()} transformed \eqn{p}-values, + #' extracted from [summary()]. + #' Does not work if the model has been fitted on factor features with more than 2 levels. + #' @return Named `numeric()`. + importance = function() { + lin_model_importance(self) } ), diff --git a/R/LearnerSurvCVGlmnet.R b/R/LearnerSurvCVGlmnet.R index 69fcf564..587fb871 100644 --- a/R/LearnerSurvCVGlmnet.R +++ b/R/LearnerSurvCVGlmnet.R @@ -75,7 +75,7 @@ LearnerSurvCVGlmnet = R6Class("LearnerSurvCVGlmnet", param_set = ps, feature_types = c("logical", "integer", "numeric"), predict_types = c("crank", "lp"), - properties = c("weights", "selected_features"), + properties = c("importance", "selected_features", "weights"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_surv.cv_glmnet" ) @@ -91,6 +91,18 @@ LearnerSurvCVGlmnet = R6Class("LearnerSurvCVGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/LearnerSurvGlmnet.R b/R/LearnerSurvGlmnet.R index 1bb28a39..f94ab79d 100644 --- a/R/LearnerSurvGlmnet.R +++ b/R/LearnerSurvGlmnet.R @@ -74,7 +74,7 @@ LearnerSurvGlmnet = R6Class("LearnerSurvGlmnet", param_set = ps, feature_types = c("logical", "integer", "numeric"), predict_types = c("crank", "lp"), - properties = c("weights", "selected_features"), + properties = c("importance", "selected_features", "weights"), packages = c("mlr3learners", "glmnet"), man = "mlr3learners::mlr_learners_surv.glmnet" ) @@ -90,6 +90,18 @@ LearnerSurvGlmnet = R6Class("LearnerSurvGlmnet", #' @return (`character()`) of feature names. selected_features = function(lambda = NULL) { glmnet_selected_features(self, lambda) + }, + + #' @description + #' Returns importance scores, calculated from the path of lambda values. + #' First, the largest `lambda` at which the feature was first included in the model + #' with a nonzero coefficient is determined. + #' Second, the [rank()] of these lambda values is calculated (using averaging for ties) + #' and returned as importance scores. + #' + #' @return (named `numeric()`) of importance scores. + importance = function() { + glmnet_importance(self) } ), diff --git a/R/helpers.R b/R/helpers.R index 18c94a73..a7c20ad1 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -1,3 +1,5 @@ +opts_default_contrasts = list(contrasts = c("contr.treatment", "contr.poly")) + # p = probability for levs[2] => matrix with probs for levs[1] and levs[2] pvec2mat = function(p, levs) { stopifnot(is.numeric(p)) @@ -42,6 +44,3 @@ extract_loglik = function(self) { } stats::logLik(self$model) } - - -opts_default_contrasts = list(contrasts = c("contr.treatment", "contr.poly")) diff --git a/R/helpers_glmnet.R b/R/helpers_glmnet.R index 969fb542..74356b33 100644 --- a/R/helpers_glmnet.R +++ b/R/helpers_glmnet.R @@ -53,6 +53,40 @@ glmnet_selected_features = function(self, lambda = NULL) { } +glmnet_importance = function(self) { + find_lambda = function(M) { + pos = apply(M, 1L, function(x) { + i = wf(x == 0, use.names = FALSE) + if (length(i)) i else Inf + }) + } + + model = self$model$glmnet.fit %??% self$model + lambdas = model$lambda + M = coef(model) + + if (is.list(M)) { + names(M) + rownames(M$virginica) + + } else { + # * remove intercept row + # * reorder with increasing lambda + M = M[rownames(M) != "(Intercept)", order(lambdas), drop = FALSE] + } + + + + # find position of smallest lambda with beta being penalized to 0 + pos = apply(M, 1L, function(x) { + i = wf(x == 0, use.names = FALSE) + if (length(i)) i else Inf + }) + + sort(rank(pos, ties.method = "average"), decreasing = TRUE) +} + + glmnet_invoke = function(data, target, pv, cv = FALSE) { saved_ctrl = glmnet::glmnet.control() on.exit(invoke(glmnet::glmnet.control, .args = saved_ctrl)) diff --git a/R/helpers_lin_models.R b/R/helpers_lin_models.R new file mode 100644 index 00000000..a277e2f5 --- /dev/null +++ b/R/helpers_lin_models.R @@ -0,0 +1,20 @@ +lin_model_importance = function(self) { + task = self$state$train_task + lvls = task$levels(task$feature_names, include_logicals = TRUE) + nlvls = lengths(lvls) + if (any(nlvls > 2L)) { + stopf("Importance cannot be extracted for models fitted on factors with more than 2 features") + } + + pvals = summary(self$model)$coefficients[, 4L] + pvals = pvals[names(pvals) != "(Intercept)"] + + # remove the appended 2nd level for binary factor levels + ii = (nlvls == 2L) + pvals = rename(pvals, + old = paste0(names(nlvls)[ii], map_chr(lvls[ii], tail, 1L)), + new = names(nlvls)[ii] + ) + + sort(-log10(pvals), decreasing = TRUE) +} diff --git a/R/zzz.R b/R/zzz.R index 94c812e1..8ec2d1af 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -4,7 +4,8 @@ #' @import checkmate #' @importFrom R6 R6Class #' @importFrom mlr3 mlr_learners LearnerClassif LearnerRegr -#' @importFrom stats predict reformulate +#' @importFrom stats predict coef reformulate +#' @importFrom utils tail #' #' @description #' More learners are implemented in the [mlr3extralearners package](https://github.com/mlr-org/mlr3extralearners). diff --git a/man/mlr_learners_classif.cv_glmnet.Rd b/man/mlr_learners_classif.cv_glmnet.Rd index d11d31b5..f04d23f3 100644 --- a/man/mlr_learners_classif.cv_glmnet.Rd +++ b/man/mlr_learners_classif.cv_glmnet.Rd @@ -149,6 +149,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerClassifCVGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerClassifCVGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerClassifCVGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerClassifCVGlmnet$clone()}} } } @@ -199,6 +200,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerClassifCVGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_classif.glmnet.Rd b/man/mlr_learners_classif.glmnet.Rd index 92ddccb1..283228ad 100644 --- a/man/mlr_learners_classif.glmnet.Rd +++ b/man/mlr_learners_classif.glmnet.Rd @@ -158,6 +158,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerClassifGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerClassifGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerClassifGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerClassifGlmnet$clone()}} } } @@ -208,6 +209,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerClassifGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_classif.log_reg.Rd b/man/mlr_learners_classif.log_reg.Rd index 15b8db3a..239da5b4 100644 --- a/man/mlr_learners_classif.log_reg.Rd +++ b/man/mlr_learners_classif.log_reg.Rd @@ -134,6 +134,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerClassifLogReg$new()}} \item \href{#method-loglik}{\code{LearnerClassifLogReg$loglik()}} +\item \href{#method-importance}{\code{LearnerClassifLogReg$importance()}} \item \href{#method-clone}{\code{LearnerClassifLogReg$clone()}} } } @@ -170,6 +171,21 @@ Extract the log-likelihood (e.g., via \code{\link[stats:logLik]{stats::logLik()} \if{html}{\out{
}}\preformatted{LearnerClassifLogReg$loglik()}\if{html}{\out{
}} } +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Importance scores as \eqn{-log_{10}()}{-log10()} transformed \eqn{p}-values, +extracted from \code{\link[=summary]{summary()}}. +Does not work if the model has been fitted on factor features with more than 2 levels. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerClassifLogReg$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +Named \code{numeric()}. +} } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/mlr_learners_regr.cv_glmnet.Rd b/man/mlr_learners_regr.cv_glmnet.Rd index 72d53ffd..caecebbc 100644 --- a/man/mlr_learners_regr.cv_glmnet.Rd +++ b/man/mlr_learners_regr.cv_glmnet.Rd @@ -142,6 +142,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerRegrCVGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerRegrCVGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerRegrCVGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerRegrCVGlmnet$clone()}} } } @@ -192,6 +193,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerRegrCVGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_regr.glmnet.Rd b/man/mlr_learners_regr.glmnet.Rd index a581ae6a..46612a4d 100644 --- a/man/mlr_learners_regr.glmnet.Rd +++ b/man/mlr_learners_regr.glmnet.Rd @@ -158,6 +158,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerRegrGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerRegrGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerRegrGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerRegrGlmnet$clone()}} } } @@ -208,6 +209,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerRegrGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_regr.lm.Rd b/man/mlr_learners_regr.lm.Rd index 670f152d..5032b971 100644 --- a/man/mlr_learners_regr.lm.Rd +++ b/man/mlr_learners_regr.lm.Rd @@ -114,6 +114,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerRegrLM$new()}} \item \href{#method-loglik}{\code{LearnerRegrLM$loglik()}} +\item \href{#method-importance}{\code{LearnerRegrLM$importance()}} \item \href{#method-clone}{\code{LearnerRegrLM$clone()}} } } @@ -150,6 +151,21 @@ Extract the log-likelihood (e.g., via \code{\link[stats:logLik]{stats::logLik()} \if{html}{\out{
}}\preformatted{LearnerRegrLM$loglik()}\if{html}{\out{
}} } +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Importance scores as \eqn{-log_{10}()}{-log10()} transformed \eqn{p}-values, +extracted from \code{\link[=summary]{summary()}}. +Does not work if the model has been fitted on factor features with more than 2 levels. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerRegrLM$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +Named \code{numeric()}. +} } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/mlr_learners_surv.cv_glmnet.Rd b/man/mlr_learners_surv.cv_glmnet.Rd index bcadeb2e..66a5e29e 100644 --- a/man/mlr_learners_surv.cv_glmnet.Rd +++ b/man/mlr_learners_surv.cv_glmnet.Rd @@ -141,6 +141,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerSurvCVGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerSurvCVGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerSurvCVGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerSurvCVGlmnet$clone()}} } } @@ -191,6 +192,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerSurvCVGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_surv.glmnet.Rd b/man/mlr_learners_surv.glmnet.Rd index 07917684..f8727618 100644 --- a/man/mlr_learners_surv.glmnet.Rd +++ b/man/mlr_learners_surv.glmnet.Rd @@ -156,6 +156,7 @@ Other Learner: \itemize{ \item \href{#method-new}{\code{LearnerSurvGlmnet$new()}} \item \href{#method-selected_features}{\code{LearnerSurvGlmnet$selected_features()}} +\item \href{#method-importance}{\code{LearnerSurvGlmnet$importance()}} \item \href{#method-clone}{\code{LearnerSurvGlmnet$clone()}} } } @@ -206,6 +207,23 @@ Custom \code{lambda}, defaults to the active lambda depending on parameter set.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-importance}{}}} +\subsection{Method \code{importance()}}{ +Returns importance scores, calculated from the path of lambda values. +First, the largest \code{lambda} at which the feature was first included in the model +with a nonzero coefficient is determined. +Second, the \code{\link[=rank]{rank()}} of these lambda values is calculated (using averaging for ties) +and returned as importance scores. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerSurvGlmnet$importance()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +(named \code{numeric()}) of importance scores. +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/tests/testthat/test_classif_cv_glmnet.R b/tests/testthat/test_classif_cv_glmnet.R index b568f2a5..1f3a5f40 100644 --- a/tests/testthat/test_classif_cv_glmnet.R +++ b/tests/testthat/test_classif_cv_glmnet.R @@ -8,6 +8,10 @@ test_that("autotest", { skip_on_os("solaris") result = run_autotest(learner, exclude = "feat_single") expect_true(result, info = result$error) + + + learner = result$learner + learner$importance() }) test_that("prob column reordering (#155)", { diff --git a/tests/testthat/test_regr_glmnet.R b/tests/testthat/test_regr_glmnet.R index 54041a56..65c30a38 100644 --- a/tests/testthat/test_regr_glmnet.R +++ b/tests/testthat/test_regr_glmnet.R @@ -10,7 +10,7 @@ test_that("autotest", { expect_true(result, info = result$error) }) -test_that("selected_features", { +test_that("selected_features + importance", { task = tsk("mtcars") learner = lrn("regr.glmnet") learner$train(task) @@ -24,4 +24,10 @@ test_that("selected_features", { learner$selected_features(Inf), character() ) + + expect_numeric( + learner$importance(), + any.missing = FALSE, + names = "unique" + ) }) diff --git a/tests/testthat/test_surv_glmnet.R b/tests/testthat/test_surv_glmnet.R index e06e42b8..9850bab3 100644 --- a/tests/testthat/test_surv_glmnet.R +++ b/tests/testthat/test_surv_glmnet.R @@ -12,7 +12,7 @@ test_that("autotest", { test_that("selected_features", { task = tsk("gbcs") - learner = lrn("surv.cv_glmnet") + learner = lrn("surv.glmnet") learner$train(task) expect_equal(