Activation Functions¶
Hyperbolic activations that preserve manifold constraints. Three families:
curvature-preserving hyp_* (HRC pattern, fixed c), Poincaré tangent-space
wrappers, and curvature-changing hrc_* (c_in → c_out).
How the HRC-pattern activations work
The hyp_* / hrc_* activations operate on the Hyperboloid: (1) extract space
components x_s = x[..., 1:], (2) apply the activation y_s = f(x_s), (3) scale
for curvature change y_s = sqrt(c_in/c_out)·y_s, (4) reconstruct time
y_t = sqrt(‖y_s‖² + 1/c_out). This avoids exp/log maps while preserving
geometry. The Poincaré activations instead use logmap_0 → activation → expmap_0.
Curvature-preserving (Hyperboloid)¶
hyperbolix.nn_layers.hyp_relu ¶
Apply ReLU activation to space components of hyperboloid point(s).
Curvature-preserving wrapper around hrc_relu(x, c_in=c, c_out=c).
This function applies the ReLU activation function to the spatial components of hyperboloid points and reconstructs valid manifold points using the hyperboloid constraint.
Mathematical formula: y = [sqrt(||ReLU(x_s)||^2 + 1/c), ReLU(x_s)]
where x_s are the spatial components x[..., 1:].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold in ambient space, where ... represents arbitrary batch dimensions. The last dimension contains the time component (x[..., 0]) and spatial components (x[..., 1:]). |
required |
c
|
float
|
Curvature parameter, must be positive (c > 0). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold, same shape as input. |
Notes
- This function applies ReLU only to spatial components, not the time component
- The time component is reconstructed using the hyperboloid constraint: -x₀² + ||x_rest||² = -1/c
- This approach avoids frequent exp/log maps for better numerical stability
- Works on arrays of any shape, similar to jax.nn.relu
- For curvature-changing transformations, use
hrc_reluwhich supports different input/output curvatures
References
Ahmad Bdeir, Kristian Schwethelm, and Niels Landwehr. "Fully hyperbolic convolutional neural networks for computer vision." arXiv preprint arXiv:2303.15919 (2023).
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import hyp_relu
>>>
>>> # Single point
>>> x = jnp.array([1.05, 0.1, -0.2, 0.15])
>>> y = hyp_relu(x, c=1.0)
>>> y.shape
(4,)
>>>
>>> # Batch of points
>>> x_batch = jnp.ones((8, 5)) # 8 points in 5-dim ambient space
>>> y_batch = hyp_relu(x_batch, c=1.0)
>>> y_batch.shape
(8, 5)
>>>
>>> # Multi-dimensional batch (e.g., feature maps)
>>> x_feature = jnp.ones((4, 16, 16, 10)) # 4 images, 16x16 spatial, 10-dim
>>> y_feature = hyp_relu(x_feature, c=1.0)
>>> y_feature.shape
(4, 16, 16, 10)
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hyp_leaky_relu ¶
hyp_leaky_relu(
x: Float[Array, "... dim_plus_1"],
c: float,
negative_slope: float = 0.01,
) -> Float[Array, "... dim_plus_1"]
Apply LeakyReLU activation to space components of hyperboloid point(s).
Curvature-preserving wrapper around hrc_leaky_relu(x, c_in=c, c_out=c, negative_slope).
This function applies the LeakyReLU activation function to the spatial components of hyperboloid points and reconstructs valid manifold points using the hyperboloid constraint.
Mathematical formula: y = [sqrt(||LeakyReLU(x_s)||^2 + 1/c), LeakyReLU(x_s)]
where x_s are the spatial components x[..., 1:], and LeakyReLU(x) = x if x > 0 else negative_slope * x.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold in ambient space, where ... represents arbitrary batch dimensions. The last dimension contains the time component (x[..., 0]) and spatial components (x[..., 1:]). |
required |
c
|
float
|
Curvature parameter, must be positive (c > 0). |
required |
negative_slope
|
float
|
Negative slope coefficient for LeakyReLU (default: 0.01). |
0.01
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold, same shape as input. |
Notes
- This function applies LeakyReLU only to spatial components
- The time component is reconstructed using the hyperboloid constraint
- LeakyReLU allows small negative values (scaled by negative_slope) which can help gradient flow compared to standard ReLU
- Works on arrays of any shape, similar to jax.nn.leaky_relu
- For curvature-changing transformations, use
hrc_leaky_reluwhich supports different input/output curvatures
References
Ahmad Bdeir, Kristian Schwethelm, and Niels Landwehr. "Fully hyperbolic convolutional neural networks for computer vision." arXiv preprint arXiv:2303.15919 (2023).
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import hyp_leaky_relu
>>>
>>> # Single point with default negative_slope
>>> x = jnp.array([1.05, 0.1, -0.2, 0.15])
>>> y = hyp_leaky_relu(x, c=1.0)
>>> y.shape
(4,)
>>>
>>> # Custom negative_slope
>>> y = hyp_leaky_relu(x, c=1.0, negative_slope=0.1)
>>>
>>> # Batch of points
>>> x_batch = jnp.ones((8, 5))
>>> y_batch = hyp_leaky_relu(x_batch, c=1.0, negative_slope=0.01)
>>> y_batch.shape
(8, 5)
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hyp_tanh ¶
Apply tanh activation to space components of hyperboloid point(s).
Curvature-preserving wrapper around hrc_tanh(x, c_in=c, c_out=c).
This function applies the hyperbolic tangent activation function to the spatial components of hyperboloid points and reconstructs valid manifold points using the hyperboloid constraint.
Mathematical formula: y = [sqrt(||tanh(x_s)||^2 + 1/c), tanh(x_s)]
where x_s are the spatial components x[..., 1:].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold in ambient space, where ... represents arbitrary batch dimensions. The last dimension contains the time component (x[..., 0]) and spatial components (x[..., 1:]). |
required |
c
|
float
|
Curvature parameter, must be positive (c > 0). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold, same shape as input. |
Notes
- This function applies tanh only to spatial components
- The time component is reconstructed using the hyperboloid constraint
- Tanh naturally bounds outputs in [-1, 1], which can help with stability
- Works on arrays of any shape, similar to jax.nn.tanh
- For curvature-changing transformations, use
hrc_tanhwhich supports different input/output curvatures
References
Ahmad Bdeir, Kristian Schwethelm, and Niels Landwehr. "Fully hyperbolic convolutional neural networks for computer vision." arXiv preprint arXiv:2303.15919 (2023).
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import hyp_tanh
>>>
>>> # Single point
>>> x = jnp.array([1.05, 0.1, -0.2, 0.15])
>>> y = hyp_tanh(x, c=1.0)
>>> y.shape
(4,)
>>>
>>> # Batch of points
>>> x_batch = jnp.ones((8, 5))
>>> y_batch = hyp_tanh(x_batch, c=1.0)
>>> y_batch.shape
(8, 5)
>>>
>>> # Verify spatial components are bounded
>>> import jax
>>> assert jnp.all(jnp.abs(y_batch[..., 1:]) <= 1.0)
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hyp_swish ¶
Apply Swish/SiLU activation to space components of hyperboloid point(s).
Curvature-preserving wrapper around hrc_swish(x, c_in=c, c_out=c).
This function applies the Swish (also known as SiLU) activation function to the spatial components of hyperboloid points and reconstructs valid manifold points using the hyperboloid constraint.
Swish is defined as: swish(x) = x * sigmoid(x)
Mathematical formula: y = [sqrt(||swish(x_s)||^2 + 1/c), swish(x_s)]
where x_s are the spatial components x[..., 1:].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold in ambient space, where ... represents arbitrary batch dimensions. The last dimension contains the time component (x[..., 0]) and spatial components (x[..., 1:]). |
required |
c
|
float
|
Curvature parameter, must be positive (c > 0). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold, same shape as input. |
Notes
- This function applies Swish only to spatial components
- The time component is reconstructed using the hyperboloid constraint
- Swish is smooth and non-monotonic, often performing well in deep networks
- Works on arrays of any shape, similar to jax.nn.swish
- For curvature-changing transformations, use
hrc_swishwhich supports different input/output curvatures
References
Ahmad Bdeir, Kristian Schwethelm, and Niels Landwehr. "Fully hyperbolic convolutional neural networks for computer vision." arXiv preprint arXiv:2303.15919 (2023).
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import hyp_swish
>>>
>>> # Single point
>>> x = jnp.array([1.05, 0.1, -0.2, 0.15])
>>> y = hyp_swish(x, c=1.0)
>>> y.shape
(4,)
>>>
>>> # Batch of points
>>> x_batch = jnp.ones((8, 5))
>>> y_batch = hyp_swish(x_batch, c=1.0)
>>> y_batch.shape
(8, 5)
>>>
>>> # Multi-dimensional batch
>>> x_feature = jnp.ones((4, 16, 16, 10))
>>> y_feature = hyp_swish(x_feature, c=1.0)
>>> y_feature.shape
(4, 16, 16, 10)
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hyp_gelu ¶
Apply GELU activation to space components of hyperboloid point(s).
Curvature-preserving wrapper around hrc_gelu(x, c_in=c, c_out=c).
This function applies the Gaussian Error Linear Unit (GELU) activation function to the spatial components of hyperboloid points and reconstructs valid manifold points using the hyperboloid constraint.
Mathematical formula: y = [sqrt(||GELU(x_s)||^2 + 1/c), GELU(x_s)]
where x_s are the spatial components x[..., 1:].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold in ambient space, where ... represents arbitrary batch dimensions. The last dimension contains the time component (x[..., 0]) and spatial components (x[..., 1:]). |
required |
c
|
float
|
Curvature parameter, must be positive (c > 0). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold, same shape as input. |
Notes
- This function applies GELU only to spatial components
- The time component is reconstructed using the hyperboloid constraint
- GELU is smooth and commonly used in transformer architectures
- Works on arrays of any shape, similar to jax.nn.gelu
- For curvature-changing transformations, use
hrc_geluwhich supports different input/output curvatures
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import hyp_gelu
>>>
>>> # Single point
>>> x = jnp.array([1.05, 0.1, -0.2, 0.15])
>>> y = hyp_gelu(x, c=1.0)
>>> y.shape
(4,)
>>>
>>> # Batch of points
>>> x_batch = jnp.ones((8, 5))
>>> y_batch = hyp_gelu(x_batch, c=1.0)
>>> y_batch.shape
(8, 5)
>>>
>>> # Multi-dimensional batch
>>> x_feature = jnp.ones((4, 16, 16, 10))
>>> y_feature = hyp_gelu(x_feature, c=1.0)
>>> y_feature.shape
(4, 16, 16, 10)
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
Poincaré (tangent-space wrappers)¶
hyperbolix.nn_layers.poincare_relu ¶
poincare_relu(
x: Float[Array, "... dim"],
c: float,
manifold_module: Poincare | None = None,
) -> Float[Array, "... dim"]
Poincaré ReLU activation: exp_0^c ∘ ReLU ∘ log_0^c.
Applies ReLU in the tangent space at the origin of the Poincaré ball, then maps back to the manifold. This is the standard nonlinearity for Poincaré ball neural networks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim)
|
Input point(s) on the Poincaré ball. Supports arbitrary batch dimensions (e.g., (batch, H, W, channels) for feature maps). |
required |
c
|
float
|
Curvature parameter (positive). |
required |
manifold_module
|
Poincare or None
|
Manifold to use (default: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim)
|
Output point(s) on the Poincaré ball. |
References
van Spengler et al. "Poincaré ResNet." ICML 2023.
Examples:
>>> import jax.numpy as jnp
>>> from hyperbolix.nn_layers import poincare_relu
>>>
>>> # Single point
>>> x = jnp.array([0.1, -0.2, 0.15])
>>> y = poincare_relu(x, c=1.0)
>>> y.shape
(3,)
>>>
>>> # Batch of feature maps
>>> x_batch = jnp.ones((4, 14, 14, 8)) * 0.1
>>> y_batch = poincare_relu(x_batch, c=1.0)
>>> y_batch.shape
(4, 14, 14, 8)
Source code in hyperbolix/nn_layers/poincare_activations.py
hyperbolix.nn_layers.poincare_leaky_relu ¶
poincare_leaky_relu(
x: Float[Array, "... dim"],
c: float,
negative_slope: float = 0.01,
manifold_module: Poincare | None = None,
) -> Float[Array, "... dim"]
Poincaré LeakyReLU activation: exp_0^c ∘ LeakyReLU ∘ log_0^c.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim)
|
Input point(s) on the Poincaré ball. |
required |
c
|
float
|
Curvature parameter (positive). |
required |
negative_slope
|
float
|
Negative slope coefficient (default: 0.01). |
0.01
|
manifold_module
|
Poincare or None
|
Manifold to use (default: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim)
|
Output point(s) on the Poincaré ball. |
Source code in hyperbolix/nn_layers/poincare_activations.py
hyperbolix.nn_layers.poincare_tanh ¶
poincare_tanh(
x: Float[Array, "... dim"],
c: float,
manifold_module: Poincare | None = None,
) -> Float[Array, "... dim"]
Poincaré tanh activation: exp_0^c ∘ tanh ∘ log_0^c.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim)
|
Input point(s) on the Poincaré ball. |
required |
c
|
float
|
Curvature parameter (positive). |
required |
manifold_module
|
Poincare or None
|
Manifold to use (default: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim)
|
Output point(s) on the Poincaré ball. |
Source code in hyperbolix/nn_layers/poincare_activations.py
Curvature-changing (HRC-based)¶
hyperbolix.nn_layers.hrc_relu ¶
hrc_relu(
x: Float[Array, "... dim_plus_1"],
c_in: float,
c_out: float,
eps: float = 1e-07,
) -> Float[Array, "... dim_plus_1"]
HRC with ReLU activation.
Equivalent to hrc(x, jax.nn.relu, c_in, c_out, eps). When c_in = c_out = c, this is equivalent to hyp_relu(x, c).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold with curvature c_in. |
required |
c_in
|
float
|
Input curvature parameter (must be positive). |
required |
c_out
|
float
|
Output curvature parameter (must be positive). |
required |
eps
|
float
|
Small value for numerical stability (default: 1e-7). |
1e-07
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold with curvature c_out. |
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hrc_leaky_relu ¶
hrc_leaky_relu(
x: Float[Array, "... dim_plus_1"],
c_in: float,
c_out: float,
negative_slope: float = 0.01,
eps: float = 1e-07,
) -> Float[Array, "... dim_plus_1"]
HRC with LeakyReLU activation.
When c_in = c_out = c, this is equivalent to hyp_leaky_relu(x, c, negative_slope).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold with curvature c_in. |
required |
c_in
|
float
|
Input curvature parameter (must be positive). |
required |
c_out
|
float
|
Output curvature parameter (must be positive). |
required |
negative_slope
|
float
|
Negative slope coefficient for LeakyReLU (default: 0.01). |
0.01
|
eps
|
float
|
Small value for numerical stability (default: 1e-7). |
1e-07
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold with curvature c_out. |
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hrc_tanh ¶
hrc_tanh(
x: Float[Array, "... dim_plus_1"],
c_in: float,
c_out: float,
eps: float = 1e-07,
) -> Float[Array, "... dim_plus_1"]
HRC with tanh activation.
When c_in = c_out = c, this is equivalent to hyp_tanh(x, c).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold with curvature c_in. |
required |
c_in
|
float
|
Input curvature parameter (must be positive). |
required |
c_out
|
float
|
Output curvature parameter (must be positive). |
required |
eps
|
float
|
Small value for numerical stability (default: 1e-7). |
1e-07
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold with curvature c_out. |
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hrc_swish ¶
hrc_swish(
x: Float[Array, "... dim_plus_1"],
c_in: float,
c_out: float,
eps: float = 1e-07,
) -> Float[Array, "... dim_plus_1"]
HRC with Swish/SiLU activation.
When c_in = c_out = c, this is equivalent to hyp_swish(x, c).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold with curvature c_in. |
required |
c_in
|
float
|
Input curvature parameter (must be positive). |
required |
c_out
|
float
|
Output curvature parameter (must be positive). |
required |
eps
|
float
|
Small value for numerical stability (default: 1e-7). |
1e-07
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold with curvature c_out. |
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
hyperbolix.nn_layers.hrc_gelu ¶
hrc_gelu(
x: Float[Array, "... dim_plus_1"],
c_in: float,
c_out: float,
eps: float = 1e-07,
) -> Float[Array, "... dim_plus_1"]
HRC with GELU activation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Array of shape (..., dim+1)
|
Input point(s) on the hyperboloid manifold with curvature c_in. |
required |
c_in
|
float
|
Input curvature parameter (must be positive). |
required |
c_out
|
float
|
Output curvature parameter (must be positive). |
required |
eps
|
float
|
Small value for numerical stability (default: 1e-7). |
1e-07
|
Returns:
| Name | Type | Description |
|---|---|---|
y |
Array of shape (..., dim+1)
|
Output point(s) on the hyperboloid manifold with curvature c_out. |
Source code in hyperbolix/nn_layers/hyperboloid_activations.py
Example¶
import jax, jax.numpy as jnp
from hyperbolix.nn_layers import hyp_relu, hrc_relu
x = jax.random.normal(jax.random.PRNGKey(0), (10, 5))
x_amb = jnp.concatenate([jnp.sqrt(jnp.sum(x**2, -1, keepdims=True) + 1.0), x], -1) # (10, 6)
y = hyp_relu(x_amb, c=1.0) # curvature-preserving
y2 = hrc_relu(x_amb, c_in=1.0, c_out=2.0) # 1.0 → 2.0
print(y.shape) # (10, 6) — same shape, still on the hyperboloid