Mục lục
- Mục tiêu bài học và vị trí trong lộ trình
- Recap Series 2 — Overfit và Underfit
- Vì sao DL nhạy hơn ML cổ điển
- Dấu hiệu overfit trong DL
- Learning curve điển hình
- Nguồn gốc overfit
- Tổng quan cách chống overfit
- Memorization — pitfall đặc thù DL
- Double Descent — góc nhìn hiện đại
- Checklist chẩn đoán overfit
- Workflow chống overfit
- Underfit — dễ nhầm với overfit
- Bias-Variance trong DL
- TensorBoard visualize learning curve
- Generalization gap
- Vì sao DL hoạt động dù over-parameterized
- Khi nào nên cố tình overfit
- Code Python — force overfit và quan sát
- Bài tập
- Tổng kết và bài kế tiếp
Mục tiêu bài học và vị trí trong lộ trình
Sau bài học, bạn sẽ:
- Nhận diện overfit qua learning curve (train loss giảm, val loss tăng) và generalization gap.
- Hiểu vì sao mạng deep với millions–billions tham số dễ overfit hơn ML cổ điển.
- Biết các nguồn gây overfit đặc thù trong DL: model quá lớn, data quá ít, train quá lâu, noise nhãn, bias dataset.
- Nắm góc nhìn hiện đại về double descent — vì sao mạng càng lớn lại có thể generalize tốt hơn.
- Áp dụng kỹ thuật overfit small batch để debug pipeline trước khi train production.
- Có workflow tổng quát chống overfit, làm khung cho các bài B22–B26 đi sâu từng kỹ thuật.
Bài này mở đầu Module 3 — Regularization & Optimization. Hai module trước đã đủ để build và train một neural network (Module 1 nền tảng ANN, Module 2 PyTorch). Module 3 trả lời câu hỏi: "train được rồi, làm sao để model generalize ra dữ liệu chưa thấy?"
Kết nối: Bài 20 — Weight Initialization đóng Module 2; Bài 22 — Dropout mở kỹ thuật regularization đầu tiên ở Module 3.
Recap Series 2 — Overfit và Underfit
Khái niệm overfit và underfit đã được giới thiệu trong Series 2 (Machine Learning) — B37 và B38. Tóm tắt nhanh để có chuẩn chung:
- Overfit: model học pattern train set quá kỹ, bao gồm cả noise. Hiệu suất train cao nhưng test/val thấp.
- Underfit: model quá đơn giản, không bắt được pattern. Cả train và test đều kém.
- Sweet spot: cân bằng — error train và val đều thấp, gap giữa chúng nhỏ.
- Bias-Variance trade-off: bias cao = underfit, variance cao = overfit. Mục tiêu giảm cả hai.
Trong ML cổ điển (linear regression, SVM, random forest với vài chục cây), capacity model còn vừa phải. Việc kiểm soát overfit thường gói gọn trong: chọn độ phức tạp model (polynomial degree, tree depth), thêm regularization L1/L2, cross-validation chọn hyperparameter.
Deep learning là một regime khác hẳn: capacity model thường vượt xa lượng pattern thực trong data — câu chuyện không còn là "chọn model vừa đủ to" mà là "model rất to + công cụ kiểm soát mạnh".
Vì sao DL nhạy hơn ML cổ điển
Hai lý do chính khiến deep learning dễ overfit hơn ML cổ điển:
- Số tham số cực lớn. Một MLP nhỏ cho MNIST
784 → 256 → 128 → 10đã có khoảng 235k tham số. ResNet-50 có 25 triệu; BERT-base 110 triệu; GPT-3 175 tỉ. Linear regression với 10 feature có 11 tham số — chênh nhau 7–10 bậc độ lớn. - Capacity cao → memorize train data. Với đủ tham số, model có thể "nhớ" từng mẫu train kèm nhãn, kể cả nhãn ngẫu nhiên. Pattern không nhất thiết là khái quát — có thể là một bảng tra cứu nội tại trong weight.
Ví dụ minh hoạ tỉ lệ tham số / dữ liệu:
- MNIST: 60k train sample. MLP 235k tham số — tỉ lệ 4 tham số / 1 mẫu.
- CIFAR-10: 50k train. ResNet-50: 500 tham số / 1 mẫu.
- ImageNet: 1.2M train. ViT-Large: 250 tham số / 1 mẫu.
Một quy tắc cũ ("số sample >= 10 × số tham số") đã bị bỏ từ lâu trong DL — thực tế hoạt động được nhờ structural prior (CNN, attention), data augmentation, và các kỹ thuật regularization sẽ học ở module này.
Dấu hiệu overfit trong DL
Ba dấu hiệu rõ rệt nhất khi nhìn vào quá trình train:
- Train loss giảm liên tục, val loss giảm rồi tăng. Đây là dấu hiệu kinh điển. Model tiếp tục giảm error trên train (vì memorize thêm), nhưng error trên val ngừng giảm và bắt đầu tăng.
- Train accuracy ~99%, val accuracy 70%. Khoảng cách lớn giữa hai con số. Model "thuộc bài" train nhưng không "hiểu" để áp dụng vào dữ liệu mới.
- Gap giữa train và val ngày càng rộng. Ở epoch đầu, hai đường gần nhau. Càng train, chúng càng tách xa — chính là generalization gap đang tăng.
Không phải mọi gap đều xấu. Một gap nhỏ (vài phần trăm accuracy) là bình thường. Cảnh báo bắt đầu khi gap > 5–10% và đang mở rộng theo epoch.
Quan sát cả loss và accuracy, vì hai chỉ số này có thể disagree: train accuracy đã 100% nhưng train loss vẫn giảm (model trở nên confident hơn ở các prediction đúng) trong khi val loss đã tăng — vẫn là overfit.
Learning curve điển hình
Plot loss theo epoch là công cụ chẩn đoán quan trọng nhất:
- Train curve: giảm gần như đều đặn, tiến dần về 0 (hoặc một sàn nào đó nếu có noise).
- Val curve: giảm cùng train ở giai đoạn đầu, đạt điểm thấp nhất ở một epoch giữa, rồi tăng dần trở lại.
- Sweet spot: epoch mà val loss đạt minimum. Đây là điểm dừng tối ưu — sau đó train thêm chỉ làm xấu generalization.
Hình dạng curve cũng tiết lộ vấn đề:
- Cả hai curve đều cao và phẳng → underfit (xem mục 12).
- Train giảm, val tăng từ rất sớm → model quá lớn so với data, cần regularization mạnh.
- Train giảm về 0 nhưng val giảm xong phẳng, không tăng → có overfit nhẹ nhưng không nguy hiểm; có thể chấp nhận.
- Val loss dao động mạnh (noisy) → batch size nhỏ, validation set nhỏ, hoặc learning rate cao.
Kỹ thuật early stopping (B24) chính là tự động dừng train tại sweet spot, dựa trên val loss.
Nguồn gốc overfit
Năm nguồn chính:
- Model quá lớn (over-parameterized): số tham số vượt xa pattern thực có trong data. Capacity dư thừa được dùng để memorize.
- Data quá ít: với 100 sample mà train MLP 100k tham số, ngay cả khi pattern đơn giản, model vẫn dễ memorize từng sample.
- Train quá lâu: dù model và data cân đối, train quá nhiều epoch sẽ đẩy weight đi xa khỏi vùng generalize tốt, đi vào vùng fit chi tiết noise.
- Noise trong train data: nhãn sai, ảnh mờ, label inconsistent. Model với capacity đủ sẽ nhớ luôn cả noise — và noise không có trên val.
- Bias dataset: train và val cùng có một pattern nào đó không tồn tại trong thực tế. Model học pattern này thay vì task thật. Ví dụ: phân loại "ngựa vs hươu" nhưng ảnh ngựa luôn chụp ngoài trời, ảnh hươu trong rừng — model học "ngoài trời/trong rừng" chứ không học hình dáng con vật.
Diagnosing nguồn nào quan trọng để chọn đúng cách chữa. Model quá lớn → giảm size hoặc thêm dropout/weight decay. Data quá ít → augmentation, transfer learning. Train quá lâu → early stopping. Noise nhãn → label smoothing, clean data. Bias dataset → audit và rebalance.
Tổng quan cách chống overfit
Toàn bộ Module 3 sẽ đi sâu từng kỹ thuật. Đây là bản đồ tổng thể, chia theo nhóm:
- More data:
- Data augmentation (B26) — biến đổi ảnh/text để tăng đa dạng train.
- Thu thập thêm data thật (đắt nhưng hiệu quả nhất).
- Transfer learning (B32) — dùng weight đã train sẵn trên dataset lớn.
- Regularization (giảm capacity hiệu dụng):
- L1 / L2 weight decay — phạt weight lớn (đã học Series 2 B21, sẽ apply cho DL).
- Dropout (B22) — ngẫu nhiên tắt neuron khi train.
- Batch Normalization (B23) — chuẩn hoá activation, có tác dụng regularize nhẹ.
- Architectural:
- Giảm số layer hoặc số neuron mỗi layer.
- Residual connection (Module 4) — giúp gradient lan tốt qua deep network.
- Training tricks:
- Early stopping (B24) — dừng train ở val loss min.
- Learning rate decay (B25) — giảm LR dần để fine-tune ở cuối.
- Gradient clipping — cap norm gradient để tránh update lớn.
Trong thực hành, hiếm khi chỉ dùng một kỹ thuật. Pipeline production thường combine: dropout + BN + early stopping + LR schedule + augmentation. Mỗi cái giải quyết một khía cạnh khác nhau, cộng lại tạo robustness.
Memorization — pitfall đặc thù DL
Một thí nghiệm quan trọng từ Zhang et al. (2017) — "Understanding deep learning requires rethinking generalization":
- Lấy CIFAR-10, thay nhãn bằng nhãn ngẫu nhiên.
- Train CNN tiêu chuẩn (Inception, ResNet, MLP) trên dataset đã shuffle label.
- Kết quả: model vẫn đạt train accuracy ~100%.
Hệ quả: deep model có thừa capacity để memorize bất kỳ ánh xạ nào, kể cả ánh xạ vô nghĩa. Việc model train được trên data thật không chứng minh nó "hiểu" — có thể nó chỉ đang dùng capacity dư thừa để memorize.
Hệ quả tiếp: lý thuyết generalization cổ điển (VC dimension, Rademacher complexity) không giải thích được vì sao deep network với capacity vô hạn vẫn generalize tốt trên data thật. Lý thuyết DL hiện đại vẫn đang đi tìm câu trả lời.
Liên quan: adversarial robustness. Model overfit pattern nhỏ trong train data sẽ dễ bị đánh lừa bằng perturbation rất nhỏ (adversarial example) — pixel thay đổi không nhìn ra bằng mắt nhưng đủ thay đổi prediction. Robustness cũng là một dạng generalization.
Double Descent — góc nhìn hiện đại
Bài học cổ điển: "model càng lớn thì càng dễ overfit". Đường cong test error theo model size có hình chữ U — đáy là sweet spot.
Quan sát hiện đại từ Belkin et al. (2019) và Nakkiran et al. (2019) — "Deep Double Descent":
- Khi model size tăng tới interpolation threshold (đủ để fit train data 100%), test error cao như dự đoán cổ điển — peak.
- Tiếp tục tăng model size vượt qua threshold: test error giảm trở lại và thấp hơn cả đáy của U cũ.
- Đường cong test error có hình "double descent" — giảm, tăng tới peak, giảm lại.
Quy luật này quan sát được trên cả model size, dataset size, và epoch number. Trực giác: ở regime over-parameterized, có rất nhiều cách fit train data — SGD ngầm chọn nghiệm có norm nhỏ / flat (implicit bias), và nghiệm đó tình cờ generalize tốt.
Thực hành: DL hiện đại thường ở regime over-parameterized với regularization tốt. Không cần sợ "model quá to" — vấn đề là regularization có đủ mạnh không. Đây là lý do GPT-3, LLaMA, Stable Diffusion với hàng tỉ tham số vẫn generalize được.
Checklist chẩn đoán overfit
Quy trình kiểm tra khi nghi ngờ model overfit:
- Plot train + val loss theo epoch. Plot cả accuracy nếu là classification. Là bước đầu tiên, không bỏ qua.
- So sánh gap. Gap nhỏ và ổn định → OK. Gap lớn và đang mở rộng → overfit.
- Check distribution train vs val. Hai tập có cùng distribution không? Val có đại diện cho dữ liệu thực tế không? Nếu val cũng khác thực tế thì val accuracy cao cũng không có ý nghĩa.
- Inspect prediction error. Lỗi của model trên val có random hay systematic? Nếu sai trên một class cụ thể, một subset cụ thể — có thể là bias dataset hơn là overfit thuần.
- Test trên một batch unseen hoàn toàn. Nếu accuracy sụp đổ → train/val có pattern chung không có ở real world.
Một lỗi hay gặp: data leakage giữa train và val. Ví dụ resize ảnh trước khi split — info từ ảnh val đã lọt vào pipeline preprocessing. Symptom: val accuracy cao bất ngờ. Cách kiểm tra: split trước, preprocess sau.
Workflow chống overfit
Thứ tự ưu tiên khi áp dụng kỹ thuật, từ rẻ tới đắt:
- Đánh giá xem có overfit không. Plot learning curve, tính gap. Đừng cố chữa khi chưa chẩn đoán.
- Thử data augmentation. Rẻ, hiệu quả, không đổi kiến trúc. Cho ảnh: flip, crop, rotate, color jitter. Cho text: synonym replacement, back-translation.
- Thử dropout. Một dòng code thêm vào model, hiệu quả rõ.
- Thử weight decay. Tham số trong optimizer (
weight_decay=1e-4), không thay đổi gì khác. - Reduce model size nếu model rõ ràng quá lớn so với data (ví dụ MLP 1M tham số trên 1k sample).
- Combine tất cả: dropout + BN + early stopping + LR schedule + augmentation. Production model gần như luôn dùng combination.
Nguyên tắc: thay đổi một thứ một lần và đo lại. Nếu đổi 3 hyperparameter cùng lúc, không biết cái nào giúp ích.
Underfit — dễ nhầm với overfit
Đối lập với overfit là underfit — model không học được pattern, train loss và val loss đều cao. Dấu hiệu:
- Cả train và val loss đều cao và không giảm thêm sau nhiều epoch.
- Accuracy ngang với random guess.
- Gap nhỏ — vì cả hai đều kém.
Nguyên nhân và cách chữa:
- Model quá nhỏ → tăng layer hoặc neuron.
- Train chưa đủ → train thêm epoch.
- Learning rate không phù hợp (quá nhỏ → chậm, quá lớn → loss không giảm) → chỉnh LR.
- Optimizer chưa hợp → thử Adam thay vì SGD vanilla.
- Init kém → xem B20.
- Feature engineering thiếu → preprocessing hoặc add feature.
Lỗi hay gặp: thấy val accuracy thấp đã vội thêm dropout và weight decay trong khi vấn đề thực là underfit — làm vậy chỉ khiến tệ hơn. Luôn check train accuracy trước. Train accuracy thấp → underfit. Train cao, val thấp → overfit.
Bias-Variance trong DL
Series 2 B38 đã trình bày bias-variance decomposition trong ML cổ điển:
\( \text{Error} = \text{Bias}^2 + \text{Variance} + \text{Irreducible Noise} \).
- Bias cao: model giả định sai về data → underfit.
- Variance cao: model nhạy với perturbation nhỏ trong train set → overfit.
- Trade-off: tăng capacity giảm bias nhưng tăng variance.
Trong DL hiện đại, picture phức tạp hơn:
- Bias rất thấp: model lớn có thể fit gần như bất cứ function nào.
- Variance phụ thuộc training tricks: ở regime over-parameterized, variance không tăng theo capacity như cổ điển — SGD implicit regularization và các kỹ thuật regularization giữ variance ở mức kiểm soát được.
- Trade-off cổ điển vẫn đúng trước interpolation threshold; sau đó hiện tượng double descent làm picture khác đi.
Thực hành: bias-variance là khung tư duy hữu ích để diagnose, nhưng đừng quá phụ thuộc vào nó khi làm DL. Plot learning curve + tính gap là tool trực tiếp hơn.
TensorBoard visualize learning curve
PyTorch tích hợp với TensorBoard qua torch.utils.tensorboard.SummaryWriter — công cụ visualize chuẩn cho learning curve, gradient distribution, model graph.
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("runs/mnist_exp1")
for epoch in range(num_epochs):
train_loss = train_one_epoch(model, train_loader, opt)
val_loss, val_acc = evaluate(model, val_loader)
writer.add_scalar("Loss/train", train_loss, epoch)
writer.add_scalar("Loss/val", val_loss, epoch)
writer.add_scalar("Acc/val", val_acc, epoch)
writer.close()
Khởi chạy UI:
tensorboard --logdir=runs --port=6006
Trong UI có thể:
- So sánh nhiều run (mỗi run là một thư mục con của
runs/). - Detect overfit từ visual: thấy ngay khi val loss bắt đầu vênh khỏi train loss.
- Plot histogram weight và gradient để debug vanishing/exploding.
Alternative: matplotlib nếu chỉ cần plot đơn giản; wandb (Weights & Biases) cho team collaboration và cloud logging.
Generalization gap
Đo lường overfit bằng một số duy nhất:
\( \text{generalization gap} = \mathcal{L}_{\text{test}} - \mathcal{L}_{\text{train}} \)
Hoặc tương đương với accuracy: gap = acc_train - acc_test.
- Gap nhỏ (gần 0): model generalize tốt. Có thể vẫn underfit nếu cả hai cùng kém — phải xem giá trị tuyệt đối.
- Gap lớn và mở rộng theo epoch: overfit rõ.
- Gap âm: hiếm — thường do val set "dễ" hơn train (label noise trong train, hoặc augmentation chỉ áp cho train).
Cách dùng: log gap mỗi epoch, plot song song với loss. Nếu gap tăng tuyến tính theo epoch, regularization đang yếu — thêm dropout hoặc weight decay. Nếu gap ổn định nhưng giá trị tuyệt đối lớn, có thể là vấn đề distribution shift (train/val khác nhau bản chất).
Lưu ý: dùng test set chỉ để báo cáo cuối, không dùng để chỉnh hyperparameter. Trong vòng lặp train/tune, dùng val set. Generalization gap dùng val set ≈ train loss là proxy thực tế nhất.
Vì sao DL hoạt động dù over-parameterized
Câu hỏi mở của lý thuyết DL hiện đại: tại sao mạng với 100M tham số train trên 1M sample lại không overfit như VC theory dự đoán? Một số giả thuyết đang được nghiên cứu:
- SGD implicit regularization. SGD không tìm minimum bất kỳ trong loss landscape — nó có xu hướng tìm flat minima (vùng có loss thấp xung quanh). Flat minima generalize tốt hơn sharp minima vì ít nhạy với perturbation.
- Loss landscape có nhiều global minima tương đương. Trong regime over-parameterized, có vô số nghiệm fit train data — SGD ngầm chọn nghiệm có norm thấp hoặc flat, không phải nghiệm bất kỳ.
- Implicit bias của optimizer. SGD, momentum, Adam có bias khác nhau. SGD vanilla có bias mạnh nhất về phía nghiệm norm nhỏ — nhiều phân tích lý thuyết tập trung vào SGD.
- Architectural prior. CNN có inductive bias về translation invariance; Transformer có bias về sequence và attention. Architecture đã hạn chế không gian function — không phải mọi function 100M tham số đều xét.
Đây là chủ đề nghiên cứu mở (Neyshabur, Belkin, Hardt, Bartlett là một số tác giả lớn). Bạn không cần hiểu sâu để làm DL applied — nhưng biết rằng "model lớn vẫn generalize được" là feature, không phải bug, sẽ giúp bớt sợ khi scale up.
Khi nào nên cố tình overfit
Nghe ngược đời, nhưng đôi khi không chống overfit là điều đúng. Hai trường hợp:
- Sanity check pipeline. Khi mới viết training loop, lo lắng pipeline có bug (forward sai shape, loss sai cách tính, data load sai nhãn). Cách test nhanh: lấy 1 batch nhỏ (8–32 sample), train liên tục cho tới khi loss tiến về 0. Nếu loss không giảm về gần 0 trên 1 batch nhỏ → có bug ở đâu đó.
- Debug architecture. Tương tự, model mới viết — cần verify nó có đủ capacity để fit. Memorize 1 batch là proof of concept.
Đây là kỹ thuật "overfit small batch" — Karpathy gọi nó là một trong những step đầu tiên cần làm khi training DL model. Pseudocode:
small_batch = next(iter(train_loader)) # lấy 1 batch
model.train()
for step in range(500):
x, y = small_batch
out = model(x)
loss = criterion(out, y)
opt.zero_grad()
loss.backward()
opt.step()
if step % 50 == 0:
print(f"step {step} loss={loss.item():.4f}")
# Kỳ vọng: loss giảm xuống < 0.01 (hoặc gần 0)
# Nếu không → có bug, dừng debug trước khi train full
Sau khi pipeline đã pass test này, mới chuyển qua train full với regularization. Đảo thứ tự (train full ngay) hay làm tốn nhiều giờ GPU mà không phát hiện bug.
Code Python — force overfit và quan sát
Demo end-to-end: tạo dataset nhỏ, train model lớn không có regularization, plot learning curve để thấy overfit.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset, DataLoader
import matplotlib.pyplot as plt
torch.manual_seed(0)
# Dataset nhỏ: 200 train, 500 val, 50 chiều input, 2 class
X = torch.randn(700, 50)
y = (X[:, 0] + X[:, 1] - X[:, 2] + 0.3 * torch.randn(700) > 0).long()
X_train, y_train = X[:200], y[:200]
X_val, y_val = X[200:], y[200:]
train_ds = TensorDataset(X_train, y_train)
val_ds = TensorDataset(X_val, y_val)
train_loader = DataLoader(train_ds, batch_size=32, shuffle=True)
val_loader = DataLoader(val_ds, batch_size=64)
# Model cố tình quá lớn: 4 hidden layer 512
model = nn.Sequential(
nn.Linear(50, 512), nn.ReLU(),
nn.Linear(512, 512), nn.ReLU(),
nn.Linear(512, 512), nn.ReLU(),
nn.Linear(512, 512), nn.ReLU(),
nn.Linear(512, 2),
)
opt = torch.optim.Adam(model.parameters(), lr=1e-3) # no weight_decay
criterion = nn.CrossEntropyLoss()
def epoch_loss(loader):
model.eval()
total, n = 0.0, 0
with torch.no_grad():
for x, t in loader:
total += criterion(model(x), t).item() * x.size(0)
n += x.size(0)
return total / n
train_losses, val_losses = [], []
for epoch in range(100):
model.train()
for x, t in train_loader:
loss = criterion(model(x), t)
opt.zero_grad()
loss.backward()
opt.step()
train_losses.append(epoch_loss(train_loader))
val_losses.append(epoch_loss(val_loader))
plt.plot(train_losses, label="train")
plt.plot(val_losses, label="val")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.legend()
plt.title("Overfit demo: 4×512 MLP on 200 samples")
plt.show()
Kết quả điển hình: train loss giảm về < 0.01 sau ~30 epoch; val loss giảm tới epoch 10–15 (val loss min ≈ 0.45), sau đó tăng dần lên ~0.8 ở epoch 100. Đường gap rộng dần — classic overfit.
Bổ sung demo overfit small batch:
small_x, small_y = next(iter(train_loader)) # 1 batch 32 mẫu
model2 = nn.Sequential(nn.Linear(50, 64), nn.ReLU(), nn.Linear(64, 2))
opt2 = torch.optim.Adam(model2.parameters(), lr=1e-3)
for step in range(300):
loss = F.cross_entropy(model2(small_x), small_y)
opt2.zero_grad()
loss.backward()
opt2.step()
if step % 50 == 0:
print(f"step {step:3d} loss={loss.item():.4f}")
Output mong đợi: loss giảm từ ~0.7 xuống < 0.01 trong vòng 300 step. Nếu không giảm → có bug trong forward, loss, hay data.
Bài tập
- Lấy MNIST, chỉ giữ 1000 sample đầu làm train set, dùng tập test gốc làm val. Build MLP
784 → 512 → 512 → 10. Train 100 epoch, batch size 32, Adamlr=1e-3, không regularization. Plot train_loss và val_loss theo epoch. - Identify epoch nào val_loss đạt minimum (sweet spot). So sánh với epoch cuối — model có overfit không? Tính generalization gap ở epoch cuối.
- Lặp lại bài 1 nhưng thêm
weight_decay=1e-4trong Adam. Plot và so sánh learning curve với bài 1. Generalization gap thay đổi thế nào? - Implement overfit small batch test: lấy 1 batch 32 sample từ MNIST, train model nhỏ
784 → 128 → 10liên tục 500 step. Verify loss giảm xuống < 0.01. Sau đó, cố tình tạo bug (ví dụ trả vềlogits.detach()trong forward), chạy lại — loss không giảm; xác nhận bug được catch. - Trên cùng MNIST 1000 sample, train liên tiếp ở 3 model size:
[128],[512],[2048, 2048](số neuron mỗi hidden layer). Plot test accuracy theo model size. Quan sát có thấy hiện tượng double descent dạng nào không (tăng dần, U, hay double descent đầy đủ). - Đọc abstract paper Zhang et al. (2017) "Understanding deep learning requires rethinking generalization" (link trong sources). Tóm tắt trong 3-4 câu phát hiện chính. Liên hệ với mục 8 của bài.
Gợi ý ngắn
- Train accuracy sẽ đạt 100% sau ~20-30 epoch; val accuracy đạt đỉnh quanh 90-93% rồi đi ngang hoặc giảm nhẹ. Val loss đi lên rõ.
- Sweet spot thường ở epoch 10-20. Gap = train_loss_cuối - val_loss_cuối có thể tới 0.5-1.0.
- Weight decay làm gap nhỏ lại, val loss min sâu hơn, ít tăng về sau. Train loss cuối hơi cao hơn (đó là trade-off).
- Loss giảm về gần 0 với model OK. Với bug detach, gradient không lan ngược → loss đứng yên ở giá trị ban đầu.
- Với 1000 sample, model nhỏ underfit, model vừa fit tốt nhất, model rất lớn có thể tệ hơn hoặc tốt hơn tuỳ regularization. Double descent đầy đủ cần thí nghiệm careful với nhiều size hơn.
- Phát hiện chính: deep network có thể đạt 100% train accuracy trên CIFAR với nhãn random; lý thuyết generalization cổ điển không giải thích được sự generalization tốt khi nhãn thật.
Tổng kết và bài kế tiếp
Module 3 đã bắt đầu. Bài này đặt nền:
- Overfit trong DL nặng hơn ML cổ điển vì số tham số quá lớn so với data — model dễ memorize.
- Dấu hiệu: train loss giảm tiếp, val loss tăng. Generalization gap mở rộng.
- Sweet spot = epoch val loss min. Train xa hơn là làm xấu.
- Nguồn overfit: model lớn, data ít, train lâu, noise nhãn, bias dataset.
- Double descent: regime over-parameterized có thể generalize tốt hơn cả U-curve cổ điển.
- Overfit small batch là kỹ thuật debug pipeline trước khi train production.
- Toolkit chống overfit chia 4 nhóm: more data, regularization, architectural, training tricks.
Các bài tiếp theo trong Module 3 sẽ đi vào từng công cụ cụ thể:
- B22 — Dropout: tắt ngẫu nhiên neuron khi train, kỹ thuật regularization đặc trưng DL.
- B23 — Batch Normalization: chuẩn hoá activation, ổn định gradient, có tác dụng regularize.
- B24 — Early Stopping: tự động dừng train ở sweet spot.
- B25 — Learning Rate Scheduling: giảm LR theo schedule, fine-tune ở cuối.
- B26 — Data Augmentation: tăng data effective qua biến đổi.
Bài kế tiếp: Bài 22 — Dropout — một dòng code, một paper Srivastava 2014, hiệu quả rõ ràng trên hầu hết kiến trúc.
- Zhang et al. (2017) - Understanding deep learning requires rethinking generalization
- Belkin et al. (2019) - Reconciling modern machine-learning practice and the classical bias-variance trade-off
- Nakkiran et al. (2019) - Deep Double Descent: Where Bigger Models and More Data Hurt
- Goodfellow, Bengio, Courville - Deep Learning Book Ch. 7 (Regularization for Deep Learning)
- CS231n - Neural Networks Part 3: Sanity Checks (overfit small batch)
- Andrej Karpathy - A Recipe for Training Neural Networks
- PyTorch Docs - torch.utils.tensorboard
- Neyshabur et al. (2014) - In Search of the Real Inductive Bias: On the Role of Implicit Regularization in Deep Learning
- Keskar et al. (2017) - On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima
