Spatially-Adaptive Gated Activation (SAGA) for medical image restoration
Project description
SAGA — Spatially-Adaptive Gated Activation
An Interpretable Deep Learning Method for Medical Image Deblurring and Restoration > Siju K.S., Vipin Venugopal, Mithun Kumar Kar, Jayakrishnan Anandakrishnan
Healthcare Analytics 9 (2026) 100468 · doi:10.1016/j.health.2026.100468
Overview
Standard activation functions (ReLU, SiLU, GELU) treat every spatial location in a feature map identically. In medical images — such as CT slices and DXA scans — the information content is not spatially uniform: anatomical boundaries carry high-frequency diagnostically-critical detail, while homogeneous regions (background, soft tissue) require smooth suppression.
SAGA introduces an adaptive residual activation block that modulates the activation response position-by-position using highly efficient depthwise and pointwise convolutions:
- Context Extraction:
T(X) = BN(W_s *3 X)(Depthwise 3x3 Convolution) - Gate Generation:
G(X) = σ(W_g *1 T(X))(Pointwise 1x1 Convolution) - Residual Boost:
B(X) = max(0, T(X) - X) - Output:
SAGA(X) = X + (G(X) ⊙ B(X))
This multi-path design lets the network selectively amplify high-frequency boundary signals while smoothly gating uniform background areas. It acts as a lightweight, drop-in structural upgrade that preserves spatial tensor dimensions without increasing the overall depth of the network.
Installation
pip install saga-activation
Or install from source:
git clone [https://github.com/sijuswamyresearch/SAGA.git](https://github.com/sijuswamyresearch/SAGA.git)
cd SAGA
pip install -e ".[dev]"
Requirements: Python ≥ 3.10, PyTorch ≥ 2.0
Quick Start
Drop-in activation replacement
Because SAGA extracts spatial features, it requires the channel dimension of the incoming tensor upon initialization.
import torch
from saga import SAGA
# Initialize SAGA with the number of incoming channels
act = SAGA(in_channels=64)
x = torch.randn(2, 64, 256, 256) # (Batch, Channels, Height, Width)
# Forward pass preserves exact tensor shape
y = act(x) # Output shape: (2, 64, 256, 256)
Inside a U-Net or ResNet block
import torch.nn as nn
from saga import SAGA
class EncoderBlock(nn.Module):
def __init__(self, in_ch, out_ch):
super().__init__()
self.block = nn.Sequential(
nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(out_ch),
SAGA(in_channels=out_ch), # ← swap in SAGA here
nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(out_ch),
SAGA(in_channels=out_ch),
)
self.pool = nn.MaxPool2d(2)
def forward(self, x):
return self.pool(self.block(x))
Pre-built residual blocks
from saga import SAGAResBlock, SAGABottleneck
res = SAGAResBlock(64) # standard residual block
bottle = SAGABottleneck(64, out_channels=128) # bottleneck variant
Gate curriculum training
For advanced optimization, you can freeze the spatial gates during the initial epochs to allow the main backbone weights to stabilize, then unfreeze them for fine-tuning.
from saga.utils import freeze_gate, unfreeze_gate
# Phase 1 – train backbone only
freeze_gate(model)
train(model, epochs=10, lr=1e-3)
# Phase 2 – fine-tune gates
unfreeze_gate(model)
train(model, epochs=5, lr=1e-4)
Repository Structure
SAGA/
├── src/
│ └── saga/ # installable Python package
│ ├── __init__.py
│ ├── activation.py # SAGA operator (core)
│ ├── blocks.py # SAGAResBlock, SAGABottleneck
│ └── utils.py # parameter counting, gate freeze helpers
│
├── tests/
│ ├── conftest.py
│ └── test_saga.py # pytest suite (shapes, gradients, CPU/GPU)
├── docs/ # Sphinx documentation source
├── pyproject.toml # Build configuration
└── README.md
Running the Tests
pytest tests/ -v
To run with coverage:
pytest tests/ --cov=saga --cov-report=term-missing
Citing
If SAGA is useful in your research, please cite:
@article{siju2026saga,
title = {An interpretable deep learning method for medical image deblurring and restoration},
author = {Siju K.S. and Vipin Venugopal and Mithun Kumar Kar and Jayakrishnan Anandakrishnan},
journal = {Healthcare Analytics},
volume = {9},
pages = {100468},
year = {2026},
doi = {10.1016/j.health.2026.100468}
}
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file saga_activation-0.1.1.tar.gz.
File metadata
- Download URL: saga_activation-0.1.1.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c59cddf387c97aad023e2dcc8dae81f2ca36b843b0db5699e094deb6ffa92aa0
|
|
| MD5 |
3ef243ce35e9597d3ff25a0ba49ae97d
|
|
| BLAKE2b-256 |
3c8c2c23a02c4ff46480622a754a60b68f2edec3a70a9d3a826c6624e466b37d
|
File details
Details for the file saga_activation-0.1.1-py3-none-any.whl.
File metadata
- Download URL: saga_activation-0.1.1-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f146590a918be36c466efd73ffd0cbaf9b7825209c61cca5a831d955b4440a0e
|
|
| MD5 |
3749d65292d31740c0c6ccb42d01bdb0
|
|
| BLAKE2b-256 |
42938c437f38a2cbd3748082da05316c19a75c3a808d3feccecca5111f9c0070
|