🎯 Mục tiêu bài học
Trong bài này, bạn sẽ học:
- ✅ Pooling Layer: Max Pooling, Average Pooling
- ✅ Kiến trúc CNN chuẩn: Conv → Pool → FC
- ✅ Feature Hierarchy: Từ low-level đến high-level features
- ✅ Flatten: Chuyển 2D → 1D cho classification
- ✅ Xây dựng CNN hoàn chỉnh với Keras
Pooling giúp CNN "nhìn" ảnh ở nhiều độ phân giải khác nhau và tập trung vào đặc trưng quan trọng nhất.
💧 Pooling là gì?
Định nghĩa
Pooling giống như việc "zoom out" bức ảnh - giảm kích thước nhưng giữ lại thông tin quan trọng nhất.
Pooling Layer thực hiện:
- Downsampling: Giảm kích thước spatial (H, W)
- Tổng hợp: Lấy đại diện cho mỗi vùng
- Giữ nguyên depth: Số channels không đổi
Tại sao cần Pooling?
| Lý do | Giải thích |
|---|---|
| Giảm tính toán | Ít pixels → ít params → nhanh hơn |
| Kiểm soát overfitting | Ít params → ít overfit |
| Translation Invariance | Đặc trưng dịch chuyển nhẹ → kết quả vẫn tương tự |
| Tăng receptive field | Neuron "nhìn" được vùng lớn hơn của ảnh gốc |
Checkpoint
Bạn hiểu tại sao cần Pooling?
📊 Max Pooling
Cách hoạt động
Max Pooling chọn giá trị lớn nhất trong mỗi window.
Max Pooling (2×2)
Đặc điểm
| Ưu điểm | Nhược điểm |
|---|---|
| Giữ được đặc trưng nổi bật | Mất vị trí chính xác |
| Robust với noise | Có thể mất thông tin quan trọng |
| Tính toán nhanh | Không có tham số học |
Code Keras
1from tensorflow.keras import layers23# Max Pooling 2×24layers.MaxPooling2D(5 pool_size=(2, 2), # Window size6 strides=(2, 2), # Thường = pool_size7 padding='valid' # 'valid' hoặc 'same'8)910# Ví dụ trong model11model = keras.Sequential([12 layers.Conv2D(32, (3, 3), activation='relu'),13 layers.MaxPooling2D((2, 2)), # Giảm size 1/214 layers.Conv2D(64, (3, 3), activation='relu'),15 layers.MaxPooling2D((2, 2)), # Giảm size 1/216])Checkpoint
Bạn đã hiểu Max Pooling?
📈 Average Pooling vs Global Average Pooling
Average Pooling
Average Pooling tính giá trị trung bình của window.
Average Pooling (2×2)
Global Average Pooling (GAP)
GAP = Average toàn bộ feature map → 1 số Rất hiệu quả để thay thế Fully Connected layer cuối!
Code Keras
1from tensorflow.keras import layers23# Average Pooling4layers.AveragePooling2D(pool_size=(2, 2))56# Global Average Pooling7layers.GlobalAveragePooling2D()89# So sánh 2 cách kết thúc CNN10# Cách 1: Flatten (cũ)11model_old = keras.Sequential([12 # ... conv layers ...13 layers.Flatten(), # 7×7×512 = 25,08814 layers.Dense(4096), # 100M params!15 layers.Dense(1000)16])1718# Cách 2: GAP (mới, tốt hơn)19model_new = keras.Sequential([20 # ... conv layers ...21 layers.GlobalAveragePooling2D(), # 51222 layers.Dense(1000) # 512K params23])So sánh các loại Pooling
| Loại | Ưu điểm | Khi nào dùng |
|---|---|---|
| Max Pooling | Giữ feature nổi bật | Giữa các conv layers |
| Average Pooling | Smooth hơn | Ít dùng |
| Global Average | Giảm params đáng kể | Trước Dense layer cuối |
Checkpoint
Bạn đã hiểu Average và Global Average Pooling?
🏗️ Kiến trúc CNN chuẩn
Cấu trúc tổng quan
Kiến trúc CNN chuẩn
Quy tắc thiết kế
| Quy tắc | Chi tiết |
|---|---|
| Spatial giảm dần | 224 → 112 → 56 → 28 → 14 → 7 |
| Channels tăng dần | 64 → 128 → 256 → 512 |
| Tổng pixels ≈ không đổi | 224×224×3 ≈ 7×7×512 |
| Conv block pattern | Conv → BatchNorm → ReLU → Pool |
"Sâu hơn, hẹp hơn" - Kích thước giảm nhưng số channels tăng, giữ tổng thông tin tương đối ổn định.
Checkpoint
Bạn đã nắm được kiến trúc CNN chuẩn?
🔬 Hierarchical Feature Learning
Từ Low-level đến High-level Features
Visualization
VGG16 Feature Visualization:
| Layer | Học được | Ví dụ |
|---|---|---|
| Conv1 | Gabor filters | Cạnh, gradient |
| Conv2-3 | Textures | Lông, vảy, nước |
| Conv4-5 | Parts | Mắt, bánh xe, cửa sổ |
| FC | Objects | Mèo, ô tô, nhà |
Receptive Field tăng dần
CNN học theo kiểu bottom-up: từ chi tiết nhỏ → ghép thành đặc trưng lớn → nhận ra object
Checkpoint
Bạn hiểu CNN học features theo thứ bậc như thế nào?
💻 Xây dựng CNN hoàn chỉnh
CNN cho MNIST (28×28×1)
1from tensorflow import keras2from tensorflow.keras import layers34def create_mnist_cnn():5 """CNN đơn giản cho MNIST"""6 model = keras.Sequential([7 # Input: 28×28×18 9 # Conv Block 110 layers.Conv2D(32, (3, 3), activation='relu', 11 input_shape=(28, 28, 1)),12 # Output: 26×26×3213 layers.MaxPooling2D((2, 2)),14 # Output: 13×13×3215 16 # Conv Block 217 layers.Conv2D(64, (3, 3), activation='relu'),18 # Output: 11×11×6419 layers.MaxPooling2D((2, 2)),20 # Output: 5×5×6421 22 # Conv Block 323 layers.Conv2D(64, (3, 3), activation='relu'),24 # Output: 3×3×6425 26 # Classification Head27 layers.Flatten(), # 3×3×64 = 57628 layers.Dense(64, activation='relu'),29 layers.Dropout(0.5),30 layers.Dense(10, activation='softmax')31 ])32 33 return model3435model = create_mnist_cnn()36model.summary()1Model: "sequential"2_________________________________________________________________3Layer (type) Output Shape Param # 4=================================================================5conv2d (Conv2D) (None, 26, 26, 32) 320 6_________________________________________________________________7max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0 8_________________________________________________________________9conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 10_________________________________________________________________11max_pooling2d_1 (MaxPooling) (None, 5, 5, 64) 0 12_________________________________________________________________13conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 14_________________________________________________________________15flatten (Flatten) (None, 576) 0 16_________________________________________________________________17dense (Dense) (None, 64) 36928 18_________________________________________________________________19dropout (Dropout) (None, 64) 0 20_________________________________________________________________21dense_1 (Dense) (None, 10) 650 22=================================================================23Total params: 93,32224Trainable params: 93,32225Non-trainable params: 026_________________________________________________________________CNN cho CIFAR-10 (32×32×3)
1def create_cifar_cnn():2 """CNN với Batch Normalization cho CIFAR-10"""3 model = keras.Sequential([4 # Input: 32×32×35 6 # Conv Block 17 layers.Conv2D(32, (3, 3), padding='same', 8 input_shape=(32, 32, 3)),9 layers.BatchNormalization(),10 layers.Activation('relu'),11 layers.Conv2D(32, (3, 3), padding='same'),12 layers.BatchNormalization(),13 layers.Activation('relu'),14 layers.MaxPooling2D((2, 2)),15 layers.Dropout(0.25),16 # Output: 16×16×3217 18 # Conv Block 219 layers.Conv2D(64, (3, 3), padding='same'),20 layers.BatchNormalization(),21 layers.Activation('relu'),22 layers.Conv2D(64, (3, 3), padding='same'),23 layers.BatchNormalization(),24 layers.Activation('relu'),25 layers.MaxPooling2D((2, 2)),26 layers.Dropout(0.25),27 # Output: 8×8×6428 29 # Conv Block 330 layers.Conv2D(128, (3, 3), padding='same'),31 layers.BatchNormalization(),32 layers.Activation('relu'),33 layers.MaxPooling2D((2, 2)),34 layers.Dropout(0.25),35 # Output: 4×4×12836 37 # Classification Head with GAP38 layers.GlobalAveragePooling2D(), # 12839 layers.Dense(256, activation='relu'),40 layers.Dropout(0.5),41 layers.Dense(10, activation='softmax')42 ])43 44 return model4546model = create_cifar_cnn()47model.compile(48 optimizer='adam',49 loss='sparse_categorical_crossentropy',50 metrics=['accuracy']51)Checkpoint
Bạn có thể xây dựng CNN hoàn chỉnh?
📐 Tính Output Size
Công thức tổng quát
Conv2D:
Pooling:
Ví dụ tính toán
1def calc_output_size(W, K, P=0, S=1):2 """3 Tính output size của conv/pool4 W: Input size5 K: Kernel size 6 P: Padding7 S: Stride8 """9 return (W - K + 2*P) // S + 11011# Ví dụ MNIST CNN12input_size = 281314# Conv1: 3×3, padding=015after_conv1 = calc_output_size(28, 3, 0, 1) # 261617# MaxPool1: 2×2, stride=218after_pool1 = calc_output_size(26, 2, 0, 2) # 131920# Conv2: 3×3, padding=021after_conv2 = calc_output_size(13, 3, 0, 1) # 112223# MaxPool2: 2×2, stride=224after_pool2 = calc_output_size(11, 2, 0, 2) # 52526# Conv3: 3×3, padding=027after_conv3 = calc_output_size(5, 3, 0, 1) # 32829print(f"28 → {after_conv1} → {after_pool1} → "30 f"{after_conv2} → {after_pool2} → {after_conv3}")128 → 26 → 13 → 11 → 5 → 3Padding='same' trick
Với padding='same' và stride=1:
- Output size = Input size
- Keras tự tính padding cần thiết
Kernel 3×3 → Padding = 1 Kernel 5×5 → Padding = 2
Checkpoint
Bạn có thể tính output size cho bất kỳ CNN nào?
🎯 Tổng kết Module 2.1-2.2
Kiến thức đã học
| Concept | Chi tiết |
|---|---|
| Pooling | Giảm spatial size, giữ features quan trọng |
| Max Pooling | Lấy max trong window - phổ biến nhất |
| Global Average Pooling | Average toàn bộ feature map - thay FC |
| CNN Architecture | Conv → Pool → Conv → Pool → FC |
| Feature Hierarchy | Low-level → Mid-level → High-level |
Best Practices
- Spatial giảm dần: 224 → 112 → 56 → 28 → 14 → 7
- Channels tăng dần: 32 → 64 → 128 → 256
- Kernel 3×3 phổ biến nhất (VGG chứng minh)
- Batch Normalization sau mỗi Conv
- Global Average Pooling thay vì Flatten+Dense
So sánh ANN vs CNN
| Aspect | ANN | CNN |
|---|---|---|
| Input | Vector 1D | Image 2D/3D |
| Connectivity | Fully connected | Local connected |
| Parameters | Rất nhiều | Ít hơn (sharing) |
| Spatial info | Mất | Giữ được |
| Translation | Không invariant | Invariant |
Bài tiếp theo
Chúng ta sẽ học về các Famous CNN Models:
- LeNet-5, AlexNet, VGGNet
- ResNet và Skip Connections
- Inception, DenseNet
🎉 Tuyệt vời! Bạn đã hiểu cách xây dựng CNN hoàn chỉnh!
