Expand description
Traits and utilities for link functions.
The link function $g$ maps the expected response $\mu$ to the linear predictor
$\omega = \mathbf{x}^\mathsf{T}\boldsymbol{\beta}$. Each family defaults to its canonical
link, but an alternative can be selected via the family’s type parameter.
§Using a provided non-canonical link
Alternative links are re-exported for convenience: exp_link for
exponential regression and logistic_link for logistic regression.
Provide a link as the family’s type parameter:
use ndarray_glm::{Exponential, ModelBuilder, array, exp_link::Log};
fn main() -> ndarray_glm::error::RegressionResult<(), f64> {
let data_y = array![1.0, 2.5, 0.8, 3.1];
let data_x = array![[0.0], [1.0], [0.5], [1.5]];
// Use the log link instead of the default negative-reciprocal canonical link.
let model = ModelBuilder::<Exponential<Log>>::data(&data_y, &data_x).build()?;
let fit = model.fit()?;
Ok(())
}§Implementing a custom non-canonical link
A non-canonical link requires two trait implementations:
Link<M>— the forward map $g(\mu) = \omega$ (Link::func) and its inverse $g^{-1}(\omega) = \mu$ (Link::func_inv).Transform— the natural-parameter transformation $\eta(\omega) = g_0(g^{-1}(\omega))$ (Transform::nat_param) and its derivative (Transform::d_nat_param), where $g_0$ is the family’s canonical link. The derivative satisfies $\eta'(\omega) = \frac{1}{g'(\mu)\,V(\mu)}$ where $V(\mu)$ is the family’s variance function evaluated at $\mu = g^{-1}(\omega)$.
Example: a square-root link $g(\mu) = \sqrt{\mu}$ for Poisson regression. The canonical
link is $\log$ and $V(\mu) = \mu$, so
$\eta(\omega) = \log(\omega^2) = 2\log\omega$ and $\eta'(\omega) = 2/\omega$:
use ndarray_glm::{Poisson, link::{Link, Transform}, num::Float};
use ndarray::Array1;
pub struct Sqrt;
impl Link<Poisson<Sqrt>> for Sqrt {
fn func<F: Float>(mu: F) -> F { num_traits::Float::sqrt(mu) }
fn func_inv<F: Float>(omega: F) -> F { omega * omega }
}
impl Transform for Sqrt {
fn nat_param<F: Float>(lin_pred: Array1<F>) -> Array1<F> {
lin_pred.mapv(|w| F::two() * num_traits::Float::ln(w))
}
fn d_nat_param<F: Float>(lin_pred: &Array1<F>) -> Array1<F> {
lin_pred.mapv(|w| F::two() / w)
}
}§Consistency tests with TestLink
The TestLink trait (available only in #[cfg(test)] builds) provides canned assertions
that every correct link implementation should satisfy. Call them from your test module:
#[cfg(test)]
mod tests {
use super::*;
use ndarray_glm::link::TestLink;
use ndarray::array;
#[test]
fn sqrt_link_checks() {
// Linear-predictor values; must lie in the domain of ω (ω > 0 for sqrt).
let lin_vals = array![0.25, 1.0, 2.0, 4.0, 9.0];
// Verify g(g⁻¹(ω)) ≈ ω.
Sqrt::check_closure(&lin_vals);
// Verify g⁻¹(g(μ)) ≈ μ; values must lie in the response domain (μ > 0 for Poisson).
Sqrt::check_closure_y(&array![0.5, 1.0, 3.0, 10.0]);
// For non-canonical links: verify nat_param(ω) = g₀(g⁻¹(ω)).
// Pass the *canonical* model variant as `Mc`. `Poisson` without a type parameter
// defaults to the canonical log link.
use ndarray_glm::Poisson;
Sqrt::check_nat_par::<Poisson>(&lin_vals);
// Verify d_nat_param matches the numerical derivative.
Sqrt::check_nat_par_d(&lin_vals);
}
}Traits§
- Canonical
- The canonical transformation by definition equates the linear predictor with the natural parameter of the response distribution. Implementing this trait for a link function automatically defines the trivial transformation functions.
- Link
- Describes the link function $
g$ that maps between the expected response $\mu$ and the linear predictor $\omega = \mathbf{x}^\mathsf{T}\boldsymbol{\beta}$: - Transform
- Establishes the relationship between the linear predictor $
\omega = \mathbf{x}\cdot\boldsymbol\beta$ and the natural parameter $\eta$.