Batch normalization

Penormalan aktivasi per batch untuk menstabilkan pelatihan jaringan yang dalam.

Daftar isi

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 μB \mu_B dan variansi σB2 \sigma_B^2 atas batch, lalu menormalisasi dan menskalakan:

x^=x−μBσB2+ϵ,y=γx^+β \hat{x} = \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}, \qquad y = \gamma \hat{x} + \beta

Pasangan γ \gamma dan β \beta 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 ϵ \epsilon adalah pembatas pembagian nol yang bernilai kecil, dan pasangan γ,β\gamma,\beta 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.

python Contoh: statistik kanal sebelum dan sesudah normalisasi
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}")
text Keluaran
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.000

Setelah 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 γ \gamma dan β \beta 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.

python Contoh: mode pelatihan dan evaluasi pada masukan 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)
text Keluaran
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 γ \gamma dan β \beta 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#