Skip to content

DS 201 · Module 1

Frame a Prediction Problem and Build a First Model

Starting from a service-demand dataset, practice defining a prediction problem, building a baseline, splitting data correctly, and training your first verifiable regression model.

Start Section 1
0 / 5 completed
Sync my progressJoin a session to keep progress across devices and share it with your instructor

Info

After you join, your completed lesson numbers are sent to your instructor together with your learner code, so they can see your progress. Use the codes your instructor gave you, and do not enter your name, company secrets or other personal data. Progress is kept with the rest of that session's data.

Learning objectives

  • Define prediction unit, target, horizon, decision, and information available at prediction time
  • Use naive/majority/mean or rule-based baselines before ML
  • Separate fitting/tuning/final evaluation; prevent future/target leakage
  • Fit a simple regression model; interpret MAE/RMSE in domain units
  • Build baseline and model with a fixed split; compare held-out performance

Prediction Problems: Target, Features, Prediction Time

35 min

Prediction Problems: Target, Features, Prediction Time

Learning goal: define prediction unit, target, horizon, decision, and information available at prediction time.

Your manager says: "Let's predict next week's case volume for each service site." That sounds like a clear task, but a lot is still undefined: what does one "prediction" correspond to: one site, one day, or one shift? Is the target the raw case count, or a binary flag for exceeding capacity? When does "next week" actually start? Most importantly, at the moment you make the prediction, which fields do you really already know, and which only appear afterward?

Skipping this step and feeding data straight into a model has a familiar consequence: a team uses a column that is only produced after a case closes, the model looks great on historical data, but the moment it goes live the numbers do not match at all, because that column simply does not exist yet at prediction time. Writing down the prediction unit, the target, and the prediction time up front avoids this kind of after-the-fact, costly surprise.

A vague task description

"Predict case volume": no defined prediction unit, no target definition, no time horizon, and no check on which columns are actually available at prediction time.

A clearly framed prediction problem

Prediction unit
One row = one service site at a given split_time, producing one prediction case (case_id) for a future window.
Target
target_numeric is the future case volume (regression); target_binary is whether it exceeds a capacity threshold (classification).
Prediction time
Every case_id carries a split_time: only features_* that existed before that moment may be used to predict.
The course dataset (check the schema before talking about models)
import pandas as pd

# clean: a service-demand prediction dataset, one row per prediction case
df = pd.read_csv("DS201_Service_Demand_Clean.csv", parse_dates=["created_at", "split_time"])
df.shape
df.dtypes
df[["case_id", "split_time", "target_numeric", "target_binary"]].head()

# Ask first: which features_* columns are actually known before split_time?
[c for c in df.columns if c.startswith("features_")]
Four questions every prediction problem must answer
QuestionThis dataset's answer
What is the prediction unit?One case_id: one service site's demand prediction as of one split_time
What is the target?target_numeric (future case volume) or target_binary (whether it exceeds a capacity threshold)
What is the decision?Whether to pre-allocate staff or resources to that site
What is available at prediction time?Only features_* produced before split_time; the target itself is never available at prediction time
Exercise: can this column be used? (simulated case)

Suppose features_queue_length_at_split records the queue length at the moment of split_time, while features_total_handling_time records the total handling hours summed up after a case closes. The first already exists at prediction time and can be used as a feature; the second is only computable once the case has ended, so it is future information. Even if it correlates strongly with the target, it cannot be used.

  • Treating 'prediction' as the same thing as 'analysis,' without first defining a clear prediction time
  • Judging whether a column can be used purely from its name, instead of actually checking when it is produced
  • Using the target's own historical values directly as a feature without checking whether it leaks the answer at prediction time
  • Different people defining 'one prediction' inconsistently, which makes later evaluation results impossible to compare

Warning

Data safety reminder: every exercise in this course uses course-provided synthetic data. Unless authorized, never paste confidential institutional data, client personal data, or other unauthorized sensitive information into an AI tool or the practice environment.

Info

Human, AI, Human: a person defines the prediction unit, target, and decision; AI may help list candidate features or sketch a timeline; a person confirms every feature is truly available at prediction time before handing the problem to a model.
Check yourself

A colleague proposes using "the average handling time computed after a case closes" as a feature to predict "this week's case volume." What is the biggest problem with this?

A colleague proposes using "the average handling time computed after a case closes" as a feature to predict "this week's case volume." What is the biggest problem with this?

Key takeaway: Completing the steps is not enough; the result must be verifiable, reproducible, and explainable.

Baselines

35 min

Baselines: What Must the Model Beat?

Learning goal: use naive/majority/mean or rule-based baselines before ML.

A colleague announces excitedly: "Our model is 82% accurate!" But if simply guessing "every site's case volume equals the overall average" already reaches 78%, the model's real gain is only 4 points, not the 82% it sounds like. Without a baseline, no score can be judged as worth the cost of building and maintaining a model.

Which baseline to pick depends on the data's own characteristics: data with a clear time pattern suits a naive baseline; data with an uneven class or value distribution often makes a majority or mean baseline already hard to beat. Spending ten minutes computing a baseline up front is far cheaper than discovering later that a model added no real value at all.

No baseline

  • Only the model score is reported, and a "high enough" number is treated as good
  • No way to tell whether the score is the model's achievement or just an easy dataset
  • Change the data or the threshold and the conclusion can flip entirely

A baseline first

  • A naive/majority/mean/rule-based baseline is "what you get without machine learning"
  • A model must clearly beat the baseline to justify training and maintenance cost
  • Baseline and model must be compared on the same validation data to be fair
Build a simple baseline for regression and for classification
import numpy as np

# Regression baseline: use the training mean case volume as every prediction
mean_baseline = df["target_numeric"].mean()
baseline_mae = (df["target_numeric"] - mean_baseline).abs().mean()

# Classification baseline: majority class (always predict "never exceeds threshold")
majority_class = df["target_binary"].mode()[0]
baseline_accuracy = (df["target_binary"] == majority_class).mean()

print(round(baseline_mae, 2), round(baseline_accuracy, 3))
Common baseline types
Baseline typeWhen to useExample
Naive (previous period)Data with a clear time orderPredict next week's volume = last week's volume
Majority / MeanThe simplest starting point for classification / regressionAlways predict the most common class, or always predict the mean
Rule-basedA known business rule of thumb"Monday volume is usually 1.3x the weekday average"
Case: a weak-looking baseline that is hard to beat (simulated)

One service site's case volume stays almost entirely between 18 and 22 per week, with very little variation. The mean baseline's MAE is only 1.8, which looks "too easy to beat," but the actual trained regression model's MAE is 1.6, a gain of only 0.2. This situation is simply easy to predict on its own; the model's real added value is very small, and whether it is worth the maintenance cost needs a separate assessment.

  • Reporting only the model's score without also reporting the matching baseline score
  • Computing baseline statistics from the training set, then comparing them against a model score measured on the test set
  • Looking only at accuracy for a classification problem without first checking the majority class share
  • Forgetting to recompute the baseline after a data refresh, leaving the comparison point stale

Warning

Reporting a model score without a baseline is one of the easiest ways to overstate a model's value: when the data is inherently easy to predict, any model will "look accurate": but that is not the model's achievement.
Check yourself

A classification model reaches 91% accuracy, but 90% of the cases belong to the majority class "did not exceed the capacity threshold." What is the most reasonable reading of that 91%?

A classification model reaches 91% accuracy, but 90% of the cases belong to the majority class "did not exceed the capacity threshold." What is the most reasonable reading of that 91%?

Key takeaway: Completing the steps is not enough; the result must be verifiable, reproducible, and explainable.

Train/Validation/Test and Leakage

45 min

Train / Validation / Test and Leakage

Learning goal: separate fitting/tuning/final evaluation; prevent future/target leakage.

A colleague keeps tweaking model parameters on the same dataset, checking the test-set score every time and keeping whichever setting scores highest. The problem: the test set has now been used to make decisions, so it is no longer "unseen data." The final reported score will be systematically inflated, and real-world performance after deployment usually disappoints.

Leakage is not always a coding mistake; often the problem is in how a column itself is defined: for example, a column computed using a statistic over the whole dataset (like a global mean) that already bakes in information from the test set. The basic rule for avoiding this kind of hidden leakage is to split the data first, and only compute any statistic afterward.

The role of each of the three splits
SplitPurposeRule
TrainLets the model learn its parametersMay be reused and retrained repeatedly
ValidationCompares models or tunes hyperparametersMay be checked many times, but is never the final reported score
TestApproximates final, unseen-data performanceChecked once; once you decide whether to adjust, you do not go back and re-edit
Split by time so the past never predicts using the future
df_sorted = df.sort_values("split_time")
n = len(df_sorted)
train = df_sorted.iloc[: int(n * 0.6)]
valid = df_sorted.iloc[int(n * 0.6): int(n * 0.8)]
test = df_sorted.iloc[int(n * 0.8):]

# Check: is train's latest time earlier than test's earliest time?
train["split_time"].max() < test["split_time"].min()
  1. Sort by time before splitting
    Service-demand data has a time order: train must be entirely earlier than valid, and valid entirely earlier than test: never shuffled randomly.
  2. Check for leakage sources
    Confirm no column is known only after the fact (for example, a field produced after a case closes), and that no single site's rows straddle both train and test.
  3. Check test only once, at the end
    The test-set score is checked once, after all tuning is finished; going back to adjust the model afterward means starting a new round of the whole process.
Case: hidden leakage (simulated)

Before splitting the data, a colleague standardizes features_queue_length across the entire dataset (subtracting the overall mean, dividing by the overall standard deviation). Because that "overall mean" already mixes in test-set values, the training stage indirectly sees test-set information. The correct order is to split first, compute the mean and standard deviation from train only, and then apply them to validation and test.

  • Any statistic (mean, standard deviation, group aggregate) should be computed from train only, then applied to validation / test
  • Confirm the same service site or case does not appear across more than one split
  • Confirm a column's production time is before split_time, rather than judging it only by whether its name sounds like a feature
  • Check the test-set score only once; if the model needs further adjustment afterward, restart the whole process

Warning

The two most common sources of leakage: (1) target leakage: using a column that only exists after the case outcome is known; (2) a broken split: randomly splitting time-ordered data lets future information quietly flow into training.
Check yourself

A time-ordered service-demand dataset is split with a "random split" instead of a "time-based split" for train/test. What is the most likely consequence?

A time-ordered service-demand dataset is split with a "random split" instead of a "time-based split" for train/test. What is the most likely consequence?

Key takeaway: Completing the steps is not enough; the result must be verifiable, reproducible, and explainable.

Regression and Evaluation

40 min

Regression and Regression Metrics: MAE, RMSE

Learning goal: fit a simple regression model; interpret MAE/RMSE in domain units.

After training, a colleague reports a single number: "RMSE is 12.4." That number is meaningless on its own unless you know its unit, how it compares to the scale of the target, and what the gap between it and MAE reveals. Regression evaluation is not about computing a metric: it is about translating that metric back into business language like "case-volume error."

When translating MAE or RMSE into business language, always report it alongside the scale of the target. "MAE is 3.2" means roughly a 16% error when the average case volume is 20, but the same 3.2 means only a 1.6% error when the average case volume is 200. Without that scale for comparison, a single error number is nearly impossible to judge.

MAE vs. RMSE
MetricCalculationCharacteristics
MAE (Mean Absolute Error)Average of the absolute value of each errorExpressed in the target's original units, easy to explain to the business; weighs every error equally
RMSE (Root Mean Squared Error)Square each error, average, then take the square rootMore sensitive to large errors; a few very large misses get amplified
Train a simple regression model and compare it to the baseline
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error

feature_cols = [c for c in df.columns if c.startswith("features_")]
model = LinearRegression().fit(train[feature_cols], train["target_numeric"])
pred = model.predict(valid[feature_cols])

mae = mean_absolute_error(valid["target_numeric"], pred)
rmse = mean_squared_error(valid["target_numeric"], pred, squared=False)
print(round(mae, 2), round(rmse, 2))
# Compare against baseline_mae from Lesson 2 to judge whether the model is worth using
Case: the same MAE, different meanings (simulated)

Site A has an average case volume of 15 and a model MAE of 3; site B has an average case volume of 150 and the same model MAE of 3. For site A, that error is about 20% of the average value and may already be large enough to disrupt staffing decisions; for site B, the same error is only about 2% of the average value, a much smaller impact. Errors should always be reported alongside their share of the target's mean or median.

  • Report MAE and RMSE together, and explain what the gap between them reveals
  • Convert the error into a percentage of the target's mean or median instead of giving only the raw number
  • State which split (validation or test) the error was computed on
  • Report the gap against the baseline alongside the error, rather than presenting it in isolation

Warning

If RMSE is clearly larger than MAE, a handful of predictions have unusually large errors. Reporting RMSE alone makes overall error look worse than it typically is; reporting MAE alone can hide those severe outlier misses. Report both together.
Check yourself

Two models on the same data both have MAE of 10, but model A has RMSE 11 and model B has RMSE 25. What is the most reasonable interpretation?

Two models on the same data both have MAE of 10, but model A has RMSE 11 and model B has RMSE 25. What is the most reasonable interpretation?

Key takeaway: Completing the steps is not enough; the result must be verifiable, reproducible, and explainable.

Guided Lab

55 min

Guided Lab: First Verifiable Predictive Model

Learning goal: with instructor guidance, build a baseline and a model with a fixed split, and compare held-out performance.

Info

Practice question: with only one page to convince stakeholders whether a model is worth using, how would you use a fixed data split, a baseline, and MAE/RMSE to prove the model actually beats not using machine learning at all?
  1. Confirm the prediction problem
    Write down this lab's prediction unit, target_numeric, decision, and the features_* available before split_time.
  2. Split by time
    Sort by split_time and cut train/validation/test, checking that the three time ranges do not overlap.
  3. Build a baseline
    Use the training mean as the mean baseline, and compute its MAE on validation.
  4. Train and compare
    Train a simple regression model, compute its MAE and RMSE on validation, and compare it to the baseline.
  5. Final evaluation
    Once a model is chosen, check the test-set score exactly once and do not adjust afterward.
  6. Note what still needs human judgment
    List what this result cannot yet answer or still needs further checking or human judgment (for example, seasonality or extreme events).
The minimum the Guided Lab should include (fill in your own output)
ItemWhat to report
Prediction problemPrediction unit, target, decision, and columns available at prediction time
Split approachTime ranges and row counts of train/validation/test
BaselineThe mean baseline's MAE
Model performanceThe model's MAE and RMSE on validation, and the gap from the baseline
Final resultThe final score checked exactly once on the test set
  • Confirm every reported output can actually be re-run, and that no number was hand-edited
  • Clearly state which columns were excluded because of leakage, rather than because they simply hurt performance
  • Any "the model beats the baseline" conclusion should include the actual size of the gap, not just "it improved"

Warning

"The code ran" does not mean "the model is trustworthy." Every number must be re-runnable and explainable, and the test set may be checked only once.

Done

If AI helps write training or evaluation code, check every item yourself: was the split done by time, are all features truly available before prediction time, was the baseline actually computed, and was the final score checked only once. AI can speed up drafting; verification and the conclusion remain a human responsibility.
Check yourself

You finish the Guided Lab and the model beats the baseline's MAE on validation, but you discover one of the features_* columns is actually produced only after a case closes. What is the most appropriate next step?

You finish the Guided Lab and the model beats the baseline's MAE on validation, but you discover one of the features_* columns is actually produced only after a case closes. What is the most appropriate next step?

Key takeaway: Completing the steps is not enough; the result must be verifiable, reproducible, and explainable.

What next?