Machine Learning Advanced: Deep Learning, NLP & Deployment
Master the frontier — gradient boosting internals, neural networks, transformers, RAG, vector databases, causal ML, MLOps, and ship a production ML system. This is the full ML engineering skill set.
Start LearningGradient Boosting Internals
28 minWhat you'll learn
- Understand boosting math
- Learn loss gradient descent
- See how trees stack
Gradient boosting trains trees sequentially — each new tree fits the NEGATIVE GRADIENT of the loss (the 'residuals' the previous trees got wrong). The final prediction is the sum of all trees' outputs. This is literally gradient descent in function space: instead of updating weights, you add trees that move predictions down the loss surface. Understanding this math makes every XGBoost parameter make sense.
# Pseudocode of gradient boosting # for each tree: # residuals = -gradient(loss, current_pred) # tree = fit(X, residuals) # pred += learning_rate * tree(X)
Try it yourself
What does each new boosting tree fit?
The negative gradient (residuals) of the loss function.
XGBoost Advanced Parameters
26 minWhat you'll learn
- Master tree and regularization params
- Control overfitting
- Tune learning rate
Beyond n_estimators and learning_rate, XGBoost has critical knobs: max_depth (tree complexity), subsample (row fraction per tree), colsample_bytree (feature fraction), reg_lambda/reg_alpha (L2/L1 regularization), min_child_weight (minimum leaf weight). Together they control the bias-variance trade-off. The standard recipe: small learning rate (0.05-0.1), shallow trees (depth 3-6), and early stopping on a validation set.
import xgboost as xgb
model = xgb.XGBClassifier(
n_estimators=1000,
learning_rate=0.05,
max_depth=4,
subsample=0.8,
colsample_bytree=0.8,
reg_lambda=1.0,
early_stopping_rounds=50
)
model.fit(X_train, y_train, eval_set=[(X_val, y_val)])
Try it yourself
What does subsample=0.8 do?
Each tree uses 80% of training rows, reducing overfitting.
LightGBM & CatBoost
26 minWhat you'll learn
- Compare modern boosting libraries
- Handle categorical features natively
- Pick the right tool
LightGBM uses leaf-wise growth and histogram binning — faster training, often better on large data. CatBoost handles categorical features natively (no one-hot needed) and is robust to target leakage with ordered boosting. In practice: try all three, pick by cross-validation. Each has strengths, but for categorical-heavy data CatBoost often wins with zero encoding effort.
from lightgbm import LGBMClassifier from catboost import CatBoostClassifier lgb = LGBMClassifier(n_estimators=500, learning_rate=0.05) cat = CatBoostClassifier(cat_features=['city','job'], verbose=0) # Train both, compare by CV
Try it yourself
Which boosting lib handles categories natively?
CatBoost.
Neural Networks from an ML Perspective
28 minWhat you'll learn
- Understand MLP as universal approximator
- Learn backprop intuition
- Connect to classical ML
A neural network is just stacked logistic regressions with non-linearities in between. Where linear models learn one decision boundary, MLPs learn many, composed into complex shapes. Backprop is the chain rule — it computes how each weight affects loss and updates them. The key ML insight: neural nets are powerful but data-hungry; gradient boosting often beats them on small tabular data.
import torch
import torch.nn as nn
mlp = nn.Sequential(
nn.Linear(50, 128), nn.ReLU(),
nn.Linear(128, 64), nn.ReLU(),
nn.Linear(64, 2)
)
print(mlp)
Try it yourself
When is a neural net preferable to gradient boosting?
Images, text, audio, or very large datasets.
Convolutional Neural Networks for ML Engineers
28 minWhat you'll learn
- Build CNNs for images
- Understand conv/pool layers
- Apply transfer learning
CNNs are the standard for image ML. Convolution filters slide over the image detecting patterns; pooling downsamples; and a classifier head outputs predictions. In practice, you rarely train from scratch — you load a pre-trained backbone (ResNet, EfficientNet) and fine-tune on your task. This transfer learning gets state-of-the-art accuracy with hundreds, not millions, of images.
import torch.nn as nn from torchvision import models model = models.resnet18(pretrained=True) model.fc = nn.Linear(512, 10) # replace classifier head for param in model.parameters(): param.requires_grad = False model.fc.requires_grad = True
Try it yourself
Why freeze the backbone?
Backbone learned general features; freezing keeps them and adapts only the head.
Sequence Models for ML
28 minWhat you'll learn
- Process sequences with RNN/LSTM
- Handle variable-length input
- Apply to time series and text
Sequences — text, sensor readings, time series — need models that respect order. RNNs maintain hidden state across steps; LSTMs add gating for long-range memory. The ML angle: sequences often become features for downstream prediction (encode a sequence, then classify). In production, embeddings + attention have largely replaced pure RNNs, but understanding sequence modeling is foundational.
import torch.nn as nn lstm = nn.LSTM(input_size=10, hidden_size=32, num_layers=2, batch_first=True) # output: (batch, seq_len, hidden) output, (h, c) = lstm(x) print(output.shape)
Try it yourself
What does the hidden state represent?
The network's memory of what it has seen so far in the sequence.
Transformers for ML
30 minWhat you'll learn
- Understand self-attention
- Use pre-trained transformers
- Fine-tune for custom tasks
Transformers process all tokens in parallel via self-attention, capturing long-range dependencies in one step. The ML angle: load a pre-trained model (BERT for understanding, GPT for generation), fine-tune on your labeled data, and you have state-of-the-art performance with little effort. Fine-tuning = train the model on your task for a few epochs with a small learning rate.
from transformers import AutoModelForSequenceClassification, Trainer
model = AutoModelForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=5)
# Fine-tune with Trainer on labeled data
Try it yourself
What is fine-tuning?
Adapting a pre-trained model to your task with a small amount of training.
Training Deep Models Efficiently
26 minWhat you'll learn
- Use GPUs and mixed precision
- Apply gradient accumulation
- Manage batch size
Deep models are compute-hungry. GPUs parallelize matrix math (10-100x speedup). Mixed precision (fp16) doubles throughput on modern GPUs with negligible accuracy loss. Gradient accumulation lets you simulate large batches on limited memory. Batch size affects convergence — larger batches train faster but may need learning rate scaling. These are the practical skills that separate experimentation from production training.
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
with autocast():
output = model(x)
loss = criterion(output, y)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
Try it yourself
What does mixed precision use?
16-bit floats for most ops, 32-bit where precision matters.
Learning to Rank
28 minWhat you'll learn
- Understand ranking vs classification
- Use LambdaMART/ListNet
- Build search and recommendation ranking
Ranking predicts ORDER, not classes. In search and recommendations, you don't care if an item is 'relevant' absolutely — you care that the most relevant item is FIRST. Pointwise (score each item), pairwise (which of two is better), and listwise (order the whole list) are the three approaches. LambdaMART (LightGBM with ranking objective) is the industry standard for search ranking.
import lightgbm as lgb model = lgb.LGBMRanker(objective='lambdarank') model.fit(X_train, y_train, group=query_groups) ranking = model.predict(X_test)
Try it yourself
What does 'group' mean in ranking?
All items belonging to the same query/user — ranked within the group.
Gaussian Processes
28 minWhat you'll learn
- Understand probabilistic prediction
- Learn uncertainty estimation
- Apply to small-data regression
Gaussian Processes (GPs) predict a DISTRIBUTION, not just a point — giving both a mean and uncertainty. They're non-parametric (grow with data), smooth, and perfect for small datasets where you need calibrated uncertainty — Bayesian optimization, experimental design, engineering optimization. The catch: they scale badly (O(n³)), so they cap out around a few thousand points.
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF
model = GaussianProcessRegressor(kernel=RBF())
model.fit(X, y)
y_mean, y_std = model.predict(X_test, return_std=True)
print('Prediction ± uncertainty:', y_mean[0], '±', y_std[0])
Try it yourself
What's the main limitation of Gaussian Processes?
O(n³) complexity — impractical beyond a few thousand points.
Bayesian Methods in ML
26 minWhat you'll learn
- Understand Bayesian reasoning
- Use probabilistic programming
- Quantify uncertainty everywhere
Bayesian ML treats parameters as distributions, not fixed values — you get full uncertainty, not point estimates. Bayes' theorem: posterior ∝ likelihood × prior. Probabilistic programming (PyMC, Stan) makes this practical. The benefit: calibrated uncertainty, better decisions under limited data, and principled regularization (the prior). It's the mathematically honest approach, at the cost of computation.
import pymc as pm
with pm.Model() as model:
theta = pm.Beta('theta', alpha=2, beta=2)
y = pm.Bernoulli('y', p=theta, observed=data)
trace = pm.sample(1000)
Try it yourself
What does the prior represent?
Your belief about parameters before observing data.
Online Learning
24 minWhat you'll learn
- Learn from streaming data
- Update models incrementally
- Handle concept drift
Online learning updates the model one sample (or mini-batch) at a time, instead of retraining on everything. It's essential for streaming data — clickstreams, sensor feeds, live dashboards — where retraining is too slow and data arrives continuously. Algorithms like SGD, Vowpal Wabbit, and River (Python) are designed for this. Concept drift — when patterns change over time — is the central challenge.
from river import linear_model, metrics
model = linear_model.LogisticRegression()
for x, y in stream:
model.learn_one(x, y) # update incrementally
pred = model.predict_one(x_new)
Try it yourself
What is concept drift?
When the data distribution changes over time, making old models stale.
Multi-Armed Bandits
26 minWhat you'll learn
- Understand explore vs exploit
- Learn epsilon-greedy and UCB
- Apply to recommendations/experiments
Multi-armed bandits are the explore-exploit framework: try options (explore) to learn which is best, while favoring the best so far (exploit). Epsilon-greedy explores randomly ε of the time; UCB explores options with high uncertainty; Thompson sampling is the Bayesian version. Applications: A/B testing that adapts, news recommendation, ad placement. Bandits continuously optimize instead of running one fixed experiment.
import numpy as np
def epsilon_greedy(epsilon, values):
if np.random.rand() < epsilon:
return np.random.choice(len(values)) # explore
return np.argmax(values) # exploit
Try it yourself
What trade-off do bandits balance?
Exploration (learning) vs exploitation (using best known).
Graph Machine Learning
30 minWhat you'll learn
- Represent data as graphs
- Learn node embeddings
- Apply graph neural networks
Graph ML handles relational data — social networks, molecules, knowledge graphs, recommendation graphs — where connections matter as much as features. Node embeddings (node2vec) learn vector representations that preserve graph structure. Graph Neural Networks (GCN, GAT) pass messages between connected nodes, combining node features with neighbors'. This is the frontier for fraud rings, drug discovery, and social analysis.
import torch_geometric.nn as gnn
from torch_geometric.nn import GCNConv
class GCN(nn.Module):
def __init__(self): super().__init__()
self.conv1 = GCNConv(16, 32)
self.conv2 = GCNConv(32, 7)
def forward(self, data):
x = self.conv1(data.x, data.edge_index)
return self.conv2(x.relu(), data.edge_index)
Try it yourself
Name one graph ML application.
Fraud detection (transaction networks), social recommendations, molecule property prediction.
Metric Learning
26 minWhat you'll learn
- Learn similarity functions
- Use triplet/contrastive loss
- Build face recognition/search
Metric learning trains models to output embeddings where similar items are close and dissimilar items are far apart — even for classes never seen in training. Triplet loss (anchor, positive, negative) and contrastive loss are the standard objectives. Applications: face recognition, image retrieval, few-shot learning. The key idea: learn a distance metric, not a classifier.
import torch
import torch.nn.functional as F
def triplet_loss(anchor, positive, negative, margin=0.2):
pos_dist = F.pairwise_distance(anchor, positive)
neg_dist = F.pairwise_distance(anchor, negative)
return F.relu(pos_dist - neg_dist + margin).mean()
Try it yourself
What does the margin in triplet loss do?
Enforces a minimum distance between positive and negative pairs.
Self-Supervised Learning
28 minWhat you'll learn
- Learn without labels
- Use pretext tasks
- Leverage unlabeled data
Self-supervised learning creates its own labels from unlabeled data — predict a masked word in a sentence, predict a rotated image's angle, predict the next frame. The model learns rich representations doing this 'pretext task', then transfers to real tasks with few labels. This is how GPT and BERT were pre-trained. It's the answer to the bottleneck of expensive labels.
# Pretext task: predict masked token sentence = 'The cat sat on the [MASK].' # Model learns to predict 'mat' from context # This unsupervised task teaches language understanding
Try it yourself
Why is self-supervision powerful?
It learns from unlimited unlabeled data, removing the labeling bottleneck.
Few-Shot & Zero-Shot Learning
26 minWhat you'll learn
- Learn from few examples
- Use pre-trained models
- Generalize to unseen classes
Few-shot learning classifies with just a handful of examples; zero-shot with none (using a class description instead). This leverages pre-trained models that already understand the world — instead of retraining, you adapt with a few examples or a prompt. The workflow: take a foundation model, provide k examples (few-shot) or a description (zero-shot), and it generalizes instantly.
from transformers import pipeline
classifier = pipeline('zero-shot-classification')
result = classifier(
'I bought a new phone',
candidate_labels=['electronics', 'food', 'travel']
)
print(result['labels'][0])
Try it yourself
What's the difference between few-shot and zero-shot?
Few-shot uses a few labeled examples; zero-shot uses none (only descriptions).
Active Learning
24 minWhat you'll learn
- Label the most valuable data
- Reduce labeling cost
- Use uncertainty sampling
Active learning flips the labeling problem: instead of labeling everything, the model picks the MOST INFORMATIVE examples for humans to label. Uncertainty sampling asks for labels on examples the model is least sure about. This can reduce labeling cost 10x with minimal accuracy loss — critical when labels are expensive (medical images, legal documents, expert annotation).
def uncertainty_sampling(model, unlabeled_pool, n=100):
probs = model.predict_proba(unlabeled_pool)
uncertainty = 1 - probs.max(axis=1) # most uncertain = lowest max prob
idx = np.argsort(uncertainty)[-n:]
return idx
Try it yourself
Why does active learning help?
It reduces labeling cost by focusing on the most informative examples.
Continual & Lifelong Learning
26 minWhat you'll learn
- Learn without forgetting
- Handle new classes over time
- Manage catastrophic forgetting
Real models face new classes and data distributions over their lifetime. Continual learning updates models without catastrophically forgetting old knowledge — the classic problem: retraining a network on new classes often destroys old ones. Solutions: replay buffers (keep examples), elastic weight consolidation (protect important weights), and parameter isolation. Essential for deployed models that keep learning.
# Elastic Weight Consolidation idea # Protect weights that mattered for old tasks loss = new_task_loss + lambda_ * sum(F_i * (theta - theta_old)**2)
Try it yourself
What is catastrophic forgetting?
When a model forgets previously learned tasks after training on new ones.
Causal ML
28 minWhat you'll learn
- Distinguish correlation from causation
- Estimate treatment effects
- Use uplift modeling
Most ML predicts outcomes; causal ML estimates WHAT HAPPENS IF we intervene — the effect of a treatment, an ad, a drug. Correlation is not causation: ice cream sales and drownings correlate (summer), but neither causes the other. Causal methods (propensity scores, double ML, uplift modeling) estimate individual treatment effects — who responds to an intervention. This is decision-making ML, used in marketing, medicine, and policy.
from econml.dml import CATE model = CATE(model_y=reg, model_t=clf) model.fit(Y, T, X) # T=treatment, Y=outcome, X=features effect = model.effect(X)
Try it yourself
Uplift modeling answers which question?
Who will respond to the intervention — not just who will convert.
Text Embeddings at Scale
26 minWhat you'll learn
- Generate sentence embeddings
- Use SBERT for semantic search
- Build retrieval systems
Sentence embeddings map whole sentences/paragraphs to vectors for semantic search, clustering, and similarity. SBERT (Sentence-BERT) fine-tunes BERT so similar sentences get close vectors — enabling fast cosine-similarity search over millions of documents. This powers modern retrieval-augmented systems and recommendation. The ML angle: embeddings turn text into features any downstream model can use.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(['How to train a model', 'Cooking pasta'])
similarity = cosine_similarity([embeddings[0]], [embeddings[1]])
Try it yourself
What does cosine similarity measure?
How similar two vectors are, based on their angle.
Text Generation Fine-tuning
28 minWhat you'll learn
- Fine-tune LLMs for your domain
- Use LoRA/QLoRA efficiently
- Generate domain-specific text
Fine-tuning an LLM adapts it to your domain — support tickets, legal docs, product copy. LoRA (Low-Rank Adaptation) fine-tunes only a tiny fraction of parameters, making it feasible on consumer GPUs. QLoRA adds 4-bit quantization, cutting memory further. The result: an LLM that speaks your domain's language, cheaply fine-tuned on modest hardware.
from peft import LoraConfig, get_peft_model config = LoraConfig(r=8, lora_alpha=32, target_modules=['q_proj','v_proj']) model = get_peft_model(base_model, config) model = prepare_model_for_kbit_training(model)
Try it yourself
What does LoRA stand for and why use it?
Low-Rank Adaptation — efficient fine-tuning of large models.
Retrieval-Augmented Generation (RAG)
30 minWhat you'll learn
- Combine retrieval with generation
- Ground LLMs in your data
- Build question-answering over documents
RAG is the production pattern for LLMs: retrieve relevant documents (embeddings + vector search), feed them to the LLM as context, and generate a grounded answer. This gives the LLM access to your private knowledge without retraining, dramatically reduces hallucination, and keeps answers up-to-date. The pipeline: embed docs → index in a vector DB → retrieve at query time → generate with context.
# RAG pipeline
query_embedding = embed(query)
docs = vector_db.search(query_embedding, top_k=5)
context = '\n'.join(docs)
answer = llm.generate(f'Context: {context}\nQuestion: {query}')
Try it yourself
What problem does RAG solve?
It grounds LLM answers in retrieved documents, reducing hallucination and enabling private data.
Vector Databases
26 minWhat you'll learn
- Store and search embeddings
- Use FAISS/Pinecone/Chroma
- Build semantic search
Vector databases index embeddings for fast similarity search — the backend of semantic search, RAG, and recommendation. Instead of exact keyword matches, they find the k nearest vectors (approximate nearest neighbor search). FAISS is Facebook's library (open-source, in-memory); Pinecone and Chroma are managed/embedded options. This is the storage layer for modern embedding-based ML.
import faiss import numpy as np dimension = 384 index = faiss.IndexFlatL2(dimension) index.add(embeddings) # store vectors D, I = index.search(query_vector, k=5) # top 5 nearest
Try it yourself
What does a vector DB store?
Vector embeddings, indexed for fast similarity search.
Sentiment & Emotion Analysis Deep Dive
24 minWhat you'll learn
- Go beyond positive/negative
- Detect fine-grained emotion
- Handle aspect-based sentiment
Basic sentiment is positive/negative; advanced analysis goes further — fine-grained emotions (joy, anger, fear), aspect-based sentiment ('battery is bad, camera is great'), and intensity. Aspect-based analysis extracts which specific feature a sentiment targets, powering product feedback mining. The ML angle: this is fine-tuned classification + span extraction, and domain matters enormously.
from transformers import pipeline
sent = pipeline('sentiment-analysis')
aspect = pipeline('token-classification', model='aspect-model')
results = sent('The battery is awful but the screen is great!')
Try it yourself
What is aspect-based sentiment?
Sentiment about specific aspects/features, not just the whole text.
Named Entity Recognition at Scale
24 minWhat you'll learn
- Extract entities from text
- Build custom entity extractors
- Apply to information pipelines
NER extracts structured entities — people, organizations, dates, amounts — from unstructured text, turning documents into structured records. Custom NER trains on your domain's entity types (drug names, product SKUs, legal citations). At scale, NER feeds knowledge graphs and databases. It's the bridge from text to structured data, powering search, compliance, and analytics.
from transformers import AutoModelForTokenClassification
model = AutoModelForTokenClassification.from_pretrained('ner-model', num_labels=7)
entities = model.predict(text) # returns PER, ORG, LOC, DATE, etc.
Try it yourself
Name one application of NER at scale.
Extracting entities from legal documents, medical records, or news for search/analytics.
Machine Translation Systems
24 minWhat you'll learn
- Build translation pipelines
- Use seq2seq transformers
- Evaluate with BLEU
Translation maps text between languages using encoder-decoder transformers. Production systems evaluate with BLEU (n-gram overlap), handle dozens of languages, and often use a pivot language. The ML angle: translation is the canonical sequence-to-sequence task — what you learn here transfers to summarization, paraphrasing, and dialogue.
from transformers import pipeline
translator = pipeline('translation', model='facebook/nllb-200-distilled-600M')
result = translator('Hello world', src_lang='eng_Latn', tgt_lang='urd_Arab')
Try it yourself
What does BLEU measure?
N-gram overlap between machine translation and reference translations.
Speech-to-Text Pipelines
26 minWhat you'll learn
- Transcribe audio with Whisper
- Handle multiple languages
- Build voice interfaces
ASR converts audio to text — the frontend of voice assistants, meeting transcription, and accessibility. Whisper processes audio spectrograms with a transformer, handling noise and multiple languages robustly. The ML angle: audio is preprocessed (resampled to 16kHz), turned into log-mel spectrograms, then fed to a seq2seq model that outputs text tokens.
from transformers import pipeline
asr = pipeline('automatic-speech-recognition', model='openai/whisper-small')
result = asr('meeting.mp3')
print(result['text'])
Try it yourself
What preprocessing does audio need before ASR?
Resample to 16kHz and convert to log-mel spectrogram.
Model Deployment Patterns
28 minWhat you'll learn
- Serve models as APIs
- Choose batch vs real-time
- Design serving architecture
A trained model becomes a product only when deployed. Real-time serving: an API endpoint returning predictions in milliseconds (FastAPI + model in memory). Batch: process large datasets offline. The architecture: load model once, preprocess input, predict, post-process output, return JSON. Deployment is where ML meets software engineering — latency, throughput, and reliability become first-class concerns.
from fastapi import FastAPI
import joblib
app = FastAPI()
model = joblib.load('model.joblib')
@app.post('/predict')
def predict(features: list):
pred = model.predict([features])
return {'prediction': pred.tolist()}
Try it yourself
Real-time vs batch serving — which for fraud detection?
Real-time — fraud detection needs instant decisions.
Docker for ML
26 minWhat you'll learn
- Containerize ML models
- Create reproducible environments
- Deploy consistently
Docker packages your model + dependencies + code into one portable container that runs anywhere — your laptop, a cloud VM, a Kubernetes cluster. This solves 'it works on my machine'. The Dockerfile: pull a Python image, install requirements, copy the model and app, expose the port. Containers are the universal deployment unit in production ML.
FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 8000 CMD ['uvicorn', 'app:app', '--host', '0.0.0.0', '--port', '8000']
Try it yourself
What problem does Docker solve?
Reproducible, portable environments — 'works on my machine' disappears.
Model Monitoring & Drift
28 minWhat you'll learn
- Monitor production ML
- Detect data and concept drift
- Alert on model decay
Deployed models decay — data distributions shift (data drift), or relationships change (concept drift). Monitoring tracks input distributions, prediction distributions, and business metrics over time, alerting when they diverge from training baselines. Tools: Evidently, WhyLabs, custom dashboards. A model that isn't monitored is a model silently failing in production.
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
report = Report(metrics=[DataDriftPreset()])
report.run(reference_data=training_df, current_data=live_df)
report.save_html('drift_report.html')
Try it yourself
What is the difference between data and concept drift?
Data drift = input distribution changes; concept drift = the input-output relationship changes.
Experiment Tracking with MLflow
26 minWhat you'll learn
- Track every experiment
- Reproduce results
- Version models and data
Experiment tracking records parameters, metrics, code versions, and model artifacts for every training run — so you can compare, reproduce, and audit. MLflow is the standard: log params/metrics, save models to a registry, compare runs in a UI. Without tracking, you'll forget which config produced that great result. This is the foundation of ML engineering discipline.
import mlflow
mlflow.set_experiment('churn-prediction')
with mlflow.start_run():
mlflow.log_params({'lr': 0.01, 'n_estimators': 100})
mlflow.log_metric('accuracy', 0.93)
mlflow.sklearn.log_model(model, 'model')
Try it yourself
Why track ML experiments?
To compare, reproduce, and audit which configuration produced which result.
Feature Stores
26 minWhat you'll learn
- Centralize features
- Ensure train/serve consistency
- Share features across teams
A feature store is a central repository for ML features — computed once, reused across models, served consistently in training and inference. The critical problem it solves: train/serve skew, where features are computed differently in training vs production, silently degrading models. Feature stores (Feast, Tecton) version features, enable reuse, and guarantee consistency.
# Feast feature store
feature_store = FeatureStore(repo_path='./feature_repo')
features = feature_store.get_online_features(
features=['user:age', 'user:total_spend'],
entity_rows=[{'user_id': 123}]
)
Try it yourself
What is train/serve skew?
When features are computed differently in training vs serving, degrading predictions.
Model Compression & Distillation
26 minWhat you'll learn
- Shrink models for deployment
- Use distillation and quantization
- Speed up inference
Production models must be fast and small. Quantization reduces precision (float32→int8, ~4x smaller). Pruning removes unimportant weights. Distillation trains a small 'student' to mimic a large 'teacher's' outputs — often retaining most accuracy at a fraction of size. For neural nets, distillation is the most effective: the student learns the teacher's soft probabilities, capturing more than hard labels.
import torch
model_fp32 = model
model_int8 = torch.quantization.quantize_dynamic(
model_fp32, {torch.nn.Linear}, dtype=torch.qint8
)
Try it yourself
Why compress ML models?
Faster inference, lower latency, cheaper serving, and edge deployment.
Explainable ML in Production
26 minWhat you'll learn
- Explain every prediction
- Use SHAP for attribution
- Satisfy compliance needs
Production ML in regulated domains — finance, healthcare, hiring — requires explaining individual predictions. SHAP computes per-feature attribution (which features pushed this decision up/down). It satisfies 'right to explanation' laws, helps debug, and builds user trust. Explainability isn't optional in production; it's often the difference between deploying and not deploying.
import shap explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X) shap.initjs() shap.force_plot(explainer.expected_value, shap_values[0], X.iloc[0])
Try it yourself
What does SHAP provide?
Per-feature contribution to each individual prediction.
Canary & Shadow Deployment
24 minWhat you'll learn
- Roll out models safely
- Compare old vs new
- Minimize deployment risk
Rolling out a new model is risky. Shadow mode runs the new model alongside the old, logging both but serving the old — you compare performance without user impact. Canary deployment routes a small percentage of traffic (5%) to the new model, ramping up if metrics hold. These patterns let you de-risk model changes, catching failures before they affect all users.
# Canary deployment
traffic_split = {'old_model': 0.95, 'new_model': 0.05}
# Monitor error rate and business metrics
# If new model holds, ramp: 0.90/0.10 → 0.50/0.50 → 0/1.0
Try it yourself
What's the difference between shadow and canary?
Shadow: new model sees traffic but doesn't serve. Canary: new model serves a small traffic fraction.
Edge ML
26 minWhat you'll learn
- Deploy models on devices
- Optimize for edge constraints
- Use edge-specific frameworks
Edge ML runs models on phones, cameras, sensors — offline, private, low-latency. Constraints: memory, battery, compute. Solutions: model compression (quantization/pruning/distillation), edge frameworks (TensorFlow Lite, ONNX Runtime, Core ML), and specialized hardware (NPUs). Applications: face unlock, voice assistants, smart cameras. Privacy is the killer app — data never leaves the device.
import onnxruntime as ort
session = ort.InferenceSession('model_quantized.onnx')
inputs = {'input': input_array}
output = session.run(None, inputs)
Try it yourself
Why deploy ML on edge devices?
Privacy (data stays on device), low latency, and offline capability.
Adversarial ML & Security
28 minWhat you'll learn
- Understand adversarial attacks
- Harden models against attacks
- Build secure ML systems
ML models can be fooled — tiny perturbations to an image that are invisible to humans can flip a classifier's decision. Adversarial attacks also include data poisoning (corrupt training data) and model extraction (stealing models). Defenses: adversarial training, input sanitization, model monitoring. As ML handles security-critical decisions, robustness against attack becomes essential, not optional.
# Adversarial attack: add imperceptible noise import torch epsilon = 0.01 perturbation = epsilon * torch.sign(gradient) adversarial_input = original_input + perturbation
Try it yourself
What is an adversarial example?
An input with tiny perturbations that changes the model's prediction.
ML at Scale: Distributed Training
28 minWhat you'll learn
- Train on multiple GPUs
- Use data and model parallelism
- Scale to massive datasets
Modern models and datasets don't fit one machine. Distributed training splits work: data parallelism (same model, different data chunks per GPU, synchronize gradients) and model parallelism (different layers on different GPUs). Frameworks: PyTorch DistributedDataParallel, Horovod, Ray. This is how GPT-4-scale models are trained — thousands of GPUs working in concert.
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel
dist.init_process_group('nccl')
model = DistributedDataParallel(model)
# Each GPU trains on its data shard, gradients sync each step
Try it yourself
What's data parallelism?
Same model replicated, each GPU trains on a data shard, gradients synchronized.
Capstone: Production ML System
70 minWhat you'll learn
- Build an end-to-end ML system
- Apply MLOps best practices
- Ship a deployed, monitored model
Your final capstone: build a complete production ML system. Pick a problem, train a model with MLflow tracking, version it, containerize with Docker, serve behind FastAPI, set up monitoring for drift, and document the whole pipeline. This integrates everything from the course — the deliverable is a deployed system, not a notebook. It's the portfolio piece that proves you're a production ML engineer.
# Production ML stack
# 1. Train (MLflow-tracked)
# 2. Package (Docker)
# 3. Serve (FastAPI)
# 4. Monitor (Evidently)
# 5. Deploy (cloud/K8s)
print('End-to-end production ML system')
Try it yourself
What separates a production ML system from a notebook?
It's deployed, containerized, monitored for drift, and reproducible.
You've completed all 40 advanced lessons. You're now an ML engineer.
Practice your skills or return to the ML hub.