RiemanianManifoldModel#
Module: leaspy.models.riemanian_manifold
Inherits from: TimeReparametrizedModel
While TimeReparametrizedModel defines when each patient progresses (time shifts and acceleration), RiemanianManifoldModel defines the geometric structure that governs how multiple biomarkers evolve together. It ensures that the progression curve is a geodesic (shortest path) on a Riemannian manifold, so that multivariate trajectories remain geometrically consistent.
This class is largely abstract — it sets up the geometric framework but delegates the actual curve shape to concrete subclasses like LogisticModel or JointModel.
Abstract Methods: What Subclasses Must Provide#
RiemanianManifoldModel does not know what the progression curve looks like. It forces subclasses to define two things:
metric(*, g)(abstract, staticmethod): The Riemannian metric tensor, computed from the parameter \(g\). This is what determines the geometry of the space. For example,LogisticModelreturns \((g + 1)^2 / g\), whileLinearModelreturns a constant metric of 1 (Euclidean space).model_with_sources(*, rt, space_shifts, metric, v0, g)(abstract, classmethod): The actual equation that computes biomarker values from reparametrized time, spatial shifts, and population parameters.model_no_sources(*, rt, metric, v0, g)(concrete): Delegates tomodel_with_sourceswithspace_shifts=torch.zeros((1, 1)), effectively removing spatial effects.
Centering \(\xi\) (Speed Factor): Identifiability Fix#
In a mixed-effects model on a manifold, there’s a non-identifiability problem: if the population velocity \(v_0\) increases while individual accelerations \(\xi_i\) decrease by the same amount, the resulting trajectories are identical — the model can’t distinguish between the two.
To fix this, RiemanianManifoldModel overrides compute_sufficient_statistics() to center \(\xi\) before each M-step:
Compute \(\bar{\xi} = \text{mean}(\xi_i)\)
Center: \(\xi_i \leftarrow \xi_i - \bar{\xi}\)
Compensate: \(\log v_0 \leftarrow \log v_0 + \bar{\xi}\)
Why this works: The mean \(\bar{\xi}\) removed from individuals is transferred to \(\log v_0\), so the overall model output doesn’t change — it’s just a redistribution between population and individual parameters. After this operation, the average \(\xi_i\) is exactly 0, which means the “typical” patient progresses at exactly the population speed \(v_0\).
This operation is safe because it only changes the magnitude of \(v_0\), not its direction — so the orthonormal basis (which depends on the direction of \(v_0\)) doesn’t need to be recomputed.
Variables Defined#
get_variables_specs() extends the parent’s specs with the geometric variables:
Variable |
Type |
Description |
|---|---|---|
|
|
Fixed at 0.0 (prior mean of \(\xi\), because average acceleration = \(e^0 = 1\)) |
|
|
Prior mean of log-velocities, shape |
|
|
Fixed at 0.01 (tight prior on |
|
|
Log-velocity vector, sampled from a Normal prior with mean |
|
|
Velocity vector, \(v_0 = e^{\log v_0}\) via |
|
|
Riemannian metric, delegates to the abstract |
|
|
Model output — delegates to |
Additional variables when source_dimension >= 1#
Variable |
Type |
Description |
|---|---|---|
|
|
Squared metric via |
|
|
Basis orthogonal to \(v_0\) w.r.t. the metric, shape |
What Comes Next#
RiemanianManifoldModel defines the geometric rules but leaves the curve equation abstract. The LogisticModel (or LinearModel) implements metric and model_with_sources, giving the manifold its concrete shape — e.g., a sigmoid surface for the logistic case.