Skip to content

stevenk42/HyperbolicGuard

Repository files navigation

HyperbolicGuard 🛡️

A lightweight PyTorch module for stabilizing hyperbolic embeddings in the Poincaré disk. Designed as a drop-in safeguard against runaway norms, invalid Möbius operations, and adversarial edge cases.

HyperbolicGuard Logo

Why?

Hyperbolic space is excellent for encoding hierarchies, trees, and taxonomies, but it’s numerically fragile:

  • 🚧 Points near the unit boundary (‖z‖ → 1) cause distance blowups
  • 🌀 Jacobians can collapse or explode
  • ⚠️ Conjugations near the boundary amplify floating-point errors
  • 🎯 Boundary attractors can collapse into narrow angular beams

HyperbolicGuard provides surgical safeguards to make hyperbolic embeddings usable in practice.


Features

  • Curvature-aware damping: soft boundary suppression
  • Hyperbolic operator norm check: power-iteration estimate of Jacobian growth
  • Stable conjugations: real-tensor Cayley transforms (disk ↔ upper half-plane)
  • Angular entropy regularization: prevent beam-forming near the rim
  • Horocycle stressors: adversarial pushes for robustness testing
  • Numerical safety: guarded denominators, no complex literals
  • Unit-tested Cayley roundtrips

Installation

git clone https://github.com/your-org/hyperbolic-guard.git
cd hyperbolic-guard
pip install -r requirements.txt

Dependencies:

  • torch >= 1.12

Usage

import torch
from hyperbolic_guard import HyperbolicGuard

guard = HyperbolicGuard(max_radius=0.95)

# Example batch of embeddings
z = torch.randn(16, 2) * 0.5

# Apply safeguards
z = project_to_radius(z, guard.max_radius)   # your projection fn
z = guard.hyperbolic_damp(z)                 # curvature-aware damping

# Monitor stability
opnorm = guard.hyp_opnorm(lambda x: f(x), z) # f = your encoder/decoder
if opnorm.quantile(0.95) > guard.tau:
    print("Warning: high operator norm detected!")

# Add angular entropy penalty to your training loss
loss = base_loss + guard.angular_entropy_penalty(z)

API

Core Methods

  • hyperbolic_damp(z, alpha=2.0) → curvature-aware damping near boundary
  • hyp_opnorm(f, z, iters=4) → per-sample hyperbolic operator norm estimate
  • disk_to_uhp(z) / uhp_to_disk(w) → Cayley transforms (real-tensor)
  • angular_entropy_penalty(z, n_bins=32, lam=1e-3) → regularizer for angular spread
  • horocycle_perturb(z, alpha, u_dir) → push along horocycles for robustness tests

Key Constants

  • max_radius=0.95 → soft wall margin
  • tau=0.99 → operator norm threshold
  • r_crit=0.85 → start angular entropy regularization

Unit Test

def test_cayley_roundtrip():
    guard = HyperbolicGuard()
    z = torch.randn(1000, 2) * 0.9  # inside disk
    w = guard.disk_to_uhp(z)
    z_recon = guard.uhp_to_disk(w)
    err = (z - z_recon).norm(dim=-1).max()
    print(f"Cayley roundtrip error: {err:.2e}")
    assert err < 1e-6

Integration Example

class HyperbolicModel(nn.Module):
    def __init__(self, f):
        super().__init__()
        self.guard = HyperbolicGuard(max_radius=0.95)
        self.f = f  # your encoder/decoder

    def forward(self, z, base_loss=0.0):
        z = project_to_radius(z, self.guard.max_radius)
        z = self.guard.hyperbolic_damp(z)

        opnorm = self.guard.hyp_opnorm(self.f, z)
        if opnorm.quantile(0.95) > self.guard.tau:
            print("Ricci flow smoothing may be needed")

        loss = base_loss + self.guard.angular_entropy_penalty(z)
        return self.f(z), loss

License

MIT License © 2025