Additional Links:
ML Linear Regression Zero to Hero
Tooling you’ll need this month
- Python 3.11+
- VS Code
- Create & use a virtualenv each week
pip install -r requirements.txtfor each project
week1-foundations/
├─ requirements.txt
├─ data.csv # (we'll generate a tiny dataset in code if you don't have one)
└─ notebook.ipynb # optional; code below also works as .pyrequirements.txtnumpy==1.26.4
pandas==2.2.2
matplotlib==3.8.4foundations.py)# Create venv, install reqs, then: python foundations.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pathlib import Path
# --- NumPy basics ---
a = np.array([1, 2, 3, 4], dtype=np.float32)
b = np.array([10, 20, 30, 40], dtype=np.float32)
print("Vector add:", a + b)
print("Dot product:", a @ b) # 1*10 + 2*20 + ...
# Matrix ops
M = np.array([[1, 2], [3, 4]], dtype=np.float32)
v = np.array([5, 6], dtype=np.float32)
print("Matrix x vector:", M @ v)
# --- Pandas basics ---
# If there's no real CSV, generate one
csv_path = Path("data.csv")
if not csv_path.exists():
rng = np.random.default_rng(42)
study_hours = rng.uniform(0, 8, size=60).round(2)
noise = rng.normal(0, 5, size=60)
marks = (study_hours * 10 + 30 + noise).clip(0, 100).round(1)
df = pd.DataFrame({"study_hours": study_hours, "marks": marks})
df.to_csv(csv_path, index=False)
df = pd.read_csv(csv_path)
print("\nHead:\n", df.head())
print("\nDescribe:\n", df.describe())
# --- Plotting ---
plt.figure()
plt.scatter(df["study_hours"], df["marks"])
plt.title("Study Hours vs Marks")
plt.xlabel("Study Hours")
plt.ylabel("Marks")
plt.grid(True)
plt.tight_layout()
plt.savefig("scatter.png")
print("\nSaved scatter plot -> scatter.png")passed = marks >= 50study_hours and marksweek2-ml/
├─ requirements.txt
├─ regression_basic.py
├─ classification_basic.py
└─ pipeline_classification.pyrequirements.txtnumpy==1.26.4
pandas==2.2.2
scikit-learn==1.5.1
matplotlib==3.8.4regression_basic.py)import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
# Synthetic "study hours -> marks" dataset
rng = np.random.default_rng(7)
hours = rng.uniform(0, 8, size=200)
noise = rng.normal(0, 5, size=200)
marks = (hours * 9 + 35 + noise).clip(0, 100)
X = hours.reshape(-1, 1)
y = marks
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=7)
model = LinearRegression()
model.fit(X_train, y_train)
pred = model.predict(X_test)
print("R^2:", round(r2_score(y_test, pred), 3))
print("MAE:", round(mean_absolute_error(y_test, pred), 2))
print("RMSE:", round(np.sqrt(mean_squared_error(y_test, pred)), 2))
print("Coef (slope):", model.coef_, "Intercept:", round(model.intercept_, 2))classification_basic.py)from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
data = load_iris()
X, y = data.data, data.target
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
clf = LogisticRegression(max_iter=1000)
clf.fit(X_tr, y_tr)
pred = clf.predict(X_te)
print("Accuracy:", round(accuracy_score(y_te, pred), 3))
print("\nClassification Report:\n", classification_report(y_te, pred, target_names=data.target_names))
print("\nConfusion Matrix:\n", confusion_matrix(y_te, pred))pipeline_classification.py)import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
texts = [
"I love this product", "Amazing quality", "Very good, recommended",
"Terrible experience", "I hate it", "Worst ever", "Pretty decent", "Not bad", "Awful packaging",
"Fantastic service", "Highly recommend", "Great value", "Works perfectly",
"Very disappointing", "Broke quickly", "Waste of money", "Not worth it", "Disappointed",
"Absolutely brilliant!", "So happy with this purchase", "Exceeded expectations", "Will buy again", "Top-notch performance",
"Complete garbage", "Regret buying this", "Poor quality control", "Never again", "False advertising"
]
labels = [1,1,1,0,0,0,1,1,0, 1,1,1,1, 0,0,0,0,0, 1,1,1,1,1, 0,0,0,0,0]
X_tr, X_te, y_tr, y_te = train_test_split(texts, labels, test_size=0.3, random_state=42, stratify=labels)
pipe = make_pipeline(TfidfVectorizer(), LogisticRegression(max_iter=1000))
pipe.fit(X_tr, y_tr)
pred = pipe.predict(X_te)
print(classification_report(y_te, pred, zero_division=0))
print("Predict('This is fantastic!') ->", pipe.predict(["This is fantastic!"])[0])sklearn.datasets)File: week3-dl/mlp_digits.py
week3-dl/
├─ requirements.txt
└─ mlp_digits.pyrequirements.txtnumpy==1.26.4
scikit-learn==1.5.1mlp_digits.pyfrom sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report, accuracy_score
digits = load_digits()
X, y = digits.data, digits.target
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=0, stratify=y)
mlp = MLPClassifier(hidden_layer_sizes=(64,), activation="relu", solver="adam", max_iter=50, random_state=0)
mlp.fit(X_tr, y_tr)
pred = mlp.predict(X_te)
print("Accuracy:", round(accuracy_score(y_te, pred), 3))
print("\nReport:\n", classification_report(y_te, pred))File tree
week3-dl-pytorch/
├─ requirements.txt
└─ mnist_torch.pyrequirements.txttorch==2.9.0
torchvision==0.24.0
numpy==1.26.4mnist_torch.pyimport torch, torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# 1) Dataset & loaders (auto-download)
transform = transforms.Compose([transforms.ToTensor()])
train_ds = datasets.MNIST(root="data", train=True, transform=transform, download=True)
test_ds = datasets.MNIST(root="data", train=False, transform=transform, download=True)
train_loader = DataLoader(train_ds, batch_size=64, shuffle=True)
test_loader = DataLoader(test_ds, batch_size=256)
# 2) Model
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Flatten(),
nn.Linear(28*28, 128),
nn.ReLU(),
nn.Linear(128, 10)
)
def forward(self, x):
return self.net(x)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = SimpleNet().to(device)
loss_fn = nn.CrossEntropyLoss()
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
# 3) Training loop
for epoch in range(3):
model.train()
total, correct, running_loss = 0, 0, 0.0
for x, y in train_loader:
x, y = x.to(device), y.to(device)
opt.zero_grad()
out = model(x)
loss = loss_fn(out, y)
loss.backward()
opt.step()
running_loss += loss.item() * x.size(0)
preds = out.argmax(1)
correct += (preds == y).sum().item()
total += y.size(0)
print(f"Epoch {epoch+1}: loss={(running_loss/total):.4f}, acc={(correct/total):.3f}")
# 4) Evaluation
model.eval()
total, correct = 0, 0
with torch.no_grad():
for x, y in test_loader:
x, y = x.to(device), y.to(device)
preds = model(x).argmax(1)
correct += (preds == y).sum().item()
total += y.size(0)
print("Test accuracy:", correct/total)SGD vs Adam, different lr⚠️ You’ll need an API key if you call a hosted LLM. Keep your key in environment variables (never commit it).
week4-llm/
├─ requirements.txt
├─ tfidf_demo.py
├─ embed_and_search.py
└─ llm_chat.pyrequirements.txtnumpy==1.26.4
scikit-learn==1.5.1
tqdm==4.66.4
openai==1.51.0 # If using OpenAI; or use your preferred provider's SDK
python-dotenv==1.0.1tfidf_demo.py)from sklearn.feature_extraction.text import TfidfVectorizer
docs = [
"AI is transforming business",
"Large language models power chatbots",
"Transformers use attention",
"Business analytics uses data and models",
]
tfidf = TfidfVectorizer()
X = tfidf.fit_transform(docs)
print("Vocabulary:", tfidf.vocabulary_)
print("Doc-term shape:", X.shape)
# Query similarity via dot product
from sklearn.metrics.pairwise import cosine_similarity
query = ["How do models help business?"]
Q = tfidf.transform(query)
scores = cosine_similarity(Q, X)[0]
print("Similarity scores:", scores)
best = scores.argmax()
print("Best match doc:", docs[best])embed_and_search.py)This simulates a mini knowledge base search using TF‑IDF embeddings.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
kb = [
"Refund policy: You can request a refund within 14 days.",
"Shipping: Orders ship within 2 business days.",
"Support: Email support@example.com for technical issues.",
"Pricing: Basic plan $9/month, Pro plan $29/month.",
]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(kb)
def search(query, top_k=2):
qv = vectorizer.transform([query])
sims = cosine_similarity(qv, X)[0]
idx = sims.argsort()[::-1][:top_k]
return [(kb[i], float(sims[i])) for i in idx]
print(search("How fast do you ship?"))
print(search("How to contact support?"))llm_chat.py)Put your key in
.envasOPENAI_API_KEY=...
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Basic chat completion
resp = client.chat.completions.create(
model="gpt-4o-mini", # pick a cost-effective model for beginners
messages=[
{"role": "system", "content": "You are a helpful tutor."},
{"role": "user", "content": "Explain attention in simple terms."}
],
temperature=0.7,
)
print(resp.choices[0].message.content)
# Summarization example
text = """Attention lets a model focus on the most relevant parts of the input.
It computes similarity between a query and keys, and uses those as weights over values."""
resp2 = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role":"system","content":"You are a concise assistant."},
{"role":"user","content":f"Summarize this in 2 lines:\n{text}"}
]
)
print("\nSummary:\n", resp2.choices[0].message.content)Swap the SDK/model if you prefer another provider. Always keep keys in env vars.
embed_and_search.py to fetch top‑k related snippets from your FAQ text fileBuild a question‑answering CLI:
scatter.pngStandardScaler + SVC pipeline; compare to Logistic RegressionObjective: Think in arrays/tables, perform basic EDA, and visualize data.
NumPy warm‑up
a,b and show: elementwise add/sub/mul, dot product, and matrix × vector.Pandas basics
data.csv (or generate synthetic dataset if empty).head(), info(), describe().Create new columns:
passed = marks >= 50hours_bucket = low/med/high by binning study_hours (e.g., pd.cut).Visualization
study_hours vs marks → scatter.png.marks → hist_marks.png.EDA metrics
df.corr(numeric_only=True)).EDA Report (Markdown or PDF)
foundations.py (or notebook.ipynb), images, EDA_REPORT.md.Stretch (★ Pro): Try Seaborn‑like styling using Matplotlib only; add a boxplot of marks by hours_bucket; handle missing values by imputation.
Submission checklist
scatter.png, hist_marks.png committedEDA_REPORT.md concise (≤1 page)Objective: Train/test split, regression + classification, metrics & comparison.
Regression
LinearRegression.Classification
load_iris() or any simple dataset.stratify=y; train LogisticRegression.Text classification pipeline
TfidfVectorizer + LogisticRegression (pipeline).Model Compare
regression_basic.py, classification_basic.py, pipeline_classification.py, MODEL_COMPARISON.md.Stretch (★ Pro): Add StandardScaler in a pipeline; use k‑fold cross‑validation; plot a simple learning curve (train size vs accuracy).
Submission checklist
random_state setMODEL_COMPARISON.mdObjective: Understand NN components and train a tiny network.
MLPClassifier on digits dataset (28×28 flattened).hidden_layer_sizes, max_iter, activation.Tuning Note
mlp_digits.py (Track A) or mnist_torch.py (Track B), TUNING_NOTE.md.Stretch (★ Pro):
Submission checklist
TUNING_NOTE.md with at least 2 configs comparedObjective: Learn vector search basics and wire an LLM for chat/summarization.
Tokenization/TF‑IDF
TfidfVectorizer on 6–10 short docs.RAG‑lite search
search(query, top_k) returning the top snippets.Call an LLM (safe key handling)
.env and load via python-dotenv.Make two calls:
CLI Q&A with Context
tfidf_demo.py, embed_and_search.py, llm_chat.py, README.md (how to set OPENAI_API_KEY).Stretch (★ Pro):
/ask?q=... returning the answer.Submission checklist
.env not committedweek1/… week2/…).Each week must have a README.md with:
pip install -r requirements.txt)| Level | Criteria |
|---|---|
| Beginner (★) | Can run given NumPy/Pandas code but struggles to explain output. Only basic printouts, no plots. |
| Intermediate (★★) | Generates scatter & histogram plots, adds new DataFrame columns, computes correlations. Writes a short EDA summary with 2–3 insights. |
| Pro (★★★) | Cleans dataset if needed, bins/derives new features, makes multiple plots with labels/titles, and delivers a neat 1-page EDA report with insights + recommendations. |
| Level | Criteria |
|---|---|
| Beginner (★) | Trains a regression or classification model but reports only accuracy without interpretation. Struggles with train/test split. |
| Intermediate (★★) | Correctly implements regression + classification, reports metrics (R², MAE, confusion matrix, classification report). Completes model comparison with 1–2 sentences of reasoning. |
| Pro (★★★) | Adds preprocessing in pipelines, tries 2+ models, interprets why one performs better, includes plots (learning curve/confusion matrix). Writes a structured short report. |
| Level | Criteria |
|---|---|
| Beginner (★) | Runs an MLP/NN example but doesn’t change hyperparameters; copies tutorial outputs. |
| Intermediate (★★) | Successfully trains a small NN, reports test accuracy, and experiments with at least 1 tuning parameter (hidden units, optimizer, epochs). Submits tuning note. |
| Pro (★★★) | Experiments with multiple configs (2+ changes), records results in a comparison table, plots loss/accuracy curves, adds dropout/early stopping, and discusses over/underfitting. |
| Level | Criteria |
|---|---|
| Beginner (★) | Runs TF-IDF demo, retrieves top-k docs, and makes a single LLM API call. No safe key handling. |
| Intermediate (★★) | Builds FAQ search with embeddings (TF-IDF), integrates with LLM API, handles API key safely via .env. Submits working CLI chatbot. |
| Pro (★★★) | Adds confidence threshold/fallback (“I don’t know”), caches embeddings, clean CLI or Flask interface, documents setup/run clearly, and explains how context improves answers. |
📊 Scoring Example (out of 100):