Kiến trúc mạng học sâu: từ nền tảng đến LLM·Chương 2 — CNN: học từ cấu trúc không gian

Chế độ xem

Từ residual ConvNet đến các backbone CNN hiện đại

Bài trước giải thích convolution như một phép toán: kernel nhỏ, chia sẻ trọng số, feature map. Bài này trả lời câu hỏi tiếp theo:

Khi đã có convolution, ta xếp chúng thành backbone như thế nào — và các ConvNet đang dùng hiện nay khác ResNet cổ điển ở điểm nào?

Một mạng ảnh không chỉ là “chồng thêm nhiều convolution”. Khi model lớn dần, kiến trúc phải giải quyết cùng lúc ba việc: huấn luyện ổn định, trộn thông tin không gian và kênh hiệu quả, kiểm soát chi phí tính toán trên phần cứng thật.

Mạch của bài:

ý tưởng còn sống từ lịch sử
  → khung ConvNet (ResNet)
  → ConvNeXt như ConvNet hiện đại hóa
  → các hướng mạnh 2022–2024
  → cách đọc và chọn backbone

Không cần học thuộc năm ra đời. Cũng không có một “CNN SOTA duy nhất”: kết quả phụ thuộc vào bài toán cụ thể, dữ liệu pretrain, độ phân giải, ngân sách tính toán và thậm chí ngày tiến hành so sánh.

Sau bài này, bạn cần làm được gì?

Ở mức cốt lõi, bạn cần:

  • phân biệt CNN (lớp mô hình) với ConvNet (backbone tích chập phân cấp) và ConvNeXt (một họ ConvNet cụ thể);
  • đọc được residual block y=F(x)+xy = F(x) + x và biết khi nào shortcut cần phép chiếu;
  • giải thích được depthwise / pointwise convolution dùng để giảm chi phí;
  • nêu được vài hướng ConvNet hiện đại: ConvNeXt / V2, kernel lớn, deformable, mobile.

Ở mức áp dụng, bạn nên:

  • đọc sơ đồ backbone lạ bằng stage, shape, downsample và kiểu kết nối;
  • chọn họ mô hình theo dữ liệu và thiết bị, không theo độ nổi tiếng;
  • không đánh đồng nhiều parameter với model luôn tốt hơn, cũng không đánh đồng ít FLOPs với latency thấp.

Lịch sử rút gọn: giữ ý tưởng, không giữ bảo tàng tên

Từ LeNet đến EfficientNet, phần lớn tên mô hình chỉ là cách đóng gói lại một số ý vẫn còn trong ConvNet hôm nay.

Ý tưởng còn dùngHọ gắn với mốc đóVấn đề được nhắm
Conv → giảm resolution → classifierLeNet-5Ghép convolution thành pipeline đầu–cuối
Scale dữ liệu + GPU + recipe (ReLU, dropout, aug)AlexNetCNN lớn chỉ mạnh khi đi cùng dữ liệu và huấn luyện
Xếp nhiều conv 3×3 đồng đềuVGGTăng độ sâu bằng block dễ đọc
Nhiều nhánh, nhiều receptive field; conv 1×1 làm bottleneckInceptionĐa quy mô trong một block, kiểm soát chi phí kênh
Skip connection, học residualResNetMạng rất sâu dễ tối ưu hơn mạng plain
Nối (concatenate) feature cũDenseNetTái sử dụng feature; khác ResNet vì nối chứ không cộng
Depthwise separable convolutionMobileNetTách lọc không gian và trộn kênh để giảm tính toán
Cân bằng depth, width, resolutionEfficientNetScale model có nguyên tắc hơn là “chỉ sâu hơn”

Ba câu rút ra từ cả bảng:

  1. Kiến trúc không thể tách khỏi dữ liệu, phần cứng và cách huấn luyện — cùng một network nhưng train với recipe khác sẽ cho kết quả khác.
  2. Mạng sâu hơn không tự động tốt hơn: mạng plain quá sâu có thể có training error còn cao hơn — đây là degradation problem trong paper ResNet, không phải overfitting (model chưa học tốt trên cả tập train).
  3. Chi phí lọc không gian và chi phí trộn kênh có thể tách riêng (depthwise rồi pointwise 1×1); ba trục depth / width / resolution nên được cân bằng khi tăng quy mô model.

Phần còn lại của bài đứng trên khung residual ConvNet, rồi mới tới các họ hiện đại.

ConvNet: CNN được xếp thành backbone phân cấp

Đây là lúc cần làm rõ ba thuật ngữ hay bị dùng lẫn lộn:

  • CNN (Convolutional Neural Network): tên lớp mô hình — mạng sử dụng convolution. Rất rộng, bao gồm mọi kiến trúc dùng phép tích chập.
  • ConvNet (Convolutional Network): trong các paper từ 2020 trở đi, thường chỉ cùng lớp đó nhưng nhấn mạnh cấu trúc backbone phân cấp gồm nhiều stage.
  • ConvNeXt: một họ ConvNet cụ thể, được Liu et al. (2022) hiện đại hóa từ ResNet. Không phải một hướng khác với ConvNet.

Nói “CNN cổ điển vs ConvNeXt” dễ hiểu nhầm là hai loại khác nhau. Đúng hơn:

ConvNeXt = ConvNet được hiện đại hóa từ ResNet bằng recipe và block design của thời Transformer.

Backbone ConvNet phân cấp thường có cấu trúc:

ảnh
 → stem (giảm resolution lần đầu, nhanh và gọn)
 → vài stage (cùng resolution trong mỗi stage, channel tăng khi xuống stage)
 → pooling / head (tổng hợp và phân loại)

Mẫu shape rất ổn định từ ResNet tới ConvNeXt:

resolution giảm dần: 224 → 112 → 56 → 28 → 14 → 7
channel tăng dần   :  64 →  64 → 128 → 256 → 512

Không gian nhỏ dần, số kênh lớn dần — trực quan có thể hiểu là: ở các stage sâu, model nhìn ít vùng không gian hơn nhưng mỗi vùng được mô tả bằng nhiều đặc trưng hơn. “Pure ConvNet” trong A ConvNet for the 2020s nghĩa là phép trộn không gian vẫn là convolution (kể cả depthwise), không phải self-attention — model vẫn có thể dùng LayerNorm, GELU, residual và lớp 1×1 như MLP.

ResNet: khung còn lại đến hôm nay

ResNet đưa vào kết nối tắt (skip connection). Residual block cơ bản:

y=F(x)+xy = F(x) + x
  • xx: input của block — đi thẳng qua đường tắt;
  • F(x)F(x): kết quả của vài convolution / activation trên nhánh chính;
  • xx và F(x)F(x) được cộng với nhau để tạo output yy.

Residual block với đường skip từ x tới phép cộng

Nguồn ảnh: LunarLullaby, Wikimedia Commons, CC BY-SA 4.0. Trang nguồn: https://commons.wikimedia.org/wiki/File:ResBlock.png

Tại sao cộng lại hiệu quả? Nếu ánh xạ mong muốn là H(x)H(x), block chỉ cần học phần hiệu chỉnh F(x)=H(x)−xF(x) = H(x) - x. Khi ánh xạ tốt gần với identity (đầu ra gần đầu vào), F(x)F(x) chỉ cần học các giá trị gần 0 — dễ hơn nhiều so với bắt cả chuỗi layer tái tạo lại identity từ đầu.

Đường skip cũng tạo ra đường ngắn để gradient truyền ngược — không vượt qua toàn bộ nhánh chính. Lưu ý: đường skip không “xóa hoàn toàn vanishing gradient”. Ý đúng hơn: nó làm việc tối ưu mạng rất sâu dễ hơn trong thực tế, không phải giải quyết triệt để về mặt lý thuyết.

Khi shape khác nhau, shortcut cần được điều chỉnh

F(x)+xF(x) + x yêu cầu hai tensor cùng shape. Nếu block thay đổi số channel hoặc giảm resolution, thì xx và F(x)F(x) sẽ không cùng shape. Khi đó, shortcut dùng phép chiếu (projection) — thường là convolution 1×1 với stride phù hợp — để đưa xx về đúng shape trước khi cộng.

Đọc ResNet-18 theo stage, không đếm từng layer

Kiến trúc ResNet-18

Nguồn ảnh: Zhang, Lipton, Li, Smola / Dive into Deep Learning; Wikimedia Commons, CC BY-SA 4.0. Trang nguồn: https://commons.wikimedia.org/wiki/File:Resnet-18_architecture.svg

Khi nhìn sơ đồ bất kỳ, tìm bốn thứ: input resolution, chỗ resolution giảm, chỗ channel tăng, và block lặp bao nhiêu lần. Đây vẫn là cách đọc ConvNeXt, InternImage hay MobileNetV4 — kiến trúc thay đổi nhưng pattern stage vẫn vậy.

Depthwise, pointwise và ba trục scale

Convolution 3×3 từ CinC_{\mathrm{in}} sang CoutC_{\mathrm{out}} có số weight 3×3×Cin×Cout3 \times 3 \times C_{\mathrm{in}} \times C_{\mathrm{out}} — tốn vì phải trộn cả không gian lẫn kênh trong một bước.

Depthwise separable convolution (MobileNet) tách hai việc đó ra:

  1. Depthwise 3×3: mỗi kênh có một kernel riêng, lọc không gian — chỉ 3×3×Cin3 \times 3 \times C_{\mathrm{in}} weight, không trộn kênh.
  2. Pointwise 1×1: nhìn toàn bộ kênh tại mỗi vị trí, trộn kênh để tạo CoutC_{\mathrm{out}} — Cin×CoutC_{\mathrm{in}} \times C_{\mathrm{out}} weight, không lọc không gian.

Tổng weight thường nhỏ hơn convolution chuẩn đáng kể. ConvNeXt dùng cùng tư duy tách này, nhưng dùng kernel depthwise lớn hơn (7×7) để mở rộng vùng tiếp nhận.

Khi muốn model lớn hơn, ba trục thường được điều chỉnh là độ sâu (depth — số layer), độ rộng (width — số channel) và độ phân giải (resolution — kích thước ảnh đầu vào). EfficientNet lập luận: kéo một trục tùy ý sẽ lãng phí; compound scaling tăng ba trục theo tỉ lệ cân bằng hơn. Điều cần nhớ là tư duy cân bằng ba trục, không phải hệ số ϕ\phi cụ thể trong paper.

ConvNeXt: hiện đại hóa ConvNet, không thay convolution bằng attention

Sau khi Vision Transformer (ViT) đạt kết quả ấn tượng, một câu hỏi phổ biến xuất hiện: CNN đã lỗi thời chưa? Paper ConvNeXt (2022) trả lời bằng thí nghiệm từng bước: lấy ResNet-50 làm điểm xuất phát, trước hết đổi recipe huấn luyện (AdamW, augmentation mạnh hơn, train lâu hơn, stochastic depth, …) rồi mới dần đổi kiến trúc cho gần với Swin Transformer, nhưng vẫn chỉ dùng convolution chuẩn để trộn không gian.

Các thay đổi kiến trúc đáng nhớ:

ResNet điển hìnhConvNeXtÝ nghĩa
Stem 7×7 stride 2 + max poolConv 4×4 stride 4 (patchify)Giảm resolution gọn, gần cách chia patch của ViT
Bottleneck co rồi giãnInverted bottleneck (giãn rồi co)Gần FFN của Transformer; trộn kênh bằng 1×1
Conv 3×3 chuẩnDepthwise 7×7Receptive field rộng hơn, tách không gian / kênh
BatchNorm, ReLULayerNorm, GELURecipe và block sát Transformer hơn
Tỷ lệ stage kiểu (3, 4, 6, 3)Nhiều compute hơn ở stage 3Macro giống hierarchical ViT

Hai bài học quan trọng hơn tên model:

  • Một phần lớn khoảng cách “CNN vs Transformer” từng đo được là do recipe huấn luyện và cách thiết kế macro, không phải chỉ do cơ chế attention.
  • Khi làm dự án, hãy so sánh model cụ thể, kích thước, dữ liệu pretraining và ngân sách tính toán — đừng so hai nhãn “CNN” với “ViT” như thể mỗi nhãn là một thứ đồng nhất.

Các hướng ConvNet mạnh gần đây

Không xếp hạng “ai SOTA nhất”. Bảng dưới là bản đồ đại diện 2021–2024: mỗi họ giải một nút khác nhau. Số ImageNet trên internet thường không cùng protocol (1K vs 22K, 224 vs 384, distillation, …).

HọNămÝ tưởng cần nhớKhi nào nghĩ tới
ConvNeXt2022Hiện đại hóa ResNet; depthwise 7×7; recipe TransformerBaseline ConvNet hiện đại, dễ lấy pretrained
ConvNeXt V22023Co-design kiến trúc với FCMAE (masked autoencoder thuần conv) và GRN (chuẩn hóa đáp ứng toàn cục theo kênh)Cần representation mạnh từ self-supervised, nhiều cỡ model
InceptionNeXt2024Tách depthwise kernel lớn thành nhánh Inception để tăng throughput GPUConvNeXt đúng accuracy nhưng chậm hơn FLOPs gợi ý
InternImage2023DCNv3: convolution biến dạng, sampling thích nghiDetection / segmentation, foundation-scale CNN
UniRepLKNet2024Kernel depthwise rất lớn (thường 13×13) + re-parameterizationReceptive field rộng, không dùng attention
EfficientNetV22021NAS và scale kèm tốc độ train; Fused-MBConvCần train/finetune nhanh, hiệu quả tham số
MobileNetV42024UIB thống nhất inverted bottleneck / ConvNeXt-like / ExtraDW; có bản Conv và Hybrid (thêm Mobile MQA)Latency trên điện thoại / NPU; đo trên thiết bị thật

Ba hướng sau ConvNeXt, gói trong một câu:

V2: pretraining × kiến trúc
InternImage: lưới sampling không còn cố định
UniRepLKNet / InceptionNeXt: nhìn rộng bằng kernel lớn, có hoặc không tách nhánh cho tốc độ

MobileNetV4 nhắc một điểm dễ quên: họ “hiện đại” không chỉ là model ImageNet lớn. Trên mobile, “tốt nhất” không phải một số accuracy cao nhất — mà là đường biên Pareto accuracy–latency trên từng loại chip (tập hợp các model không có model nào vừa nhanh hơn vừa chính xác hơn cùng lúc). Bản Hybrid có thể không chạy được trên mọi DSP; số 87% ImageNet trong paper gắn với recipe distillation và dữ liệu bổ sung — không phải so sánh kiến trúc thuần túy.

Một cách đọc backbone chưa từng gặp

Bước 1: input và output

Input: 3×224×224
Output: 1000 logits

Bước 2: các stage

Nhóm block cùng resolution và channel.

Stage 1: 64 channel, 56×56
Stage 2: 128 channel, 28×28
Stage 3: 256 channel, 14×14
Stage 4: 512 channel, 7×7

Bước 3: điểm downsample

Pooling, convolution stride 2, hoặc stem patchify.

Bước 4: kiểu kết nối và phép trộn không gian

  • residual cộng;
  • concatenate (DenseNet-style);
  • multi-branch;
  • mixer: conv chuẩn, depthwise, deformable, kernel lớn, hoặc (ở hybrid) attention.

Bước 5: block lặp

Biết block và số lần lặp thì đã hiểu phần lớn architecture.

Chọn backbone theo bài toán và phần cứng

Tình huốngHướng bắt đầu hợp lý
Học đọc kiến trúc lần đầuResNet-18 / ResNet-50: skip và stage rõ
Baseline ảnh, GPU trung bình, pretrained sẵnConvNeXt-Tiny / Small, hoặc ConvNeXt V2 cỡ tương ứng
Dataset nhỏPretrained backbone rồi fine-tune; đừng train from scratch một họ SOTA
Điện thoại, web, edgeMobileNetV4 Conv hoặc EfficientNetV2; đo latency trên máy thật
Detection / segmentation, cần sampling linh hoạtInternImage hoặc ConvNeXt đã có config trong thư viện detection
Muốn RF rộng, vẫn thuần convUniRepLKNet hoặc ConvNeXt; cân nhắc InceptionNeXt nếu GPU throughput kém

Tên model chỉ là điểm bắt đầu. Cùng backbone nhưng khác preprocessing, resolution hoặc weight pretrained có thể cho kết quả lệch nhau đáng kể. Thư viện như timm cho phép nạp convnext_tiny, efficientnetv2_*, mobilenetv4_conv_* kèm pretrained weight chỉ với một dòng — bài thực hành tiếp theo sẽ dùng chúng trong pipeline, không cần cài đặt lại từ phương trình.

Accuracy, parameter và FLOPs không nói cùng một chuyện

Ba con số thường xuất hiện trong paper nhưng đo những thứ khác nhau:

Chỉ sốĐo gìHạn chế
ParameterSố weight cần lưu vào bộ nhớKhông nói gì về tốc độ chạy
FLOPs / MACsLượng phép tính nhân-cộng mỗi forward pass (ở một resolution cố định)Không phản ánh latency thực tế
LatencyThời gian chạy thật trên phần cứng và runtime cụ thểThay đổi theo chip, batch, precision, compiler

Ít FLOPs hơn chưa chắc nhanh hơn trên thiết bị thật. Depthwise kernel lớn có thể nhẹ về số nhân nhưng nặng về truy cập bộ nhớ — InceptionNeXt ra đời đúng vì lý do này. Batch size, precision (fp16/int8), cách implement kernel và compiler đều có thể đảo thứ hạng mô hình.

Khi triển khai thực tế: benchmark trực tiếp trên môi trường mục tiêu, không chỉ dựa vào FLOPs trong paper.

Một bài tập chuyển giao

Cho backbone giả định:

Input 3×224×224
Stem: Conv 7×7, stride 2 → 64×112×112
Pool 3×3, stride 2       → 64×56×56
Stage A: residual block ×2
Stage B: residual block ×2, block đầu stride 2 → 128×28×28
Stage C: residual block ×2, block đầu stride 2 → 256×14×14
Stage D: residual block ×2, block đầu stride 2 → 512×7×7
Global average pooling
Linear → 5 classes

Hãy trả lời:

  1. Có bao nhiêu lần resolution giảm?
  2. Vì sao block đầu mỗi stage mới thường không dùng identity shortcut thuần?
  3. Vì sao số channel thường tăng khi resolution giảm?
  4. Nếu đổi conv 3×3 chuẩn trong block thành depthwise 7×7 rồi pointwise 1×1, bạn đang đi gần họ nào hơn — ResNet gốc hay ConvNeXt?
  5. Global average pooling nhận 512×7×7 và trả ra shape gì cho một sample?
  6. Nếu model này đúng accuracy trên GPU nhưng chậm hơn một InceptionNeXt cùng FLOPs, bạn sẽ đo thêm chỉ số nào trước khi kết luận “nặng hơn”?

Nếu chỉ nhớ 10 ý

  • CNN là lớp mô hình; ConvNet là backbone tích chập phân cấp; ConvNeXt là một họ ConvNet hiện đại hóa từ ResNet.
  • Lịch sử CNN đáng nhớ ở mức ý tưởng: pipeline, recipe, 3×3, đa quy mô, residual, tách DW/PW, scale ba trục.
  • Mạng sâu hơn có thể khó tối ưu; degradation khác overfitting.
  • Residual: y=F(x)+xy = F(x) + x; đổi shape thì shortcut cần projection.
  • Đọc backbone theo stage, shape, downsample và mixer không gian.
  • Depthwise lọc từng kênh; pointwise 1×1 trộn kênh.
  • ConvNeXt giữ convolution, đổi recipe + stem + inverted bottleneck + DW 7×7 + LN/GELU.
  • Sau ConvNeXt: V2 (FCMAE + GRN), InternImage (DCNv3), kernel lớn (UniRepLKNet / InceptionNeXt), mobile (MobileNetV4).
  • Không có CNN SOTA phổ quát; so trong cùng protocol.
  • Parameter, FLOPs và latency là ba thước khác nhau.

Câu hỏi tự kiểm tra

  1. CNN, ConvNet và ConvNeXt khác nhau như thế nào trong cách dùng thuật ngữ của bài này?
  2. Degradation problem khác overfitting ở điểm nào?
  3. Viết công thức residual block cơ bản. Khi nào shortcut cần projection?
  4. Depthwise và pointwise chia nhiệm vụ thế nào? ConvNeXt dùng chúng ra sao so với MobileNet gốc?
  5. Vì sao paper ConvNeXt đổi recipe ResNet trước khi đổi kiến trúc?
  6. ConvNeXt V2 thêm gì ngoài việc “stack thêm layer”?
  7. InternImage và UniRepLKNet mở receptive field theo hai cách khác nhau như thế nào?
  8. InceptionNeXt giải quyết khe hở nào giữa FLOPs và tốc độ GPU?
  9. Ít parameter có đồng nghĩa latency luôn thấp hơn không?
  10. Khi nhìn architecture lạ, bốn thông tin nào nên tìm trước?

Mạch nối sang bài thực hành

Biết tên họ ConvNet chưa đủ để có hệ thống ảnh đáng tin cậy. Một ConvNeXt pretrained vẫn có thể cho kết quả tệ nếu:

  • chia train/test sai (ảnh gần trùng nằm cả hai split);
  • augmentation làm đổi nhãn mà không hay;
  • preprocessing không khớp pretrained weights;
  • label mapping lỗi giữa lúc train và lúc inference;
  • xem test set nhiều lần rồi chọn model dựa vào test — không còn là đánh giá độc lập.

Bài tiếp theo chuyển từ đọc architecture sang dùng CNN đúng trong một pipeline thực: dữ liệu, pretrained backbone, đánh giá và cách debug khi có lỗi.

Tài liệu tham khảo và đọc thêm