KMNet: Discrete-Time Survival Analysis with Deep Learning
⚡ State-of-the-art survival analysis with deep learning and ranking losses ⚡
Documentation • Features • Installation • Quick Start • Demo Notebook • Citation
🎯 Use Cases & Applications
KMNet combines the power of deep neural networks with Kaplan-Meier inspired ranking losses to deliver state-of-the-art performance in discrete-time survival analysis. Perfect for clinical research, reliability engineering, and time-to-event prediction.
It extends standard neural survival models by incorporating a novel Kaplan-Meier inspired rank loss, allowing the model to learn not just from local hazard rates but also from global ranking constraints inherent in survival data.
This library provides a high-performance implementation using PyTorch JIT to speed up custom loss calculations, making it suitable for large-scale survival datasets.
🚀 Key Features
📊 Why KMNet?
| Feature | Traditional Methods | DeepSurv/Cox-PH | KMNet |
|---|---|---|---|
| Handles Non-Linear Effects | ❌ | ✅ | ✅ |
| Captures Ranking Information | ⚠️ Partial | ❌ | ✅ |
| Discrete Time Bins | ❌ | ❌ | ✅ |
| GPU Acceleration | ❌ | ✅ | ✅ |
| Flexible Loss Functions | ❌ | ⚠️ Limited | ✅ |
| JIT-Optimized | N/A | ❌ | ✅ |
📦 Installation
pip install kmnet
Or install the latest development version from source:
git clone https://github.com/yuvrajiro/KMNet.git
cd KMNet
pip install -e ".[dev]"
Requirements
- Python >= 3.8
- PyTorch >= 1.7.0
- NumPy, Pandas
- torchtuples
- pycox
- numba
⚡ Quick Start
Here is a complete example of how to use KMNet on a synthetic dataset. You can also check out the interactive demo notebook and the full documentation.
1. Data Preparation
KMNet requires the target variable (time and event) to be discretized. We use label_transforms from pycox for this.
import numpy as np
import pandas as pd
from kmnet.model import KMNet
# Generate synthetic data
def make_data(n=1000):
X = np.random.randn(n, 5).astype('float32')
T = np.random.exponential(1 / (0.1 * np.exp(0.5 * X[:, 0])))
C = np.random.exponential(1 / 0.05, size=n)
time = np.minimum(T, C)
event = (T <= C).astype('float32')
return X, time, event
X, time, event = make_data()
# Discretize time into 20 bins
num_durations = 20
labtrans = KMNet.label_transform(num_durations)
get_target = lambda df: (df['duration'].values, df['event'].values)
df = pd.DataFrame({'duration': time, 'event': event})
y = labtrans.fit_transform(*get_target(df))
2. Define the Neural Network
You can use any PyTorch network architecture. The output dimension must match the number of time bins.
import torch.nn as nn
in_features = X.shape[1]
out_features = labtrans.out_features
net = nn.Sequential(
nn.Linear(in_features, 32),
nn.ReLU(),
nn.Linear(32, 32),
nn.ReLU(),
nn.Linear(32, out_features)
)
3. Train the Model
Initialize KMNet and fit it to the data.
# Initialize model with the discretized time grid
model = KMNet(net, duration_index=labtrans.cuts)
# Train
batch_size = 64
epochs = 10
model.fit(X, y, batch_size, epochs, verbose=True)
4. Prediction and Visualization
Predict survival functions and plot them.
import matplotlib.pyplot as plt
# Predict survival probabilities for the first 5 samples
surv_df = model.predict_surv_df(X[:5])
# Plot
plt.figure(figsize=(10, 6))
for col in surv_df.columns:
plt.step(surv_df.index, surv_df[col], where="post")
plt.ylabel("Survival Probability")
plt.xlabel("Time")
plt.title("Predicted Survival Curves")
plt.show()
🔬 Mathematical Background
KMNet models the discrete conditional survival $p(t | x)$. The survival function is given by:
$$ \boxed{S(t | x) = \prod_{k=0}^{t} p(k | x)} $$
The loss function $\mathcal{L}$ is a weighted sum of two components:
$$ \boxed{\mathcal{L} = \alpha \mathcal{L}{bce} + (1 - \alpha)\lambda \mathcal{L}{Rank}} $$
📖 Click to expand detailed explanation
Loss Components
-
$\mathcal{L}_{bce}$ (Negative Log-Likelihood):
- Standard survival loss for discrete time
- Ensures the model fits the observed event times
- Handles censored data correctly
-
$\mathcal{L}_{Rank}$ (Rank Loss):
- Enforces correct ordering: $S(T_i | x_i) < S(T_i | x_j)$ if $T_i < T_j$
- Inspired by the Kaplan-Meier estimator
- Maintains global structure of survival curves
- Differentiable approximation using softplus/exponential penalties
📊 Performance & Optimization
⚡ Speed Benchmarks
The KMNet class leverages TorchScript (JIT) to compile the custom loss functions, eliminating Python interpreter overhead.
|
Benchmark Setup:
Results:
|
Scalability:
Tested on Intel i7, 16GB RAM |
🛠️ Advanced Configuration
You can customize the loss function parameters when initializing the model:
base: 'nll' (Negative Log-Likelihood) or 'bce' (Binary Cross-Entropy)rank_mode: 'full' (CDF-based) or 'conditional' rankingrank_penalty: 'softplus' or 'exp' for the ranking loss formulation
from kmnet.model import KMLoss
loss = KMLoss(
alpha=0.5, # Weight for NLL vs Rank loss
sigma=0.1, # Kernel width for soft ranking
base='nll', # 'nll' or 'bce'
rank_mode='full', # 'full' (CDF-based) or 'conditional'
rank_penalty='softplus' # 'softplus' or 'exp'
)
model = KMNet(net, loss=loss, duration_index=labtrans.cuts)
💬 Getting Help
- 📖 Documentation: yuvrajiro.github.io/KMNet (quickstart, method, API reference)
- 💡 Issues: Found a bug? Open an issue
- 💬 Discussions: Have questions? Start a discussion
- 📧 Email: For collaboration inquiries: yuvrajiro@gmail.com
🤝 Contributing
We welcome contributions! KMNet is an open-source research project.
How to contribute
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Areas we'd love help with:
- 📝 Documentation improvements
- 🧪 Additional benchmarks and examples
- 🐛 Bug fixes and testing
- ✨ New features (e.g., competing risks, time-varying covariates)
📄 License
Distributed under the MIT License. See LICENSE for more information.
📚 Citation (Under Consideration)
The paper is under review. Until it is published, please cite the software:
@software{goswami_kmnet,
title = {KMNet: Discrete-Time Survival Analysis with a Kaplan-Meier Inspired Rank Loss},
author = {Goswami, Rahul},
url = {https://github.com/yuvrajiro/KMNet},
year = {2025}
}
🏆 Acknowledgments
KMNet builds upon excellent work from:
- PyCox for survival analysis utilities
- TorchTuples for training infrastructure
- The PyTorch team for JIT compilation capabilities
Built with ❤️ for the survival analysis community
⭐ Star us on GitHub if KMNet helps your research!
Metadata
Release files for kmnet 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kmnet-0.2.0.tar.gz | 78.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kmnet-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 91.5 kB
Release files / kmnet-0.2.0.tar.gz
| Download URL | kmnet-0.2.0.tar.gz |
|---|---|
| Size | 78.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bebd1f613e0d76bad7c377480e24e975bc0bf3b70dd8cf2715dfbfb0b95777be
|
|
BLAKE2b-256 checksum How to use checksums |
51364ae8e40d843c420f85b904df5c0d3c90547c2444710fe292e42fbdeba58b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / kmnet-0.2.0-py3-none-any.whl
| Download URL | kmnet-0.2.0-py3-none-any.whl |
|---|---|
| Size | 12.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ea150717b9a4dae7b67c87fd1e6e7383c2d27d5c2b91ed5d2c3c3a66ea845fbb
|
|
BLAKE2b-256 checksum How to use checksums |
6754e9902368234e5c190f1db0b92b0d9c7da652ac097a64757a01ad989c151f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|