On this page:
<require>
<provide>
<data>
<fit>
<run-example>
<*>

3.5 Binomial logistic regression (classification)🔗

The binomial family fits a two-class classifier: instead of a numeric response, y is a 0/1 class label and the model returns the log-odds of class 1. Under the hood this is glmnet’s lognet coordinate-descent solver rather than the Gaussian elnet, but the elastic-net knobs are identical — α mixes the L1/L2 penalty and λ sets its strength — so #:alpha 1.0 is the lasso (sparse) logistic and #:alpha 0.0 the ridge logistic.

The synthetic data below is linearly separable: class 1 has high x₁ and low x₂, class 0 the reverse, and x₃ is pure noise — identically distributed in both classes. A lasso-penalized fit recovers the signs (β₁ > 0, β₂ < 0), drives the noise coefficient exactly to 0.0, and classifies every training point correctly.

(require glmnet)

(provide run-example)

<data> ::=
(define X '((1.0 5.0 2.0)
            (2.0 6.0 1.0)
            (2.0 5.0 3.0)
            (1.0 4.0 1.0)
            (3.0 6.0 2.0)
            (2.0 4.0 2.0)
            (6.0 2.0 2.0)
            (5.0 1.0 1.0)
            (6.0 1.0 3.0)
            (5.0 2.0 1.0)
            (4.0 1.0 2.0)
            (6.0 3.0 2.0)))
(define y '(0 0 0 0 0 0 1 1 1 1 1 1))

logistic-fit with #:alpha 1.0 is the sparse (lasso) logistic. The third coefficient — the noise predictor x₃ comes back exactly 0.0, while x₁ and x₂ keep their (opposite) signs. The logistic-result also carries logistic-result-dev-ratio, the fraction of null deviance explained (the logistic analogue of ).

<fit> ::=

(define result (logistic-fit X y #:lambda 0.04))

Given a fit, logistic-predict-proba returns the class-1 probability for each row and logistic-predict thresholds it into a hard 0/1 label:

(logistic-predict-proba result X)
; => (0.02 0.05 ... 0.97 0.99) -- low for class 0, high for class 1
(logistic-predict result X)
; => (0 0 0 0 0 0 1 1 1 1 1 1) -- every training point correct

(define (run-example)
  <data>
  <fit>
  result)

<*> ::=