🚀 Month 3 — AI & LLM Fundamentals (with code)


Additional Links:

ML Linear Regression Zero to Hero

Boston Kaggle

Tooling you’ll need this month


Week 1 — Foundations for AI: NumPy, Pandas, Plotting, Data Thinking

Goals

File tree

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 .py

requirements.txt

numpy==1.26.4
pandas==2.2.2
matplotlib==3.8.4

Starter code (foundations.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")

Mini‑project


Week 2 — Machine Learning Essentials (scikit‑learn)

Goals

File tree

week2-ml/
├─ requirements.txt
├─ regression_basic.py
├─ classification_basic.py
└─ pipeline_classification.py

requirements.txt

numpy==1.26.4
pandas==2.2.2
scikit-learn==1.5.1
matplotlib==3.8.4

Simple Regression (regression_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))

Simple Classification (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 + Text (TF‑IDF) (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])

Mini‑project


Week 3 — Neural Networks & Deep Learning Intro

Goals

Option A — Quick start with scikit‑learn MLP (no heavy deps)

File: week3-dl/mlp_digits.py

week3-dl/
├─ requirements.txt
└─ mlp_digits.py

requirements.txt

numpy==1.26.4
scikit-learn==1.5.1

mlp_digits.py

from 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))

Option B — PyTorch (beginner‑friendly training loop)

File tree

week3-dl-pytorch/
├─ requirements.txt
└─ mnist_torch.py

requirements.txt

torch==2.9.0
torchvision==0.24.0
numpy==1.26.4

mnist_torch.py

import 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)

Mini‑project


Week 4 — LLM Fundamentals (NLP → Embeddings → Calling an LLM)

Goals

⚠️ You’ll need an API key if you call a hosted LLM. Keep your key in environment variables (never commit it).

File tree

week4-llm/
├─ requirements.txt
├─ tfidf_demo.py
├─ embed_and_search.py
└─ llm_chat.py

requirements.txt

numpy==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.1

1) Tokenization & TF‑IDF (tfidf_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])

2) Tiny Embeddings + Search Demo (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?"))

3) Call an LLM (chat or summarization) — OpenAI SDK (llm_chat.py)

Put your key in .env as OPENAI_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.

Mini‑project (LLM + Retrieval “RAG‑lite”)


What interns submit each week


Stretch goals (for ★★★ “Pro” track)


Weekly Assignment & Project Sheet


Week 1 — Foundations: NumPy, Pandas, Plotting, EDA

Objective: Think in arrays/tables, perform basic EDA, and visualize data.

Assignments

  1. NumPy warm‑up

  2. Pandas basics

  3. Visualization

  4. EDA metrics

Mini‑Project

EDA Report (Markdown or PDF)

Stretch (★ Pro): Try Seaborn‑like styling using Matplotlib only; add a boxplot of marks by hours_bucket; handle missing values by imputation.

Submission checklist


Week 2 — Machine Learning Essentials (scikit‑learn)

Objective: Train/test split, regression + classification, metrics & comparison.

Assignments

  1. Regression

  2. Classification

  3. Text classification pipeline

Mini‑Project

Model Compare

Stretch (★ Pro): Add StandardScaler in a pipeline; use k‑fold cross‑validation; plot a simple learning curve (train size vs accuracy).

Submission checklist


Week 3 — Neural Networks Intro

Objective: Understand NN components and train a tiny network.

Track A (no heavy deps): Scikit‑learn MLP

Track B (recommended if GPU available): PyTorch

Mini‑Project

Tuning Note

Stretch (★ Pro):

Submission checklist


Week 4 — LLM Fundamentals: Tokenization, Embeddings, API

Objective: Learn vector search basics and wire an LLM for chat/summarization.

Assignments

  1. Tokenization/TF‑IDF

  2. RAG‑lite search

  3. Call an LLM (safe key handling)

Mini‑Project

CLI Q&A with Context

Stretch (★ Pro):

Submission checklist


🔎 Review & Scoring (lightweight)


📦 Submission Format (every week)


Grading Rubric


Week 1 — Foundations (NumPy, Pandas, Plotting, EDA)

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.

Week 2 — Machine Learning Essentials (Regression, Classification, Pipelines)

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.

Week 3 — Neural Networks Intro (MLP / PyTorch)

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.

Week 4 — LLM Fundamentals (Tokenization, Embeddings, API)

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.

✅ Final Evaluation (End of Month 3)

Suggested Weightage


📊 Scoring Example (out of 100):