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.7

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.7
File Size Uploaded
survival_rl-0.0.7.tar.gz 8.0 kB Details

Built distribution (wheel)

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

Total release size: 16.8 kB

Release files / survival_rl-0.0.7.tar.gz

Download URL survival_rl-0.0.7.tar.gz
Size 8.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0f53302da92cea6b176f3f64ef35189cfe548f972498601bedd26cedd0cf8ab6
BLAKE2b-256 checksum
How to use checksums
890bd052cb37aa420a85355a810508fd39242fe49a8064fb51569cacff98e361
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

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

Download URL survival_rl-0.0.7-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6df5b52540fffb06ce369786731844ab6b78f842efe72ea6c6d7305f044f29bd
BLAKE2b-256 checksum
How to use checksums
3e8ff56c9ebd00395aa2bf87071ae3d68cd5e6e32330c64873f334687246d7e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Release history Release notifications | RSS feed

0.0.9

2 release files

0.0.8

2 release files

This release

0.0.7 This release

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