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.
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
# 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: 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}'")"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.
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.
This is the inference step from the lesson: the frozen threshold learned during training was 3. What does this code print?
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}'")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
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.)
print("new value is spam?", 6 >= best_t)acc = sum((v >= t) == label for v, label in data) / len(data)
data = [(1, False), (4, True), (2, False), (5, True)]
for t in range(0, 8):
if acc > best_acc: best_acc, best_t = acc, t
best_t, best_acc = 0, 0
This code is meant to measure the model's training accuracy the way the lesson does. It has a bug — what's wrong?
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%}")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: