Choose a Response Family

Pick the right distribution for your outcome variable.

The family argument tells Whittaker which probability distribution governs the response and which link function connects the linear predictor to the mean. Choosing the right family is the single most important modeling decision. A mismatched family produces biased smooths and unreliable standard errors.

The family table

Family Class Link Use when
Gaussian wk.Gaussian() identity Continuous, unbounded, roughly symmetric
Poisson wk.Poisson() log Non-negative integer counts
Binomial wk.Binomial() logit Binary (0/1) or proportion
Gamma wk.Gamma() log Positive, right-skewed (costs, durations)
Negative Binomial wk.NegativeBinomial() log Overdispersed counts
Beta wk.Beta() logit Proportions strictly in (0, 1)
Tweedie wk.Tweedie() log Zero-inflated positive (insurance)
Inverse Gaussian wk.InverseGaussian() log Positive, heavy right tail

Pass any family as a keyword argument: wk.GAM("y ~ s(x)", family=wk.Poisson()).

Gaussian (default)

Gaussian is appropriate when the response is continuous and can take any real value. The mcycle head-acceleration data fits this description.

import whittaker as wk

data = wk.load_dataset("mcycle")
# Fit default Gaussian GAM
model_g = wk.GAM("accel ~ s(times)").fit(data)
model_g.summary()
GAM fit summary
============================================================
Formula:    accel ~ s(times)
Family:     Gaussian(link='identity')
Inference:  GCV
Observations: 133
Coefficients: 10

Parametric coefficients:
  Term                       Estimate    Std.Err    t value    p-value
  ------------------------ ---------- ---------- ---------- ----------
  (Intercept)                -45.6924     1.8364    -24.882    < 1e-16

Approximate significance of smooth terms:
  Term                        EDF Ref.df     Chi.sq    p-value
  ------------------------ ------ ------ ---------- ----------
  s(times)                   7.92      8    663.396    < 1e-16

Total EDF:  8.92
Scale est:  448.517253
Deviance:   55653.7152
Null dev:   357878.4929
Dev. expl:  84.4%
GCV score:  480.746119
AIC:        1198.44
BIC:        1224.22

Poisson

Use Poisson when the response is a non-negative integer count. The fish dataset records the number of fish caught at different water temperatures and depths.

data = wk.load_dataset("fish")
# Fit Poisson GAM for count response
model_p = wk.GAM(
    "count ~ s(temperature) + depth",
    family=wk.Poisson(),
).fit(data)
model_p.summary()
GAM fit summary
============================================================
Formula:    count ~ s(temperature) + depth
Family:     Poisson(link='log')
Inference:  GCV
Observations: 300
Coefficients: 11

Parametric coefficients:
  Term                       Estimate    Std.Err    z value    p-value
  ------------------------ ---------- ---------- ---------- ----------
  (Intercept)                  2.1998     0.0479     45.901    < 1e-16
  depth                       -0.0249     0.0018    -13.916    < 1e-16

Approximate significance of smooth terms:
  Term                        EDF Ref.df     Chi.sq    p-value
  ------------------------ ------ ------ ---------- ----------
  s(temperature)             4.24      5    294.821    < 1e-16

Total EDF:  6.24
Scale est:  1.000000
Deviance:   321.0387
Null dev:   843.4578
Dev. expl:  61.9%
GCV score:  1.116056
AIC:        1304.77
BIC:        1327.88

The log link keeps predicted counts positive. Deviance explained replaces R² as the fit statistic.

Binomial

Use Binomial for binary (0/1) outcomes or proportions formed from counts. The credit dataset has a binary default column and continuous predictors income and debt_ratio.

data = wk.load_dataset("credit")
# Fit Binomial GAM for binary outcome
model_b = wk.GAM(
    "default ~ s(income) + s(debt_ratio)",
    family=wk.Binomial(),
).fit(data)
model_b.summary()
GAM fit summary
============================================================
Formula:    default ~ s(income) + s(debt_ratio)
Family:     Binomial(link='logit')
Inference:  GCV
Observations: 1000
Coefficients: 19

Parametric coefficients:
  Term                       Estimate    Std.Err    z value    p-value
  ------------------------ ---------- ---------- ---------- ----------
  (Intercept)                 -0.3591     0.0725     -4.954  7.258e-07

Approximate significance of smooth terms:
  Term                        EDF Ref.df     Chi.sq    p-value
  ------------------------ ------ ------ ---------- ----------
  s(income)                  2.90      3    113.502    < 1e-16
  s(debt_ratio)              1.75      2    100.420    < 1e-16

Total EDF:  5.65
Scale est:  1.000000
Deviance:   1144.6940
Null dev:   1364.9020
Dev. expl:  16.1%
GCV score:  1.157741
AIC:        1156.00
BIC:        1183.73

The logit link maps predicted probabilities into the real line. Predictions from model_b.predict() are on the probability scale by default.

Other families

Every family in the table follows the same pattern (pass an instance to family=). No other part of the API changes. For overdispersed counts try wk.NegativeBinomial() and for strictly bounded proportions try out wk.Beta().