Day 01 · Overview
Week 1FNX 101 · 01Welcome to the Lab
Become a data detective: clean a real penguin dataset with pandas, then tour the AI models you'll build all course.
Today you will
3- Load a real penguin dataset with pandas and size it up
- Hunt down missing values, then filter, group and count to answer real questions
- Run four pretrained models and try to fool, bend and break them
Today's items
2 h 30 minLab A
FNX 101 · 01Day 1 — The Data Detective 🔍
Mission briefing: Welcome to the Lab, recruit. Before we let you anywhere near an AI model, you have to pass the entrance exam — and it isn't about code. Every powerful AI system is built on top of data, and a researcher who can't read their data ships broken models. This morning a crate of penguin measurements arrived from a field station in Antarctica. Interrogate it.
Today you will:
- Load a real dataset with pandas and size it up (
.head,.info,.describe) - Hunt down missing values and clean the data
- Filter, group, and count to answer real questions
- Plot the data — and spot a pattern a machine could learn tomorrow
No neural networks today. Just you, the data, and a magnifying glass. Every researcher here will tell you the same thing: AI is 80% understanding your data, and 20% everything else.
A precise reading
This course focuses on learning from data. AI also includes rule-based and search systems. Tables are a useful starting point, but images, audio and text need representations suited to their structure.
# ╔═══════════════════════════════════════════════════════════════════╗
# ║ SETUP — run me first! (identical in every Lab notebook) ║
# ╚═══════════════════════════════════════════════════════════════════╝
import os, sys, pathlib
IN_COLAB = "google.colab" in sys.modules
SMOKE = os.environ.get("SMOKE_TEST", "0") == "1" # tiny fast run for automated tests
REPO_URL = "https://github.com/A-Halimi/ai-studio-internship.git" # instructor: set once
if IN_COLAB:
if not pathlib.Path("/content/ai-studio-internship").exists():
!git clone -q {REPO_URL} /content/ai-studio-internship
%cd /content/ai-studio-internship/notebooks/day01
HERE = pathlib.Path.cwd()
REPO = HERE.parents[1] # .../notebooks/dayNN -> repo root
DATA_DIR = pathlib.Path(os.environ.get("COURSE_DATA_DIR", REPO / "data"))
SAMPLES_DIR = REPO / "data_samples" # small datasets shipped with the repo
MODELS_DIR = REPO / "ai_studio" / "models" # where your Studio modules unlock
for p in (REPO / "data", MODELS_DIR):
p.mkdir(parents=True, exist_ok=True)
import random
import numpy as np
SEED = 42
random.seed(SEED); np.random.seed(SEED)
print(f"✅ Setup done | Colab: {IN_COLAB} | Smoke test: {SMOKE}")
print(f" data: {DATA_DIR}")import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option("display.max_columns", None) # never hide a column when we print
print("Detective toolkit loaded 🕵️")🐧 Meet the suspects
Our data comes from Palmer Station, Antarctica, where researchers measured hundreds of penguins from three species:
| Species | How to spot it |
|---|---|
| Adelie | The classic tuxedo penguin, found all over the peninsula |
| Chinstrap | Named for the thin black line under its chin |
| Gentoo | The big one, with a bright orange bill |
For each penguin they recorded four body measurements, plus which island it lived on and its sex:
bill_length_mm,bill_depth_mm— the beakflipper_length_mm— the "wing"body_mass_g— weight in grams
One row is one penguin. One column is one thing we measured. Rows are examples, columns are features — this is exactly how almost all machine-learning data is organized. Get comfortable with the shape.
Step 1 — Load the evidence
pandas is the tool every data scientist reaches for first. It reads a spreadsheet-like file into a DataFrame — think of it as a programmable Excel sheet. .head() shows the first few rows so we can eyeball what we are dealing with.
penguins = pd.read_csv(SAMPLES_DIR / "penguins.csv")
print(f"Loaded {len(penguins)} penguins, {penguins.shape[1]} columns each.")
penguins.head()Step 2 — Size it up
Two commands you will run on every new dataset for the rest of your career:
.info()— how many rows, the type of each column, and how many values are actually present (non-null). The place to spot missing data..describe()— count, mean, min, max, and quartiles for every number column. The place to spot weird values (a penguin weighing 0 g? a typo?).
penguins.info()penguins.describe()🧪 Exercise 1 — Count the gaps
Real data is messy. Some penguins are missing measurements — maybe a pen ran dry, maybe a bird wriggled free before the scale settled.
- Compute how many values are missing in each column and store it in
missing_per_column. - Expected: a couple of missing body measurements, and about a dozen missing
sexvalues.
# How many values are missing in each column?
# ==================== YOUR CODE HERE ====================
### HINT: penguins.isna() marks every cell True (missing) or False
### HINT: chain .sum() on that to count the missing values per column
...
print(missing_per_column)
assert missing_per_column.sum() == 19, "Expected 19 missing values in total across all columns."Step 3 — Clean it up
For today's investigation we want only penguins with a complete record. dropna() removes any row that has at least one missing value. We keep the original around and work on a clean copy called df.
⚠️ Dropping rows is the quick fix, not always the right one — throwing away data can bias your results. Later in the Lab you will learn gentler repairs (filling a gap with a sensible guess). For 11 rows out of 344, dropping is fine.
df = penguins.dropna().reset_index(drop=True)
print(f"Before: {len(penguins)} penguins")
print(f"After : {len(df)} penguins ({len(penguins) - len(df)} dropped)")
assert len(df) == 333, "A clean dataset should have 333 complete records."
df.head()Ask questions, get answers
A DataFrame is not just for looking at — it is for interrogating. Three moves answer almost any question about a dataset:
- Filter — keep only the rows that match a condition
- Group — split rows into buckets (e.g. by species) and summarize each bucket
- Count — tally how often each value appears
Let's use all three.
🧪 Exercise 2 — The heavyweights
Find every penguin heavier than 5000 grams (that's 5 kg — a chunky bird).
- Build a filtered DataFrame called
heavy. - Expected: around 60 penguins — and if you peek at their species, they will almost all be the same one. Remember which; it comes up again.
# ==================== YOUR CODE HERE ====================
### HINT: a condition like df["body_mass_g"] > 5000 gives True/False for every row
### HINT: put that condition inside df[ ... ] to keep only the True rows
...
print(f"{len(heavy)} penguins over 5000 g")
print(heavy["species"].value_counts())
assert len(heavy) > 40, "That is fewer heavyweights than expected — check your condition."🧪 Exercise 3 — The average penguin, by species
Split the penguins by species and compute the mean of every numeric column for each group.
- Produce a table called
species_means. - Hint:
.groupby("species")makes the buckets;.mean(numeric_only=True)averages the numbers (thenumeric_only=Trueskips text columns likeisland). - Expected: one row per species, with Gentoo standing out as the biggest on nearly every measurement.
# ==================== YOUR CODE HERE ====================
...
species_means🧪 Exercise 4 — Who lives where?
Count how many penguins were recorded on each island.
- Store the result in
island_counts. - Expected: three islands (Biscoe, Dream, Torgersen), with Biscoe hosting the most.
# ==================== YOUR CODE HERE ====================
### HINT: .value_counts() on a single column tallies each distinct value
...
print(island_counts)See it to believe it
Tables are precise but slow to read. A good plot shows a pattern in a glance. Start with a histogram: it slices a numeric column into bins and shows how many penguins land in each — the shape of the data.
Here is one we made for you: body mass, drawn separately for each species so you can compare. Run it.
plt.figure(figsize=(8, 5))
for species, group in df.groupby("species"):
plt.hist(group["body_mass_g"], bins=20, alpha=0.6, label=species)
plt.xlabel("Body mass (g)")
plt.ylabel("Number of penguins")
plt.title("Body mass by species")
plt.legend()
plt.show()See how Gentoo (heavier) sits clearly to the right, while Adelie and Chinstrap overlap almost completely? Body mass alone can pick out a Gentoo — but it can't tell an Adelie from a Chinstrap. We need a smarter view.
🧪 Exercise 5 — The scatter plot that changes everything
A scatter plot puts one measurement on the x-axis and another on the y-axis, one dot per penguin. The magic move: color each dot by species. If the species land in separate regions, we have found structure a machine could learn.
Plot bill length (x) against bill depth (y), one color per species.
- Loop over the species; for each one, call
plt.scatter(...)on just that group's rows with alabel=. - The scaffold handles the axis labels and legend — you write the scatter loop.
- Expected: three fairly distinct blobs of color.
plt.figure(figsize=(8, 6))
# ==================== YOUR CODE HERE ====================
### HINT: for species, group in df.groupby("species"):
### HINT: plt.scatter(group["bill_length_mm"], group["bill_depth_mm"], label=species, alpha=0.7)
...
plt.xlabel("Bill length (mm)")
plt.ylabel("Bill depth (mm)")
plt.title("Bill shape separates the species")
plt.legend()
plt.show()🔍 The revelation
Look at that. Each species forms its own cluster — a region of the plot where its penguins live. You could almost draw the dividing lines with a ruler.
That is the whole idea behind tomorrow's mission. If you can see the boundary, a machine can learn it. Hand a computer these dots and their colors, and it can work out the dividing lines on its own — then color in a brand-new, unlabeled dot for you. That's called classification, and it's the first AI superpower you'll build. 🐧
Why bill length and depth? Because together they capture shape, not just size. Size (mass, flipper) mostly separates Gentoo from the rest; shape is what finally splits Adelie from Chinstrap.
🧪 Exercise 6 — What moves together?
When one measurement goes up, do the others go up too? Correlation measures exactly that, from +1 (perfect lockstep), through 0 (unrelated), to −1 (perfect opposites).
- Compute the correlation matrix of the four numeric columns and store it in
corr. - We'll draw it as a heatmap so the strong pairs jump out.
- Hint: select the four columns, then call
.corr().
numeric_cols = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]
# ==================== YOUR CODE HERE ====================
...
plt.figure(figsize=(6, 5))
sns.heatmap(corr, annot=True, cmap="coolwarm", vmin=-1, vmax=1, fmt=".2f")
plt.title("Correlation between measurements")
plt.show()
corrRead the map. The brightest off-diagonal square is flipper length ↔ body mass at about +0.87 — long-flippered penguins are heavy penguins. That makes sense: both grow with the overall size of the bird.
Notice that bill_length and bill_depth are only weakly (even negatively) correlated — which is exactly why they made such a good scatter plot. Two measurements that don't move together carry independent information, and independent information is what pulls the species apart.
🗒️ The Detective's Report
Time to prove you can work solo.
🧪 Exercise 7 — Close the case
Answer three questions with one line of pandas each — no plots, just the value. Everything you need you have already used above.
- Which species is heaviest on average?
- Which island hosts the most Gentoo penguins?
- What is the mean flipper length of Chinstrap penguins?
# 1) Heaviest species on average
# ==================== YOUR CODE HERE ====================
### HINT: group by species, take the mean body_mass_g, then .idxmax() names the winner
...
# 2) Island with the most Gentoo penguins
# ==================== YOUR CODE HERE ====================
### HINT: keep only Gentoo rows first, then value_counts the island column, then .idxmax()
...
# 3) Mean flipper length of Chinstrap penguins
# ==================== YOUR CODE HERE ====================
...
print(f"1. Heaviest species on average : {heaviest_species}")
print(f"2. Island with most Gentoo : {top_gentoo_island}")
print(f"3. Chinstrap mean flipper (mm) : {chinstrap_flipper:.1f}")
assert heaviest_species == "Gentoo"
assert top_gentoo_island == "Biscoe"
assert round(chinstrap_flipper, 1) == 195.8
print("\n✅ Case closed — all three answers check out.")🏁 Checkpoint
Case closed, Detective. You just did what every AI project starts with — long before a single model is trained:
- ✅ Loaded and inspected a real dataset (
.head,.info,.describe) - ✅ Found and removed missing data
- ✅ Filtered, grouped, and counted to answer real questions
- ✅ Visualized the data — and spotted species clusters with your own eyes
- ✅ Measured which features carry independent information
You proved the Lab's motto: understand your data before you model it.
Next up — Notebook 1b: "Meet the Machines." 🤖 You've earned a reward: a hands-on tour of four finished AI systems — vision, mood-reading, story-writing, and a sorting hat. Play with them today; you will build every one over the next two weeks.
Tomorrow (Day 2): those penguin clusters you found? You'll hand them to a machine, train it to identify a brand-new penguin on its own, and unlock the very first tab of your AI Studio. 🔓
Lab B
FNX 101 · 01Day 1 — Meet the Machines 🤖
Mission briefing: You passed the entrance exam, so here's your reward: a walk through the Lab's equipment room. Four finished AI machines are humming on the benches — one that sees, one that reads moods, one that writes stories, and a sorting hat that files text into any categories you invent. Today you just get to play with them. There's a catch, though: by Demo Day you will have rebuilt every single one yourself.
Previously in the Lab: you were the Data Detective — you can read data. Now meet the machines that devour it.
Today you will:
- See the map of AI — how machine learning, deep learning, and the "superpowers" fit together
- Run four pretrained models: image recognition, sentiment, text generation, zero-shot sorting
- Try to fool them, bend them, and break them (that's how you learn what they can't do)
- Meet the AI Studio — the app you'll assemble one tab per day
These models were trained on giant datasets using enormous computers. You won't train them today — you'll borrow them, the way real researchers stand on each other's shoulders.
A precise reading
This course focuses on learning from data. AI also includes rule-based and search systems. Tables are a useful starting point, but images, audio and text need representations suited to their structure.
# ╔═══════════════════════════════════════════════════════════════════╗
# ║ SETUP — run me first! (identical in every Lab notebook) ║
# ╚═══════════════════════════════════════════════════════════════════╝
import os, sys, pathlib
IN_COLAB = "google.colab" in sys.modules
SMOKE = os.environ.get("SMOKE_TEST", "0") == "1" # tiny fast run for automated tests
REPO_URL = "https://github.com/A-Halimi/ai-studio-internship.git" # instructor: set once
if IN_COLAB:
if not pathlib.Path("/content/ai-studio-internship").exists():
!git clone -q {REPO_URL} /content/ai-studio-internship
%cd /content/ai-studio-internship/notebooks/day01
%pip -q install transformers==5.13.0
HERE = pathlib.Path.cwd()
REPO = HERE.parents[1] # .../notebooks/dayNN -> repo root
DATA_DIR = pathlib.Path(os.environ.get("COURSE_DATA_DIR", REPO / "data"))
SAMPLES_DIR = REPO / "data_samples" # small datasets shipped with the repo
MODELS_DIR = REPO / "ai_studio" / "models" # where your Studio modules unlock
for p in (REPO / "data", MODELS_DIR):
p.mkdir(parents=True, exist_ok=True)
import random
import numpy as np
SEED = 42
random.seed(SEED); np.random.seed(SEED)
print(f"✅ Setup done | Colab: {IN_COLAB} | Smoke test: {SMOKE}")
print(f" data: {DATA_DIR}")import torch
torch.manual_seed(SEED)
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if DEVICE.type == "cuda":
print(f"⚡ Running on GPU: {torch.cuda.get_device_name(0)}")
else:
print("🐢 No GPU found — running on CPU. Everything still works, just slower.")🗺️ The map of AI
People throw around "AI", "machine learning", and "deep learning" as if they mean the same thing. They don't — they nest, like Russian dolls:
- Artificial Intelligence — any program that does something we'd call "smart."
- Machine Learning — a kind of AI that isn't hand-coded with rules; it learns patterns from data. (Yesterday you saw the patterns; ML is teaching a machine to find them.)
- Deep Learning — machine learning with neural networks stacked many layers deep. It powers almost every jaw-dropping AI you've heard of.
And there are three ways a machine can learn:
- Supervised — learn from labeled examples ("this penguin is a Gentoo"). ← Day 2
- Unsupervised — find structure with no labels ("these things clump together"). ← Day 3
- Reinforcement — learn by trial, reward, and error, like training a dog. ← Day 9
Run the next cell for the map.
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch
fig, (axL, axR) = plt.subplots(1, 2, figsize=(11, 5))
# Left: AI contains ML contains Deep Learning (nested boxes)
axL.set_xlim(0, 10); axL.set_ylim(0, 10); axL.axis("off")
for x, y, w, h, label, color, fs in [
(0.5, 0.5, 9.0, 9.0, "Artificial Intelligence", "#e8f0fe", 13),
(1.6, 1.6, 6.8, 6.3, "Machine Learning", "#c6dafc", 12),
(2.8, 2.6, 4.4, 3.9, "Deep Learning", "#8ab4f8", 12),
]:
axL.add_patch(FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.02",
fc=color, ec="#222", lw=1.5))
axL.text(x + w / 2, y + h - 0.5, label, ha="center", va="top",
fontsize=fs, fontweight="bold")
axL.text(5.0, 3.9, "neural networks\nwith many layers", ha="center", va="center",
fontsize=10, style="italic")
axL.set_title("AI ⊃ Machine Learning ⊃ Deep Learning", fontweight="bold")
# Right: the three ways to learn + two superpowers
axR.set_xlim(0, 10); axR.set_ylim(0, 10); axR.axis("off")
axR.set_title("How machines learn", fontweight="bold")
for i, (name, desc, color) in enumerate([
("Supervised", "learn from labeled examples", "#a5d6a7"),
("Unsupervised", "find structure, no labels", "#fff59d"),
("Reinforcement", "learn by trial and reward", "#ef9a9a"),
]):
y = 8.2 - i * 2.3
axR.add_patch(FancyBboxPatch((0.5, y - 0.9), 9.0, 1.6, boxstyle="round,pad=0.02",
fc=color, ec="#222"))
axR.text(5.0, y + 0.15, name, ha="center", fontsize=12, fontweight="bold")
axR.text(5.0, y - 0.5, desc, ha="center", fontsize=9)
axR.text(5.0, 0.6, "Two superpowers you'll build: Vision (images) + Language (text)",
ha="center", fontsize=10, fontweight="bold")
plt.tight_layout()
plt.show()👁️ Superpower 1 — Vision
First up: a machine that looks at a photo and names what's in it. Ours is ResNet-18, a neural network trained on ImageNet — 1.2 million photos across 1000 categories (dogs, castles, teapots, you name it).
We don't have to train it — we just download the finished brain and use it. Two details matter:
.eval()puts the network in "just answer, don't learn" mode.weights.transforms()is the exact preprocessing (resize, crop, normalize) the model expects. Feed it anything else and it gets confused — models are picky eaters.
from torchvision.models import resnet18, ResNet18_Weights
from sklearn.datasets import load_sample_image
from PIL import Image
weights = ResNet18_Weights.DEFAULT
model = resnet18(weights=weights).eval().to(DEVICE)
preprocess = weights.transforms() # the model's required input pipeline
categories = weights.meta["categories"] # the 1000 label names
print(f"ResNet-18 ready — it knows {len(categories)} categories.")
def classify_top5(img_array):
"""Return the model's 5 most confident labels for one image (a NumPy array)."""
img = Image.fromarray(img_array)
batch = preprocess(img).unsqueeze(0).to(DEVICE) # 1 image -> a batch of 1
with torch.no_grad():
logits = model(batch)
probs = torch.softmax(logits, dim=1)[0] # turn scores into probabilities
top_p, top_i = probs.topk(5)
return [(categories[i], p.item()) for i, p in zip(top_i, top_p)]
def show_top5(img_array, title):
preds = classify_top5(img_array)
labels = [name for name, _ in preds][::-1]
scores = [p for _, p in preds][::-1]
fig, (ax_img, ax_bar) = plt.subplots(1, 2, figsize=(10, 4))
ax_img.imshow(img_array); ax_img.axis("off"); ax_img.set_title(title)
ax_bar.barh(labels, scores)
ax_bar.set_xlim(0, 1)
ax_bar.set_xlabel("Confidence")
ax_bar.set_title("Top-5 guesses")
plt.tight_layout(); plt.show()
return predschina = load_sample_image("china.jpg") # a photo that ships with scikit-learn
_ = show_top5(china, "china.jpg")flower = load_sample_image("flower.jpg")
_ = show_top5(flower, "flower.jpg")🔬 Your turn (mini-task)
Look at the two bar charts. In a sentence or two, jot down what the model got right and what it got wrong. Was it confidently correct? Confidently wrong? Notice that it never says "I don't know" — it always spreads its bet across the labels it was trained on, even for a photo that matches none of them well. Keeping models honest about their own uncertainty is a real research problem.
💬 Superpower 2 — Reading the mood
Next machine: sentiment analysis. It reads a sentence and decides whether the feeling behind it is positive or negative, with a confidence score.
The transformers library gives us a one-liner called a pipeline: name the task, name the model, and it downloads and wires everything up. Ours is a DistilBERT model fine-tuned on movie reviews.
from transformers import pipeline
mood = pipeline("text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english",
device=0 if DEVICE.type == "cuda" else -1)
sentences = [
"I absolutely loved this movie, what a ride!",
"This is the worst day I have ever had.",
"The food was okay, nothing special.",
]
for s in sentences:
r = mood(s)[0]
print(f"{r['label']:8} ({r['score']:.2f}) {s}")🧪 Exercise 1 — Fool the mood reader
These models learn from patterns of words, so they struggle with things humans read instantly — like sarcasm.
- Write a sentence that sounds positive word-for-word but really means the opposite, and store it in
sarcastic. - Goal: get the model to answer POSITIVE for something you clearly meant as a complaint.
# ==================== YOUR CODE HERE ====================
### HINT: pile on happy words for an unhappy situation
### HINT: e.g. "Oh great, my flight got cancelled again. I just LOVE airports."
...
result = mood(sarcastic)[0]
print(f"{result['label']} ({result['score']:.2f}) {sarcastic}")✍️ Superpower 3 — The story writer
This machine generates text. Give GPT-2 the start of a sentence and it keeps going, one word at a time, each word guessed from everything before it. (Yes — it's a distant, much smaller ancestor of the models you talk to today.)
A couple of dials:
max_new_tokens— how many words to add.temperature— the "creativity" knob. Low = safe and repetitive, high = wild. We use0.9for some spice.
storyteller = pipeline("text-generation", model="gpt2",
device=0 if DEVICE.type == "cuda" else -1)
MAX_NEW = 20 if SMOKE else 40
prompt = "In the year 3000, the last robot on Earth discovered"
torch.manual_seed(SEED) # reproducible demo
out = storyteller(prompt, max_new_tokens=MAX_NEW, do_sample=True,
temperature=0.9, pad_token_id=50256)
print(out[0]["generated_text"])🧪 Exercise 2 — Be the author
Swap in your own prompt and see what the machine dreams up.
- Set
my_promptto any opening you like — a fairy tale, a news headline, a recipe. - Run it a few times: because
do_sample=True, you get a different story every time.
# ==================== YOUR CODE HERE ====================
### HINT: anything goes — the funnier the opener, the funnier the result
...
torch.manual_seed(SEED) # reproducible demo
out = storyteller(my_prompt, max_new_tokens=MAX_NEW, do_sample=True,
temperature=0.9, pad_token_id=50256)
print(out[0]["generated_text"])🎩 Superpower 4 — The sorting hat
The last machine is the cleverest trick. Zero-shot classification sorts text into categories it was never trained on. You invent the labels on the spot, and it figures out which one fits best.
"Zero-shot" means zero training examples for your specific categories — it reasons about the meaning of the words instead.
sorter = pipeline("zero-shot-classification",
model="typeform/distilbert-base-uncased-mnli",
device=0 if DEVICE.type == "cuda" else -1)
text = "I spent all weekend building a robot that sorts my socks by color."
labels = ["technology", "sports", "cooking", "art"]
res = sorter(text, candidate_labels=labels)
for lbl, score in zip(res["labels"], res["scores"]):
print(f"{lbl:12} {score:.2f}")🧪 Exercise 3 — Invent the categories
Give the sorting hat your own text and your own labels.
- Set
my_textto any sentence, andmy_labelsto 3–5 categories it might fall into. - Try to trip it up: a sentence that could belong to two categories at once is the interesting case.
my_text = "The championship match went to overtime and the crowd went wild."
# ==================== YOUR CODE HERE ====================
### HINT: pick categories the text might plausibly belong to
...
res = sorter(my_text, candidate_labels=my_labels)
print(f"Text: {my_text}\n")
for lbl, score in zip(res["labels"], res["scores"]):
print(f"{lbl:12} {score:.2f}")🧪 This is the mission: your AI Studio
Everything you just played with was built by other people. Over the next two weeks you'll build your own versions — and they'll live inside one app: the AI Studio.
The Studio has one tab per capability. Each starts 🔒 locked, and you unlock it by finishing that day's notebook (which trains and saves the model the tab needs):
| Day | Tab | What you'll build |
|---|---|---|
| 2 | 🐧 Prediction Machine | classify penguins from measurements |
| 3 | 🎨 Pattern Finder | discover groups in data with no labels |
| 5 | ✍️ Digit Reader | recognize handwritten digits |
| 6 | 🕵️ Photo Detective | recognize objects in photos |
| 7 | 🪨📄✂️ RPS Arena | play rock–paper–scissors through the camera |
| 8 | 💬 Language Lab | understand and generate text |
| 9 | 🎮 Game Master | an agent that learns to win a game |
Want a peek? From the repo root run:
python ai_studio/app.py
Today every tab shows 🔒 — you haven't built anything yet. That padlock wall is the mission. By Demo Day (Day 10) you'll open the app and every lock will be gone. 🔓
📦 A note on the first run. Outside the course's Docker container, the very first time you load these models your computer downloads roughly 1.5 GB of weights from the internet, so give it a minute. Inside the Lab's container everything is pre-baked — no download, no waiting. Either way, you only pay this cost once.
🏁 Checkpoint
You've met the machines. In a single afternoon you:
- ✅ Placed AI, machine learning, and deep learning on the same map
- ✅ Ran a vision model that names objects in photos
- ✅ Ran a sentiment model — and fooled it with sarcasm
- ✅ Made a language model write, and a zero-shot model sort
- ✅ Saw the AI Studio you're about to fill, one locked tab at a time
The big secret: none of these are magic. Each is a pattern-finder trained on data — the same idea you'll master step by step.
Tomorrow (Day 2): you stop borrowing and start building. You'll train your own classifier on yesterday's penguins and unlock the first tab of your Studio — 🐧 Prediction Machine. 🔓