Skip to main content

Survival RL

Explorations into an application of survival analysis to RL, proposed by Tiofack et al. of Inria earlier this year

Install

$ pip install survival-rl

Usage

HazardCritic takes a batch of states, actions and events, and predicts for each state-action pair the time bin in which the event is first dwelled upon, conditioned on that event. It is trained by maximum likelihood on the predicted logits, where reach_event_index marks the observed time bin, and -1 (or anything at or past horizon_cutoff) is treated as right censored.

import torch
from survival_rl import HazardCritic

critic = HazardCritic(
    dim = 64,
    depth = 2,
    dim_state = 8,
    num_actions = 3,
    pred_time_bins = 32
)

state  = torch.randn(16, 8)
action = torch.randn(16, 3)
event  = torch.randn(16, 8)     # every state and action is conditioned on the event

reach_event_index = torch.randint(0, 32, (16,))
horizon_cutoff    = torch.full((16,), 32)

loss = critic(state, action, event, reach_event_index = reach_event_index, horizon_cutoff = horizon_cutoff)
loss.backward()

Once trained, a policy can be extracted for reaching the event, or avoiding it with negate = True, given any actor of the form (state, event) -> action.

class Actor(torch.nn.Module):
    def __init__(self, dim_state = 8, dim_event = 8, num_actions = 3):
        super().__init__()
        self.net = torch.nn.Sequential(
            torch.nn.Linear(dim_state + dim_event, 64),
            torch.nn.SiLU(),
            torch.nn.Linear(64, num_actions)
        )

    def forward(self, state, event):
        return self.net(torch.cat((state, event), dim = -1))

actor = Actor()

# maximize the value to reach the event

loss = -critic.extract_policy(actor, state, event).mean()
loss.backward()

# or pass `negate = True` to avoid the event instead

loss = -critic.extract_policy(actor, state, event, negate = True).mean()
loss.backward()

The reach indices for training are computed from any trajectory data with compute_first_dwell_time, which finds the first time each trajectory dwells within eps of its event.

import torch
from survival_rl import compute_first_dwell_time

states = torch.randn(4, 64, 8)      # (batch, time, dim)
event  = states[:, -1:]             # (batch, num_queries, dim)

# first dwell of each trajectory at its event - -1 means it was never reached,
# and is right censored at `horizon_cutoff`

reach_event_index, horizon_cutoff = compute_first_dwell_time(event, states = states, eps = 0.25)

For a variant where the time bins compete for a single unit of mass through a softmax, use HazardCriticCompetitive in place of HazardCritic.

Citations

@inproceedings{Tiofack2026SVL,
    title     = {SVL: Goal-Conditioned Reinforcement Learning as Survival Learning},
    author    = {Franki Nguimatsia Tiofack and Fabian Schramm and Th{\'e}otime Le Hellard and Justin Carpentier},
    booktitle = {International Conference on Machine Learning (ICML)},
    year      = {2026},
    url       = {https://arxiv.org/abs/2604.17551}
}
@article{Tiofack2026SRL,
    title   = {Survival Reinforcement Learning: Toward Scalable Self-Supervised RL},
    author  = {Franki Nguimatsia-Tiofack and Fabian Schramm and Th{\'e}otime Le Hellard and Justin Carpentier},
    journal = {arXiv preprint arXiv:2605.31273},
    year    = {2026},
    note    = {19th European Workshop on Reinforcement Learning (EWRL), Oral},
    url     = {https://arxiv.org/abs/2605.31273}
}

Metadata

Release files for survival-rl 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for survival-rl 0.0.9
File Size Uploaded
survival_rl-0.0.9.tar.gz 8.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for survival-rl 0.0.9
File Interpreter ABI Platform
survival_rl-0.0.9-py3-none-any.whl Python 3 none any Details

Total release size: 18.7 kB

Release files / survival_rl-0.0.9.tar.gz

Download URL survival_rl-0.0.9.tar.gz
Size 8.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b6ff2f68197730c02faff0f305abaa50f29e9b4c6ac2bd02f6c5391a0b0b566d
BLAKE2b-256 checksum
How to use checksums
f19f4cd219fb32d30d1bf080bf784a68b398f1bc03ccae67b5aba2a4a0f3776c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Release files / survival_rl-0.0.9-py3-none-any.whl

Download URL survival_rl-0.0.9-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80a703cec8f4aaa90f761dc88750b4ef9430d6255b8b748306bba74ecaf9d37e
BLAKE2b-256 checksum
How to use checksums
ac4fe7b5c66fb8c2280758098e84473ba7011d79b4caf9b8c5faff68c1a7fc91
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Release history Release notifications | RSS feed

This release

0.0.9 This release

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page