Batch normalization adalah layer yang menormalisasi aktivasi setiap kanal terhadap statistik batch saat itu, lalu menskalakannya kembali dengan parameter yang dipelajari. Topik ini menjelaskan masalah yang mendorong penemuannya, mekanika hitungannya beserta statistik berjalan untuk inference, dan perilaku yang berbeda antara mode pelatihan dan mode evaluasi. Setelah selesai, baris nn.BatchNorm2d pada resep CNN dapat dibaca lengkap dengan konsekuensinya.
Masalah yang diselesaikannya#
Pelatihan jaringan dalam menghadapi masalah bergerak yang halus. Perubahan bobot layer awal mengubah distribusi masukan yang diterima layer berikutnya, sehingga setiap layer belajar mengejar target yang terus bergerak selama pelatihan, dan efek ini memperparah sifat sensitif skala yang dibahas pada topik Inisialisasi. Batch normalization menyelesaikannya dari arah yang langsung, yaitu menormalisasi aktivasi setiap layer sehingga distribusi masukan antar layer dijaga tetap rapi, dan hasilnya adalah pelatihan yang lebih stabil serta toleran terhadap learning rate yang lebih besar.
Nama normalisasi batch berasal dari sumber statistiknya, yaitu rata-rata dan variansi yang dihitung dari batch saat itu. Pada citra, normalisasi dilakukan per kanal, sehingga seluruh posisi spasial dalam satu kanal berbagi statistik yang sama. Estimasi yang stabil menuntut batch yang cukup besar, dan batas praktisnya sering disebut sekitar delapan contoh minimum, karena batch dua atau empat membuat statistiknya terlalu bising untuk dipercaya.
Mekanika normalisasi dan parameter pelajarannya#
Untuk setiap kanal, layer menghitung rata-rata dan variansi atas batch, lalu menormalisasi dan menskalakan:
Pasangan dan dipelajari bersama bobot lain, dan keberadaannya penting, karena normalisasi tanpa koreksi memaksa setiap kanal ke distribusi yang persis sama dan menghapus kemampuan membedakan skala. Tanda adalah pembatas pembagian nol yang bernilai kecil, dan pasangan memberi jalan pulang bila identitas ternyata paling baik.
Kode berikut menerapkan BatchNorm2d pada batch kecil dan memeriksa statistik sebelum sesudahnya, sehingga efek normalisasi per kanal terlihat pada angka.
import torch
import torch.nn as nn
torch.manual_seed(0)
bn = nn.BatchNorm2d(2)
x = torch.randn(64, 2, 4, 4) * 3.0 + 5.0
y = bn(x)
for kanal in (0, 1):
print(f"kanal {kanal}: sebelum rata={x[:, kanal].mean():.3f} std={x[:, kanal].std():.3f}"
f" | sesudah rata={y[:, kanal].mean():.3f} std={y[:, kanal].std():.3f}")kanal 0: sebelum rata=5.098 std=3.111 | sesudah rata=-0.000 std=1.000
kanal 1: sebelum rata=4.981 std=3.004 | sesudah rata=-0.000 std=1.000Setelah normalisasi, kedua kanal bertemu pada rata-rata mendekati nol dan simpangan baku mendekati satu, meskipun masukannya berskala lima dan tiga. Skala aslinya tidak hilang selamanya, karena pasangan dan yang dipelajari dapat mengembalikan skala mana pun yang menguntungkan loss, dan kemampuan itu yang membedakan normalisasi dari pembuangan informasi.
Statistik berjalan dan dua mode yang berbeda#
Normalisasi yang bergantung pada batch menimbulkan pertanyaan pada inference, saat model dipakai satu contoh dan tidak ada batch untuk dihitung. Jawabannya adalah statistik berjalan (running statistics), yaitu rata-rata dan variansi yang dihitung ulang secara perlahan selama pelatihan dan disimpan sebagai bagian dari model. Pada mode pelatihan, statistik batch yang dipakai untuk menormalisasi, dan statistik berjalan diperbarui. Pada mode evaluasi, statistik berjalan yang dipakai, sehingga keluaran tidak lagi bergantung pada komposisi batch.
Pergantian mode diatur model.train() dan model.eval(), dan lupa memanggilnya adalah kesalahan klasik yang gejalanya licik, yaitu evaluasi yang baik di notebook dengan batch besar tetapi kacau saat diserving per contoh. Kode berikut memeriksa perilaku dua mode tersebut pada masukan yang sama.
import torch
import torch.nn as nn
torch.manual_seed(0)
bn = nn.BatchNorm1d(1)
bn.train()
for _ in range(50):
bn(torch.randn(32, 1) * 2.0 + 1.0)
bn.eval()
satu_contoh = torch.tensor([[3.0]])
print("mode eval, batch 1 :", round(bn(satu_contoh).item(), 4))
bn.train()
try:
print("mode train, batch 1 :", round(bn(satu_contoh).item(), 4))
except ValueError as pesan:
print("mode train, batch 1 :", pesan)mode eval, batch 1 : 0.9379
mode train, batch 1 : Expected more than 1 value per channel when training, got input size torch.Size([1, 1])Pada mode evaluasi, satu contoh bernilai 3 dinormalisasi terhadap statistik berjalan yang sudah mengenal distribusi masukan, dan keluarannya bernilai di sekitar satu karena 3 terletak kira-kira satu simpangan baku di atas rata-ratanya. Pada mode pelatihan, batch berisi satu contoh membuat variansi tidak terdefinisi, dan PyTorch menolaknya dengan ValueError yang pesannya eksplisit. Penolakan tersebut adalah versi ketat dari perhitungan yang rusak, dan pada batch yang berisi dua contoh nyaris identik, kerusakan yang sama akan berlalu diam-diam sebagai statistik yang tidak berarti.
Posisi dalam resep dan biayanya#
Penempatan yang lazim adalah sesudah konvolusi dan sebelum aktivasi, sehingga resep satu blok menjadi konvolusi, batch normalization, lalu ReLU, dan susunan ini muncul berulang pada topik Arsitektur klasik. Manfaatnya paling terasa pada jaringan yang dalam, karena setiap layer yang menormalkan masukannya membuat ketergantungan antar layer melemah. Biayanya juga jelas, yaitu ketergantungan pada ukuran batch dan dua tensor statistik per kanal yang harus dibawa ke serving, dan keduanya menjadi pertimbangan ketika batch kecil tidak terhindarkan, misalnya pada citra beresolusi tinggi.
Alternatif yang bekerja tanpa batch seperti layer normalization dipertemukan kembali pada modul Transformer, karena arsitektur tersebut memilihnya persis atas alasan ketergantungan batch ini.
Ringkasan#
- Batch normalization menormalkan aktivasi per kanal terhadap statistik batch, lalu menskalakannya kembali dengan dan yang dipelajari.
- Statistik berjalan dipelihara selama pelatihan sehingga mode evaluasi tidak bergantung pada batch, dan
model.eval()mengaktifkannya. - Mode yang salah menghasilkan gejala licik, dan kontras keluaran satu contoh pada dua mode memperlihatkannya secara langsung.
- Penempatan lazimnya adalah antara konvolusi dan aktivasi, dengan harga berupa ketergantungan ukuran batch.
Referensi#
- Batch Normalization: Accelerating Deep Network Training — arXiv — Makalah asli Ioffe dan Szegedy yang menurunkan metode dan eksperimennya.
- torch.nn.BatchNorm2d — PyTorch — Dokumentasi yang memuat statistik berjalan, momentum, dan beda mode pelatihan-evaluasi.
- Batch Normalization — Dive into Deep Learning — Bab yang menurunkan mekanika dan implementasinya dari nol.