The Course on One Page
Every template, formula, and checklist from the thirteen sessions. Keep it open during homework; bring it to your project presentation. Each block names the session that teaches it.
Four lines before the keyboard
Then name the baseline: majority class, the mean, or same-period-last-time. Every model must beat it.
Seven questions before you trust a score
- Would I know this value at the moment I need the prediction?
- Is it recorded after the outcome (call duration, reservation status, follow-up visits)?
- Is it downstream of a decision the model will influence (offer sent, line reduced)?
- Is it aggregated over a window that includes the future (lifetime average)?
- Did any fitted transformer (scaler, imputer, encoder, selector) see the test rows?
- Does the split match production — new customers (GroupKFold), later dates (TimeSeriesSplit)?
- Did the score jump to near-perfect from one column? That is a leak, not a discovery.
The pipeline every project starts from
Split first. Everything that learns from data lives inside the Pipeline. Swap the last step; nothing else changes.
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, stratify=y, random_state=835)
num = X.select_dtypes(include='number').columns
cat = X.columns.difference(num)
prep = ColumnTransformer([
('num', Pipeline([('imp', SimpleImputer(strategy='median')), ('sc', StandardScaler())]), num),
('cat', OneHotEncoder(handle_unknown='ignore'), cat),
])
model = Pipeline([('prep', prep), ('clf', ANY_ESTIMATOR)])
cv = StratifiedKFold(5, shuffle=True, random_state=835)
print(cross_val_score(model, X_tr, y_tr, cv=cv, scoring='roc_auc').mean()) # tune here
model.fit(X_tr, y_tr) # then touch the test set once Which number for whom
| Task | Metric | Reads as | Report to |
|---|---|---|---|
| Regression | MAE | typical miss, in units | operations, sales |
| Regression | RMSE | typical miss, big misses count extra | risk, finance |
| Regression | MAPE | typical miss as a % | executives — never near zero |
| Regression | R² | share of variance explained vs. the mean | analysts |
| Classification | ROC-AUC | ranking quality; P(positive scores above negative) | model comparison, balanced classes |
| Classification | PR-AUC | precision across recall levels | rare positives (fraud, default) |
| Classification | Precision / Recall | "of those flagged…" / "of those who actually…" | at the chosen threshold |
| Classification | Brier / calibration curve | does 0.8 mean 80%? | before any dollar calculation |
| Forecasting | MAE vs. seasonal naive | gain over "same hour last week" | always report the baseline |
Four cells, four business meanings
| predicted: yes | predicted: no | |
| actually yes | TP · caught | FN · missed (the expensive cell) |
| actually no | FP · false alarm (wasted action) | TN · left alone |
The threshold is a business decision
A $50 offer and a $450 save → p* = 0.10. Act on anyone above it. With a contact budget, sort by score and take the top k instead (gain chart). Check calibration before the probabilities enter any dollar arithmetic; a churn score is not an uplift score.
from sklearn.model_selection import TunedThresholdClassifierCV
from sklearn.metrics import make_scorer, confusion_matrix
def profit(y_true, y_pred): # write the business scorer in dollars
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
return VALUE_OF_CATCH * tp - COST_OF_ACTION * (tp + fp)
tuned = TunedThresholdClassifierCV(model, scoring=make_scorer(profit), cv=5).fit(X_tr, y_tr)
print(tuned.best_threshold_) # break-even ≈ cost / (cost + value) Match the splitter to production
The 2026 default stack
Knobs that matter for boosting: learning rate × number of trees (with early stopping), then leaves / depth, then regularization. Trees need no scaling; distance and gradient models do.
The four questions an executive will ask
Five sections, one page each at most
Full brief, rubric, and deadlines on the Project page.