ModernCS
Session 1.190 minFree preview

What a Prediction Problem Is

Rows, features, a target, and framing a question someone actually has.

By the end of this session you will be able to:

  • Turn a vague request from a real person into a written prediction problem: a row, a target, and a prediction moment
  • Choose the unit of analysis that matches the decision you will make, instead of inheriting whatever shape the CSV arrived in
  • Reject a feature because it would not exist at the moment the prediction is made

A request is not a prediction problem yet

Someone in the registrar's office says: "too many first years are dropping the intro course, can you do something with the data?"

That is a real question and it is not yet a prediction problem. It is a why question, and machine learning does not answer why. What a supervised model does is narrower and dumber: you hand it a table where every row is one thing, one column of that table is an answer you already know, and it learns to guess that column from the others. That is the whole contract.

So the work here is translation. You take a sentence a person said and turn it into four commitments:

  1. The row. What is one thing? One student, one ticket, one week?
  2. The target. Which single column holds the answer, defined precisely enough that two people fill it in the same way?
  3. The prediction moment. When does the model get asked?
  4. The features. What is known at that moment, and nothing more.

Get these wrong and every later step is wasted. A flawless training loop on a badly framed table produces a model that is confidently useless, which is worse than no model, because someone will believe it.

The row is the decision you are making

Here is what raw data from that request actually looks like. It is a support log, one line per message:

ticket_id,student_id,opened_at,channel,text
8841,S1042,2026-02-11T09:12,email,"cannot submit lab 2, upload fails"
8842,S1187,2026-02-11T09:40,chat,"where is the recording for week 3"
8843,S1042,2026-02-12T14:02,email,"still failing, deadline is friday"
8844,S1042,2026-02-19T08:55,chat,"dropping the course, how do i withdraw"

This file has a shape already, and that shape is one row per ticket. The most common beginner move is to accept it. That is a mistake, because you cannot act on a ticket. You can act on a student.

The same raw events support at least three framings:

  • One row per ticket. Will this ticket need a human reply? Useful if you are staffing a helpdesk.
  • One row per student. Did this student withdraw? Useful if you are deciding who gets a phone call.
  • One row per student per week. Did this student withdraw in the next four weeks? Useful if you want a warning every Monday.

None is more correct in general. The right one matches the decision. If the intervention is an advisor calling a student once in week 4, your row is one student, and that log gets squashed down into per-student columns: ticket count, days since last ticket, whether the word "withdraw" ever appeared. Pick the row first, because the row determines what a feature even means.

The target is a column you can fill in for the past

A target is not an idea. It is a value that exists, right now, for rows that already happened. "Students who are struggling" is not a target: nobody can go into last year's data and write down a 1 or a 0 for it without arguing. Compare:

Dropped means the student made no submission after week 6 and had no completion mark recorded at the end of the semester.

That one you can compute. Two different people would produce the same column. The definition carries a cutoff, a source, and a rule for the ambiguous cases, and that is what makes it a target rather than a vibe.

The target's type also decides what kind of problem you have, for free, once the definition is written. A yes or no column is classification. A number like "how many days until withdrawal" is regression. You do not choose by taste; you read it off the column.

Here is the framing written out. Copy this shape and fill it in for your own problem:

Row:              one enrolled student, one course, one semester
Target:           dropped = no submission after week 6
                  and no completion mark at semester end
Target type:      binary, 1 or 0
Prediction made:  end of week 3
Features (known at end of week 3):
                  submissions_on_time_wk1_3
                  minutes_on_platform_wk1_3
                  support_tickets_wk1_3
                  prior_courses_completed
                  registered_late

Features are only what you knew before the answer

Look at that last line of the spec: known at end of week 3. Every feature has to pass that test.

The tempting column here is final_grade. It sits right there in the student record, it correlates beautifully with dropping out, and it will push your accuracy to something that looks like a triumph. It is also recorded in June, three months after the moment your model gets asked. In production that column is empty, and your model has nothing to say.

This is the most common way a beginner's first project dies: it scores wonderfully in a notebook and predicts nothing in the world, because half its inputs are consequences of the target rather than facts available before it. The fix is not statistical. The fix is the sentence "at the end of week 3", written down before you build the table and applied to every column.

Once the framing holds, the table has a fixed shape that every tool in this course expects. In scikit-learn (1.9) that convention is X with shape (n_samples, n_features) and y with shape (n_samples,):

import numpy as np
 
# One row per student, one column per feature.
X = np.array([
    [3, 210, 1, 2, 0],
    [0,  35, 4, 0, 1],
    [7, 480, 0, 5, 0],
    [1,  60, 3, 1, 1],
])
y = np.array([0, 1, 0, 1])   # 1 = dropped
 
print(X.shape)   # (4, 5)  samples, features
print(y.shape)   # (4,)    one target value per row
print(len(X) == len(y))   # must be True

Four students, five features each, four answers. If those two lengths ever disagree, your framing broke somewhere and no amount of tuning repairs it.

Try it

Take a request someone has genuinely made of you or of your department. Not a Kaggle dataset: a sentence a person said. If you have none, use this one: "we keep running out of lab machines on Tuesdays, can you predict that?"

Write the five-line spec from above: row, target, target type, prediction moment, and at least four features. Then run the audit. Cross out every feature that would not be filled in at your prediction moment. Your success condition is two-part:

  1. You can describe one single row out loud, including what its target value is and why.
  2. After crossing out, you still have at least three features left.

If you crossed out most of your list, that is a result, not a failure. Your prediction moment is too early or your target sits too far in the past, and you fix the framing, not the data.

Common mistakes

  • Predicting something nobody will act on. If no decision changes based on the output, you are producing a number for a slide. Ask what happens on the day the prediction says yes; if there is no answer, reframe.
  • Letting the file choose the row. The CSV arrives with one row per event, so people model events. Choose the row from the decision, then aggregate the raw records to reach it.
  • A target written in adjectives. "At risk", "engaged", "high value" cannot be computed. Rewrite it until it contains a threshold, a date, and a rule for ties.
  • A feature recorded after the target. Final grades, closing notes, refund flags. They leak the answer, and they will not exist when the model is asked for real.
  • Framing a why question as a prediction. A model that predicts dropping tells you what accompanies it, not what causes it. Reading it as cause is how a project ends up recommending you cancel the tutorials the struggling students attended.

Where this goes next

Next session, "Tables in Python", you put this framing into code: load a CSV with pandas, select the rows and columns your spec asked for, check the types, and find what is missing. The spec you wrote today is the thing you build there.

That was one session of 5 in this phase.

Machine Learning runs to 4 phases. Buy the whole course, or just the phase you need.