Skip to main content

RANI: Rational Adaptive Normalizing Initialization — a novel self-normalizing activation function with learnable parameters

Project description

RANI — Rational Adaptive Normalizing Initialization

A novel self-normalizing activation function with learnable per-layer parameters.

Author: Nikki Rani


What is RANI?

RANI is a new activation function that combines three properties that no existing activation function has simultaneously:

Property RANI SELU GELU Swish PReLU
Self-normalizing (no BatchNorm needed)
Learnable per-layer parameters
Zero transcendentals on positive branch

Formula

RANI(x) = λ · x · (1 + α·|x|) / (1 + |x|)    for x ≥ 0   ← rational, no exp()
RANI(x) = λ · α · (eˣ − 1)                     for x < 0   ← exponential

Default parameters — derived from self-normalizing fixed-point equations:

Parameter Symbol Default value Role
Asymmetry α 1.6733 Controls negative saturation depth and positive slope
Scale λ 1.0507 Controls overall function amplitude

Both parameters are learned per layer during training via backpropagation.


Install

pip install rani

Quick Start — PyTorch

import torch.nn as nn
from rani import RANI, init_rani_network

# Build a network with RANI activations
model = nn.Sequential(
    nn.Linear(784, 512),
    RANI(),                    # alpha=1.6733, lam=1.0507 — both learnable
    nn.Linear(512, 256),
    RANI(),
    nn.Linear(256, 128),
    RANI(),
    nn.Linear(128, 10),
)

# Apply the mathematically correct weight initialization for RANI
# (LeCun normal: std = 1/sqrt(fan_in) — derived from the fixed-point equations)
init_rani_network(model)

# Train normally with any optimizer
import torch
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

Functional version with fixed parameters:

from rani import rani
import torch

x = torch.randn(32, 256)
y = rani(x)                    # alpha=1.6733, lam=1.0507 fixed

Check what the network learned after training:

for name, module in model.named_modules():
    if isinstance(module, RANI):
        print(f"{name}: alpha={module.alpha.item():.4f}, lam={module.lam.item():.4f}")
# Each layer learns its own optimal alpha and lambda values

Why does it work without BatchNorm?

RANI is mathematically self-normalizing. If the input to a layer has mean 0 and variance 1, the output also has mean 0 and variance 1 — regardless of how many layers deep you go.

This is proved via the fixed-point equations:

E[ RANI(Z) ]   = 0    ← mean is preserved as zero
E[ RANI(Z)² ]  = 1    ← variance is preserved as one

where Z ~ N(0, 1). The initialization values α = 1.6733, λ = 1.0507 are the exact numerical solution to this system.

After initialization, α and λ are free to be learned — each layer adapts to its own optimal values. This is the key advantage over SELU, where these values are permanently fixed.


FLOP Count — Why the Positive Branch Is Cheap

The positive branch uses only:

Operation Count
Multiply 3
Add 2
Divide 1
Transcendentals (exp, erf, sigmoid) 0

Compare with GELU (needs erf), Swish (needs exp via sigmoid), and Mish (needs 2 × exp + tanh). RANI's positive branch is faster on both CPU and GPU for this reason.


Running the Tests

cd rani-activation
pytest tests/test_torch.py -v

Expected output: 14 passed


Mathematical Foundation

The complete derivation covers 6 parts: formal definition, regularity proofs, self-normalizing fixed-point equations, stability analysis via the Banach contraction theorem, and FLOP count comparison.

Key results:

Result Description
Theorem 3.1 RANI is continuous on all of ℝ
Theorem 3.3 RANI is Lipschitz with L = λ·max(1, α)
Theorem 3.4 RANI saturates at −λα as x → −∞
Result 4.1 α* = 1.6733, λ* = 1.0507 (self-normalizing init)
Theorem 5.1 Fixed point (0, 1) is stable attractor, ρ(J) < 1

Full mathematical details and paper citation coming soon.


Package Structure

rani/
├── __init__.py         ← package entry point
├── torch_rani.py       ← PyTorch implementation
└── tf_rani.py          ← TensorFlow implementation (pending Python 3.14 support)

Citation

Citation details will be added after paper publication.


License

Apache License 2.0 — see LICENSE for details.

Author

Nikki Rani GitHub | PyPI

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

rani-1.0.1.tar.gz (20.1 kB view details)

Uploaded Source

Built Distribution

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

rani-1.0.1-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file rani-1.0.1.tar.gz.

File metadata

  • Download URL: rani-1.0.1.tar.gz
  • Upload date:
  • Size: 20.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for rani-1.0.1.tar.gz
Algorithm Hash digest
SHA256 eb108fb6115d290f244fa6ed0e5dae283b6ac1477e6acbf409e933f3fbebcdbe
MD5 e695ecc5644e148a6c112a9db0933143
BLAKE2b-256 52aff2a03aba1fd380b69498b210a021edca62230d94c2a8b0017ae97c5c53b2

See more details on using hashes here.

File details

Details for the file rani-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: rani-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for rani-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0a4e904375ac51a18608cf38ab340c7a74ece6d5d2eceff1327bb354ce6ce4d6
MD5 b8b43dccb4543536ad22edd9d2e29878
BLAKE2b-256 0a7cec7939219318dc18879c368bdb3cc52218eb17ebb9b3990084844fd593c1

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