GradientBoostingSurvivalAnalysis

Gradient-boosted survival model minimizing the Cox partial-likelihood loss.

Usage

Source

GradientBoostingSurvivalAnalysis(
    *,
    n_estimators=100,
    learning_rate=0.1,
    max_depth=3,
    min_samples_leaf=3,
    subsample=1.0,
    max_features=None,
    random_state=None,
)

Builds an additive risk score by sequentially fitting shallow squared-error regression trees to the negative gradient of the negative Cox partial log-likelihood (the martingale residuals under the current model) and adding a shrunken version of each tree. The result is a flexible, non-linear generalization of the Cox model: strong predictive performance on structured tabular data, without a global proportional-hazards assumption on individual covariates. A Breslow baseline hazard turns the additive log-risk score into per-subject survival and cumulative-hazard functions.

Parameters

n_estimators: int = 100

Number of boosting iterations (trees).

learning_rate: float = 0.1

Shrinkage applied to each tree’s contribution. Smaller values need more trees but generalize better.

max_depth: int = 3

Maximum depth of each regression tree (interaction depth).

min_samples_leaf: int = 3

Minimum number of samples in each leaf of a tree.

subsample: float = 1.0

Fraction of the training rows sampled (without replacement) to grow each tree. Values below 1.0 give stochastic gradient boosting.

max_features: Any = None

Covariates considered per split: None (all, default), "sqrt", "log2", an int, or a float fraction.

random_state: Any = None
Seed or numpy.random.Generator for subsampling and per-node feature selection.

Examples

Fit a gradient-boosted survival model on the bundled lung dataset:

import greenwood as gw

lung = gw.load_dataset("lung", backend="pandas").dropna(subset=["ph.ecog", "ph.karno"])

# Fit the model and score the first five subjects
gbm = gw.GradientBoostingSurvivalAnalysis(
    n_estimators=200, learning_rate=0.05, max_depth=2, random_state=0
).fit("Surv(time, status) ~ age + sex + ph.ecog + ph.karno + wt.loss", data=lung)
gbm.predict(lung)[:5]
array([0.63006698, 1.09057783, 0.59369757, 1.18981321, 0.58051085])

Methods

Name Description
fit() Fit the gradient-boosted survival model to a right-censored response.
predict() Predict a risk score, linear predictor, or survival / cumulative-hazard curves.
variable_importance() Impurity-based variable importance (normalized total squared-error reduction).

fit()

Fit the gradient-boosted survival model to a right-censored response.

Usage

Source

fit(
    surv,
    covariates=None,
    *,
    data=None,
)

Parameters

surv: Surv | Outcome | str

A right-censored Surv response, built with gw.Surv(time=..., event=...). An Outcome or a formula string such as 'Surv(time, status == 2) ~ age + sex' is also accepted, with its columns read from data. The right-hand side sets covariates.

covariates: Any = None

A dataframe, a 2-D array, or a right-hand-side formula string evaluated against data. A list of column names in data also works.

data: Any = None
A data frame (pandas, Polars, PyArrow, DuckDB, a lazy frame, …) holding the columns named by the response and covariates. When surv is an Outcome or a formula, rows with a missing value in any column used are dropped before fitting. Covariate formula strings and lists of column names are also resolved here.

Returns

self
The fitted estimator, with cached attributes including trees_, event_times_, feature_importances_, n_features_in_, and feature_names_in_.

Examples

Fit a gradient-boosted model on the lung dataset and inspect the feature importances. Importances are normalized so they sum to one:

import greenwood as gw

lung = gw.load_dataset("lung", backend="pandas").dropna(
    subset=["ph.ecog", "ph.karno"]
)

gbm = gw.GradientBoostingSurvivalAnalysis(
    n_estimators=200, learning_rate=0.05, max_depth=2, random_state=0
).fit("Surv(time, status) ~ age + sex + ph.ecog + ph.karno + wt.loss", data=lung)
gbm
GradientBoostingSurvivalAnalysis (200 trees, learning_rate=0.05, max_depth=2)
n = 213, events = 151, features = 5 (13 observations deleted due to missingness)

The formula interface works the same way:

gbm2 = gw.GradientBoostingSurvivalAnalysis(
    n_estimators=100, random_state=0
).fit(
    "Surv(time, status == 2) ~ age + sex + ph.ecog + ph.karno",
    data=lung,
)
gbm2
GradientBoostingSurvivalAnalysis (100 trees, learning_rate=0.1, max_depth=3)
n = 226, events = 163, features = 4

predict()

Predict a risk score, linear predictor, or survival / cumulative-hazard curves.

Usage

Source

predict(
    newdata=None,
    *,
    type="risk",
    times=None,
    format=None,
)
  1. type="risk" (default): the relative hazard \exp(F(x)), a 1-D array where higher values indicate higher risk.
  2. type="lp": the additive log-risk score F(x) (the boosted Cox linear predictor).
  3. type="survival": survival S(t \mid x) = \exp(-H_0(t)\,e^{F(x)}) at times.
  4. type="cumulative_hazard": H(t \mid x) = H_0(t)\,e^{F(x)} at times.

Parameters

newdata: Any = None

Covariates to predict for. None predicts for the training subjects. A data frame may also hold other columns. The covariates are picked out by name and coded as they were at fit time, so the frame the model was fit on can be passed as is.

type: str = "risk"

One of "risk", "lp", "survival", or "cumulative_hazard".

times: Any = None

Times at which to evaluate curves. Defaults to the training event times.

format: str | None = None
DataFrame backend for curve output.

Returns

numpy.ndarray or DataFrame
A risk / linear-predictor vector, or a curve frame with a time column and one column per subject.

variable_importance()

Impurity-based variable importance (normalized total squared-error reduction).

Usage

Source

variable_importance(
    *,
    format=None,
)

Each split’s reduction in squared error is credited to its covariate and summed across all trees, then normalized to sum to one. Returns a table sorted by importance.