Weight decay adalah regularisasi yang menghukum besar nilai bobot dengan menambahkan suku penalti pada loss, dan dalam bentuk paling umum ia diimplementasikan langsung di dalam optimizer sebagai parameter weight_decay. Topik ini menurunkan hubungannya dengan penalti L2, menunjukkan cara PyTorch menghitungnya, dan menetapkan batas tempat ia diterapkan. Setelah selesai, baris weight_decay=1e-4 pada optimizer terbaca sebagai keputusan yang sadar, bukan konstanta yang disalin.
Penalti L2 dan efeknya pada pembaruan#
Penalti L2 mendefinisikan loss baru sebagai loss asli ditambah suku yang sebanding dengan jumlah kuadrat bobot:
Gradien suku tambahannya adalah , sehingga setiap pembaruan gradient descent memuat suku . Bagian pertama mengalikan seluruh bobot dengan faktor yang sedikit di bawah satu pada setiap langkah, dan itulah asal nama decay, yaitu bobot menyusut perlahan menuju nol kecuali ditarik balik oleh gradien data. Bobot yang tidak berguna bagi loss akan terus menyusut karena gradiennya nyaris nol, sehingga solusi yang dihasilkan cenderung menggunakan lebih sedikit bobot besar.
Penafsiran statistiknya juga bernilai. Bobot yang besar membuat prediksi sensitif terhadap perubahan kecil masukan, dan menyusutkannya menurunkan kepekaan itu, sehingga model cenderung lebih tahan terhadap bising. Perspektif Bayesian membacanya sebagai prior Gauss pada bobot, tetapi untuk kebutuhan praktis cukup dua kalimat tadi, yaitu bobot besar dihukum dan penyusutannya berjalan terus selama pelatihan.
Implementasi di dalam optimizer PyTorch#
PyTorch tidak menambahkan suku penalti ke loss secara manual, melainkan menggabungkannya ke dalam langkah optimizer. Kode berikut membandingkan pembaruan SGD dengan dan tanpa weight decay pada bobot yang gradiennya nol, sehingga penyusutannya terlihat murni tanpa gangguan data.
import torch
w = torch.tensor([1.0], requires_grad=True)
opt = torch.optim.SGD([w], lr=0.1, weight_decay=0.1)
for langkah in range(1, 6):
opt.zero_grad()
w.grad = torch.zeros_like(w)
opt.step()
print(f"langkah {langkah}: w = {w.item():.5f}")langkah 1: w = 0.99000
langkah 2: w = 0.98010
langkah 3: w = 0.97030
langkah 4: w = 0.96060
langkah 5: w = 0.95099Gradien yang sengaja dibuat nol memperlihatkan suku decay saja, yaitu faktor per langkah, dan lima langkah menyusutkan bobot dari 1 ke sekitar 0,951. Angka ini mengingatkan dua hal sekaligus, yaitu decay berjalan pada setiap langkah tanpa melihat data, dan nilainya yang tampak kecil seperti 0,1 pada SGD dengan lr 0,1 ternyata memberi hukuman yang kuat karena efeknya dikalikan learning rate.
Adam memerlukan satu catatan tambahan. Pada Adam, weight_decay bawaan menambahkan ke gradien sebelum diadaptasi, yang tidak identik dengan penalti L2 murni karena skala langkah adaptif ikut menyentuhnya. Varian AdamW memisahkan decay dari adaptasi sehingga penaltinya bersih, dan kaidah kerja jalur ini adalah memakai AdamW ketika Adam dipilih bersama weight decay.
Kaidah penerapan dan tanda kerjanya#
Weight decay diterapkan pada bobot, dan menyasar bias serta parameter normalisasi justru merugikan. Bias tidak perlu disusutkan karena nilainya bebas menggeser fungsi tanpa efek skala, sedangkan pada batch normalization justru dituntut bebas untuk mengatur skala, sehingga menghukumnya justru menghalangi normalisasi bekerja. Pola yang lazim adalah dua grup parameter pada optimizer, satu berisi bobot dengan decay dan satu berisi bias serta parameter normalisasi tanpa decay.
import torch
import torch.nn as nn
model = nn.Sequential(nn.Linear(16, 32), nn.BatchNorm1d(32), nn.ReLU(), nn.Linear(32, 4))
bobot = [p for nama, p in model.named_parameters() if nama.endswith("weight")]
lainnya = [p for nama, p in model.named_parameters() if not nama.endswith("weight")]
opt = torch.optim.AdamW([
{"params": bobot, "weight_decay": 1e-4},
{"params": lainnya, "weight_decay": 0.0},
], lr=1e-3)
print("grup dengan decay :", len(opt.param_groups[0]["params"]))
print("grup tanpa decay :", len(opt.param_groups[1]["params"]))grup dengan decay : 3
grup tanpa decay : 3Pemisahan nama weight membuat dua grup terbentuk secara eksplisit, yaitu dua matriks bobot dalam grup decay dan dua vektor bias beserta pasangan normalisasi di grup bebas. Nilai decay yang lazim pada pelatihan CNN berada di sekitar hingga , dan seperti hyperparameter regularisasi lain, penilaiannya dilakukan pada data validasi lewat kesenjangan train-validasi yang sudah dilatih pada modul Disiplin pelatihan.
Hubungan dengan alat regularisasi lainnya#
Weight decay, dropout, dan augmentasi data saling melengkapi dan tidak saling menggantikan. Augmentasi menambah variasi informasi pada sisi data, dropout memaksa pembagian peran antar neuron pada sisi arsitektur, dan weight decay menjaga besaran bobot pada sisi parameter. Jaringan visi modern memakai ketiganya bersama, dan urutan penerapan yang disarankan tetap sama dengan topik Dropout, yaitu mulai dari sisi data yang murah, lalu tambahkan penalti parameter bila kurva validasi masih menuntut lebih.
Satu batas penutup, yaitu weight decay pada embedding besar dan layer penuh lebar dapat menunduk kinerja bila diberlakukan seragam, dan pengecualian per kelompok parameter seperti di atas adalah cara menanganinya secara terstruktur.
Ringkasan#
- Penalti L2 menambahkan pada loss, dan gradiennya menyusutkan bobot dengan faktor setiap langkah.
- PyTorch mengimplementasikannya sebagai
weight_decaydi dalam optimizer, dan AdamW adalah varian yang benar ketika dipadukan dengan Adam. - Decay diterapkan pada bobot saja, sedangkan bias dan parameter normalisasi dikelompokkan bebas dari penalti.
- Nilai lazimnya sampai , dan kewajarannya dinilai pada validasi bersama alat regularisasi lain.
Referensi#
- Decoupled Weight Decay Regularization — arXiv — Makalah Loshchilov dan Hutter yang memisahkan decay dari adaptasi dan memperkenalkan AdamW.
- torch.optim.AdamW — PyTorch — Dokumentasi yang menegaskan beda penerapan decay Adam dan AdamW.
- Weight Decay — Dive into Deep Learning — Bab yang menurunkan penalti norm dan eksperimennya pada regresi linier.