DEV Community

Alex Towell
Alex Towell

Posted on • Originally published at metafunctor.com

symlik: Symbolic Likelihood Models in Python

I've released symlik, a Python library for symbolic likelihood models. The core idea: write your log-likelihood as a symbolic expression, and let the computer derive everything needed for inference.

The Problem

Traditional statistical computing requires either:

  1. Manual derivation - Work out score functions and information matrices by hand, then implement them
  2. Numerical approximation - Use finite differences, which can be unstable and slow

Both approaches have drawbacks. Manual derivation is error-prone and tedious. Numerical methods accumulate errors and don't give you the symbolic form.

The Solution

symlik takes a third approach: symbolic differentiation. Define your model once, get exact derivatives automatically.

from symlik.distributions import exponential

model = exponential()
data = {'x': [1.2, 0.8, 2.1, 1.5]}

mle, _ = model.mle(data=data, init={'lambda': 1.0})
se = model.se(mle, data)

print(f"Rate: {mle['lambda']:.3f} +/- {se['lambda']:.3f}")
# Rate: 0.714 +/- 0.357
Enter fullscreen mode Exit fullscreen mode

Behind the scenes, symlik:

  1. Symbolically differentiates the log-likelihood to get the score function
  2. Differentiates again for the Hessian
  3. Computes Fisher information from the Hessian
  4. Derives standard errors from the inverse information matrix

All exact. No numerical approximation.

Custom Models

The real power is defining custom models using s-expressions:

from symlik import LikelihoodModel

# Exponential: l(lambda) = sum[log(lambda) - lambda*x_i]
log_lik = ['sum', 'i', ['len', 'x'],
           ['+', ['log', 'lambda'],
            ['*', -1, ['*', 'lambda', ['@', 'x', 'i']]]]]

model = LikelihoodModel(log_lik, params=['lambda'])

# Symbolic derivatives available
score = model.score()       # Gradient
hess = model.hessian()      # Hessian matrix
info = model.information()  # Fisher information
Enter fullscreen mode Exit fullscreen mode

Heterogeneous Data

One of symlik's strengths is handling mixed observation types - exactly what you need for reliability analysis with censored data:

from symlik import ContributionModel
from symlik.contributions import complete_exponential, right_censored_exponential

model = ContributionModel(
    params=["lambda"],
    type_column="status",
    contributions={
        "observed": complete_exponential(),
        "censored": right_censored_exponential(),
    }
)
Enter fullscreen mode Exit fullscreen mode

Each observation type contributes differently to the likelihood. symlik handles the bookkeeping.

Installation

pip install symlik
Enter fullscreen mode Exit fullscreen mode

Documentation at queelius.github.io/symlik.

Top comments (0)