چیتشیت
آموزش شبکههای عصبی
Training Neural Networks
انتخاب بهینهساز، مقداردهی اولیه، نرمالسازی، منظمسازی و اسکژولر؛ و سپس دیباگ در صورت رفتار نامطلوب تابع زیان (loss).
فهرست مطالب
یک گام AdamW
معماریگام آموزش
گامبهگام- zero_gradپاککردن گرادیانهای دستهی قبلی.
- Forwardاجرای مدل روی دسته.
- Lossمقایسهی خروجی با تارگتها.
- backwardمحاسبهی گرادیان تمام پارامترها.
- Clipمحدودکردن نُرم گرادیان کلی. این گام اختیاری است.
- stepبهروزرسانی وزنها توسط بهینهساز.
- Scheduleفراخوانی
scheduler.step()بعد ازoptimizer.step()انجام میشود.
حلقهی آموزش با AdamW و کسینوسی
کدpython
optimizer = optim.AdamW(model.parameters(), lr=3e-4, weight_decay=0.01)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100)
for epoch in range(100):
optimizer.zero_grad() # پاککردن گرادیانهای قدیمی
output = model(torch.randn(32, 784)) # گذر رو به جلو
loss = torch.nn.functional.cross_entropy(output, torch.randint(0, 10, (32,)))
loss.backward() # محاسبهی grad. با قاعدهی زنجیرهای
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step() # بهروزرسانی وزنها
scheduler.step() # بعد از optimizer.step()
# گرمکردن و سپس کسینوسی، از کتابخانهی HuggingFace
scheduler = get_cosine_schedule_with_warmup(
optimizer, num_warmup_steps=2000, num_training_steps=100000)
فرمولهای کلیدی
مفهومها- قاعدهی زنجیرهای
- $\frac{dy}{dx} = f'(g(x)) \cdot g'(x)$
- گشتاورهای Adam
- $m_t = \beta_1 m_{t-1} + (1 - \beta_1) \cdot \text{gradient}$ و $v_t = \beta_2 v_{t-1} + (1 - \beta_2) \cdot \text{gradient}^2$
- تصحیح سوگیری
- $\hat{m} = \frac{m_t}{1 - \beta_1^t}$ و $\hat{v} = \frac{v_t}{1 - \beta_2^t}$
- بهروزرسانی AdamW
- $w = w - \text{lr} \cdot \frac{\hat{m}}{\sqrt{\hat{v}} + \epsilon} - \text{lr} \cdot \lambda w$
- افت کسینوسی
- $\text{lr}(t) = \text{lr}_{\min} + 0.5 \cdot (\text{lr}_{\max} - \text{lr}_{\min}) \cdot \left(1 + \cos\left(\frac{\pi t}{T}\right)\right)$
- پیشگرمایش خطی
- $\text{lr}(t) = \text{lr}_{\max} \cdot \frac{t}{\text{warmup\_steps}} \quad \text{for } t < \text{warmup\_steps}$
- واریانس مقداردهی اولیه
- Kaiming برابر $\mathrm{Var}(w) = \frac{2}{\text{fan}_{\text{in}}}$، Xavier برابر $\mathrm{Var}(w) = \frac{2}{\text{fan}_{\text{in}} + \text{fan}_{\text{out}}}$
- دراپاوت معکوس
- $\text{output} = \text{activation}(z) \cdot \text{mask} / (1 - p)$ حین آموزش
انتخاب بر اساس سناریو
دستورها| Situation | انتخاب |
|---|---|
Transformer or LLM | AdamW با lr=1e-4 و wd=0.01-0.1 |
CNN or ResNet | SGD + Momentum با lr=0.1 و momentum=0.9 |
GAN | Adam با lr=2e-4 و beta1=0.5 |
Fine-tuning | AdamW با lr=2e-5 و wd=0.01 |
Not sure yet | AdamW با lr=3e-4 و wd=0.01 |
Sigmoid or tanh layers | مقداردهی اولیه Xavier |
ReLU, GELU or Swish layers | مقداردهی اولیه Kaiming |
Transformer residual layers | مقیاسدهی با 1/sqrt(2N)، N لایه |
کد مقداردهی اولیه، نرمالسازی و منظمسازی
کار و کد| وظیفه | کد |
|---|---|
| مقداردهی اولیه Kaiming برای ReLU | nn.init.kaiming_normal_(layer.weight, nonlinearity='relu') |
| مقداردهی اولیه Xavier | nn.init.xavier_uniform_(layer.weight) |
| BatchNorm بعد از Linear | nn.BatchNorm1d(256) |
| LayerNorm در ترنسفورمر | nn.LayerNorm(d_model) |
| دراپاوت در MLP | nn.Dropout(0.3) |
| افت کسینوسی تا یک کف مشخص | CosineAnnealingLR(optimizer, T_max=1000, eta_min=1e-5) |
| یافتن اولین NaN یا Inf | with torch.autograd.detect_anomaly(): |
| اندازهگیری نُرم گرادیان | torch.nn.utils.clip_grad_norm_(model.parameters(), float("inf")) |
مقادیر پیشفرض بهینهساز
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Adam lr | 0.001 | ابتدا lr را تغییر دهید |
beta1 | 0.9 | تقریباً هیچوقت تغییر ندهید |
beta2 | 0.999 | در صورت نیاز در مرحله دوم تغییر دهید |
epsilon | 1e-8 | تقریباً هیچوقت تغییر ندهید |
AdamW weight_decay | 0.01 | با نرخ تطبیقی مقیاس نمیشود |
SGD momentum | 0.9 | حدود 10 گرادیان آخر |
SGD weight decay on CNNs | 1e-4 | با اسکژولر گامی یا کسینوسی |
Gradient clip max_norm | 1.0 | محدودسازی با نُرم گرادیان کلی |
پیشفرضهای منظمسازی و اسکژولر
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Dropout, transformers | 0.1 | مدلهای LayerNorm |
Dropout, MLPs | 0.5 | خاموششدن نیمی از نورونها |
BatchNorm momentum | 0.1 | 90% قدیمی بهعلاوه 10% جدید |
BatchNorm eps | 1e-5 | اضافهشده به واریانس |
Warmup share | 3-5% | از کل گامها |
Cosine floor eta_min | 1e-5 | کمترین نرخ یادگیری |
Step decay factor | 0.1 | در دورههای (epoch) ثابت |
Log clamp eps | 1e-7 | حفظ متناهیبودن log(p) |
عیبیابی
عیبیابیگیرکردن تابع زیان (loss) در -log(1/num_classes)
- علت
- مدل یک توزیع یکنواخت پیشبینی میکند
- راهحل
- بررسی پایپلاین داده و لیبلها
NaN شدن تابع زیان (loss) بعد از چند گام
- علت
- نرخ یادگیری بسیار بالاست
- راهحل
- کاهش lr به میزان 10 برابر
NaN شدن آنی تابع زیان (loss)
- علت
- log(0) یا تقسیم بر صفر
- راهحل
- محدودکردن پیشبینیها به [eps, 1-eps]
نوسان تابع زیان (loss)
- علت
- عدم فراخوانی
optimizer.zero_grad() - راهحل
- فراخوانی آن قبل از
loss.backward()
تفاوت دقت ارزیابی بین اجراها
- علت
- عدم فراخوانی
model.eval() - راهحل
- افزودن
model.eval()وtorch.no_grad()
دقت آموزش بالا، دقت آزمون پایین
- علت
- بیشبرازش
- راهحل
- دراپاوت، کاهش وزن، دادهی بیشتر
صفر بودن همهی گرادیانها
- علت
- نورونهای مردهی ReLU یا گراف جداشده از نشست
- راهحل
- استفاده از LeakyReLU، بررسی
.requires_grad
توقف یادگیری در لایههای اولیه
- علت
- مشتق سیگموئید حداکثر 0.25 است
- راهحل
- استفاده از ReLU یا GELU با مقداردهی اولیه Kaiming
واژهنامه
اصطلاحها- SGD
- گرادیان کاهشی تصادفی روی یک دستهی کوچک.
- AdamW
- الگوریتم Adam با کاهش وزن تفکیکشده.
- BatchNorm
- نرمالسازی هر ویژگی در کل دستهی کوچک.
- LayerNorm
- نرمالسازی هر نمونه در تمام ویژگیهای آن.
- RMSNorm
- الگوریتم LayerNorm بدون کسر میانگین.
- 1cycle
- نرخ یادگیری در یک چرخه ابتدا بالا میرود و سپس افت میکند.
- SGDR
- تبرید کسینوسی با شروعهای مجدد گرم.
- LR range test
- افزایش نرخ یادگیری در یک اجرای کوتاه برای یافتن نقطه واگرایی تابع زیان (loss).
پرسشها
پرسش و پاسخ- چرا AdamW و نه Adam با L2؟
- بهینهساز Adam عبارت L2 را با نرخ تطبیقی خود مقیاس میکند. AdamW تمام وزنها را به یک نسبت کاهش میدهد.
- چرا گرمکردن؟
- گشتاورهای Adam با صفر شروع میشوند. گامهای اولیه بزرگ از آمارههای نامناسب پیروی میکنند.
- چرا تصحیح سوگیری؟
- در گام 1 با beta1 برابر 0.9، مقدار m معادل 0.1 گرادیان خواهد بود.
- چرا LayerNorm در ترنسفورمرها؟
- چون به اندازهی دسته یا طول توالی وابسته نیست.
- چرا Kaiming برای ReLU؟
- تابع ReLU نیمی از اکتیویشنها را صفر میکند، بنابراین واریانس 2/fan_in است.
نکات
نکتهها- ابتدا آزمون بیشبرازش روی یک بچ را اجرا کنید. تابع زیان (loss) باید تقریباً صفر شود.
- قبل از مقصر دانستن هر چیز دیگر، 3 نرخ یادگیری با اختلاف 10 برابری را تست کنید.
- اگر قرار است فقط یک هایپرپارامتر را تنظیم کنید، نرخ یادگیری را تنظیم کنید.
- حین دیباگ، ابعاد تنسور را بعد از هر عملیات چاپ کنید.
- بررسی کنید که اندازهی گرادیانها در لایههای مختلف نزدیک به هم باشد.
- متد
.to(device)را روی مدل و دادهها اعمال کنید.