چیت‌شیت

آموزش شبکه‌های عصبی

Training Neural Networks

انتخاب بهینه‌ساز، مقداردهی اولیه، نرمال‌سازی، منظم‌سازی و اسکژولر؛ و سپس دیباگ در صورت رفتار نامطلوب تابع زیان (loss).

  • ۱۲ بخش
  • ۷ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. یک گام AdamW
  2. گام آموزش
  3. حلقه‌ی آموزش با AdamW و کسینوسی
  4. فرمول‌های کلیدی
  5. انتخاب بر اساس سناریو
  6. کد مقداردهی اولیه، نرمال‌سازی و منظم‌سازی
  7. مقادیر پیش‌فرض بهینه‌ساز
  8. پیش‌فرض‌های منظم‌سازی و اسکژولر
  9. عیب‌یابی
  10. واژه‌نامه
  11. پرسش‌ها
  12. نکات

یک گام AdamW

معماری
AdamWتابع زیان (loss)خروجی گذر رو به جلوloss.backward()قاعده‌ی زنجیره‌ای گرادیان‌ها را محاسبه می‌کندclip_grad_norm_max_norm=1.0گشتاور اول m_tمیانگین، beta1 0.9گشتاور دوم v_tواریانس، beta2 0.999تصحیح سوگیریتقسیم بر 1 - beta^tبه‌روزرسانی Adamlr · m̂ / (√v̂ + ε)کاهش وزن تفکیک‌شدهمنهای lr · λ · w

گام آموزش

گام‌به‌گام
  1. zero_gradپاک‌کردن گرادیان‌های دسته‌ی قبلی.
  2. Forwardاجرای مدل روی دسته.
  3. Lossمقایسه‌ی خروجی با تارگت‌ها.
  4. backwardمحاسبه‌ی گرادیان تمام پارامترها.
  5. Clipمحدودکردن نُرم گرادیان کلی. این گام اختیاری است.
  6. stepبه‌روزرسانی وزن‌ها توسط بهینه‌ساز.
  7. 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 LLMAdamW با lr=1e-4 و wd=0.01-0.1
CNN or ResNetSGD + Momentum با lr=0.1 و momentum=0.9
GANAdam با lr=2e-4 و beta1=0.5
Fine-tuningAdamW با lr=2e-5 و wd=0.01
Not sure yetAdamW با 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 برای ReLUnn.init.kaiming_normal_(layer.weight, nonlinearity='relu')
مقداردهی اولیه Xaviernn.init.xavier_uniform_(layer.weight)
BatchNorm بعد از Linearnn.BatchNorm1d(256)
LayerNorm در ترنسفورمرnn.LayerNorm(d_model)
دراپ‌اوت در MLPnn.Dropout(0.3)
افت کسینوسی تا یک کف مشخصCosineAnnealingLR(optimizer, T_max=1000, eta_min=1e-5)
یافتن اولین NaN یا Infwith torch.autograd.detect_anomaly():
اندازه‌گیری نُرم گرادیانtorch.nn.utils.clip_grad_norm_(model.parameters(), float("inf"))

مقادیر پیش‌فرض بهینه‌ساز

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Adam lr0.001ابتدا lr را تغییر دهید
beta10.9تقریباً هیچ‌وقت تغییر ندهید
beta20.999در صورت نیاز در مرحله دوم تغییر دهید
epsilon1e-8تقریباً هیچ‌وقت تغییر ندهید
AdamW weight_decay0.01با نرخ تطبیقی مقیاس نمی‌شود
SGD momentum0.9حدود 10 گرادیان آخر
SGD weight decay on CNNs1e-4با اسکژولر گامی یا کسینوسی
Gradient clip max_norm1.0محدودسازی با نُرم گرادیان کلی

پیش‌فرض‌های منظم‌سازی و اسکژولر

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Dropout, transformers0.1مدل‌های LayerNorm
Dropout, MLPs0.5خاموش‌شدن نیمی از نورون‌ها
BatchNorm momentum0.190% قدیمی به‌علاوه 10% جدید
BatchNorm eps1e-5اضافه‌شده به واریانس
Warmup share3-5%از کل گام‌ها
Cosine floor eta_min1e-5کمترین نرخ یادگیری
Step decay factor0.1در دوره‌های (epoch) ثابت
Log clamp eps1e-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) را روی مدل و داده‌ها اعمال کنید.