An extremely-randomized survival forest (extra survival trees).
ExtraSurvivalTrees(
*,
n_estimators=100,
max_depth=None,
min_samples_split=6,
min_samples_leaf=3,
max_features="sqrt",
bootstrap=False,
oob_score=False,
engine="numpy",
random_state=None,
)
Like RandomSurvivalForest, but at each node the split threshold for every candidate covariate is drawn at random (uniformly between the covariate’s minimum and maximum at that node) rather than optimized. The extra randomization further decorrelates the trees, often lowering variance and speeding up fitting at the cost of a little bias. Following the extra-trees convention, each tree is grown on the full sample (bootstrap=False) by default; set bootstrap=True to enable out-of-bag scoring and permutation variable importance.
Parameters
n_estimators: int = 100
-
Number of trees in the forest.
max_depth: int | None = None
-
Maximum depth of each tree (None for unlimited).
min_samples_split: int = 6
-
Minimum node size eligible for splitting.
min_samples_leaf: int = 3
-
Minimum subjects in each child of a split.
max_features: Any = "sqrt"
-
Covariates considered per split: "sqrt" (default), "log2", an int, a float, or None.
bootstrap: bool = False
-
Whether to grow each tree on a bootstrap sample. False by default (the extra-trees convention); required to be True for oob_score and variable_importance.
oob_score: bool = False
-
Whether to compute an out-of-bag concordance estimate after fitting (requires bootstrap=True).
engine: str = "numpy"
-
Compute backend for the split search: "numpy" (default, deterministic) or "numba" (faster on large datasets, requires the fast extra). "auto" uses Numba when available.
random_state: Any = None
-
Seed or
numpy.random.Generator for split randomization and per-node feature selection.
Examples
Fit extra survival trees on the bundled lung dataset:
import greenwood as gw
# Load data and build a right-censored response
lung = gw.load_dataset("lung", backend="pandas").dropna(subset=["ph.ecog", "ph.karno"])
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
cols = ["age", "sex", "ph.ecog", "ph.karno", "wt.loss"]
# Fit with bootstrap sampling so an out-of-bag score is available
ext = gw.ExtraSurvivalTrees(
n_estimators=100, bootstrap=True, oob_score=True, random_state=0
).fit(y, lung[cols])
ext
ExtraSurvivalTrees (100 log-rank trees, max_features='sqrt')
n = 213, events = 151, features = 5
out-of-bag concordance = 0.6124