SPP-Net: Phá bỏ rào cản kích thước ảnh cố định trong mạng CNN
Bài viết phân tích chi tiết về SPP-Net, mô hình CNN tiên phong cho phép xử lý ảnh với mọi kích thước mà không cần crop hay warp, giúp cải thiện độ chính xác và giảm overfitting. Tác giả cũng hướng dẫn triển khai SPP-Net từ đầu bằng PyTorch, kèm theo kết quả thử nghiệm ấn tượng trên cả bài toán phân loại và phát hiện vật thể.

SPP-Net: Phá bỏ rào cản kích thước ảnh cố định trong mạng CNN
Trong lĩnh vực thị giác máy tính, các mô hình CNN truyền thống thường bị giới hạn bởi kích thước đầu vào cố định, buộc phải crop hoặc warp ảnh — dẫn đến mất mát thông tin và giảm độ chính xác. SPP-Net ra đời như một giải pháp đột phá, cho phép mạng CNN xử lý ảnh với mọi kích thước và tỷ lệ khung hình một cách linh hoạt.
Với cơ chế Spatial Pyramid Pooling (SPP), bài báo của He et al. (2014) không chỉ giải quyết bài toán kích thước ảnh mà còn giúp mô hình giảm overfitting đáng kể. Trên thực tế, SPP-Net đạt tốc độ nhanh gấp 38 lần so với R-CNN trong bài toán phát hiện vật thể mà vẫn giữ nguyên độ chính xác mAP 59.2% trên tập dữ liệu ImageNet.
Vì sao CNN truyền thống bị giới hạn kích thước đầu vào?
Các mô hình CNN cổ điển yêu cầu ảnh đầu vào có kích thước cố định vì lớp fully-connected (FC) ở cuối mạng. Lớp convolution có thể xử lý ảnh với mọi kích thước nhờ chia sẻ trọng số trên toàn bộ không gian ảnh — ví dụ, một kernel 3×3 chỉ cần 9 trọng số (hoặc 10 nếu tính bias) bất kể ảnh lớn hay nhỏ.
Ngược lại, lớp FC yêu cầu một số lượng trọng số tương ứng với từng phần tử trong tensor. Nếu ảnh có kích thước 10×10, mạng cần 100 trọng số sau khi flatten; nếu kích thước thay đổi, số trọng số cũng phải thay đổi theo — điều này khiến FC không thể xử lý ảnh với độ phân giải đa dạng.
Giải pháp từ SPP-Net
Kiến trúc SPP-Net so với CNN truyền thống
Ý tưởng cốt lõi của SPP-Net là đặt một lớp Spatial Pyramid Pooling giữa các lớp convolution và lớp fully-connected. Lớp này chia không gian tensor thành các lưới (grid) với nhiều kích thước khác nhau: 4×4, 2×2 và 1×1. Với mỗi lưới, ta thực hiện max pooling rồi flatten và nối tất cả lại thành một vector có chiều dài cố định.
Điểm quan trọng là số lượng grid luôn cố định bất kể kích thước ảnh đầu vào. Ví dụ, với cấu hình trên, vector đặc trưng luôn có chiều dài (4×4 + 2×2 + 1×1) × số kênh, dù ảnh là 8×8 hay 12×8.
Ưu điểm vượt trội của SPP-Net
1. Giảm overfitting hiệu quả
Cách SPP hoạt động giúp mô hình kháng overfitting tốt hơn so với CNN truyền thống. Lý do là flatten trực tiếp phá hủy cấu trúc không gian của feature map, buộc lớp FC học các đặc trưng phụ thuộc vị trí — điều này phá vỡ tính bất biến tịnh tiến của lớp convolution. Với SPP, chúng ta vẫn giữ được thông tin không gian chi tiết qua lưới nhỏ (4×4) và thông tin tổng quan qua lưới lớn (1×1).
2. Đa dạng kích thước huấn luyện
SPP-Net cho phép huấn luyện với ảnh có kích thước và tỷ lệ khung hình khác nhau. Các tác giả thậm chí còn chủ động thay đổi kích thước ảnh ngẫu nhiên trong khoảng 180×180 đến 224×224 sau mỗi epoch để mô hình học tốt hơn.
Quá trình xử lý trong lớp SPP
Kết quả thử nghiệm ấn tượng
Trên bài toán phân loại
Kết quả trên tập ImageNet 2012 cho thấy việc thêm SPP giúp giảm loss phân loại đáng kể, và giá trị này còn giảm thêm khi huấn luyện với nhiều tỷ lệ ảnh khác nhau. Điều này được quan sát nhất quán trên mọi mô hình backbone, chứng minh rằng lợi ích của SPP không phụ thuộc vào kiến trúc CNN cụ thể.
Trên bài toán phát hiện vật thể
Kết quả thử nghiệm trên bài toán phát hiện vật thể khiến SPP-Net trở nên nổi bật:
- Nhanh gấp 38 lần so với R-CNN trong khi giữ nguyên mAP 59.2%
- Có thể đạt tốc độ nhanh hơn 100 lần nếu chỉ dự đoán trên một tỷ lệ duy nhất, với sự hy sinh nhẹ về mAP
Điều này đến từ cách SPP-Net thông minh hơn: thay vì đưa từng vùng đề xuất qua toàn bộ CNN (như R-CNN với ~2000 bounding box), SPP-Net chỉ cần trích xuất đặc trưng một lần trên toàn bộ ảnh, sau đó dùng SPP và các lớp FC để phân loại các vùng đề xuất từ feature map sâu.
Triển khai SPP-Net từ đầu với PyTorch
1. Lớp SPP
class SPP(nn.Module):
def forward(self, x):
pooled_outputs = []
for grid in GRIDS:
pooled = F.adaptive_max_pool2d(x, output_size=(grid, grid))
pooled = torch.flatten(pooled, start_dim=1)
pooled_outputs.append(pooled)
return torch.cat(pooled_outputs, dim=1)
Lớp SPP này sử dụng adaptive pooling — chúng ta chỉ cần chỉ định kích thước đầu ra mong muốn và hàm sẽ tự động tính toán kernel size cùng stride phù hợp. Điều này giúp SPP hoạt động nhất quán trên mọi kích thước ảnh đầu vào.
2. Mô hình ZF-5 tích hợp SPP
class ZF5_SPPNet(nn.Module):
def __init__(self):
super().__init__()
# Các lớp convolution giống ZF-5
self.conv1 = nn.Conv2d(3, 96, kernel_size=7, stride=2, padding=0)
self.norm1 = nn.LocalResponseNorm(size=5)
self.pool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.conv2 = nn.Conv2d(96, 256, kernel_size=5, stride=2, padding=1)
self.norm2 = nn.LocalResponseNorm(size=5)
self.pool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=0)
self.conv3 = nn.Conv2d(256, 384, kernel_size=3, stride=1, padding=1)
self.conv4 = nn.Conv2d(384, 384, kernel_size=3, stride=1, padding=1)
self.conv5 = nn.Conv2d(384, 256, kernel_size=3, stride=1, padding=1)
# Lớp SPP
self.spp = SPP()
spp_out_size = 256 * sum([grid**2 for grid in GRIDS]) # 5376
# Các lớp FC
self.fc6 = nn.Linear(spp_out_size, 4096)
self.fc7 = nn.Linear(4096, 4096)
self.fc8 = nn.Linear(4096, 1000)
Khi truyền ảnh 224×224 qua mạng, ta có thể quan sát quá trình biến đổi: sau conv1 và pool1 tensor còn 55×55, sau conv2 và pool2 còn 13×13, rồi qua SPP tạo ra vector 5376 chiều trước khi vào các lớp FC.
Kết luận
SPP-Net đánh dấu một bước tiến quan trọng trong thiết kế kiến trúc CNN, mở đường cho các mô hình xử lý ảnh linh hoạt hơn. Kỹ thuật này sau đó đã ảnh hưởng đến nhiều kiến trúc hiện đại — ví dụ như việc tích hợp SPP vào các mô hình phát hiện vật thể như YOLO và Faster R-CNN.
Với các bạn quan tâm đến deep learning tại Việt Nam, việc hiểu và triển khai SPP-Net không chỉ giúp nắm vững kiến thức nền tảng mà còn có thể áp dụng trực tiếp vào các bài toán thực tế như phân loại ảnh y tế, nhận diện biển số xe hay giám sát giao thông — những bài toán mà kích thước ảnh đầu vào thường rất đa dạng.



