Skip to main content

Python foundations for AI

โฑ 25 min

Hookโ€‹

You follow a tutorial that fits a model in one line: model.fit(X, y). It works on the tutorial's data, so you point it at your own spreadsheet and it explodes with could not convert string to float. The tutorial never showed you what X and y actually are, so when your data does not already look like theirs, you are stuck. Every model in this school expects the same two shapes, and once you can build them from raw records, the rest stops being magic.

Conceptโ€‹

A machine-learning model does not see rows, columns, or spreadsheets. It sees two things: a list of feature vectors โ€” the numeric inputs for each example, conventionally called X โ€” and a matching list of labels โ€” the answer for each example, conventionally called y. A feature vector is simply an ordered group of numbers describing one example; the label is what you want to predict for it. Getting from raw data to a clean (X, y) pair is most of the work, and Python's built-in structures are the tools for it.

You already met these structures in a general context; here is what each one does in the shape of ML data:

  • A list holds the examples in order โ€” X is a list of feature vectors, y is a list of labels, and position i in one lines up with position i in the other.
  • A tuple is a natural feature vector: (tenure_months, monthly_charges) is a fixed, ordered group of numbers you never mutate.
  • A dict is how a raw record usually arrives โ€” a CSV or JSON reader hands you {"tenure_months": "2", "monthly_charges": "89.0"}, with keys naming columns and values still as strings.
  • A list comprehension is how you pull one column out of many rows, and zip is how you walk X and y together without index bookkeeping.

The move you will make constantly is turning a list of raw dicts into X and y. Read a feature out of each dict, coerce it to a number, and collect the results:

# A dataset is rows; each row pairs a feature vector with a label.
dataset = [
({"tenure_months": 2, "monthly_charges": 89.0}, "churn"),
({"tenure_months": 40, "monthly_charges": 55.0}, "stay"),
({"tenure_months": 8, "monthly_charges": 95.0}, "churn"),
]
X = [(row["tenure_months"], row["monthly_charges"]) for row, _ in dataset]
y = [label for _, label in dataset]
print(X)
print(y)
[(2, 89.0), (40, 55.0), (8, 95.0)]
['churn', 'stay', 'churn']

The rule that holds across the whole school: X and y are two aligned sequences, one feature vector and one label per example, and keeping them aligned is your job. Every model, metric, and split in this course assumes that alignment; break it and you will train on one example's features against another example's answer.

StructureIts job in ML dataExample
listOrdered collection of examples (X and y)[(2, 89.0), (40, 55.0)]
tupleOne feature vector: fixed, ordered numbers(2, 89.0)
dictA raw record at the input boundary{"tenure_months": "2"}
comprehensionExtract a feature or label column from rows[r["plan"] for r in records]
๐Ÿง  Knowledge check
1. In machine-learning code, what are X and y?
2. A CSV reader hands you rows as dicts with all values as strings. Before those rows can be feature vectors, what must you do?

Worked exampleโ€‹

Let me turn a batch of raw usage records into X and y for a task that predicts a user's plan from their activity. The records arrive as dicts with everything as strings โ€” the typical output of a CSV reader โ€” and I want feature vectors of (sessions, minutes) paired with the plan label.

raw_records = [
{"id": "u-1", "sessions": "12", "minutes": "240", "plan": "pro"},
{"id": "u-2", "sessions": "3", "minutes": "35", "plan": "free"},
{"id": "u-3", "sessions": "9", "minutes": "180", "plan": "pro"},
]

X = [(int(r["sessions"]), int(r["minutes"])) for r in raw_records]
y = [r["plan"] for r in raw_records]

for features, label in zip(X, y):
print(features, "->", label)

mean_sessions = sum(sessions for sessions, _ in X) / len(X)
print("mean sessions:", round(mean_sessions, 2))
(12, 240) -> pro
(3, 35) -> free
(9, 180) -> pro
mean sessions: 8.0

Three decisions in that small block matter. First, I dropped id from the feature vector on purpose: an identifier carries no signal a model should learn from, and feeding it in invites the model to memorize rows. Second, I cast sessions and minutes with int(...) right where I build the vector, so nothing downstream ever sees a string where it expects a number. Third, I used zip(X, y) to walk the aligned pair together โ€” no range(len(X)) index juggling, and the alignment is obvious to anyone reading it. The mean at the end is a first taste of the summary statistics you will lean on in the next lesson.

Hands-onโ€‹

Your turn, with a different dataset. The exercise below hands you raw sensor records as dicts and asks you to build X as a list of (temperature, humidity) tuples and y as the list of state labels, coercing the numeric fields as you go. It runs in Python Arena, so there is nothing to install.

โ–ถ Python Arenaai101-rows-to-features-and-labels
Open in Python Arena โ†—

Success criteria: your code returns X and y as aligned sequences of the same length, with each feature vector a tuple of two numbers and each label a string. The Arena checks the alignment and types against a hidden set of records automatically.

Recapโ€‹

  • You can describe any supervised dataset as X (feature vectors) and y (aligned labels), one entry per example.
  • You can turn a list of raw dicts into X and y, coercing string fields to numbers and dropping identifiers that carry no signal.
  • You can walk the aligned pair with zip instead of index bookkeeping, keeping features and labels lined up.

Next up: where those rows come from. You will load a real dataset from a CSV file and describe it with summary statistics before you trust it.

๐Ÿง  Knowledge check
1. Why is zip(X, y) preferred over looping with range(len(X)) to pair features with labels?
2. You are building feature vectors from user records that include a unique user_id. Should user_id go into the feature vector?
๐Ÿ“Œ Key takeaways
  • A supervised dataset is two aligned sequences: X (feature vectors) and y (labels). - Raw records arrive as dicts of strings; extract and coerce fields to build numeric feature vectors. - Keep X and y aligned with zip, and keep identifiers out of the features.