Mục lục
- Mục tiêu bài học
- Data Augmentation là gì
- Mục tiêu của DA
- Image augmentation phổ biến
- torchvision.transforms — API chuẩn
- CHỈ apply train — không cho val/test
- Train vs Test transforms
- Recipe CIFAR-10 và ImageNet
- Cutout, Mixup, CutMix
- AutoAugment, RandAugment, TrivialAugment
- Augmentation cho detection và segmentation
- Albumentations
- torchvision.transforms.v2
- Augmentation cho text
- Augmentation cho audio
- Test-Time Augmentation (TTA)
- Domain-specific — cẩn thận
- Trade-off và cách tune
- Code Python — pipeline CIFAR-10 và Mixup
- Bài tập
- Tổng kết Module 3
Mục tiêu bài học
Sau bài học, bạn sẽ:
- Hiểu DA là gì và vì sao nó vừa tăng effective dataset size vừa hoạt động như regularizer.
- Liệt kê các kỹ thuật image augmentation: geometric, color, noise, Cutout, Mixup, CutMix, AutoAugment, RandAugment, TrivialAugment.
- Viết được pipeline
transforms.Composeđúng chuẩn cho CIFAR-10 và ImageNet. - Hiểu vì sao chỉ apply augmentation cho train set, không cho val/test, và viết hai pipeline riêng biệt.
- Biết khi nào dùng
torchvision.transforms.v2hoặc Albumentations thay vì v1. - Hiểu công thức Mixup, CutMix và implement Mixup thủ công.
- Biết Test-Time Augmentation (TTA) cho prediction và trade-off compute.
- Cẩn thận với domain-specific: không flip OCR, không rotate X-ray.
Bài này nối tiếp các bài regularization trong Module 3: B22 — Dropout, B23 — BatchNorm, B24 — Early Stopping, B25 — LR Schedule. DA là công cụ regularize tác động lên data — bổ sung cho các kỹ thuật regularize tác động lên model.
Data Augmentation là gì
Data Augmentation (DA) là tạo sample huấn luyện mới bằng cách áp dụng các phép biến đổi bảo toàn nhãn lên sample có sẵn. Ví dụ:
- Ảnh: lật ngang một ảnh "mèo" vẫn là "mèo"; cắt một vùng ngẫu nhiên 32×32 từ ảnh padding 40×40 cũng vẫn là cùng class.
- Text: thay vài từ bằng synonym ("nhanh" → "mau") thường không đổi nhãn sentiment.
- Audio: dịch pitch một bán âm, thêm noise nhẹ — vẫn nhận diện được cùng từ.
Augmentation thường sinh on-the-fly trong DataLoader: mỗi epoch model thấy một version khác nhau của cùng sample. Không cần lưu hàng triệu file augmented xuống đĩa — chỉ apply transform trong __getitem__ của dataset.
Lưu ý: augmentation chỉ là một dạng synthetic data, không phải data thật. Nếu collect được data mới (cùng phân phối), giá trị thường cao hơn augment data cũ.
Mục tiêu của DA
- Tăng effective dataset size: với DA, model thấy nhiều version của một sample qua các epoch — như có dataset to hơn mà không phải collect data thật.
- Regularize: ép model học invariance với biến đổi (vd: ảnh "chó" lật ngang vẫn là chó). Model không thể "ghi nhớ" một ảnh cụ thể vì mỗi lần nó thấy ảnh đã biến đổi khác đi.
- Giảm overfit: hệ quả trực tiếp của hai điểm trên. Gap train/val co lại.
- Cân bằng class (đôi khi): augment mạnh hơn cho minority class trong dataset imbalanced.
Liên hệ với B21 — Overfitting: DA là một trong các "phòng tuyến" chống overfit, thường có ảnh hưởng mạnh nhất khi dataset nhỏ. Trên CIFAR-10, chỉ riêng RandomCrop(32, padding=4) + RandomHorizontalFlip có thể giảm test error 2–4% so với train không augmentation.
Image augmentation phổ biến
Các nhóm transform thường gặp cho ảnh:
- Geometric:
RandomHorizontalFlip,RandomVerticalFlip,RandomRotation,RandomAffine(translate, scale, shear),RandomResizedCrop,RandomCrop(kèm padding),RandomPerspective. - Color:
ColorJitter(brightness, contrast, saturation, hue),RandomGrayscale,RandomAdjustSharpness,RandomAutocontrast,RandomEqualize. - Noise / blur:
GaussianBlur,RandomInvert,RandomPosterize,RandomSolarize; Gaussian noise thường viết bằng custom transform. - Occlusion:
RandomErasing(Cutout),Mixup,CutMix. - Auto-policy:
AutoAugment,RandAugment,TrivialAugmentWide,AugMix— search hoặc cố định policy gồm chuỗi transform.
Một pipeline tối thiểu cho image classification thường gồm 2–4 transform random + Resize + ToTensor + Normalize. Đắt nhất thường là RandomResizedCrop trên ảnh lớn.
torchvision.transforms — API chuẩn
API chuẩn trong PyTorch cho image transform là torchvision.transforms. Pattern: Compose nhiều transform thành một pipeline, truyền vào Dataset.
from torchvision import transforms
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(brightness=0.2, contrast=0.2),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]),
])
Thứ tự thường gặp:
- Random transform hình học (crop, flip, rotate) — apply trên PIL Image.
- Random transform màu (ColorJitter) — vẫn trên PIL.
ToTensor()— chuyển PIL[0, 255]sang Tensor[0, 1]shape(C, H, W).Normalize(mean, std)— chuẩn hoá theo channel.mean/stdImageNet là default phổ biến nếu bạn dùng pretrained backbone.- (Tuỳ chọn)
RandomErasing— Cutout, apply trên Tensor sau ToTensor.
Một số transform yêu cầu input PIL (ColorJitter v1), một số yêu cầu Tensor (RandomErasing). Đặt sai thứ tự sẽ raise type error — kiểm tra docstring của từng transform.
CHỈ apply train — không cho val/test
Đây là quy tắc bắt buộc và lỗi phổ biến của người mới: apply random augmentation cho cả val/test.
Lý do:
- Val / test phải reflect distribution thực tế — tức distribution mà model sẽ gặp khi deploy. Nếu user gửi ảnh thường, đừng đo metric trên ảnh đã rotate ngẫu nhiên.
- Random transform tạo nhiễu cho metric. Mỗi lần chạy val, kết quả khác nhau (vì augment khác nhau) → không so sánh được epoch này với epoch kia.
- Model selection sai: dựa trên val_loss / val_acc bị nhiễu để chọn early-stopping checkpoint hoặc tune hyperparameter là không hợp lệ.
Val / test chỉ nên có các transform deterministic: Resize, CenterCrop, ToTensor, Normalize. Không random crop, không flip, không color jitter, không Mixup.
Ngoại lệ: Test-Time Augmentation (TTA, mục 16) cố tình augment ở inference để average prediction — đó là kỹ thuật riêng, áp dụng có chủ đích, không phải để đo metric.
Train vs Test transforms
Pattern chuẩn: hai pipeline tách biệt, mỗi pipeline cho một dataset.
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
train_transform = transforms.Compose([
transforms.Resize(256),
transforms.RandomCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(0.2, 0.2, 0.2),
transforms.ToTensor(),
transforms.Normalize(mean, std),
])
test_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean, std),
])
train_ds = datasets.ImageFolder("data/train", transform=train_transform)
val_ds = datasets.ImageFolder("data/val", transform=test_transform)
Lưu ý CenterCrop ở test thay vì RandomCrop — vẫn cắt về cùng size 224 như train (để input shape khớp với model) nhưng deterministic.
Một số code base xếp Resize đến size lớn hơn target rồi crop về target ở cả hai — đó là pattern phổ biến để giữ ratio và bù padding.
Recipe CIFAR-10 và ImageNet
CIFAR-10 (32×32, 10 class) — recipe ResNet kinh điển:
cifar_mean = (0.4914, 0.4822, 0.4465)
cifar_std = (0.2470, 0.2435, 0.2616)
train_transform = transforms.Compose([
transforms.RandomCrop(32, padding=4), # pad 4, crop 32
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(cifar_mean, cifar_std),
])
test_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(cifar_mean, cifar_std),
])
Đơn giản nhưng mạnh: bài luận ResNet (He et al. 2015) báo recipe này giảm test error ~1.5% so với không augment trên CIFAR-10.
ImageNet (224×224, 1000 class) — recipe modern:
imagenet_mean = [0.485, 0.456, 0.406]
imagenet_std = [0.229, 0.224, 0.225]
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(0.4, 0.4, 0.4),
transforms.ToTensor(),
transforms.Normalize(imagenet_mean, imagenet_std),
])
test_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(imagenet_mean, imagenet_std),
])
Recipe modern (ConvNeXt, Swin Transformer) thường bổ sung RandAugment, RandomErasing và Mixup/CutMix khi train từ đầu — augment mạnh tay hơn để bù cho model lớn.
Cutout, Mixup, CutMix
Cutout (DeVries & Taylor 2017, arXiv:1708.04552) — che ngẫu nhiên một vùng vuông của ảnh bằng giá trị cố định (0 hoặc mean). Trong torchvision gọi là RandomErasing:
transforms.RandomErasing(p=0.5, scale=(0.02, 0.33))
Mixup (Zhang et al. 2017, arXiv:1710.09412) — kết hợp tuyến tính hai ảnh và label:
\[ \tilde{x} = \lambda \, x_1 + (1 - \lambda) \, x_2 \]
\[ \tilde{y} = \lambda \, y_1 + (1 - \lambda) \, y_2 \]
Trong đó \( \lambda \sim \text{Beta}(\alpha, \alpha) \) với \( \alpha \) thường 0.2–1.0. Label phải ở dạng one-hot (hoặc dùng soft cross-entropy). Mixup ép model học decision boundary "trơn" giữa các class, cải thiện generalization và calibration.
CutMix (Yun et al. 2019, arXiv:1905.04899) — thay vì blend, cắt một patch chữ nhật của ảnh 2 và paste vào ảnh 1. Label trộn theo tỉ lệ diện tích:
def cutmix(x1, y1, x2, y2, alpha=1.0):
lam = float(torch.distributions.Beta(alpha, alpha).sample())
H, W = x1.shape[-2:]
cut_w = int(W * (1 - lam) ** 0.5)
cut_h = int(H * (1 - lam) ** 0.5)
cx, cy = torch.randint(W, (1,)).item(), torch.randint(H, (1,)).item()
x1_b = max(cx - cut_w // 2, 0); x2_b = min(cx + cut_w // 2, W)
y1_b = max(cy - cut_h // 2, 0); y2_b = min(cy + cut_h // 2, H)
x1[..., y1_b:y2_b, x1_b:x2_b] = x2[..., y1_b:y2_b, x1_b:x2_b]
lam = 1 - ((x2_b - x1_b) * (y2_b - y1_b) / (H * W))
y_mix = lam * y1 + (1 - lam) * y2
return x1, y_mix
So sánh: Cutout đơn giản nhất, Mixup mạnh nhất cho calibration, CutMix nhỉnh hơn cả hai trên ImageNet (theo paper gốc). Recipe modern thường mix cả ba.
AutoAugment, RandAugment, TrivialAugment
Thay vì chọn từng transform thủ công, các phương pháp auto policy chọn (hoặc search) chuỗi transform tự động.
- AutoAugment (Cubuk et al. 2018, arXiv:1805.09501): RL search policy gồm 25 sub-policy, mỗi sub-policy là 2 transform. PyTorch có sẵn policy cho ImageNet / CIFAR-10 / SVHN:
transforms.AutoAugment(policy=AutoAugmentPolicy.IMAGENET). - RandAugment (Cubuk et al. 2019, arXiv:1909.13719): bỏ search, chỉ còn 2 hyperparameter — \( N \) (số transform apply mỗi sample) và \( M \) (magnitude).
transforms.RandAugment(num_ops=2, magnitude=9). Dùng phổ biến trong ConvNeXt, ViT recipe. - TrivialAugmentWide (Müller & Hutter 2021, arXiv:2103.10158): còn đơn giản hơn — chọn ngẫu nhiên 1 transform và 1 magnitude mỗi sample, không hyperparameter.
transforms.TrivialAugmentWide(). Cạnh tranh hoặc nhỉnh RandAugment trên nhiều benchmark. - AugMix (Hendrycks et al. 2019, arXiv:1912.02781): augment + mix nhiều version → tăng robustness với corruption (ImageNet-C).
Khuyến nghị mặc định hiện nay: thử TrivialAugmentWide trước — không hyperparameter, kết quả thường tốt. Nếu muốn tune sâu hơn thì chuyển sang RandAugment.
Augmentation cho detection và segmentation
Image classification có một input (ảnh) và một label (class). Detection / segmentation có nhiều hơn:
- Object detection: ảnh + bounding box. Khi flip ảnh, bbox phải lật theo (\( x \to W - x \)). Khi rotate, bbox phải tính lại — thường giữ minimum-enclosing-box mới.
- Semantic / instance segmentation: ảnh + mask. Flip / crop / rotate phải áp đồng thời lên cả ảnh và mask với cùng tham số ngẫu nhiên.
- Keypoint detection: ảnh + toạ độ keypoint. Tương tự bbox — transform phải apply lên keypoint.
torchvision.transforms v1 chỉ nhận một input (ảnh) — không thể áp cùng transform lên ảnh + mask + bbox với cùng seed một cách an toàn. Hai giải pháp:
- torchvision.transforms.v2 (mục 13) — native support multi-target.
- Albumentations (mục 12) — library hàng đầu cho detection / segmentation.
Albumentations
Albumentations (Buslaev et al. 2020) là library augmentation cho computer vision, được dùng rộng rãi trong Kaggle competitions và codebase production.
Ưu điểm so với torchvision.transforms v1:
- Nhanh hơn — implement bằng OpenCV và NumPy thay vì PIL. Trên ảnh lớn (1024×1024), Albumentations thường nhanh 2–5×.
- Nhiều transform hơn — gồm các transform domain-specific (medical, satellite, document).
- Native multi-target — apply cùng transform cho image + mask + bboxes + keypoints với cùng tham số ngẫu nhiên.
import albumentations as A
from albumentations.pytorch import ToTensorV2
train_transform = A.Compose([
A.RandomResizedCrop(224, 224),
A.HorizontalFlip(p=0.5),
A.ColorJitter(0.2, 0.2, 0.2, p=0.5),
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
ToTensorV2(),
], bbox_params=A.BboxParams(format="pascal_voc", label_fields=["labels"]))
out = train_transform(image=img_np, bboxes=bboxes, labels=labels)
img_t, bboxes_aug, labels_aug = out["image"], out["bboxes"], out["labels"]
Trade-off: Albumentations dùng NumPy array (HWC, uint8) trong khi torchvision dùng PIL. Cần convert trong custom dataset.
torchvision.transforms.v2
Từ torchvision 0.15 (PyTorch 2.0+), namespace torchvision.transforms.v2 trở thành API khuyến nghị. Cải tiến chính:
- Tensor-native — thao tác trực tiếp trên Tensor (CPU hoặc GPU), không cần convert qua PIL. Nhanh hơn v1 thường 1.5–3×.
- Multi-target support — pass
(image, mask)hoặc(image, bboxes), transform apply nhất quán lên cả hai. - API tương thích — phần lớn tên transform giống v1, chỉ cần đổi import.
from torchvision.transforms import v2
train_transform = v2.Compose([
v2.RandomResizedCrop(224, antialias=True),
v2.RandomHorizontalFlip(),
v2.ColorJitter(0.2, 0.2, 0.2),
v2.ToDtype(torch.float32, scale=True),
v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
Cho project mới: dùng v2. Cho code cũ: v1 vẫn hoạt động, chưa cần migrate ngay nhưng nên lên kế hoạch.
Augmentation cho text
Text khó augment hơn ảnh vì biến đổi nhỏ cũng có thể đổi nghĩa. Một số kỹ thuật phổ biến (preview Series 4 — LLM & GenAI):
- EDA (Easy Data Augmentation) (Wei & Zou 2019, arXiv:1901.11196): synonym replacement, random insertion, random swap, random deletion. Đơn giản, hiệu quả cho classification dữ liệu nhỏ.
- Back-translation: dịch câu sang ngôn ngữ khác (vd: tiếng Pháp) rồi dịch ngược về tiếng gốc. Thường giữ nghĩa nhưng đổi cách diễn đạt. Đắt vì cần model dịch.
- Noisy translation / NMT augmentation: thêm noise vào input dịch máy để học model robust hơn.
- Token-level masking: như MLM của BERT — mask 15% token, model dự đoán. Đây là pretraining task chứ không thuần "augmentation".
- Paraphrase bằng LLM (modern): dùng LLM sinh paraphrase. Chất lượng cao nhưng tốn API call.
Library: nlpaug, TextAttack cho EDA và back-translation. HuggingFace datasets + transformer pipeline cho paraphrase.
Augmentation cho audio
Audio cho phép nhiều biến đổi bảo toàn nhãn:
- Time stretch: kéo dài / rút ngắn thời gian mà không đổi pitch.
- Pitch shift: dịch cao độ ±vài bán âm.
- Add noise: Gaussian noise, background noise (mưa, đám đông).
- Volume / gain: tăng / giảm âm lượng.
- SpecAugment (Park et al. 2019, arXiv:1904.08779): trên spectrogram — mask một dải tần số (frequency masking) hoặc một dải thời gian (time masking). Tương đương Cutout cho audio. Dùng phổ biến trong ASR (Wav2Vec, Whisper).
Library: torchaudio.transforms (PyTorch native), audiomentations (waveform), nlpaug.augmenter.audio.
Test-Time Augmentation (TTA)
Test-Time Augmentation là kỹ thuật cố ý augment ở inference: với mỗi sample, sinh \( K \) version (vd: ảnh gốc + flip + 4 crop), chạy model trên cả \( K \), average prediction.
def tta_predict(model, x, augs):
model.eval()
preds = []
with torch.no_grad():
for aug in augs:
x_aug = aug(x)
logits = model(x_aug)
preds.append(torch.softmax(logits, dim=-1))
return torch.stack(preds).mean(dim=0)
Hiệu quả:
- Tăng accuracy nhẹ — thường 0.3–1% trên image classification.
- Cải thiện calibration (probabilistic prediction "mượt" hơn).
- Tốn 5–10× compute ở inference. Không phù hợp cho real-time / API có SLA chặt.
TTA khác với augment train: ở train là để regularize, ở test là để ensemble nhiều "view" của cùng sample. Thường chỉ apply transform nhẹ (flip, multi-crop), không augment mạnh.
Domain-specific — cẩn thận
"Bảo toàn nhãn" phụ thuộc vào domain. Một số bẫy:
- OCR / chữ viết tay: KHÔNG
RandomHorizontalFliphayRandomVerticalFlip— chữ ngược không phải là cùng chữ. "b" lật ngang thành "d". - X-ray, CT, MRI: cẩn thận với rotate / flip — orientation có ý nghĩa lâm sàng (vd: phổi trái khác phổi phải). Thường chỉ rotate ±10°, không flip ngang.
- Document / receipt: rotate nhỏ OK (chụp nghiêng), flip không OK.
- Map / satellite: rotate / flip hai chiều thường OK — ảnh từ trên xuống không có "trên/dưới" cố định.
- Self-driving: flip ngang phải xử lý cẩn thận với lái xe bên phải / bên trái; rotate có thể phá ngữ cảnh đường.
- Sentiment text: "không tốt" → "tốt" sau random deletion là đổi nhãn — EDA cần kiểm soát kỹ.
Quy tắc: tự hỏi "Sample sau khi augment có còn cùng nhãn theo annotator người không?". Nếu không chắc, bỏ transform đó.
Trade-off và cách tune
- Quá mạnh: model thấy sample biến dạng đến mức không còn giống test distribution → train loss cao, val accuracy không cải thiện hoặc giảm.
- Quá nhẹ: ít hiệu quả regularize, gap train/val vẫn lớn.
- Vừa phải: train loss tăng nhẹ (model làm việc khó hơn), val loss giảm rõ.
Heuristic tune:
- Bắt đầu với recipe minimum:
RandomCrop+HorizontalFlip+Normalize. - Đo baseline.
- Thêm dần: ColorJitter → RandAugment → RandomErasing → Mixup. Mỗi bước đo val_acc.
- Nếu val_acc đi xuống, lùi lại.
- Model lớn / dataset nhỏ → augment mạnh hơn; model nhỏ / dataset lớn → augment nhẹ hơn.
Augment cũng làm train chậm hơn (CPU bottleneck nếu pipeline đắt). Đo throughput trước/sau augment, tăng num_workers và persistent_workers=True trong DataLoader để bù.
Code Python — pipeline CIFAR-10 và Mixup
Setup augmentation cho CIFAR-10 với two pipelines train/test:
import torch
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
cifar_mean = (0.4914, 0.4822, 0.4465)
cifar_std = (0.2470, 0.2435, 0.2616)
train_tf = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(cifar_mean, cifar_std),
transforms.RandomErasing(p=0.25),
])
test_tf = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(cifar_mean, cifar_std),
])
train_ds = datasets.CIFAR10("./data", train=True, download=True, transform=train_tf)
test_ds = datasets.CIFAR10("./data", train=False, download=True, transform=test_tf)
train_loader = DataLoader(train_ds, batch_size=128, shuffle=True, num_workers=2)
test_loader = DataLoader(test_ds, batch_size=256, shuffle=False, num_workers=2)
Expected behavior: với cùng CNN nhỏ (vd: 4-layer ConvNet), recipe trên giảm test error 2–4% so với train không augment, train_loss cuối cao hơn (vì task khó hơn) nhưng val_loss thấp hơn rõ.
Mixup thủ công — apply ở level batch trong training loop:
import torch.nn.functional as F
def mixup_batch(x, y, num_classes, alpha=0.2):
lam = float(torch.distributions.Beta(alpha, alpha).sample())
idx = torch.randperm(x.size(0), device=x.device)
x_mix = lam * x + (1 - lam) * x[idx]
y_oh = F.one_hot(y, num_classes).float()
y_mix = lam * y_oh + (1 - lam) * y_oh[idx]
return x_mix, y_mix
def soft_cross_entropy(logits, soft_targets):
log_probs = F.log_softmax(logits, dim=-1)
return -(soft_targets * log_probs).sum(dim=-1).mean()
for x, y in train_loader:
x, y = x.to(device), y.to(device)
x_m, y_m = mixup_batch(x, y, num_classes=10, alpha=0.2)
logits = model(x_m)
loss = soft_cross_entropy(logits, y_m)
optimizer.zero_grad(); loss.backward(); optimizer.step()
TTA preview — flip + crop ensemble cho inference:
def tta_eval(model, x):
model.eval()
views = [x, torch.flip(x, dims=[-1])] # original + horizontal flip
with torch.no_grad():
probs = [F.softmax(model(v), dim=-1) for v in views]
return torch.stack(probs).mean(dim=0)
TTA đơn giản (chỉ flip) thường tăng accuracy 0.2–0.5% trên CIFAR-10 với cost 2× compute. Crop-ensemble (5-crop hoặc 10-crop) thêm 0.3% nữa với cost 5–10×.
Bài tập
- Compose pipeline augmentation cho MNIST:
RandomRotation(±10°),RandomAffine(translate=(0.1, 0.1)),ToTensor,Normalize((0.1307,), (0.3081,)). Vì sao KHÔNGRandomHorizontalFlipcho MNIST? - Visualize: lấy 4 ảnh từ CIFAR-10, mỗi ảnh apply pipeline train 8 lần và plot grid 4×8. Quan sát sự đa dạng.
- Train CNN nhỏ (3 conv + 2 FC) trên CIFAR-10 trong 30 epoch. Hai run: (a) không augment, (b) có augment
RandomCrop(padding=4)+RandomHorizontalFlip. So sánh test accuracy. (preview B31 — train CNN trên CIFAR-10). - Thêm
RandomErasing(p=0.25)vào run (b) ở câu 3. Test accuracy thay đổi thế nào? - Implement
RandomErasingthủ công bằngtorchvision.transforms.Lambda: với xác suất 0.25, chọn vùng chữ nhật ngẫu nhiên trong ảnh và set về 0. Verify bằng visualize. - Implement Mixup theo code mục 19. Train CNN CIFAR-10 với và không Mixup. So sánh test accuracy và độ "tự tin" của model (mean max-prob trên test set).
- Demo lỗi: apply
train_tf(có random) cho val dataset. Chạy validation 3 lần trên cùng val set — val_acc có khác nhau giữa các lần không? Tại sao? - So sánh tốc độ: dùng
%timeitđo thời gian apply pipelineRandomResizedCrop(224) + Flip + ColorJitter + ToTensor + Normalizetrên 100 ảnh PIL 512×512 vớitorchvision.transformsv1 vs Albumentations vsv2(Tensor-native). - Implement TTA flip + 4 corner crop cho CIFAR-10. Compare với inference baseline (1 forward). Accuracy tăng bao nhiêu, latency tăng bao nhiêu?
Đáp án ngắn
- Không flip MNIST vì "6" lật ngang không còn là "6", "9" tương tự. Flip phá nhãn.
- Mỗi ảnh trong grid khác nhau về crop / flip — pipeline sinh ra random sample mỗi lần được gọi.
- Augment thường cải thiện ~2–4% test accuracy với CNN nhỏ trên CIFAR-10 sau 30 epoch.
- RandomErasing thường thêm 0.5–1% nữa, đặc biệt giảm overfit ở các epoch cuối.
- Verify bằng plot — vùng đen ngẫu nhiên xuất hiện trong ~25% ảnh.
- Mixup thường tăng test accuracy 0.5–1.5% và giảm overconfidence — mean max-prob giảm vì model học soft label.
- Val_acc thay đổi giữa các lần (do random crop / flip), không thể so sánh được. Đó là lý do val/test phải deterministic.
- Albumentations và
v2thường nhanh hơn v1 1.5–3× trên ảnh lớn;v2nhanh nhất nếu input là Tensor sẵn. - TTA flip + 4-crop thường tăng accuracy 0.5–1% với cost ~5× latency.
Tổng kết Module 3
Module 3 — Regularization & Optimization (6 bài) — kết thúc tại bài này. Bộ công cụ đã có:
- B21 — Overfitting trong DL: nhận diện gap train/val, các "phòng tuyến" tổng quát.
- B22 — Dropout: tắt ngẫu nhiên neuron khi train, scale ở eval.
- B23 — BatchNorm: normalize activation theo batch, ổn định gradient, cho phép LR lớn hơn.
- B24 — Early Stopping & Checkpoint: dừng train khi val không cải thiện, save best model.
- B25 — LR Schedule: giảm LR theo lịch (Step, Cosine, Plateau, Warmup, OneCycle).
- B26 — Data Augmentation (bài này): tăng effective data, ép invariance, regularize ở mức data.
Phối hợp thực tế trong một training script CNN CIFAR-10 hoặc fine-tuning trên dataset nhỏ:
- Dataset: train pipeline có DA (Crop, Flip, RandAugment, RandomErasing); val pipeline deterministic.
- Model: có Dropout giữa các FC layer, BatchNorm sau mỗi Conv.
- Optimizer: AdamW hoặc SGD-momentum, weight_decay 1e-4.
- Scheduler: CosineAnnealingLR hoặc OneCycleLR.
- Loop: Early Stopping với patience 10–20, save best checkpoint theo val_acc.
- (Tuỳ chọn) Mixup / CutMix ở batch level, TTA ở inference.
Đến đây, bạn đã có đủ tool để train một deep network trên dataset thực, kiểm soát overfit và đẩy accuracy. Module 4 (từ B27) chuyển sang kiến trúc cụ thể: CNN cho ảnh. Bài kế tiếp giải thích vì sao MLP không hiệu quả cho ảnh và CNN giải bài toán đó như thế nào.
- torchvision - Transforms (v1 và v2)
- torchvision - v2 API reference
- torchvision - RandomErasing
- torchvision - AutoAugment
- torchvision - RandAugment
- torchvision - TrivialAugmentWide
- Albumentations - Documentation
- DeVries & Taylor (2017) - Improved Regularization of CNNs with Cutout
- Zhang et al. (2017) - mixup: Beyond Empirical Risk Minimization
- Yun et al. (2019) - CutMix: Regularization Strategy to Train Strong Classifiers
- Cubuk et al. (2018) - AutoAugment: Learning Augmentation Strategies from Data
- Cubuk et al. (2019) - RandAugment: Practical automated data augmentation
- Müller & Hutter (2021) - TrivialAugment: Tuning-free Yet State-of-the-Art Data Augmentation
- Hendrycks et al. (2019) - AugMix: A Simple Data Processing Method to Improve Robustness and Uncertainty
- Wei & Zou (2019) - EDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasks
- Park et al. (2019) - SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition
