چیت‌شیت

بهینه‌سازها و برنامه‌های زمان‌بندی نرخ یادگیری

Optimizers and Learning Rate Schedules

SGD، Adam یا AdamW را انتخاب کنید، به نرخ یادگیری شکل دهید، سپس گرادیان‌ها را با ایمنی clip، مقیاس‌بندی و انباشت کنید.

  • ۱۱ بخش
  • ۵ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. مقایسه‌ی بهینه‌سازها در کنار هم
  2. قواعد به‌روزرسانی
  3. زمان استفاده از هر بهینه‌ساز
  4. مقایسه‌ی برنامه‌های زمان‌بندی در کنار هم
  5. انتخاب برنامه‌ی زمان‌بندی
  6. کسینوسی با پیش‌گرمایش خطی
  7. Clip و مقیاس‌بندی در یک گام
  8. انباشت گرادیان‌ها
  9. اعداد مهم
  10. عیب‌یابی
  11. پرسش‌ها

مقایسه‌ی بهینه‌سازها در کنار هم

مقایسه
بهینه‌سازپیش‌فرض‌هارفتار
SGDlr=0.01یک نرخ برای تمام وزن‌ها. درون دره نوسان می‌کند
SGDMomentumlr=0.01, beta=0.9حدود 10 گرادیان آخر را نگه می‌دارد. 3,000 تا 5,000 گام، نه 10,000
RMSPropepsilon=1e-8هر گرادیان را بر RMS متحرک تقسیم می‌کند
Adamlr=0.001, beta1=0.9, beta2=0.999تکانه به‌علاوه‌ی RMSProp به‌علاوه‌ی تصحیح سوگیری
AdamWweight_decay=0.01مشابه Adam. کاهش وزن با فاکتور تطبیقی مقیاس‌بندی نمی‌شود

قواعد به‌روزرسانی

مفهوم‌ها
SGD
$w = w - \text{lr} \cdot g$
تکانه
$m_t = \beta m_{t-1} + g$، سپس $w = w - \text{lr} \cdot m_t$
RMSProp
$s_t = \beta s_{t-1} + (1 - \beta) g^2$، گام $\text{lr} \cdot g / (\sqrt{s_t} + \epsilon)$
گشتاورهای Adam
$m_t = \beta_1 m_{t-1} + (1 - \beta_1) g$ و $v_t = \beta_2 v_{t-1} + (1 - \beta_2) g^2$
تصحیح سوگیری
$\hat{m} = m_t / (1 - \beta_1^t)$. برای حدود 10 گام اول اهمیت دارد.
گام Adam
$w = w - \text{lr} \cdot \hat{m} / (\sqrt{\hat{v}} + \epsilon)$
گام AdamW
گام Adam، سپس $- \text{lr} \cdot \lambda w$ روی وزن‌ها.

زمان استفاده از هر بهینه‌ساز

نکته‌ها
  • برای ترنسفورمر یا LLM از AdamW استفاده کنید: lr=1e-4 و wd=0.01-0.1.
  • برای CNN یا ResNet از SGD + Momentum استفاده کنید: lr=0.1 و momentum=0.9 و weight_decay=1e-4.
  • برای GAN از Adam استفاده کنید: lr=2e-4 و beta1=0.5.
  • برای فاین‌تیونینگ از AdamW استفاده کنید: lr=2e-5 و wd=0.01.
  • وقتی هنوز نمی‌دانید، از AdamW با lr=3e-4 و wd=0.01 استفاده کنید.
  • اگر پیش‌فرض‌ها جواب نداد، اول lr را تغییر دهید. بعد $\beta_2$. تقریباً هرگز $\beta_1$ یا $\epsilon$ را تغییر ندهید.

مقایسه‌ی برنامه‌های زمان‌بندی در کنار هم

دستورها
دستورکارکرد
constant_schedule(step, lr=0.01)نرخ یکسان در هر گام. مناسب مدل‌های کوچک و اشکال‌زدایی
step_decay_schedule(step, lr=0.1, step_size=100, gamma=0.1)کاهش lr با ضریب گاما در گام‌های ثابت. افت‌های ناگهانی می‌تواند تابع زیان (loss) را جهش دهد
cosine_schedule(step, lr=0.01, total_steps=1000, lr_min=1e-5)کسینوسی از lr تا lr_min. پیش‌فرض امن برای بودجه‌ی متوسط
warmup_cosine_schedule(step, lr=0.01, total_steps=1000, warmup_steps=100, lr_min=1e-5)افزایش خطی، سپس کسینوسی. مناسب بودجه‌ی زیاد
one_cycle_schedule(step, lr=0.01, total_steps=1000)صعود از lr/25، سپس نزول تا lr/10000. مناسب بودجه‌ی کم
CosineWithWarmup(warmup_steps, total_steps, lr_max, lr_min)گرم‌کردن به‌علاوه‌ی کسینوسی با مرزهای کنترل‌شده. ثابت روی lr_min
InverseSqrtWarmup(warmup_steps, lr_max)پیش‌گرمایش خطی، سپس lr_max * sqrt(warmup_steps / step)
LinearWarmupConstant(warmup_steps, lr_max)پیش‌گرمایش خطی، سپس lr_max ثابت. یک خط مبنا برای ابطال‌سنجی

انتخاب برنامه‌ی زمان‌بندی

گام‌به‌گام
  1. تعداد کل گام‌ها نامشخصاز LR ثابت با افت دستی استفاده کنید.
  2. بودجه‌ی زیاد، روزها یا هفته‌هااز گرم‌کردن به‌علاوه‌ی افت کسینوسی استفاده کنید. گرم‌کردن = 1 تا 5٪ گام‌ها.
  3. بودجه‌ی متوسطاز تبرید کسینوسی استفاده کنید. lr_min = lr_max / 10 تنظیم شود.
  4. بودجه‌ی کم، چند ساعتاز 1cycle استفاده کنید. lr_max را با آزمون دامنه‌ی LR پیدا کنید.
  5. فاین‌تیونینگ مدل Llama یا GPTاز get_cosine_schedule_with_warmup با گرم‌کردن = 3 تا 5٪ کل گام‌ها استفاده کنید.

کسینوسی با پیش‌گرمایش خطی

کد
python
def lr(self, step: int) -> float:
    if step < 0:
        raise ValueError(f"step must be non-negative, got {step}")
    if self.warmup_steps > 0 and step <= self.warmup_steps:
        return self.lr_max * (step / self.warmup_steps)  # 0 در گام 0
    if step >= self.total_steps:
        return self.lr_min                               # کف، بدون برونیابی
    decay_span = max(1, self.total_steps - self.warmup_steps)
    progress = (step - self.warmup_steps) / decay_span
    cosine = 0.5 * (1.0 + math.cos(math.pi * progress))
    return self.lr_min + (self.lr_max - self.lr_min) * cosine

Clip و مقیاس‌بندی در یک گام

کد
python
self.optimizer.zero_grad(set_to_none=True)
with torch.amp.autocast(device_type=self.device_type, dtype=self.amp_dtype):
    predictions = self.model(inputs)
    loss = self._loss_fn(predictions, targets)
if not torch.isfinite(loss).all().item():  # رد شدن، update() را فراخوانی نکنید
    return self._record_skip(...)
self.scaler.scale(loss).backward()
self.scaler.unscale_(self.optimizer)       # clip پس از unscale
if has_non_finite_grad(self.model.parameters()):
    self.scaler.update()                   # رد شدن، مقیاس‌بخش نصف می‌شود
pre_clip, post_clip = clip_global_l2_norm(list(self.model.parameters()), self.max_norm)
self.scaler.step(self.optimizer)
self.scaler.update()                       # فاکتور را دوبرابر یا نصف می‌کند

انباشت گرادیان‌ها

کد
python
accumulation_steps = effective_batch // (micro_batch * world_size)
for x, y in chunks(x_full, y_full, n):   # n میکروبچ
    scaled = criterion(model(x), y) / n  # تقسیم قبل از backward
    scaled.backward()                    # گرادیان‌ها در param.grad جمع می‌شوند
opt.step()                               # یک‌بار به‌ازای هر دسته‌ی مؤثر
with no_sync_context(model):             # همه‌ی میکروبچ‌ها به‌جز آخری
    loss.backward()

اعداد مهم

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Adam/AdamW lr1e-4 to 3e-4فاین‌تیونینگ از 1e-5 تا 5e-5 استفاده می‌کند
Warmup1-5%درس 44 می‌گوید 1 تا 3 درصد کل گام‌ها
lr_min10 percentاز lr_max. مقدار صفر آموزش را ناتمام می‌گذارد
Step decay$\gamma = 0.1$مقدار step_size = 30 نرخ یادگیری را هر 30 دوره 10 برابر کاهش می‌دهد
max_norm1.0پیش‌فرض آموزش مدل زبانی
Scaling factor2^17یک اجرای سالم نزدیک 2^17 یا 2^18 اشباع می‌شود
Skip rate alert5 percentروی یک پنجره‌ی متحرک 1,000 گامی
Accumulation checkmax_abs_diff < 1e-4دسته‌ی کامل در برابر میکروبچ‌ها

عیب‌یابی

عیب‌یابی
  • انفجار تابع زیان (loss)، وزن‌های NaN

    علت
    lr بیش از حد بالا (lr > 0.01)
    راه‌حل
    کاهش lr. افزودن گرم‌کردن
  • تابع زیان (loss) به‌کندی کاهش می‌یابد

    علت
    lr بیش از حد پایین (lr < 0.00001)
    راه‌حل
    افزایش lr. ابتدا بررسی بازه‌ای lr_max
  • تابع زیان (loss) نزدیک کمینه نوسان می‌کند

    علت
    lr ثابت در اواخر کار بیش از حد بزرگ است
    راه‌حل
    کاهش با کسینوسی یا پله‌ای
  • تابع زیان (loss) در یک دسته عمودی بالا می‌رود

    علت
    جهش نُرم گرادیان
    راه‌حل
    برش نُرم L2 سراسری روی 1.0
  • فاکتور مقیاس‌بندی هرگز تغییر نکرد

    علت
    عدم وجود update() در مسیر پرش
    راه‌حل
    فراخوانی scaler.update() در هر گام
  • گام بهینه‌ساز 16 برابر بیش از حد بزرگ است

    علت
    تابع زیان (loss) روی میکروبچ‌ها جمع شده است
    راه‌حل
    تقسیم هر تابع زیان بر accum_steps
  • باگ‌های ظریف اسکژولر

    علت
    ابتدا scheduler.step()
    راه‌حل
    ابتدا optimizer.step() فراخوانی شود
  • گرم‌کردن طولانی مقیاس نمی‌پذیرد

    علت
    گرم‌کردن به‌صورت یک عدد مطلق تنظیم شده
    راه‌حل
    تنظیم گرم‌کردن به‌صورت کسری از کل گام‌ها

پرسش‌ها

پرسش و پاسخ
چرا گرم‌کردن برای Adam؟
برآوردهای گشتاور آن از صفر شروع می‌شوند. گام‌های اولیه از آماره‌های نامناسب استفاده می‌کنند.
چرا AdamW به‌جای Adam به‌علاوه‌ی L2؟
هر پارامتر به همان نسبت منقبض می‌شود.
چرا SGD برای CNNها؟
الگوریتم SGD مینیمم‌های مسطح‌تری پیدا می‌کند که اغلب تعمیم‌پذیری بهتری دارند.
روش 1cycle به چه چیزی نیاز دارد؟
تعداد کل گام‌ها از پیش.
آیا انباشت گرادیان در زمان صرفه‌جویی می‌کند؟
خیر. دوبرابر کردن accum_steps زمان واقعی را به‌ازای هر گام بهینه‌ساز دوبرابر می‌کند.
آیا autocast پردازنده به مقیاس‌بندی تابع زیان نیاز دارد؟
خیر. قابلیت autocast پردازنده به‌طور پیش‌فرض از BF16 استفاده می‌کند.