Skip to content

Quick Start

For pricing models with spline terms, the default starting point is an explicit feature spec plus fit_reml() with selection_penalty=0.

from superglm import Categorical, Numeric, Spline, SuperGLM

features = {
    "DrivAge": Spline(kind="ps", k=14, knot_strategy="quantile_rows"),
    "VehAge": Spline(kind="cr", k=10, knot_strategy="quantile_rows"),
    "BonusMalus": Spline(kind="cr", k=12, knot_strategy="quantile_tempered"),
    "Area": Categorical(base="most_exposed"),
    "LogDensity": Numeric(),
}

model = SuperGLM(
    family="poisson",
    selection_penalty=0.0,
    features=features,
)
model.fit_reml(df, y, sample_weight=exposure, max_reml_iter=30)

predictions = model.predict(df)
print(model.summary())

Large-n REML

If the dataset is large, keep the same workflow but turn on discrete REML:

model = SuperGLM(
    family="poisson",
    selection_penalty=0.0,
    discrete=True,
    n_bins=256,
    features=features,
)
model.fit_reml(df, y, sample_weight=exposure, max_reml_iter=30)

Auto-Detect Mode For Quick Prototypes

Auto-detect mode still exists and is useful for a quick first pass, but explicit feature specs are the better default for pricing work.

from superglm import SuperGLM

model = SuperGLM(
    family="poisson",
    selection_penalty=0.0,
    splines=["DrivAge", "VehAge", "BonusMalus"],
    n_knots=10,
)
model.fit_reml(df, y, sample_weight=exposure)

Eager Polars Input

The same named-frame API accepts eager Polars frames. Install Polars separately and collect a LazyFrame before passing it to SuperGLM.

import polars as pl

from superglm import SuperGLM

X = pl.DataFrame({"age": [20.0, 30.0, 40.0], "region": ["N", "S", "N"]})
y = [0.0, 1.0, 2.0]

model = SuperGLM(family="poisson", splines=["age"]).fit(X, y)
predictions = model.predict(X)

Input storage remains Polars through fitting and prediction. Public tabular results such as inference tables, diagnostics, plot data, and rating-table payloads remain pandas DataFrames.

Sparse Screening Or Fixed-Penalty Fitting

If your goal is sparse screening or compression rather than GAM-style REML inference, use fit() with selection_penalty > 0 instead:

model = SuperGLM(
    family="poisson",
    penalty="group_elastic_net",
    selection_penalty=0.01,
    spline_penalty=0.1,
    features=features,
)
model.fit(df, y, sample_weight=exposure)

Weights And Offsets

For the Poisson frequency examples on this page, sample_weight=exposure weights a per-exposure rate response by exposure. It does not enter the linear predictor or automatically multiply the mean. Weight semantics are family-specific. In particular, Tweedie uses finite, strictly positive EDM prior weights with Var(Y_i | x_i) = phi * mu_i**p / w_i, not replication counts. The exposure= fit alias has been removed.

Two common patterns for count models:

import numpy as np

# Raw count target: offset absorbs exposure, model estimates a rate
model.fit(df, claim_counts, offset=np.log(exposure))

# Rate target (count / exposure): sample_weight carries exposure
model.fit(df, claim_rate, sample_weight=exposure)

Next steps: