AI Skill Report Card

Building Predictive Models

A-85·Nov 8, 2026·Source: Web
14 / 15
Python
import pandas as pd from sklearn.model_selection import train_test_split, StratifiedKFold from catboost import CatBoostClassifier import optuna from sklearn.metrics import roc_auc_score import shap # 1. Load & split df = pd.read_csv("clients.csv") X, y = df.drop(columns=["default"]), df["default"] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.15, stratify=y, random_state=42 ) X_train, X_val, y_train, y_val = train_test_split( X_train, y_train, test_size=0.176, stratify=y_train, random_state=42 ) # → 70/15/15 overall # 2. Baseline model baseline = CatBoostClassifier(verbose=0, random_state=42) baseline.fit(X_train, y_train, cat_features=["category_col"]) baseline_auc = roc_auc_score(y_val, baseline.predict_proba(X_val)[:, 1]) print(f"Baseline AUC: {baseline_auc:.3f}") # 3. Hyperparameter tuning def objective(trial): params = { "depth": trial.suggest_int("depth", 4, 10), "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.3, log=True), "l2_leaf_reg": trial.suggest_float("l2_leaf_reg", 1, 10), "iterations": trial.suggest_int("iterations", 200, 1000), } model = CatBoostClassifier(**params, verbose=0, random_state=42) model.fit(X_train, y_train, cat_features=["category_col"]) preds = model.predict_proba(X_val)[:, 1] return roc_auc_score(y_val, preds) study = optuna.create_study(direction="maximize") study.study_optimize = study.optimize(objective, n_trials=50) # 4. Final model + interpretation best_model = CatBoostClassifier(**study.best_params, verbose=0, random_state=42) best_model.fit(X_train, y_train, cat_features=["category_col"]) explainer = shap.TreeExplainer(best_model) shap_values = explainer.shap_values(X_test)
Recommendation▾
Fix the minor bug in Quick Start code: `study.study_optimize = study.optimize(...)` should just be `study.optimize(...)`
14 / 15

Progress:

  • Step 1: EDA — distributions, missing values, class balance, correlations
  • Step 2: Preprocessing — impute missing values, scale/normalize numeric features, encode categoricals
  • Step 3: Split data 70/15/15 (train/val/test), stratify on target for classification
  • Step 4: Train baseline model (no tuning) and pick primary metric
  • Step 5: Hyperparameter search (Optuna/GridSearch) on train, score on validation
  • Step 6: Cross-validate best config (stratified k-fold, k=5) to confirm stability
  • Step 7: Evaluate on held-out test set once, final check for overfitting
  • Step 8: Interpret via SHAP/LIME, analyze error cases
  • Step 9: Log experiment (MLflow/W&B), package model for deployment

Metric selection by task:

  • Imbalanced classification → AUC-ROC, PR-AUC, F1
  • Balanced classification → Accuracy, F1
  • Regression → RMSE, MAE, R²
  • Business-critical → cost-weighted custom metric

Overfitting checks:

  • Train metric >> validation metric → overfitting signal
  • Learning curves: gap between train/val loss growing with model complexity
  • Cross-validation std across folds too high → unstable model
  • Use regularization (L2, early stopping, max_depth limits) when gap detected
Recommendation▾
Add a concrete input/output example showing a 'bad outcome' (e.g., a model that overfits) alongside the two successful cases to demonstrate failure detection
15 / 20

Example 1: Input: Bank customer table, 50,000 rows (age, income, credit history, loan amount), binary target "default" Process: pandas preprocessing → OrdinalEncoder for categoricals → CatBoostClassifier with 5-fold stratified CV → Optuna tuning (50 trials) → SHAP feature importance Output: AUC-ROC = 0.87; top factors: credit history (0.34), debt-to-income ratio (0.22), number of late payments (0.18)

Example 2: Input: E-commerce churn dataset, 10,000 users, heavy class imbalance (5% churn) Process: SMOTE oversampling on train only → LightGBM with scale_pos_weight → stratified k-fold CV → threshold tuning on PR curve instead of default 0.5 Output: PR-AUC = 0.61 (vs 0.30 baseline), optimal threshold = 0.32 maximizes F1

Recommendation▾
Include a brief note on deployment packaging (e.g., saving with joblib/pickle, versioning) since the workflow checklist mentions it but the skill doesn't elaborate
  • Always split off test set first and touch it only once, at the very end
  • Fit preprocessing (scalers, encoders, imputers) on train only, then transform val/test — never fit on full dataset
  • Use stratified splits/folds for classification, especially with imbalance
  • Start with a simple baseline (logistic regression, mean predictor) before complex models — it defines the bar to beat
  • Prefer CatBoost/LightGBM when categorical features are present (native handling beats one-hot encoding)
  • Track every experiment (params, metrics, data version) in MLflow or W&B — don't rely on memory
  • Report confidence intervals from cross-validation, not a single fold score
  • Explain predictions with SHAP before shipping — business stakeholders need reasons, not just scores
  • Data leakage: scaling/imputing/feature-selecting on the whole dataset before splitting — inflates validation scores unrealistically
  • Tuning on test set: using test metric to pick hyperparameters turns test into a second validation set — scores become optimistic
  • Ignoring class imbalance: using accuracy as the metric when target is 95/5 — a trivial "always predict majority" model scores 95%
  • Overfitting via too many Optuna trials on small validation set: small val sets cause the search to fit noise — use CV instead for small data
  • Skipping error analysis: deploying a model with good aggregate AUC but systematic failures on a specific subgroup
  • No baseline comparison: complex model gains 1% AUC over logistic regression but costs 10x latency and interpretability
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
15/20
Completeness
18/20
Format
15/15
Conciseness
13/15