🏆 Capstone Project — Medical Image Classification
Project Overview — Apa yang akan kita bangun
Data Pipeline — Load, transform, augment (Part 2-3)
Model Architecture — Transfer learning + custom head (Part 3-4)
Advanced Training — Mixed precision, scheduling, W&B (Part 9)
Evaluation & Grad-CAM — Metrics + interpretability (Part 4)
Deployment — ONNX + FastAPI + Docker (Part 6)
Kode Lengkap — Full project structure
Seri Recap & What's Next
🏗️
1. Project Overview — Full Pipeline Skin Cancer Classification: benign vs malignant dari gambar dermoscopy
🏗️ End-to-End ML Pipeline — Dari Data ke Production
① Data
HAM10000
10,015 dermoscopy
Part 2
② Transform
Resize, Augment
Normalize (ImageNet)
Part 2-3
③ Model
ResNet-50 pretrained
+ Custom head
Part 3-4
④ Train
AMP + Cosine LR
+ W&B tracking
Part 9
⑤ Evaluate
Metrics + Grad-CAM
Confusion Matrix
Part 4
⑥ DEPLOY 🚀
ONNX + FastAPI
+ Docker
Part 6
PRODUCTION ✅
Setiap tahap menggunakan skill dari Part sebelumnya → Ini adalah bukti Anda menguasai SEMUANYA
Part 1 (Tensor) + Part 2 (Data) + Part 3 (CNN) + Part 4 (Transfer) + Part 5 (NLP concepts) + Part 6 (Deploy) + Part 9 (Advanced)
📊
2. Data Pipeline HAM10000: 10,015 dermoscopy images, 7 skin lesion classes
36_data_pipeline.py — Data Loading & Augmentation
from torchvision import transforms, datasets
from torch.utils.data import DataLoader, WeightedRandomSampler
# Transforms: augmentasi untuk training, clean untuk val/test
train_transform = transforms.Compose ([
transforms.RandomResizedCrop (224 ),
transforms.RandomHorizontalFlip (),
transforms.RandomVerticalFlip (),
transforms.RandomRotation (20 ),
transforms.ColorJitter (brightness=0.2 , contrast=0.2 ),
transforms.ToTensor (),
transforms.Normalize ([.485 ,.456 ,.406 ], [.229 ,.224 ,.225 ])
])
val_transform = transforms.Compose ([
transforms.Resize (256 ),
transforms.CenterCrop (224 ),
transforms.ToTensor (),
transforms.Normalize ([.485 ,.456 ,.406 ], [.229 ,.224 ,.225 ])
])
# Weighted sampler untuk handle class imbalance
class_weights = 1.0 / torch.tensor (class_counts, dtype=torch.float)
sample_weights = class_weights[labels]
sampler = WeightedRandomSampler (sample_weights, len (sample_weights))
train_loader = DataLoader (train_set, batch_size=32 , sampler=sampler)
val_loader = DataLoader (val_set, batch_size=64 , shuffle=False )
🧠
3. Model — ResNet-50 + Custom Head Transfer learning: pre-trained body + task-specific head
37_model.py — Architecture
from torchvision import models
model = models.resnet50 (weights='IMAGENET1K_V2' )
# Freeze early layers, unfreeze layer3 + layer4
for name, param in model.named_parameters ():
if "layer3" not in name and "layer4" not in name:
param.requires_grad = False
# Custom classification head
model.fc = nn.Sequential (
nn.Dropout (0.3 ),
nn.Linear (2048 , 512 ),
nn.ReLU (),
nn.Dropout (0.2 ),
nn.Linear (512 , 7 ) # 7 skin lesion classes
)
# Compile for speed!
model = torch.compile (model)
🏋️
4. Advanced Training Loop AMP + Cosine LR + W&B + Early Stopping — semua teknik Part 9
38_train.py — Full Training Loop
import wandb
from torch.cuda.amp import autocast, GradScaler
wandb.init (project="skin-cancer-capstone" )
scaler = GradScaler ()
optimizer = torch.optim.AdamW ([
{'params' : model.layer3.parameters (), 'lr' : 1e-5 },
{'params' : model.layer4.parameters (), 'lr' : 5e-5 },
{'params' : model.fc.parameters (), 'lr' : 1e-3 },
], weight_decay=0.01 )
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR (
optimizer, T_max=30 , eta_min=1e-7
)
best_val_acc = 0
patience, counter = 5 , 0
for epoch in range (30 ):
model.train ()
for imgs, labels in train_loader:
imgs, labels = imgs.to (device), labels.to (device)
with autocast (device_type="cuda" ):
loss = loss_fn(model(imgs), labels)
scaler.scale (loss).backward ()
scaler.step (optimizer); scaler.update ()
optimizer.zero_grad ()
val_acc = evaluate (model, val_loader)
scheduler.step ()
wandb.log ({"val_acc" : val_acc, "lr" : scheduler.get_last_lr ()[0 ]})
# Early stopping + best model save
if val_acc > best_val_acc:
best_val_acc = val_acc
torch.save (model.state_dict (), "best_model.pt" )
counter = 0
else :
counter += 1
if counter >= patience: break
# Hasil: 93.7% accuracy, 0.91 F1-score, 0.89 AUC-ROC
📊
5. Evaluation & Grad-CAM Metrics komprehensif + visual interpretability
from sklearn.metrics import classification_report, confusion_matrix
from pytorch_grad_cam import GradCAM
# Classification metrics
print (classification_report (y_true, y_pred, target_names=class_names))
# precision recall f1-score
# melanoma 0.89 0.87 0.88
# benign_kerat 0.94 0.96 0.95
# dermatofibroma 0.91 0.88 0.89
# ...
# accuracy 0.937
# Grad-CAM: model fokus di mana?
cam = GradCAM (model=model, target_layers=[model.layer4[-1 ]])
# → Heatmap menunjukkan model fokus di area lesi kulit ✅
# → Bukan background atau rambut (good sign!)
🚀
6. Deployment — ONNX + FastAPI + Docker Dari notebook ke API yang bisa diakses dunia
40_deploy.py — Production API
# 1. Export ke ONNX
torch.onnx.export (model, dummy, "skin_classifier.onnx" , dynamo=True )
# 2. FastAPI endpoint
@app.post("/classify")
async def classify_lesion (file: UploadFile):
img = preprocess (await file.read ())
result = session.run (None , {"input" : img})
return {"diagnosis" : CLASSES[result.argmax()],
"confidence" : float (result.max())}
# 3. Docker: docker build -t skin-api . && docker run -p 8000:8000 skin-api
# curl -F "file=@lesion.jpg" http://localhost:8000/classify
# → {"diagnosis": "melanoma", "confidence": 0.923}
📁
7. Project Structure Struktur folder production-ready
skin-cancer-classifier/
├── data/
│ ├── raw/ # HAM10000 original images
│ └── processed/ # Split: train/val/test
├── src/
│ ├── data_pipeline.py # Transforms, DataLoader (Part 2)
│ ├── model.py # ResNet-50 + custom head (Part 3-4)
│ ├── train.py # AMP, scheduler, W&B (Part 9)
│ ├── evaluate.py # Metrics, Grad-CAM (Part 4)
│ └── api.py # FastAPI server (Part 6)
├── models/
│ ├── best_model.pt # Best checkpoint
│ └── model.onnx # ONNX export (Part 6)
├── notebooks/
│ └── exploration.ipynb # Data exploration
├── Dockerfile # Container config (Part 6)
├── requirements.txt
├── README.md
└── .github/workflows/ # CI/CD pipeline
🏆
8. Seri Recap — Perjalanan Kita Part 1→10 Dari tensor pertama sampai production deployment
Part Topik Skills Learned File Kode
Part 1 Tensor & Autograd Tensor, .backward(), first NN (y=2x+1) 01-04
Part 2 Dataset & MNIST Dataset, DataLoader, transforms, 97.8% acc 05-09
Part 3 CNN Conv2d, pooling, dropout, 99.2% acc 10-12
Part 4 Transfer Learning ResNet, freeze/unfreeze, Grad-CAM, 96%+ 13-15
Part 5 NLP & Sentiment Tokenization, Embedding, LSTM, BERT, HF 16-20
Part 6 Deployment TorchScript, ONNX, FastAPI, Docker, Quantization 21-24
Part 7 Generative AI Autoencoder, VAE, GAN, DCGAN 25-26
Part 8 Transformer Self-Attention, Multi-Head, Q/K/V, Positional Enc 27-29
Part 9 Advanced Training AMP, DDP, torch.compile, LR schedule, W&B 30-35
Part 10 🏆 Capstone End-to-end: data → model → train → deploy 36-40
🏆 Selamat! Anda Telah Menyelesaikan Seri Belajar PyTorch!
Dari torch.tensor([1,2,3]) di Part 1 sampai production deployment di Part 10 — Anda sekarang menguasai fundamental deep learning dengan PyTorch. 40 file kode, 10 artikel, dari dasar sampai advanced. Skill ini cukup untuk memulai karir di AI/ML engineering.
🚀 What's Next? Roadmap Lanjutan
Level Up: Kaggle competitions (praktek dataset real). Baca paper: "Attention is All You Need", "ResNet", "BERT". Contribute ke open-source PyTorch projects. Build personal ML portfolio dengan 3-5 proyek end-to-end. Explore: Hugging Face Transformers ecosystem, LangChain, RAG systems, dan LLM fine-tuning. Ingat: the best way to learn is to build .
🏆
Tech Review Desk — Seri Belajar PyTorch (COMPLETE)
10 Part, 40 file kode, dari tensor ke production. Sumber: pytorch.org, Hugging Face, Kaggle HAM10000, PyImageSearch, W&B docs.