alterlab-scikit-survival — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited alterlab-scikit-survival (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
scikit-survival is a Python library for survival analysis built on top of scikit-learn. It provides specialized tools for time-to-event analysis, handling the unique challenge of censored data where some observations are only partially known.
Survival analysis aims to establish connections between covariates and the time of an event, accounting for censored records (particularly right-censored data from studies where participants don't experience events during observation periods).
Use this skill when:
scikit-survival provides multiple model families, each suited for different scenarios:
#### Cox Proportional Hazards Models Use for: Standard survival analysis with interpretable coefficients
CoxPHSurvivalAnalysis: Basic Cox modelCoxnetSurvivalAnalysis: Penalized Cox with elastic net for high-dimensional dataIPCRidge: Ridge regression for accelerated failure time modelsSee: references/cox-models.md for detailed guidance on Cox models, regularization, and interpretation
#### Ensemble Methods Use for: High predictive performance with complex non-linear relationships
RandomSurvivalForest: Robust, non-parametric ensemble methodGradientBoostingSurvivalAnalysis: Tree-based boosting for maximum performanceComponentwiseGradientBoostingSurvivalAnalysis: Linear boosting with feature selectionExtraSurvivalTrees: Extremely randomized trees for additional regularizationSee: references/ensemble-models.md for comprehensive guidance on ensemble methods, hyperparameter tuning, and when to use each model
#### Survival Support Vector Machines Use for: Medium-sized datasets with margin-based learning
FastSurvivalSVM: Linear SVM optimized for speedFastKernelSurvivalSVM: Kernel SVM for non-linear relationshipsHingeLossSurvivalSVM: SVM with hinge lossClinicalKernelTransform: Specialized kernel for clinical + molecular dataSee: references/svm-models.md for detailed SVM guidance, kernel selection, and hyperparameter tuning
#### Model Selection Decision Tree
Start
├─ High-dimensional data (p > n)?
│ ├─ Yes → CoxnetSurvivalAnalysis (elastic net)
│ └─ No → Continue
│
├─ Need interpretable coefficients?
│ ├─ Yes → CoxPHSurvivalAnalysis or ComponentwiseGradientBoostingSurvivalAnalysis
│ └─ No → Continue
│
├─ Complex non-linear relationships expected?
│ ├─ Yes
│ │ ├─ Large dataset (n > 1000) → GradientBoostingSurvivalAnalysis
│ │ ├─ Medium dataset → RandomSurvivalForest or FastKernelSurvivalSVM
│ │ └─ Small dataset → RandomSurvivalForest
│ └─ No → CoxPHSurvivalAnalysis or FastSurvivalSVM
│
└─ For maximum performance → Try multiple models and compareBefore modeling, properly prepare survival data:
#### Creating Survival Outcomes
from sksurv.util import Surv
# From separate arrays
y = Surv.from_arrays(event=event_array, time=time_array)
# From DataFrame
y = Surv.from_dataframe('event', 'time', df)#### Essential Preprocessing Steps
See: references/data-handling.md for complete preprocessing workflows, data validation, and best practices
Proper evaluation is critical for survival models. Use appropriate metrics that account for censoring:
#### Concordance Index (C-index) Primary metric for ranking/discrimination:
from sksurv.metrics import concordance_index_censored, concordance_index_ipcw
# Harrell's C-index
c_harrell = concordance_index_censored(y_test['event'], y_test['time'], risk_scores)[0]
# Uno's C-index (recommended)
c_uno = concordance_index_ipcw(y_train, y_test, risk_scores)[0]#### Time-Dependent AUC Evaluate discrimination at specific time points:
from sksurv.metrics import cumulative_dynamic_auc
times = [365, 730, 1095] # 1, 2, 3 years
auc, mean_auc = cumulative_dynamic_auc(y_train, y_test, risk_scores, times)#### Brier Score Assess both discrimination and calibration:
from sksurv.metrics import integrated_brier_score
ibs = integrated_brier_score(y_train, y_test, survival_functions, times)See: references/evaluation-metrics.md for comprehensive evaluation guidance, metric selection, and using scorers with cross-validation
Handle situations with multiple mutually exclusive event types:
from sksurv.nonparametric import cumulative_incidence_competing_risks
# Pass SEPARATE arrays: integer-coded event status (0=censored, 1, 2, ...)
# and the observed time. Do NOT collapse the status to a boolean.
times, cif = cumulative_incidence_competing_risks(event_status, time)
# cif[0] = total risk (any event); cif[1:] = CIF for each event type k
cif_event1, cif_event2 = cif[1], cif[2]Use competing risks when:
See: references/competing-risks.md for detailed competing risks methods, cause-specific hazard models, and interpretation
Estimate survival functions without parametric assumptions:
#### Kaplan-Meier Estimator
from sksurv.nonparametric import kaplan_meier_estimator
time, survival_prob = kaplan_meier_estimator(y['event'], y['time'])#### Nelson-Aalen Estimator
from sksurv.nonparametric import nelson_aalen_estimator
time, cumulative_hazard = nelson_aalen_estimator(y['event'], y['time'])from sksurv.datasets import load_breast_cancer
from sksurv.linear_model import CoxPHSurvivalAnalysis
from sksurv.metrics import concordance_index_ipcw
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 1. Load and prepare data
X, y = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 2. Preprocess
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 3. Fit model
estimator = CoxPHSurvivalAnalysis()
estimator.fit(X_train_scaled, y_train)
# 4. Predict
risk_scores = estimator.predict(X_test_scaled)
# 5. Evaluate
c_index = concordance_index_ipcw(y_train, y_test, risk_scores)[0]
print(f"C-index: {c_index:.3f}")The IPCW scorer wrappers (as_concordance_index_ipcw_scorer, as_integrated_brier_score_scorer, as_cumulative_dynamic_auc_scorer) WRAP the estimator and override its .score() method — they are NOT passed to scoring=. Pass the wrapped object as the GridSearchCV estimator and prefix tuned params with estimator__. There is no valid scoring='concordance_index_ipcw' string.
import numpy as np
from sksurv.linear_model import CoxnetSurvivalAnalysis
from sklearn.model_selection import GridSearchCV
from sksurv.metrics import as_concordance_index_ipcw_scorer
# 1. Penalized Cox for feature selection (l1_ratio near 1 = lasso-like sparsity)
estimator = CoxnetSurvivalAnalysis(l1_ratio=0.9, fit_baseline_model=True)
# 2. Wrap the estimator so .score() uses Uno's C-index, then tune.
# tau caps the evaluation horizon to avoid unstable IPCW weights in the tail.
wrapped = as_concordance_index_ipcw_scorer(estimator, tau=y['time'].max())
param_grid = {'estimator__alpha_min_ratio': [0.01, 0.001]}
cv = GridSearchCV(wrapped, param_grid, cv=5)
cv.fit(X, y)
# 3. Identify selected features (unwrap to reach the Coxnet estimator)
best_model = cv.best_estimator_.estimator_
selected_features = np.where(best_model.coef_.ravel() != 0)[0]from sksurv.ensemble import GradientBoostingSurvivalAnalysis
from sklearn.model_selection import GridSearchCV
from sksurv.metrics import as_concordance_index_ipcw_scorer, concordance_index_ipcw
# 1. Define parameter grid
param_grid = {
'learning_rate': [0.01, 0.05, 0.1],
'n_estimators': [100, 200, 300],
'max_depth': [3, 5, 7]
}
# 2. Grid search (wrap estimator so .score() is Uno's C-index; prefix params)
gbs = GradientBoostingSurvivalAnalysis(random_state=42)
wrapped = as_concordance_index_ipcw_scorer(gbs, tau=y_train['time'].max())
param_grid = {f'estimator__{k}': v for k, v in param_grid.items()}
cv = GridSearchCV(wrapped, param_grid, cv=5, n_jobs=-1)
cv.fit(X_train, y_train)
# 3. Evaluate best model on held-out test set
best_model = cv.best_estimator_.estimator_
risk_scores = best_model.predict(X_test)
c_index = concordance_index_ipcw(y_train, y_test, risk_scores)[0]from sksurv.linear_model import CoxPHSurvivalAnalysis
from sksurv.ensemble import RandomSurvivalForest, GradientBoostingSurvivalAnalysis
from sksurv.svm import FastSurvivalSVM
from sksurv.metrics import concordance_index_ipcw, integrated_brier_score
# Define models
models = {
'Cox': CoxPHSurvivalAnalysis(),
'RSF': RandomSurvivalForest(n_estimators=100, random_state=42),
'GBS': GradientBoostingSurvivalAnalysis(random_state=42),
'SVM': FastSurvivalSVM(random_state=42)
}
# Evaluate each model
results = {}
for name, model in models.items():
model.fit(X_train_scaled, y_train)
risk_scores = model.predict(X_test_scaled)
c_index = concordance_index_ipcw(y_train, y_test, risk_scores)[0]
results[name] = c_index
print(f"{name}: C-index = {c_index:.3f}")
# Select best model
best_model_name = max(results, key=results.get)
print(f"\nBest model: {best_model_name}")scikit-survival fully integrates with scikit-learn's ecosystem:
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sksurv.linear_model import CoxPHSurvivalAnalysis
from sksurv.metrics import as_concordance_index_ipcw_scorer
# Build the pipeline, then wrap it so .score() is Uno's C-index.
# Wrapping the whole pipeline keeps scaling inside each CV fold (no leakage).
pipeline = Pipeline([
('scaler', StandardScaler()),
('model', CoxPHSurvivalAnalysis())
])
wrapped = as_concordance_index_ipcw_scorer(pipeline, tau=y['time'].max())
# Cross-validation uses the wrapped estimator's .score(); leave scoring=None
scores = cross_val_score(wrapped, X, y, cv=5)
# Grid search: params live under estimator__ (wrapper) then the pipeline step
param_grid = {'estimator__model__alpha': [0.1, 1.0, 10.0]}
cv = GridSearchCV(wrapped, param_grid, cv=5)
cv.fit(X, y).score()); pass the wrapped object as the estimator and prefix params with estimator__This skill includes detailed reference files for specific topics:
Load these reference files when detailed information is needed for specific tasks.
sksurv.datasets for practice datasets (GBSG2, WHAS500, veterans lung cancer, etc.)# Models
from sksurv.linear_model import CoxPHSurvivalAnalysis, CoxnetSurvivalAnalysis, IPCRidge
from sksurv.ensemble import RandomSurvivalForest, GradientBoostingSurvivalAnalysis
from sksurv.svm import FastSurvivalSVM, FastKernelSurvivalSVM
from sksurv.tree import SurvivalTree
# Evaluation metrics
from sksurv.metrics import (
concordance_index_censored,
concordance_index_ipcw,
cumulative_dynamic_auc,
brier_score,
integrated_brier_score,
as_concordance_index_ipcw_scorer,
as_integrated_brier_score_scorer
)
# Non-parametric estimation
from sksurv.nonparametric import (
kaplan_meier_estimator,
nelson_aalen_estimator,
cumulative_incidence_competing_risks
)
# Data handling
from sksurv.util import Surv
from sksurv.preprocessing import OneHotEncoder, encode_categorical
from sksurv.datasets import load_gbsg2, load_breast_cancer, load_veterans_lung_cancer
# Kernels
from sksurv.kernels import ClinicalKernelTransform~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.