Skip to main content

Spatially-Adaptive Gated Activation (SAGA) for medical image restoration

Project description

SAGA — Spatially-Adaptive Gated Activation

CI PyPI version License: MIT DOI Paper

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 — CT slices, 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 a learned spatial gating map that modulates the activation response position-by-position:

G(X)    = σ(W_g * X)        # spatial gate (depthwise-separable conv)
SAGA(X) = G(X) ⊙ φ(X)      # φ = SiLU (default)

This two-path design lets the network selectively amplify high-frequency boundary signals while smoothly gating uniform background areas — without increasing the depth of the network.


Installation

pip install saga-activation

Or install from source:

git clone 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

import torch
from saga import SAGA

# Replace any activation layer with SAGA
act = SAGA(in_channels=64)          # matches the channel dim of your feature map
x   = torch.randn(2, 64, 256, 256)  # (B, C, H, W)
y   = act(x)                         # same shape: (2, 64, 256, 256)

Inside a U-Net encoder 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, 3, padding=1, bias=False),
            nn.BatchNorm2d(out_ch),
            SAGA(out_ch),                          # ← swap in SAGA here
            nn.Conv2d(out_ch, out_ch, 3, padding=1, bias=False),
            nn.BatchNorm2d(out_ch),
            SAGA(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

Base-activation variants

from saga import SAGA

act_relu = SAGA(64, base_activation="relu")
act_gelu = SAGA(64, base_activation="gelu")
act_tanh = SAGA(64, base_activation="tanh")

Gate curriculum training

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/
├── 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, edge cases, GPU, gradients)
│
├── SAGA_Supplementary_Code/     # original experimental pipeline
│   ├── models/
│   │   ├── saga_layer.py        # raw research implementation
│   │   ├── unet.py
│   │   ├── resnet.py
│   │   ├── edsr.py
│   │   └── vggnet.py
│   ├── generate_dataset.py
│   ├── train.py
│   ├── evaluate.py
│   ├── xai_analysis.py
│   └── clinical_validation.py
│
├── docs/                        # Sphinx documentation source
├── .github/workflows/ci.yml     # GitHub Actions CI
├── pyproject.toml
└── README.md

Experimental Results (summary)

Model Activation CT PSNR (dB) CT SSIM DXA PSNR (dB) DXA SSIM
U-Net ReLU 32.14 0.891 30.87 0.873
U-Net SiLU 33.01 0.902 31.54 0.881
U-Net SAGA 34.67 0.921 33.12 0.903
DeblurResNet ReLU 31.89 0.883 30.21 0.864
DeblurResNet SAGA 34.11 0.916 32.78 0.897

Full results and ablation studies are reported in the paper.


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

saga_activation-0.1.0.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

saga_activation-0.1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file saga_activation-0.1.0.tar.gz.

File metadata

  • Download URL: saga_activation-0.1.0.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.5

File hashes

Hashes for saga_activation-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f30235a078a30660d2fb560c163145b6b883ee650fb92a581adf4ff23d91e5e1
MD5 180478d177d9842f7b23e97252381a85
BLAKE2b-256 176d4bb3ab2c288658d62638e920e2914d8b50291f051977400e99d325984fee

See more details on using hashes here.

File details

Details for the file saga_activation-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for saga_activation-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c0b9830b13b4fb774e4c08fab0d28e4de07e679e3811a5f0e0c1925468606d15
MD5 5b8168bfd21f5a84819c4475da3258eb
BLAKE2b-256 0f924dfa40fc833e93bd5cc21bc9e7b34bdb39936f67c19b3cfa1b52f24ef2f9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page