omnibias.curvature.glm_fisher
Scoped parameter-curvature formulas, Fisher and Gauss–Newton constructions, natural steps, and sharpness utilities.
import omnibias.curvature.glm_fisherModule contract & mathematical conventions
Multi-parameter Fisher information for one-layer GLM fields (JAX).
Two complementary objects lift the *scalar* Fisher information
A''(theta) (the exact one-dimensional Fisher information) to many parameters:
fisher_information_metric-- the exponential-family **Fisher-Rao metric in natural coordinates**: the(d, d)diagonal matrixdiag(A''(eta_1), ..., A''(eta_d))fordcoordinates sharing the scalar log-partitionbase. This is the direct multivariate generalisation of the 1-D Fisher information; hand it toomnibias-geometry(seeomnibias.geometry.jax.ops.exponential_family_fisher_metric) to obtain its Christoffel symbols and curvature.
glm_fisher-- the(P, P)Fisher information of the one-layer field **parameters**theta = (b, c, beta, W)under a GLM observation model whose natural parameter is the field outputeta_n = f_theta(x_n). It reuses the closed-form per-sample gradientomnibias.curvature.one_layer.one_layer_param_gradand weights each outer product by the GLM varianceA''(eta_n):
.. math::
F(\theta) = \frac{1}{B} \sum_n A''(\eta_n)\, g_n g_n^\top, \qquad g_n = \nabla_\theta \eta_n .
This is the Fisher-scoring / IRLS information matrix and generalises omnibias.curvature.one_layer.mse_gauss_newton_fisher (the Gaussian family, A'' = 1).
Shared formulas do not imply universal floating-point identity. Verify dtype, shape, derivative-order support, and the stated numerical assumptions for the path you use.
fisher_information_metric
omnibias.curvature.fisher_information_metricSource ↗fisher_information_metric(eta: Array | float, *, base: str='softplus') -> ArrayExponential-family Fisher-Rao metric diag(A''(eta_k)) in natural coords.
eta carries the natural parameters on its last axis (shape (..., d));
the returned metric has shape (..., d, d) and is diagonal with the GLM
variance A''(eta_k) of the scalar log-partition base on the diagonal.
For d == 1 this is the 1-D Fisher information embedded as a (1, 1)
matrix.
Parameters
| Name | Type & default | Contract |
|---|---|---|
etapositional-or-keyword | Array | floatRequired | See the operation contract and implementation below. |
basekeyword-only | strDefault: 'softplus' | See the operation contract and implementation below. |
ArrayRead the implementation
def fisher_information_metric(
eta: Array | float, *, base: str = "softplus"
) -> Array:
r"""Exponential-family Fisher-Rao metric ``diag(A''(eta_k))`` in natural coords.
``eta`` carries the natural parameters on its last axis (shape ``(..., d)``);
the returned metric has shape ``(..., d, d)`` and is diagonal with the GLM
variance ``A''(eta_k)`` of the scalar log-partition ``base`` on the diagonal.
For ``d == 1`` this is the 1-D Fisher information embedded as a ``(1, 1)``
matrix.
"""
v = _log_partition_derivative(eta, base=base, order=2)
d = v.shape[-1]
eye = jnp.eye(d, dtype=v.dtype)
out: Array = v[..., :, None] * eye
return outOther public import paths
omnibias.curvature.fisher_information_metricomnibias.curvature.glm_fisher.fisher_information_metric
glm_fisher
omnibias.curvature.glm_fisher.glm_fisherSource ↗glm_fisher(X: Array, W: Array, beta: Array, c: Array, b: Array, *, activation: str='tanh', family: str='bernoulli') -> Array(P, P) GLM Fisher information of the one-layer field parameters.
The field output eta_n = b + sigma(W x_n + beta) . c is the natural
parameter of the chosen exponential family ("bernoulli" /
"poisson" / "gaussian"). Returns
F = (1/B) sum_n A''(eta_n) g_n g_n^T with g_n the closed-form
per-sample parameter gradient -- a positive-semidefinite Fisher matrix.
Parameters
| Name | Type & default | Contract |
|---|---|---|
Xpositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
Wpositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
betapositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
cpositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
bpositional-or-keyword | ArrayRequired | See the operation contract and implementation below. |
activationkeyword-only | strDefault: 'tanh' | See the operation contract and implementation below. |
familykeyword-only | strDefault: 'bernoulli' | See the operation contract and implementation below. |
ArrayExecuted regression · gaussian step equals mse newton at zero damping
Recorded coverage confirms this test executed the API body. This example belongs to the pinned upstream test suite. It may use fixtures and imports from its full file. Run it from that checkout with its test dependencies installed.
def test_gaussian_step_equals_mse_newton_at_zero_damping() -> None:
X, W, beta, c, b, rng = _problem(D=3, H=3, B=60, seed=5)
Y = jnp.asarray(rng.normal(size=X.shape[0]))
g_b, g_c, g_be, g_W = glm_natural_gradient_step(
X, Y, W, beta, c, b, family="gaussian", learning_rate=1.0, damping=0.0
)
n_b, n_c, n_be, n_W = mse_newton_step(X, Y, W, beta, c, b, learning_rate=1.0, damping=0.0)
assert jnp.allclose(g_b, n_b, atol=1e-8)
assert jnp.allclose(g_c, n_c, atol=1e-8)
assert jnp.allclose(g_be, n_be, atol=1e-8)
assert jnp.allclose(g_W, n_W, atol=1e-8)python -m pytest "packages/omnibias-curvature/tests/test_natural_gradient.py::test_gaussian_step_equals_mse_newton_at_zero_damping" -qRead the implementation
def glm_fisher(
X: Array,
W: Array,
beta: Array,
c: Array,
b: Array,
*,
activation: str = "tanh",
family: str = "bernoulli",
) -> Array:
r"""``(P, P)`` GLM Fisher information of the one-layer field parameters.
The field output ``eta_n = b + sigma(W x_n + beta) . c`` is the natural
parameter of the chosen exponential ``family`` (``"bernoulli"`` /
``"poisson"`` / ``"gaussian"``). Returns
``F = (1/B) sum_n A''(eta_n) g_n g_n^T`` with ``g_n`` the closed-form
per-sample parameter gradient -- a positive-semidefinite Fisher matrix.
"""
spec = get_activation(activation)
n_batch = X.shape[0]
def per_sample(x_n: Array) -> tuple[Array, Array]:
eta = b + spec.forward(W @ x_n + beta) @ c
g = one_layer_param_grad(x_n, W, beta, c, b, activation)
return eta, g
etas, gs = jax.vmap(per_sample)(X) # (B,), (B, P)
w = _glm_weights(etas, family) # (B,)
fisher: Array = (gs.T * w) @ gs / n_batch
return fisher