Cross-validation
Blocked K-fold cross-validation for choosing a class count. Each decision-maker's
complete choice history remains within one fold. Use the same immutable LCLSpec
as estimation and pass it with spec=.
Experimental
The API remains experimental and may change between minor releases. See the model-selection tutorial for a complete example.
import lcl
from lcl import FitOptions
cv_results = lcl.cv_optimal_classes(
data,
spec=spec,
num_classes_list=[2, 3, 4],
fit_options=FitOptions(seed=42, starts=3),
)
folds= may be an integer, an explicit sequence of test-panel groups, or a
mapping from panel ID to a user fold label. Explicit folds must cover every panel
exactly once. This makes externally defined geographic, temporal, or grouped
splits reproducible without row leakage.
Inference is skipped by default because covariance estimation does not affect held-out likelihood. Every validation fold is transformed with its training fold's fitted encoder.
Avg_OOS_LL is the pooled mean held-out log likelihood per panel. If any fold
fails, Avg_OOS_LL and Total_OOS_LL are NaN; use
Avg_Successful_OOS_LL and Fold_Errors for diagnosis, not model ranking.
Convergence is reported independently in Converged_Folds,
Nonconverged_Folds, and Fold_Converged.
Fold_SE_Panel_LL contains within-fold standard errors and SE_OOS_LL is the
pooled panel-level standard error. Selected_Best marks the largest mean score;
Selected_One_SE marks the smallest class count within one best-model standard
error of it.
lcl.cv_optimal_classes(data, alts_col=None, cases_col=None, panels_col=None, num_classes_list=None, utility_formula=None, membership_formula=None, choice_col=None, case_varnames=None, dem_varnames=None, dems_data=None, numeraire=None, folds=5, seed=42, *, spec=None, options=None, fit_options=None, optimization_options=None, inference=None, numeraire_min_abs=None)
Select a latent-class count with blocked panel-level cross-validation.
Every test fold is transformed by the encoder fitted on its training fold. Formula-derived columns therefore retain their training-time categorical meaning, and unseen categories produce Formulaic's explicit warning or error.
Avg_OOS_LL is the mean held-out log likelihood per panel, pooled across
all folds. It is set to NaN when any fold fails so an incomplete class
sweep cannot silently compete with complete results. The successful-fold-only
value remains available in Avg_Successful_OOS_LL for diagnosis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Any
|
Long-format choice data. |
required |
alts_col
|
str | None
|
Alternative column. |
None
|
cases_col
|
str | None
|
Choice-situation, panel, and chosen-alternative indicator columns. |
None
|
panels_col
|
str | None
|
Choice-situation, panel, and chosen-alternative indicator columns. |
None
|
choice_col
|
str | None
|
Choice-situation, panel, and chosen-alternative indicator columns. |
None
|
num_classes_list
|
Sequence[int] | None
|
Candidate class counts, each at least two. |
None
|
utility_formula
|
str | None
|
Separate Formulaic specifications. |
None
|
membership_formula
|
str | None
|
Separate Formulaic specifications. |
None
|
case_varnames
|
Sequence[str] | None
|
Explicit utility and class-membership variables. |
None
|
dem_varnames
|
Sequence[str] | None
|
Explicit utility and class-membership variables. |
None
|
dems_data
|
Any | None
|
Separate panel-level demographic data. |
None
|
numeraire
|
str | None
|
Utility coefficient constrained to be strictly negative. |
None
|
folds
|
int
|
Number of blocked panel folds. |
5
|
seed
|
int
|
Random seed for panel shuffling. |
42
|
spec
|
LCLSpec | None
|
Preferred declarative model specification. |
None
|
fit_options
|
FitOptions | None
|
EM settings, including independent starts per training fold. |
None
|
optimization_options
|
OptimizationOptions | None
|
M-step optimizer settings. |
None
|
inference
|
InferenceOptions | None
|
Inference settings. By default CV skips covariance work. |
None
|
numeraire_min_abs
|
float | None
|
Minimum absolute magnitude for a keyword-specified numeraire. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per valid class count, with aggregate metrics and list-valued per-fold diagnostics. |
Source code in src/lcl/_cross_validation.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | |