Đi hết một kiến trúc CNN
Đi hết một kiến trúc CNN
Từ ảnh vào tới lớp phân loại, mỗi lớp một dòng. Hai cột tham số và phép tính kể hai câu chuyện ngược nhau.
Bạn đã biết một phép tích chập làm gì với một cửa sổ nhỏ, biết lớp gộp thu bản đồ lại thế nào, và biết kết nối tắt cứu gradient ra sao. Bài này ghép tất cả lại: xếp chúng thành một mạng thật, cho ảnh chạy từ đầu tới cuối, rồi lập hoá đơn.
Hoá đơn ấy có ba con số cho mỗi lớp: kích thước ra H × W × C, số tham số phải học, và số phép nhân cộng phải làm. Hầu hết người mới học chỉ nhớ cột giữa, và đó là lý do họ đoán sai chỗ mạng tốn tiền.
Thử ngay
| # | Lớp | Ra (H × W × C) | Tham số | % tham số | Nhân cộng | % nhân cộng | Kích hoạt |
|---|---|---|---|---|---|---|---|
| 0 | ảnh vào | 28 × 28 × 1 | 0 | 0,0% | 0 | 0,0% | 784 |
| 1 | tích chập 5×5, bước 1, đệm 2, ra 6 kênh | 28 × 28 × 6 | 156 | 0,3% | 117.600 | 28,2% | 4.704 |
| 2 | gộp cực đại 2×2, bước 2 | 14 × 14 × 6 | 0 | 0,0% | 0 | 0,0% | 1.176 |
| 3 | tích chập 5×5, bước 1, đệm 0, ra 16 kênh | 10 × 10 × 16 | 2.416 | 3,9% | 240.000 | 57,6% | 1.600 |
| 4 | gộp cực đại 2×2, bước 2 | 5 × 5 × 16 | 0 | 0,0% | 0 | 0,0% | 400 |
| 5 | kết nối đầy đủ, ra 120 | 1 × 1 × 120 | 48.120 | 78,0% | 48.000 | 11,5% | 120 |
| 6 | kết nối đầy đủ, ra 84 | 1 × 1 × 84 | 10.164 | 16,5% | 10.080 | 2,4% | 84 |
| 7 | kết nối đầy đủ, ra 10 | 1 × 1 × 10 | 850 | 1,4% | 840 | 0,2% | 10 |
| Cộng dồn cả mạng | 61.706 | 61,7 k | 416.520 | 416,5 k | 8.878 | ||
Tham số ở cuối, phép tính ở đầu
Ở trạng thái mặc định, mạng nhỏ kiểu LeNet có 61.706 tham số và 416.520 phép nhân cộng. Chia hai con số đó cho hai nhóm lớp:
- Hai lớp tích chập giữ
2.572tham số, tức 4,2%, nhưng làm357.600phép nhân cộng, tức 85,9%. - Ba lớp kết nối đầy đủ giữ
59.134tham số, tức 95,8%, nhưng chỉ làm58.920phép nhân cộng, tức 14,1%.
Hai thanh phần trăm trong sim vẽ đúng hai phân bố ngược nhau đó. Lý do nằm ở chỗ tái dùng trọng số. Lớp tích chập đầu tiên chỉ có 6 × 1 × 5 × 5 + 6 = 156 tham số, nhưng nó trượt bộ nhân đó qua 28 × 28 vị trí và 6 kênh, nên phải làm 117.600 phép nhân cộng. Lớp kết nối đầy đủ thì ngược hẳn: nó có 400 × 120 + 120 = 48.120 tham số và làm đúng 48.000 phép nhân cộng, tức mỗi trọng số dùng đúng một lần. Một bộ nhân dùng lại hàng nghìn lần thì rẻ về bộ nhớ và đắt về tính toán; một ma trận dày dùng một lần thì ngược lại.
Hãy tự kiểm: kéo cao ảnh vào và rộng ảnh vào từ 28 lên 56. Số tham số của hai lớp tích chập không nhúc nhích, còn số phép nhân cộng của chúng vọt lên. Kích thước ảnh không mua thêm trọng số cho lớp tích chập, nó chỉ mua thêm việc.
Bộ nhớ kích hoạt thường lớn hơn bộ nhớ trọng số
Khi huấn luyện, mạng phải giữ đầu ra của mọi lớp cho tới lúc lan truyền ngược đi qua, vì gradient của một lớp cần biết lớp đó đã xuất ra cái gì. Chỗ nhớ ấy gọi là bộ nhớ kích hoạt, và nó nhân lên theo cỡ lô, trong khi trọng số thì không.
Ở cấu hình mặc định, cỡ lô 32, mỗi số 4 byte:
- Trọng số:
61.706 × 4 = 246.824byte, tức241,0 KiB. Con số này không đổi dù bạn huấn luyện với lô1hay lô512. - Kích hoạt:
8.878 × 32 × 4 = 1.136.384byte, tức1,1 MiB, gấp460,4%bộ nhớ trọng số.
Kéo cỡ lô xuống rồi xem ô phần trăm. Ở lô 6 nó là 86,3%, trọng số vẫn nặng hơn. Ở lô 7 nó thành 100,7%, kích hoạt đã vượt. Nói cách khác, chỉ cần bảy ảnh một lượt là cái mạng bé xíu này đã tốn bộ nhớ cho kích hoạt nhiều hơn cho chính nó. Bấm kiến trúc mẫu Khối kiểu ResNet có kết nối tắt để thấy trường hợp gắt hơn hẳn: 3,5 MiB trọng số so với 144,4 MiB kích hoạt, tỉ lệ 4069,9%, vì mỗi khối tắt giữ tới bảy tensor trung gian thay vì một.
Đây chính là lý do nhiều người thuộc lòng số tham số của mô hình rồi vẫn hết VRAM: họ tính nhầm cột.
Chỗ tham số bùng nổ, và cách giết nó
Nhìn dòng lớp kết nối đầy đủ đầu tiên. Nó nhận cả bản đồ 5 × 5 × 16 duỗi thẳng thành 400 số, nên riêng nó đã ăn 48.120 trong tổng 61.706 tham số. Trên kiến trúc mẫu kiểu VGG chỗ này còn dữ hơn: bản đồ 4 × 4 × 256 duỗi ra thành 4.096 số, và lớp đầy đủ đầu tiên một mình chiếm 2.097.664 tham số, tức 64,6% cả mạng, trong khi chỉ làm 1,4% khối lượng tính toán.
Bật công tắc Gộp trung bình toàn cục trên thanh công cụ. Sim chèn một lớp gộp ngay trước lớp đầy đủ đầu tiên, lớp đó lấy trung bình mỗi kênh trên toàn bộ bản đồ nên đưa H × W × C về đúng 1 × 1 × C với 0 tham số. Trên mạng LeNet, lớp đầy đủ đầu tiên chỉ còn nhận 16 số thay vì 400, nên nó tụt từ 48.120 xuống 2.040, và tổng tham số sụp từ 61.706 xuống 15.626. Phần hụt đúng bằng (400 - 16) × 120 = 46.080. Trên mạng kiểu VGG, phần hụt là (4.096 - 256) × 512 = 1.966.080, tức cắt 60,5% tham số mà chỉ mất 1,3% khối lượng tính toán.
Đó là lý do gần như mọi kiến trúc hiện đại đều bỏ phần đầu đầy đủ khổng lồ và gộp toàn cục trước khi phân loại.
Khi hai nhánh không khớp
Chọn kiến trúc mẫu Khối kiểu ResNet, rồi tìm khối tắt có bước 2. Tắt ô nhánh tắt chiếu 1×1 của nó. Bảng đứt ngay và báo: nhánh chính ra 16×16×128 còn nhánh tắt vẫn là 32×32×64, không cộng được.
Đây là lỗi thật, không phải tình huống dựng lên. Kết nối tắt cộng đầu vào thẳng vào đầu ra, nên hai bên phải cùng cả kích thước không gian lẫn số kênh. Khi khối hạ kích thước bằng bước 2, hoặc khi nó đổi số kênh, đường tắt đồng nhất hết dùng được, và cách chữa tiêu chuẩn là cho nhánh tắt một phép chiếu 1×1 chạy cùng bước. Bật lại ô đó và xem khối tốn thêm đúng 8.576 tham số cho phép chiếu ấy.
Trong một mạng tích chập, tham số dồn về các lớp kết nối đầy đủ ở cuối còn phép nhân cộng dồn về các lớp tích chập ở đầu, nên đếm tham số không cho biết mạng chạy nhanh hay chậm. Bộ nhớ lúc huấn luyện lại do kích hoạt quyết định chứ không do trọng số, vì nó nhân theo cỡ lô. Gộp trung bình toàn cục cắt phần lớn tham số ở chỗ chuyển sang lớp đầy đủ mà gần như không đụng tới khối lượng tính toán.
Sim này đếm gì và không biết gì
Sim đếm đúng kích thước, số tham số, số phép nhân cộng và số phần tử kích hoạt theo cấu hình bạn đặt. Nó không huấn luyện gì cả, nên nó không nói được kiến trúc nào chính xác hơn kiến trúc nào. Một mạng có ít tham số hơn không vì thế mà tốt hơn, và ngược lại.
Con số bộ nhớ là chặn dưới, không phải mức thật. Nó bỏ qua trạng thái của optimizer, thường gấp hai tới ba lần bộ nhớ trọng số với Adam, bỏ qua vùng nhớ cho gradient, bỏ qua phân mảnh của bộ cấp phát và vùng đệm của thư viện. Nó cũng đếm đúng một tensor cho mỗi dòng bảng, trừ khối tắt vốn được kê riêng số tensor giữ bên trong; framework thật có thể ghi đè tại chỗ nên giữ ít hơn, hoặc giữ nhiều hơn vì các bản sao trung gian.
Vài quy ước kế toán ở đây là lựa chọn chứ không phải chân lý, và sách khác có thể chọn khác: mọi lớp tích chập đều có bias (nhiều mạng bỏ bias khi ngay sau là chuẩn hoá theo lô), chuẩn hoá theo lô tính 2 × C tham số học được và không tính hai bộ đệm chạy, gộp cực đại và ReLU chỉ so sánh nên ghi 0 phép nhân cộng, còn gộp trung bình có nhân nên được tính. Ba kiến trúc mẫu là minh hoạ, số kênh và độ sâu đã rút xuống cho tính tay được; chúng mượn dáng của LeNet, VGG và ResNet chứ không phải bản sao của bất kỳ mạng đã công bố nào.
- 1Ở cấu hình mặc định, nhóm lớp nào giữ phần lớn tham số và nhóm nào làm phần lớn phép nhân cộng?
- 2Bật gộp trung bình toàn cục trên mạng mẫu LeNet, tổng tham số tụt từ 61.706 xuống 15.626. Phần hụt đó đến từ đâu?
- 3Ở cỡ lô 32, kích hoạt tốn 1,1 MiB còn trọng số tốn 241,0 KiB. Thay đổi nào đưa trọng số trở lại vị trí nặng hơn?