ML FoundationsBeginner8 min01 / 13

What is Machine Learning?

Discover how machines learn patterns from data instead of following hand-written rules — and why that changes everything.

Every morning your email client silently sorts hundreds of messages, deciding which ones are spam — without you ever writing a rule like "if it says FREE MONEY it's spam". Your phone unlocks when it sees your face. Netflix knows you'll enjoy that obscure documentary before you do. None of these systems were programmed with explicit instructions for every situation. They learned from examples. That's Machine Learning — and this lesson will show you exactly what that means.

#Traditional Programming vs. Machine Learning

Traditional programming works like a recipe: you write rules (your code) + feed it data → the computer follows your rules and produces answers. A spam filter built the old way might say: "if the subject contains 'WINNER' AND the sender is unknown, mark as spam." You, the programmer, had to invent every rule.

Machine Learning flips the script: you give the computer data (many examples) + answers (labels like spam / not-spam) → the computer discovers the rules itself. The result is called a model. The model is not a list of if-statements; it's a compact mathematical summary of the patterns found in your examples.

Think of it like

Teaching by Example

Imagine teaching a child what a dog is. You don't hand them a biology textbook — you point at many dogs and say "dog", point at cats and say "not dog", and eventually the child builds an internal sense of dog-ness. Machine Learning works the same way: show the algorithm thousands of labelled examples, and it builds its own internal rules — even rules it cannot fully explain in words.

#Learning From Scratch — in Pure Python

The program searched for the best rule on its own — we never hard-coded the number 3. That search is the essence of learning.
# Training data: (exclamation_marks, is_spam)
data = [
    (0, False), (1, False), (0, False), (2, False),
    (5, True),  (7, True),  (4, True),  (6, True),
    (1, False), (3, True),
]

best_threshold, best_accuracy = 0, 0
for t in range(0, 8):
    correct = sum(1 for marks, spam in data if (marks >= t) == spam)
    acc = correct / len(data)
    if acc > best_accuracy:
        best_accuracy, best_threshold = acc, t

print(f"Learned rule: spam if exclamation_marks >= {best_threshold}")
print(f"Training accuracy: {best_accuracy:.0%}")

#The Two Phases: Training and Inference

Every ML system has two distinct phases.

Training (learning): Feed the algorithm labelled examples. It adjusts its internal numbers — called parameters — to minimise mistakes. This happens once, or periodically when fresh data arrives.

Inference (predicting): Take the finished, frozen model and give it a brand-new, unseen input. It produces a prediction in milliseconds. No learning happens here.

Your face-unlock model was trained on photos before your phone left the factory. Every time you hold it up, it runs inference — a single quick calculation with the frozen model. The two phases are always separate.

Inference just applies the frozen learned rule to new inputs — no training data needed anymore.
# Inference: apply the frozen threshold to new emails
def predict_spam(marks, threshold):
    return marks >= threshold

new_emails = [
    ("Meeting at 3pm?", 1),
    ("YOU WON!!!!!", 5),
    ("Lunch tomorrow", 0),
]
for subject, marks in new_emails:
    label = "SPAM" if predict_spam(marks, best_threshold) else "OK"
    print(f"{label}: '{subject}'")
Common mistake

"More data always helps" — not quite

A common misconception: throwing more data at a model always makes it better. In reality, garbage in, garbage out — biased or mislabelled data produces a biased model no matter how much of it you have. Quality beats quantity: 1,000 carefully labelled examples often outperform 1,000,000 noisy ones. Good ML engineering means choosing the right data and the right model together.

#Real-World ML All Around You

Once you see the training/inference pattern, you spot ML everywhere:

  • Spam filters — trained on millions of labelled emails, predicting in real time
  • Recommendations — Netflix and Spotify trained on billions of histories to predict what you enjoy next
  • Face unlock — trained on face photos, running inference every time you lift your phone
  • Fraud detection — trained on normal vs. fraudulent transactions, flagging suspicious charges instantly
  • Medical imaging — trained on labelled X-rays, helping radiologists spot anomalies earlier

In every case: labelled examples in during training; fast predictions out during inference.

Quick check

A spam filter is trained on 10,000 labelled emails, then deployed. Which phase is happening when it classifies a brand-new email you just received?

In practice, two lines replace our hand-written search loop:

``python model.fit(X_train, y_train) # training preds = model.predict(X_test) # inference ``

Libraries like scikit-learn, PyTorch, and TensorFlow handle the heavy optimisation for you. But understanding the loop we built from scratch is what separates someone who uses ML from someone who understands it. You now know what ML is at a conceptual and mechanical level. In the next lessons we'll zoom into specific types of ML — supervised, unsupervised, and reinforcement learning — and build real models from scratch. The journey has begun!

Key takeaways

  • Traditional programming: rules + data -> answers. ML: data + answers -> rules (the model).
  • Training is the learning phase; inference is the frozen prediction phase — always separate.
  • ML works by searching for parameters that minimise mistakes on labelled examples.
  • Data quality matters more than quantity — biased data produces biased models.
  • Spam filters, face unlock, recommendations, and fraud detection all follow the same two-phase ML pattern.
Practice challenges
Test yourself · earn XP
0/4
Predict the output#1

This is the inference step from the lesson: the frozen threshold learned during training was 3. What does this code print?

predict-output
def predict_spam(marks, threshold):
    return marks >= threshold

best_threshold = 3
new_emails = [("Hi", 2), ("WIN NOW!!!", 4)]
for subject, marks in new_emails:
    label = "SPAM" if predict_spam(marks, best_threshold) else "OK"
    print(f"{label}: '{subject}'")
Fill in the blank#2

The lesson says libraries like scikit-learn replace our hand-written search loop with two lines: one for the training phase and one for the inference phase. Complete the method names.

model.(X_train, y_train)   # training
preds = model.(X_test)     # inference
Reorder the lines#3

Put the lines in the correct order to first LEARN a threshold from labelled data, then use it for inference on a new value. (The frozen threshold must exist before you predict with it.)

1
print("new value is spam?", 6 >= best_t)
2
    acc = sum((v >= t) == label for v, label in data) / len(data)
3
data = [(1, False), (4, True), (2, False), (5, True)]
4
for t in range(0, 8):
5
    if acc > best_acc: best_acc, best_t = acc, t
6
best_t, best_acc = 0, 0
Fix the bug#4

This code is meant to measure the model's training accuracy the way the lesson does. It has a bug — what's wrong?

fix-bug
data = [(0, False), (5, True), (6, True), (1, False)]
threshold = 3

correct = sum(1 for marks, spam in data if marks >= threshold)
acc = correct / len(data)
print(f"accuracy: {acc:.0%}")
Your turn
Practice exercise

Write a learn_threshold(data) function that takes a list of (value, is_positive) tuples and returns the integer threshold t (0–10) such that predicting value >= t gives the highest accuracy on the training data. Then write predict(value, threshold) that returns True if the value meets or exceeds the threshold. Test both on the provided dataset and print the learned threshold, training accuracy, and a sample prediction.

Try it live — edit the code and hit Run to execute real Python:

solution.py · editable