Chapter 17: Exercises - Introduction to Predictive Analytics
Overview
These exercises build fundamental skills in predictive modeling for football analytics. Progress from basic classification to complete ML pipelines.
Level 1: Fundamentals (Recall and Basic Application)
Exercise 1.1: Classification vs Regression
Categorize each prediction problem as classification or regression.
Problems: 1. Predicting whether a team will win their next game 2. Predicting how many points a team will score 3. Predicting the defensive coverage on a play 4. Predicting a player's rushing yards per game 5. Predicting whether a fourth down conversion will succeed 6. Predicting a quarterback's passer rating 7. Predicting which team will win the national championship 8. Predicting the point spread margin
Starter Table: | Problem | Type | Reasoning | |---------|------|-----------| | 1. Win next game | | | | 2. Points scored | | | | ... | | |
Exercise 1.2: Train-Test Split
Implement a proper train-test split for football game data.
Task: Split game data while avoiding data leakage.
Starter Code:
import pandas as pd
import numpy as np
def temporal_train_test_split(games_df: pd.DataFrame,
test_year: int = 2023,
target_col: str = 'home_win'):
"""
Split games into train/test sets based on season.
Parameters:
-----------
games_df : pd.DataFrame
Game data with 'season' column
test_year : int
First year to include in test set
target_col : str
Name of target column
Returns:
--------
tuple : (X_train, X_test, y_train, y_test)
"""
# TODO: Split data by season
# TODO: Separate features from target
# TODO: Return split data
pass
# Test with sample data
np.random.seed(42)
sample_games = pd.DataFrame({
'season': np.random.choice([2020, 2021, 2022, 2023], 200),
'home_epa': np.random.normal(0.1, 0.1, 200),
'away_epa': np.random.normal(0.05, 0.1, 200),
'home_win': np.random.choice([0, 1], 200)
})
X_train, X_test, y_train, y_test = temporal_train_test_split(sample_games)
print(f"Training games: {len(X_train)}")
print(f"Test games: {len(X_test)}")
Exercise 1.3: Basic Logistic Regression
Train a logistic regression model to predict game outcomes.
Task: Build a simple win prediction model.
Starter Code:
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
def train_win_predictor(X_train, y_train, X_test, y_test):
"""
Train logistic regression for win prediction.
Returns:
--------
dict : Model and evaluation metrics
"""
# TODO: Initialize model
# TODO: Fit model
# TODO: Make predictions
# TODO: Calculate accuracy
pass
Exercise 1.4: Evaluate Model Performance
Calculate multiple evaluation metrics for a classifier.
Task: Implement evaluation function.
Starter Code:
from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score, confusion_matrix)
def evaluate_classifier(y_true, y_pred):
"""
Calculate classification metrics.
Returns:
--------
dict : All metrics
"""
# TODO: Calculate accuracy
# TODO: Calculate precision
# TODO: Calculate recall
# TODO: Calculate F1 score
# TODO: Generate confusion matrix
pass
Exercise 1.5: Feature Scaling
Implement feature scaling for model input.
Task: Use StandardScaler appropriately.
from sklearn.preprocessing import StandardScaler
def scale_features(X_train, X_test):
"""
Scale features using StandardScaler.
Important: Fit scaler on training data only!
Returns:
--------
tuple : (X_train_scaled, X_test_scaled, scaler)
"""
# TODO: Initialize scaler
# TODO: Fit on training data
# TODO: Transform both train and test
pass
Level 2: Application (Apply Concepts to New Situations)
Exercise 2.1: Cross-Validation Pipeline
Implement k-fold cross-validation for model evaluation.
Task: Build a complete CV pipeline.
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.linear_model import LogisticRegression
def cross_validate_model(X, y, n_folds=5):
"""
Perform stratified k-fold cross-validation.
Parameters:
-----------
X : np.ndarray
Feature matrix
y : np.ndarray
Target vector
n_folds : int
Number of folds
Returns:
--------
dict : CV results with mean, std, and all fold scores
"""
# TODO: Create StratifiedKFold splitter
# TODO: Initialize model
# TODO: Run cross_val_score
# TODO: Return results dictionary
pass
Exercise 2.2: Feature Engineering for Games
Create predictive features from raw game statistics.
Task: Engineer features that capture team strength.
def engineer_game_features(team_stats: pd.DataFrame,
schedule: pd.DataFrame) -> pd.DataFrame:
"""
Create features for game prediction.
Required features:
1. Differential features (home - away)
2. Rolling averages (last 5 games)
3. Opponent-adjusted metrics
4. Home field indicator
Returns:
--------
pd.DataFrame : Games with engineered features
"""
# TODO: Merge team stats for home teams
# TODO: Merge team stats for away teams
# TODO: Calculate differentials
# TODO: Add home advantage indicator
pass
Exercise 2.3: Model Comparison
Compare multiple models on the same dataset.
Task: Train and compare logistic regression vs. random forest.
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
def compare_models(X, y):
"""
Compare multiple classification models.
Models to compare:
1. Logistic Regression
2. Random Forest (n_estimators=100)
Returns:
--------
pd.DataFrame : Comparison of model performance
"""
models = {
'Logistic Regression': LogisticRegression(max_iter=1000),
'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42)
}
results = []
for name, model in models.items():
# TODO: Cross-validate each model
# TODO: Store results
pass
return pd.DataFrame(results)
Exercise 2.4: Probability Calibration Assessment
Evaluate how well-calibrated model probabilities are.
Task: Create a calibration assessment function.
from sklearn.calibration import calibration_curve
import matplotlib.pyplot as plt
def assess_calibration(y_true, y_prob, n_bins=10):
"""
Assess probability calibration.
Returns:
--------
dict : Brier score, ECE, and calibration data
"""
# TODO: Calculate Brier score
# TODO: Calculate calibration curve
# TODO: Calculate Expected Calibration Error (ECE)
# TODO: Create calibration plot
pass
Exercise 2.5: Baseline Comparison
Compare model performance to baselines.
Task: Implement baseline models for comparison.
def create_baselines(y_train, y_test):
"""
Create baseline predictions.
Baselines:
1. Random guess (50%)
2. Majority class
3. Historical home team win rate
Returns:
--------
dict : Baseline accuracies
"""
# TODO: Random baseline
# TODO: Majority class baseline
# TODO: Historical rate baseline
pass
Level 3: Analysis (Break Down and Examine)
Exercise 3.1: Feature Importance Analysis
Analyze which features drive predictions.
Task: Extract and visualize feature importance.
import matplotlib.pyplot as plt
def analyze_feature_importance(model, feature_names, top_n=10):
"""
Analyze and visualize feature importance.
Works with:
- Logistic Regression (coefficients)
- Random Forest (feature_importances_)
Returns:
--------
pd.DataFrame : Ranked feature importance
"""
# TODO: Extract importance scores
# TODO: Create ranking DataFrame
# TODO: Create visualization
# TODO: Return top features
pass
Exercise 3.2: Error Analysis
Analyze where the model makes mistakes.
Task: Identify patterns in prediction errors.
def analyze_errors(X_test, y_test, y_pred, feature_names):
"""
Analyze prediction errors.
Analysis:
1. Characteristics of correctly predicted games
2. Characteristics of incorrectly predicted games
3. Features that differ between correct/incorrect
Returns:
--------
dict : Error analysis results
"""
# TODO: Split into correct and incorrect
# TODO: Compare feature distributions
# TODO: Identify error patterns
pass
Exercise 3.3: Temporal Performance Analysis
Analyze how model performance changes over time.
Task: Track accuracy by season and week.
def temporal_performance(games_df, predictions, actuals):
"""
Analyze performance over time.
Questions:
1. Does accuracy vary by season?
2. Does accuracy improve as season progresses?
3. Are there systematic biases early vs late season?
Returns:
--------
pd.DataFrame : Performance by time period
"""
# TODO: Calculate accuracy by season
# TODO: Calculate accuracy by week
# TODO: Identify trends
pass
Exercise 3.4: Overfitting Detection
Detect and diagnose overfitting.
Task: Create functions to detect overfitting.
def detect_overfitting(model, X_train, y_train, X_test, y_test):
"""
Detect overfitting by comparing train/test performance.
Indicators:
1. Large train-test accuracy gap
2. Perfect training accuracy
3. Learning curves
Returns:
--------
dict : Overfitting diagnosis
"""
# TODO: Calculate training accuracy
# TODO: Calculate test accuracy
# TODO: Assess gap
# TODO: Generate learning curves
pass
Exercise 3.5: Sample Size Analysis
Analyze impact of sample size on model performance.
Task: Create learning curves to understand data requirements.
from sklearn.model_selection import learning_curve
def analyze_sample_size(model, X, y, train_sizes):
"""
Analyze how sample size affects performance.
Returns:
--------
dict : Learning curve data and visualization
"""
# TODO: Generate learning curve data
# TODO: Plot training and validation scores
# TODO: Identify minimum viable sample size
pass
Level 4: Synthesis (Combine Elements in New Ways)
Exercise 4.1: Complete Prediction Pipeline
Build an end-to-end prediction pipeline.
Task: Create a class that handles the entire ML workflow.
class GamePredictionPipeline:
"""
Complete pipeline for game outcome prediction.
Components:
1. Data preparation
2. Feature engineering
3. Model training with CV
4. Evaluation
5. Prediction on new games
"""
def __init__(self, model_type='logistic'):
# TODO: Initialize components
pass
def prepare_data(self, raw_data: pd.DataFrame) -> pd.DataFrame:
# TODO: Clean and prepare data
pass
def engineer_features(self, data: pd.DataFrame) -> pd.DataFrame:
# TODO: Create features
pass
def train(self, X: pd.DataFrame, y: pd.Series) -> dict:
# TODO: Train with cross-validation
pass
def evaluate(self, X_test: pd.DataFrame, y_test: pd.Series) -> dict:
# TODO: Generate evaluation report
pass
def predict(self, new_games: pd.DataFrame) -> pd.DataFrame:
# TODO: Make predictions on new data
pass
Exercise 4.2: Ensemble Model Builder
Create an ensemble combining multiple models.
Task: Build a voting classifier with multiple base models.
from sklearn.ensemble import VotingClassifier
def build_ensemble(X_train, y_train, X_test, y_test):
"""
Build ensemble model combining multiple classifiers.
Ensemble components:
1. Logistic Regression
2. Random Forest
3. Gradient Boosting
Returns:
--------
dict : Ensemble model and performance
"""
# TODO: Define base models
# TODO: Create VotingClassifier
# TODO: Train ensemble
# TODO: Compare to individual models
pass
Exercise 4.3: Hyperparameter Optimization
Optimize model hyperparameters.
Task: Implement grid search for hyperparameter tuning.
from sklearn.model_selection import GridSearchCV
def optimize_hyperparameters(X, y, model_type='random_forest'):
"""
Find optimal hyperparameters using grid search.
Returns:
--------
dict : Best parameters and performance
"""
param_grids = {
'random_forest': {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 20, None],
'min_samples_split': [2, 5, 10]
},
'logistic': {
'C': [0.001, 0.01, 0.1, 1.0, 10.0],
'penalty': ['l1', 'l2']
}
}
# TODO: Set up GridSearchCV
# TODO: Fit grid search
# TODO: Extract best parameters
# TODO: Evaluate best model
pass
Exercise 4.4: Model Monitoring System
Build a system to monitor model performance over time.
Task: Create monitoring infrastructure.
class ModelMonitor:
"""
Monitor prediction model performance.
Features:
1. Log predictions and outcomes
2. Calculate rolling accuracy
3. Detect performance degradation
4. Alert when retraining needed
"""
def __init__(self, model_name: str, baseline_accuracy: float):
# TODO: Initialize monitoring state
pass
def log_prediction(self, game_id: str, prediction: dict):
# TODO: Store prediction
pass
def log_outcome(self, game_id: str, actual: int):
# TODO: Store actual outcome
pass
def get_performance_report(self, window: int = 50) -> dict:
# TODO: Calculate recent performance
pass
def check_for_drift(self, threshold: float = 0.05) -> dict:
# TODO: Compare recent vs historical performance
pass
Exercise 4.5: Interactive Prediction Dashboard
Build a simple dashboard for predictions.
Task: Create functions for a prediction interface.
def create_prediction_interface(model, team_stats: pd.DataFrame):
"""
Create interface for making predictions.
Features:
1. Select home team
2. Select away team
3. Display prediction with confidence
4. Show feature contributions
"""
# TODO: Create team selection
# TODO: Generate prediction
# TODO: Display results
pass
Level 5: Evaluation (Judge and Justify)
Exercise 5.1: Model Selection Justification
Choose and justify the best model for a scenario.
Scenario: A college athletic department wants to predict game outcomes to set expectations with boosters.
Task: 1. Train multiple models 2. Evaluate each on relevant criteria 3. Write a recommendation memo explaining your choice
Criteria to consider: - Accuracy - Calibration of probabilities - Interpretability for stakeholders - Computational requirements - Maintenance burden
Exercise 5.2: Ethical Considerations
Evaluate ethical implications of football predictions.
Task: Write an analysis addressing: 1. Impact on gambling and integrity concerns 2. Privacy of player data used in models 3. Transparency of predictions to affected parties 4. Potential for biased predictions
Exercise 5.3: Feature Selection Debate
Evaluate different approaches to feature selection.
Task: Compare three approaches and recommend one: 1. Domain expertise only (manually selected features) 2. Statistical selection (correlation-based) 3. Model-based selection (importance from random forest)
Include: - Pros and cons of each approach - When each is appropriate - Your recommendation with justification
Exercise 5.4: Validation Strategy Critique
Evaluate a proposed validation strategy.
Proposed Strategy: "We'll use 5-fold cross-validation on all games from 2018-2023 to evaluate our model."
Task: 1. Identify problems with this approach 2. Propose an improved strategy 3. Explain why your approach is better
Exercise 5.5: Production Readiness Assessment
Evaluate whether a model is ready for production deployment.
Task: Create a production readiness checklist and evaluate a model against it.
Model Details: - Logistic regression for game predictions - 65% accuracy on test set (2023 season) - Trained on 2018-2022 data - Uses 12 features - No monitoring implemented
Deliverable: - Readiness checklist (10+ items) - Assessment of current state - Recommendations for production deployment
Submission Guidelines
Code Requirements
- All Python code must be executable
- Include docstrings for all functions
- Follow PEP 8 style guidelines
- Include type hints
Analysis Requirements
- Show your reasoning
- Compare to baselines
- Discuss limitations
Report Requirements
- Clear structure
- Data-driven conclusions
- Actionable recommendations
Grading Rubric
| Level | Weight | Criteria |
|---|---|---|
| Level 1 | 15% | Correct implementation, basic functionality |
| Level 2 | 25% | Complete pipeline, proper validation |
| Level 3 | 25% | Thorough analysis, meaningful insights |
| Level 4 | 20% | Working system, good design |
| Level 5 | 15% | Sound judgment, clear justification |