# Supervised model failure cases

Original synthetic teaching cases. Initial scope covers a prespecified linear regression/baseline and exact correlated-predictor penalties. Later extensions are documented when executed; this README does not imply all twenty planned algorithm articles already exist.

Run `python linear_cases.py` from this directory for eight checks. The included `synthetic-duration.csv` has320 independent rows split160train/80validation/80test. Generator seed20261007, load_index uniform[0,10], conditional mean5+2*x+.8*(x-5)^2, normal noise SD1+.15*x. Duration is in illustrative minutes, not measured service data. `generator_mean_minutes` is retained for teaching diagnostics but excluded from the predictor list. `python make_fixture.py` regenerates the fixture on the recorded NumPy version.

Local runtime:Python3.12.0, NumPy2.4.4, pandas3.0.2, scikit-learn1.9.0. LinearRegression fits only load_index and an intercept on training data. Intercept12.0958901, coefficient2.1280934; mean baseline23.000506. Validation RMSE linear6.077002 versus baseline8.448281; test6.290466 versus7.851779. Test residual mean(actual-predicted)=-2.133628. Training residual sum and dot product with load are near zero, but residual correlation with squared load is.224089, exposing a remaining curved pattern. These are independent synthetic-row results, not business forecasts or causal effects.

Separate duplicate-predictor case: x=[-2,-1,0,1,2], X=[x,x], y=3*x, no intercept, feature units unchanged. Ridge alpha1 gives coefficients[10/7,10/7]; cyclic Lasso alpha.5 gives[2.75,0]; ElasticNet alpha.5,l1_ratio.5 gives[23/17,23/17]. Analytical references verify the solutions. Exact duplicate columns make individual effects unidentifiable; coordinate selection does not establish unique importance.

Adding a third column[1,-2,2,-2,1], orthogonal to x, gives ElasticNet coefficients[23/17,23/17,0] and training MSE.17301038. This deliberately constructed linear case illustrates a zero coefficient alongside shared duplicate-signal coefficients; it does not prove general feature irrelevance.

Penalty conventions are explicit: Ridge objective is SSE+alpha*sum(coef^2). Lasso uses SSE/(2*n)+alpha*sum(abs(coef)); ElasticNet adds alpha*l1_ratio*L1 + .5*alpha*(1-l1_ratio)*L2 to SSE/(2*n). Equal numerical alpha across these objectives does not imply equal regularization strength. This noiseless coefficient example has no held-out comparison and makes no predictive superiority claim.

Primary references: [LinearRegression](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html), [Ridge](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html), [Lasso](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html), [ElasticNet](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html). Stable docs showed1.9.1; local execution used1.9.0.

## Tree and ensemble diagnostics

Run `python tree_cases.py` for seven checks, and `python render_trees.py` for the original depth/boosting figures. Tree depths2/4/unrestricted yield leaves4/16/160, train RMSE3.180037/1.797396/0 and validation3.095016/1.756895/1.976038. Validation chooses depth4; its test RMSE2.073809. The unrestricted fit reaches depth15 and interpolates training rows.

Forest:300 bootstrap trees,seed20261008,n_jobs1,one predictor,max_features1.0. Out-of-bag omission probability(159/160)^160=.3667268147; each row has90–130 eligible trees. Default OOB R2=.9428892825, recomputed from OOB predictions; OOB RMSE2.159532, separate validation RMSE1.740242. OOB is neither entity-grouped nor chronological; all rows here are independently generated and no learned preprocessing precedes bootstrapping.

Boosting:depth2,learning_rate.1,seed20261009,600 fitted stages, declared checkpoints10/50/100/300/600. Training RMSE4.008974/1.487219/1.271472/.762461/.419413; validation3.906762/1.702497/1.726997/1.763795/1.838244. Validation chooses50, test RMSE1.975885. This is staged checkpoint selection, not callback early stopping. These related teaching cases share a fixture and do not establish an independent production leaderboard across algorithm families.

## XGBoost and LightGBM extension

`boosting_cases.py` requires the additional packages in `boosting-requirements.txt`. They are installed locally in `.playwright-mcp/ds-boosting-venv` at the repository root. This extension environment enables system site packages to reuse the existing scientific reference dependencies; it is **not** the isolated clean-environment reproduction reported for the separate evaluation lab. XGBoost3.4.1 and LightGBM4.7.0 are local to this extension environment; `pip check` passes. Stable XGBoost documentation identified3.4.2, but the package index did not offer that version, so the executed version is explicitly3.4.1.

From the repository root, run `.\.playwright-mcp\ds-boosting-venv\Scripts\python.exe 11-Blog-Programme/labs/ds-supervised/boosting_cases.py`. The script records eight checks in `boosting-verification.json`. Article checks use that interpreter and include its runtime/package versions in their execution-cache dependency key.

XGBoost:depth2,learning_rate.1,hist,600-round maximum,20-round patience,seed20261010,n_jobs1. Only the80-row validation set enters `eval_set`;160 rows train. Best zero-based iteration80 means81 selected trees;101 rounds are retained after patience. Best validation RMSE1.6273077871; test RMSE using the best range2.0402115479. Scikit-learn predictions, native booster predictions with iteration_range(0,81), and JSON roundtrip predictions agree. The full validation history is saved; no test set chooses stopping.

LightGBM:150 original category-training rows,seed20261011. Plans basic/team/enterprise have authored base targets10/30/20 plus2*load and noise SD.1. `categorical-training.csv` is included; its plan column is reconstructed as unordered pandas categories. At load.5, predictions are11.238926/30.869862/21.087089. Reordering pandas category codes while preserving labels leaves predictions unchanged. An unseen plan and a missing plan both predict21.087089 in this fit. Manually supplying independently reassigned integer codes swaps basic/enterprise predictions, with maximum change9.848164. Serialization preserves the pandas category mapping. These are encoding-consistency probes, not held-out accuracy or unknown-category reliability evidence.

## Classical classification checks

Run `python classical_cases.py` for eight checks. The KNN construction uses two labelled reference points and shows that changing one feature's unit can reverse the nearest neighbour. The SVM case uses 400 seeded concentric-ring rows split 240/80/80; training-only scaling and validation select the RBF kernel (validation balanced accuracy .925 versus .625 for linear), after which the selected model scores .9875 on the synthetic test split. The Naive Bayes case enumerates a balanced XOR rule: overall feature correlation is zero, class-conditional factorization fails, Bernoulli Naive Bayes is correct on two of four patterns, and a depth-two tree represents all four. These are narrow failure demonstrations, not algorithm rankings.

## Outcome and decision checks

Run `python decision_cases.py` for fourteen checks. It creates `event-counts.csv` only when absent and writes `decision-verification.json`. The count fixture contains 500 independent Poisson draws with equal one-hour exposure; the unpenalized log-linear model has test mean Poisson deviance .9498 versus 2.8123 for the training-mean baseline. The duration fixture's prespecified 90th-quantile model has test pinball loss .5151 versus 1.6714 for a constant training quantile, with 70 of 80 test outcomes below its estimate. Coverage is descriptive, not a guaranteed conditional interval.

Monotonic cases compare a justified increasing rule with a deliberately misspecified U-shaped rule on a 1,001-point grid. The increasing constraint removes all decreasing steps in both; known-rule RMSE improves from 1.0263 to .7126 for the increasing case but worsens from 1.3356 to 5.9701 for the U-shape. The multi-output case shows a one-split shared tree choosing a different root after target rescaling, while separate stumps recover both constructed rules on four new probes.

The cost table reuses frozen validation probabilities from the evaluation lab without altering that reference experiment. With authored costs FP=1 and FN=5, thresholds .3/.5/.7 have losses 59/145/235 and select 64/24/0 rows. A 30-case capacity limit changes the feasible choice from .3 to .5. Learning curves use ten nested training permutations at sizes 40/80/160 against the same fixed 80-row validation set; their ranges are descriptive rather than confidence intervals. The partial-dependence construction fits two models that agree on the observed relation x2=2*x1 but produce different marginal curves because feature replacement moves four of five rows off that relationship.

Primary references: [PoissonRegressor](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.PoissonRegressor.html), [HistGradientBoostingRegressor](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.HistGradientBoostingRegressor.html), [MultiOutputRegressor](https://scikit-learn.org/stable/modules/generated/sklearn.multioutput.MultiOutputRegressor.html), and [partial dependence](https://scikit-learn.org/stable/modules/partial_dependence.html). Stable documentation showed 1.9.1; local execution used 1.9.0.
