skills/scikit-survival/references/svm-models.md
Verified for scikit-survival 0.28.0 on 2026-07-23.
Survival SVMs optimize ranking, regression, or a mixture. They generally return a scalar score, not a baseline survival function or cumulative hazard function. Therefore:
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sksurv.svm import FastSurvivalSVM
model = make_pipeline(
StandardScaler(),
FastSurvivalSVM(
alpha=1.0,
rank_ratio=1.0,
max_iter=1000,
tol=1e-5,
random_state=20260723,
),
)
model.fit(X_train, y_train)
risk = model.predict(X_test)
Current signature:
FastSurvivalSVM(
alpha=1, *,
rank_ratio=1.0,
fit_intercept=False,
max_iter=20,
verbose=False,
tol=None,
optimizer=None,
random_state=None,
timeit=False,
)
Key semantics:
rank_ratio=1.0: ranking-only objective; higher predictions indicate shorter
survival/higher event risk.0 < rank_ratio < 1: mixed ranking and regression.rank_ratio=0.0: regression-only objective.rank_ratio < 1, prediction is time-oriented (internally based on log
observed time): lower prediction means shorter survival. For a metric requiring
higher event risk, use -prediction and document the conversion.alpha controls regularization; tune it within inner CV.Do not use an arbitrary sign simply because a C-index improves. The sign follows the model objective and target interpretation.
from sksurv.svm import FastKernelSurvivalSVM
model = FastKernelSurvivalSVM(
alpha=1.0,
rank_ratio=1.0,
kernel="rbf",
gamma=0.05,
max_iter=100,
tol=1e-5,
random_state=20260723,
)
model.fit(X_train_scaled, y_train)
risk = model.predict(X_test_scaled)
Current signature:
FastKernelSurvivalSVM(
alpha=1, *,
rank_ratio=1.0,
fit_intercept=False,
kernel="rbf",
gamma=None,
degree=3,
coef0=1,
kernel_params=None,
max_iter=20,
verbose=False,
tol=None,
optimizer=None,
random_state=None,
timeit=False,
)
Kernel choices follow scikit-learn pairwise-kernel behavior, including "linear",
"poly", "rbf", "sigmoid", callable kernels, and "precomputed" where
supported. Do not copy older examples that use gamma="scale" without checking
the current API; the current scikit-survival parameter default is None.
Kernel fitting and prediction depend on training rows and can require quadratic-size kernel matrices. Enforce row/memory bounds before fitting.
Current additional estimators:
HingeLossSurvivalSVM(alpha=1.0, solver="ecos", kernel="linear", pairs="all", ...)MinlipSurvivalAnalysis(alpha=1.0, solver="ecos", kernel="linear", pairs="nearest", ...)NaiveSurvivalSVM(penalty="l2", loss="squared_hinge", dual=False, alpha=1.0, ...)Important current differences:
HingeLossSurvivalSVM and MinlipSurvivalAnalysis do not have a
random_state constructor parameter.NaiveSurvivalSVM uses a linear-SVM-style formulation and is mainly useful for
small comparisons; it is not the fast implementation.Use the exact current signature rather than transferring parameters across SVM classes.
Scale continuous features and fit scaling only on training folds:
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
preprocess = ColumnTransformer(
[
(
"num",
make_pipeline(SimpleImputer(strategy="median"), StandardScaler()),
numeric_columns,
),
(
"cat",
make_pipeline(
SimpleImputer(strategy="most_frequent"),
OneHotEncoder(
drop="first",
handle_unknown="ignore",
sparse_output=False,
),
),
categorical_columns,
),
],
sparse_threshold=0.0,
)
model = make_pipeline(
preprocess,
FastSurvivalSVM(rank_ratio=1.0, random_state=20260723),
)
Do not call StandardScaler.fit_transform(X) before cross-validation. Keeping it
inside the pipeline makes every inner and outer fold independent.
For "precomputed", training input must be a square
(n_train, n_train) kernel matrix; test input must be
(n_test, n_train) with columns in the identical training order.
sksurv.kernels.ClinicalKernelTransform and clinical_kernel() support mixed
continuous, ordinal, and nominal DataFrame columns, including pandas/Polars in
0.28. They do not accept an ad hoc list of (clinical, molecular) tuples as a
special API. Fit the transform on a clearly typed training DataFrame or explicitly
precompute the kernel:
from sksurv.kernels import clinical_kernel
from sksurv.svm import FastKernelSurvivalSVM
kernel_train = clinical_kernel(X_train_typed)
kernel_test = clinical_kernel(X_test_typed, X_train_typed)
model = FastKernelSurvivalSVM(
kernel="precomputed",
rank_ratio=1.0,
random_state=20260723,
)
model.fit(kernel_train, y_train)
risk = model.predict(kernel_test)
Any data-dependent kernel typing, scaling, or parameter choice belongs inside the training/CV protocol.
Tune at least alpha; for kernel models also tune kernel and its parameters.
Keep the grid bounded:
from sklearn.model_selection import GridSearchCV
search = GridSearchCV(
pipeline,
{
"fastkernelsurvivalsvm__alpha": [0.1, 1.0, 10.0],
"fastkernelsurvivalsvm__gamma": [0.01, 0.05, 0.2],
},
cv=inner_splits,
error_score="raise",
n_jobs=1,
)
search.fit(X_outer_train, y_outer_train)
The actual parameter prefix depends on pipeline step names. Run this search within each outer fold for a nested-CV performance estimate. Do not:
alpha/gamma;For IPCW metrics, fit the censoring distribution on the corresponding outer training outcomes and keep the time grid within that fold's support.
predict_survival_function() or add a separately validated calibration stage.These are capability distinctions, not guarantees of performance.
SVM margins are arbitrary-scale predictions. A high C-index or dynamic AUC says that orderings discriminate under the chosen censoring estimator and horizon; it does not establish:
Report optimization convergence, score direction, kernel, preprocessing, tuning resamples, and censoring assumptions.
Official sources checked 2026-07-23: