From ac3ca838b73085bb63b0320313bc65bc98fe8af9 Mon Sep 17 00:00:00 2001 From: john Date: Wed, 20 Dec 2023 12:12:03 +0100 Subject: [PATCH] add doc for PipeOpBreslow --- NAMESPACE | 1 + R/PipeOpBreslow.R | 72 ++++++++++- man/mlr_pipeops_compose_breslow_distr.Rd | 156 +++++++++++++++++++++++ man/mlr_pipeops_compose_crank.Rd | 1 + man/mlr_pipeops_compose_distr.Rd | 1 + 5 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 man/mlr_pipeops_compose_breslow_distr.Rd diff --git a/NAMESPACE b/NAMESPACE index 23807b0b8..de8a03ef4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -69,6 +69,7 @@ export(MeasureSurvUnoAUC) export(MeasureSurvUnoTNR) export(MeasureSurvUnoTPR) export(MeasureSurvXuR2) +export(PipeOpBreslow) export(PipeOpCrankCompositor) export(PipeOpDistrCompositor) export(PipeOpPredRegrSurv) diff --git a/R/PipeOpBreslow.R b/R/PipeOpBreslow.R index 189719475..af5dd36e8 100644 --- a/R/PipeOpBreslow.R +++ b/R/PipeOpBreslow.R @@ -1,14 +1,73 @@ #' @title PipeOpBreslow #' @name mlr_pipeops_compose_breslow_distr +#' @template param_pipelines #' @description -#' A short description... +#' Composes a survival distribution (`distr`) from the linear predictor +#' predictions (`lp`) of a given [LearnerSurv] generated during training and +#' prediction using the [breslow] estimator. +#' The input `learner` needs to be able to predict `lp` type of predictions (eg +#' a Cox-type of model). #' +#' @section Dictionary: +#' This [PipeOp][mlr3pipelines::PipeOp] can be instantiated via the +#' [Dictionary][mlr3misc::Dictionary] [mlr_pipeops][mlr3pipelines::mlr_pipeops] +#' or with the associated sugar function [po()][mlr3pipelines::po]: +#' ``` +#' PipeOpBreslow$new(learner) +#' mlr_pipeops$get("breslowcompose", learner) +#' po("breslowcompose", learner, overwrite = TRUE) +#' ``` +#' +#' @section Input and Output Channels: +#' [PipeOpBreslow] is like a [LearnerSurv]. +#' It has one input channel, named `input` that takes a [TaskSurv] during training +#' and another [TaskSurv] during prediction. +#' [PipeOpBreslow] has one output channel named `output`, producing `NULL` during +#' training and a [PredictionSurv] during prediction. +#' +#' @section State: +#' The `$state` slot stores the `times` and `status` survival target variables of +#' the train [TaskSurv] as well as the `lp` predictions on the train set. +#' +#' @section Parameters: +#' The parameters are: +#' * `overwrite` :: `logical(1)` \cr +#' If `FALSE` (default) then the compositor does nothing and returns the +#' input `learner`'s [PredictionSurv]. +#' If `TRUE` or in the case that the input `learner` doesn't have `distr` +#' predictions, then the `distr` is overwritten with the `distr` composed +#' from `lp` and the train set information using [breslow]. +#' This is useful for changing the prediction `distr` from one model form to +#' another. +#' @seealso [pipeline_distrcompositor] +#' @export +#' @family survival compositors +#' @examples +#' \dontrun{ +#' if (requireNamespace("mlr3pipelines", quietly = TRUE)) { +#' library(mlr3) +#' library(mlr3pipelines) +#' task = tsk("rats") +#' part = partition(task, ratio = 0.8) +#' train_task = task$clone()$filter(part$train) +#' test_task = task$clone()$filter(part$test) +#' +#' learner = lrn("surv.coxph") # learner with lp predictions +#' b = po("breslowcompose", learner = learner, overwrite = TRUE) +#' +#' b$train(list(train_task)) +#' p = b$predict(list(test_task))[[1L]] +#' } +#' } PipeOpBreslow = R6Class("PipeOpBreslow", inherit = mlr3pipelines::PipeOp, public = list( #' @description #' Creates a new instance of this [R6][R6::R6Class] class. - #' @param id description + #' @param learner ([LearnerSurv])\cr + #' Survival learner which must provide `lp`-type predictions + #' @param id (character(1))\cr + #' Identifier of the resulting object. initialize = function(learner, id = "po_breslow", param_vals = list(overwrite = FALSE)) { if ("lp" %nin% learner$predict_types) { stopf("Learner %s must provide lp predictions", learner$id) @@ -37,6 +96,8 @@ PipeOpBreslow = R6Class("PipeOpBreslow", ), active = list( + #' @field learner \cr + #' The input learner. learner = function(rhs) { assert_ro_binding(rhs) private$.learner @@ -86,8 +147,11 @@ PipeOpBreslow = R6Class("PipeOpBreslow", p = learner$predict(task) pv = self$param_set$get_values(tags = "predict") - if (is.null(pv$overwrite) || !pv$overwrite) { - #browser() + overwrite = pv$overwrite + + # If learner predicts `distr` and overwrite is FALSE don't use breslow + if ("distr" %in% learner$predict_types & !overwrite) { + browser() pred = list(p) } else { # missing lp diff --git a/man/mlr_pipeops_compose_breslow_distr.Rd b/man/mlr_pipeops_compose_breslow_distr.Rd new file mode 100644 index 000000000..d4242542e --- /dev/null +++ b/man/mlr_pipeops_compose_breslow_distr.Rd @@ -0,0 +1,156 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpBreslow.R +\name{mlr_pipeops_compose_breslow_distr} +\alias{mlr_pipeops_compose_breslow_distr} +\alias{PipeOpBreslow} +\title{PipeOpBreslow} +\description{ +Composes a survival distribution (\code{distr}) from the linear predictor +predictions (\code{lp}) of a given \link{LearnerSurv} generated during training and +prediction using the \link{breslow} estimator. +The input \code{learner} needs to be able to predict \code{lp} type of predictions (eg +a Cox-type of model). +} +\section{Dictionary}{ + +This \link[mlr3pipelines:PipeOp]{PipeOp} can be instantiated via the +\link[mlr3misc:Dictionary]{Dictionary} \link[mlr3pipelines:mlr_pipeops]{mlr_pipeops} +or with the associated sugar function \link[mlr3pipelines:po]{po()}: + +\if{html}{\out{
}}\preformatted{PipeOpBreslow$new(learner) +mlr_pipeops$get("breslowcompose", learner) +po("breslowcompose", learner, overwrite = TRUE) +}\if{html}{\out{
}} +} + +\section{Input and Output Channels}{ + +\link{PipeOpBreslow} is like a \link{LearnerSurv}. +It has one input channel, named \code{input} that takes a \link{TaskSurv} during training +and another \link{TaskSurv} during prediction. +\link{PipeOpBreslow} has one output channel named \code{output}, producing \code{NULL} during +training and a \link{PredictionSurv} during prediction. +} + +\section{State}{ + +The \verb{$state} slot stores the \code{times} and \code{status} survival target variables of +the train \link{TaskSurv} as well as the \code{lp} predictions on the train set. +} + +\section{Parameters}{ + +The parameters are: +\itemize{ +\item \code{overwrite} :: \code{logical(1)} \cr +If \code{FALSE} (default) then the compositor does nothing and returns the +input \code{learner}'s \link{PredictionSurv}. +If \code{TRUE} or in the case that the input \code{learner} doesn't have \code{distr} +predictions, then the \code{distr} is overwritten with the \code{distr} composed +from \code{lp} and the train set information using \link{breslow}. +This is useful for changing the prediction \code{distr} from one model form to +another. +} +} + +\examples{ +\dontrun{ +if (requireNamespace("mlr3pipelines", quietly = TRUE)) { + library(mlr3) + library(mlr3pipelines) + task = tsk("rats") + part = partition(task, ratio = 0.8) + train_task = task$clone()$filter(part$train) + test_task = task$clone()$filter(part$test) + + learner = lrn("surv.coxph") # learner with lp predictions + b = po("breslowcompose", learner = learner, overwrite = TRUE) + + b$train(list(train_task)) + p = b$predict(list(test_task))[[1L]] +} +} +} +\seealso{ +\link{pipeline_distrcompositor} + +Other survival compositors: +\code{\link{mlr_pipeops_compose_crank}}, +\code{\link{mlr_pipeops_compose_distr}} +} +\concept{survival compositors} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpBreslow} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{learner}}{\cr +The input learner.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpBreslow-new}{\code{PipeOpBreslow$new()}} +\item \href{#method-PipeOpBreslow-clone}{\code{PipeOpBreslow$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpBreslow-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpBreslow$new( + learner, + id = "po_breslow", + param_vals = list(overwrite = FALSE) +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{learner}}{(\link{LearnerSurv})\cr +Survival learner which must provide \code{lp}-type predictions} + +\item{\code{id}}{(character(1))\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpBreslow-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpBreslow$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_compose_crank.Rd b/man/mlr_pipeops_compose_crank.Rd index 904329722..40af4ab71 100644 --- a/man/mlr_pipeops_compose_crank.Rd +++ b/man/mlr_pipeops_compose_crank.Rd @@ -86,6 +86,7 @@ if (requireNamespace("mlr3pipelines", quietly = TRUE)) { \link{pipeline_crankcompositor} Other survival compositors: +\code{\link{mlr_pipeops_compose_breslow_distr}}, \code{\link{mlr_pipeops_compose_distr}} } \concept{survival compositors} diff --git a/man/mlr_pipeops_compose_distr.Rd b/man/mlr_pipeops_compose_distr.Rd index 77883ab9b..6044963d4 100644 --- a/man/mlr_pipeops_compose_distr.Rd +++ b/man/mlr_pipeops_compose_distr.Rd @@ -93,6 +93,7 @@ if (requireNamespace("mlr3pipelines", quietly = TRUE)) { \link{pipeline_distrcompositor} Other survival compositors: +\code{\link{mlr_pipeops_compose_breslow_distr}}, \code{\link{mlr_pipeops_compose_crank}} } \concept{survival compositors}