در مثال پیشآموزش متنی، واژههایی از جمله بهصورت خودکار mask میشوند و مدل باید واژه حذفشده را حدس بزند؛ مثلاً در جمله “What ___ you saying?” انتظار میرود واژهای مانند “are” یا “were” را پیشبینی کند. مدلی که در این وظیفه خوب عمل کند بخش مهمی از ساختار زبان را آموخته است و میتوان آن را برای مسئله اصلی reuse و روی داده برچسبخورده fine-tune کرد.
بهینهسازهای سریعتر
آموزش یک DNN بسیار بزرگ میتواند دردناک و کند باشد. تا اینجا چهار راه برای سریعتر و بهترکردن آموزش دیدیم: مقداردهی اولیه مناسب وزنها، تابع فعالسازی مناسب، Batch Normalization و reuse کردن بخشهایی از یک شبکه pretrained. یک جهش سرعت دیگر از انتخاب optimizer بهتر از gradient descent معمولی به دست میآید. در این بخش Momentum، Nesterov Accelerated Gradient، AdaGrad، RMSProp، Adam و چند مشتق Adam بررسی میشوند.
Momentum
توپ بولینگ را تصور کنید که روی شیبی ملایم میغلتد: ابتدا آهسته است اما بهتدریج سرعت میگیرد تا به سرعت نهایی برسد. این همان شهود momentum optimization است. gradient descent معمولی روی شیب ملایم گام کوچک و روی شیب تند گام بزرگ برمیدارد، اما «سرعت جمع نمیکند». در نتیجه رسیدن آن به مینیمم میتواند بسیار کندتر باشد.
Gradient descent وزنها را مستقیماً با رابطه θ ← θ − η∇θJ(θ) تغییر میدهد و گرادیانهای قبلی را فراموش میکند. اگر گرادیان محلی کوچک باشد، حرکت نیز بسیار کند است. Momentum در عوض یک بردار m نگه میدارد:
1. m ← βm − η∇θJ(θ)
2. θ ← θ + m
در اینجا گرادیان مانند شتاب عمل میکند نه سرعت. β میزان momentum یا اصطکاک مؤثر را کنترل میکند و بین ۰ و ۱ است؛ مقدار متداول ۰٫۹ است. اگر گرادیان تقریباً ثابت بماند، اندازه بهروزرسانی نهایی حدود 1/(1−β) برابر gradient×learning-rate میشود؛ با β=۰٫۹ این عامل ۱۰ است. بنابراین optimizer میتواند plateauها را بسیار سریعتر پشت سر بگذارد.
در سطح هزینه کشیده و دراز، gradient descent از دیواره تند سریع پایین میآید اما در امتداد دره آهسته حرکت میکند. Momentum در مسیر دره سرعت جمع میکند و سریعتر به کف میرسد. البته ممکن است از مینیمم عبور کند و چند بار نوسان کند؛ وجود اصطکاک یا β کمتر از ۱ این نوسان را میرایی میدهد.
optimizer = tf.keras.optimizers.SGD(
learning_rate=0.001, momentum=0.9)
Momentum یک ابرپارامتر بیشتر اضافه میکند، اما مقدار ۰٫۹ در بسیاری از مسائل خوب کار میکند و تقریباً همیشه از gradient descent ساده سریعتر است.
Nesterov Accelerated Gradient
NAG یا Nesterov momentum، گرادیان را نه در موقعیت فعلی θ، بلکه کمی جلوتر در جهت momentum یعنی در θ+βm اندازه میگیرد:
1. m ← βm − η∇θJ(θ + βm)
2. θ ← θ + m
چون بردار momentum معمولاً در جهت کلی optimum است، گرادیانِ نقطهای کمی جلوتر اغلب تصحیح دقیقتری ایجاد میکند. اختلاف هر گام کوچک است، اما در طول آموزش جمع میشود و NAG میتواند بهطور محسوسی سریعتر از momentum معمولی باشد. همچنین وقتی momentum وزنها را از عرض یک دره عبور میدهد، گرادیان جلوتر زودتر به سمت کف دره اشاره میکند و نوسان را کاهش میدهد.
شکل ۱۱-۷ - در momentum معمولی گرادیان پیش از گام momentum محاسبه میشود؛ Nesterov ابتدا نقطه جلوتر را میبیند و گرادیان را آنجا اندازه میگیرد.
optimizer = tf.keras.optimizers.SGD(
learning_rate=0.001, momentum=0.9, nesterov=True)
AdaGrad
در سطح هزینه کشیده، gradient descent ابتدا در راستای تندترین شیب حرکت میکند که الزاماً مستقیم به optimum اشاره نمیکند. AdaGrad با کوچککردن مؤلفه گرادیان در ابعادی که شیب مکرراً بزرگ است، جهت حرکت را زودتر به سمت optimum اصلاح میکند:
1. s ← s + ∇J(θ) ⊗ ∇J(θ)
2. θ ← θ − η ∇J(θ) ⊘ √(s + ε)
در گام اول، مربع گرادیانها در بردار s جمع میشود. اگر تابع هزینه در بعد i تند باشد، si بهسرعت بزرگ میشود. در گام دوم، هر مؤلفه گرادیان بر مقدار مربوط در s تقسیم میشود؛ ε نیز برای جلوگیری از تقسیم بر صفر است و مقدار بسیار کوچکی مانند 10⁻¹⁰ دارد. نتیجه یک adaptive learning rate است: نرخ مؤثر در ابعاد تند سریعتر از ابعاد ملایم کاهش مییابد.
شکل ۱۱-۸ - AdaGrad جهت حرکت را زودتر اصلاح میکند تا به سمت optimum متمایل شود.
AdaGrad روی مسائل ساده درجهدو خوب است، اما برای DNNها غالباً نرخ یادگیری را بیش از حد کاهش میدهد و پیش از رسیدن به global optimum تقریباً متوقف میشود. بنابراین وجود optimizer Adagrad در Keras به این معنا نیست که انتخاب مناسبی برای شبکه عمیق است؛ ولی فهم آن برای درک optimizerهای adaptive بعدی مهم است.
RMSProp
RMSProp مشکل توقف زودهنگام AdaGrad را با فراموشکردن تدریجی گرادیانهای خیلی قدیمی حل میکند. بهجای جمع همه مربع گرادیانها از ابتدای آموزش، از میانگین نمایی کاهنده استفاده میکند:
1. s ← ρs + (1−ρ) ∇J(θ) ⊗ ∇J(θ)
2. θ ← θ − η ∇J(θ) ⊘ √(s + ε)
مقدار ρ معمولاً ۰٫۹ است و اغلب نیازی به تنظیم زیاد ندارد:
optimizer = tf.keras.optimizers.RMSprop(
learning_rate=0.001, rho=0.9)
بهجز مسائل بسیار ساده، RMSProp تقریباً همیشه از AdaGrad مناسبتر است و تا پیش از فراگیرشدن Adam، انتخاب محبوب بسیاری از پژوهشگران بود.
Adam
Adam مخفف Adaptive Moment Estimation است و ایدههای Momentum و RMSProp را ترکیب میکند. مانند Momentum میانگین نمایی گرادیانهای گذشته را نگه میدارد و مانند RMSProp میانگین نمایی مربع گرادیانها را نیز دنبال میکند. اولی برآورد moment اول (میانگین) و دومی برآورد moment دوم (واریانس مرکزنشده) است:
1. m ← β₁m − (1−β₁)∇J(θ)
2. s ← β₂s + (1−β₂)∇J(θ)⊗∇J(θ)
3. m̂ ← m / (1−β₁ᵗ)
4. ŝ ← s / (1−β₂ᵗ)
5. θ ← θ + η m̂ ⊘ (√ŝ + ε)
t شماره iteration از ۱ است. β₁ نقشی شبیه momentum و β₂ نقشی شبیه ρ در RMSProp دارد. چون m و s از صفر آغاز میشوند، در ابتدای آموزش به صفر bias دارند؛ گامهای ۳ و ۴ این bias اولیه را تصحیح میکنند.
مقادیر متداول و پیشفرض Keras عبارتاند از β₁=0.9، β₂=0.999 و ε بسیار کوچک. Adam نیز چون نرخ یادگیری را تطبیقی تنظیم میکند، معمولاً نسبت به η حساسیت کمتری دارد و مقدار ۰٫۰۰۱ اغلب نقطه شروع خوبی است:
optimizer = tf.keras.optimizers.Adam(
learning_rate=0.001, beta_1=0.9, beta_2=0.999)
AdaMax
در Adam، مقیاس بهروزرسانی بر پایه norm نوع ℓ2 از گرادیانهای زمانکاهنده است. AdaMax این ایده را با norm نوع ℓ∞، یعنی بیشینه قدرمطلق، جایگزین میکند. این تغییر در بعضی datasetها AdaMax را پایدارتر از Adam میکند، اما در حالت کلی Adam معمولاً بهتر است. اگر Adam روی مسئلهای رفتار نامطلوب داشت، AdaMax یک گزینه آزمایشی مناسب است.
Nadam
Nadam در واقع Adam بههمراه ترفند Nesterov است و در بسیاری از مسائل اندکی سریعتر از Adam همگرا میشود. مقایسههای تجربی گزارش کردهاند که Nadam اغلب از Adam بهتر بوده، هرچند گاهی RMSProp از آن پیشی گرفته است.
AdamW و Weight Decay
AdamW نسخهای از Adam است که تکنیک regularization به نام weight decay را بهدرستی یکپارچه میکند. Weight decay در هر iteration اندازه وزنها را با ضرب در یک ضریب کمتر از ۱، مثلاً ۰٫۹۹، کمی کاهش میدهد. این ایده شبیه ℓ2 regularization است و در SGD از نظر ریاضی با آن معادل میشود؛ اما در Adam و خانواده آن، ℓ2 regularization و weight decay معادل نیستند. ترکیب ساده Adam با ℓ2 ممکن است مدلهایی با تعمیم ضعیفتر بسازد؛ AdamW این مشکل را با جداکردن درست weight decay از بهروزرسانی adaptive رفع میکند.
در Keras با جایگزینی کلاس optimizer میتوان از این نسخهها استفاده کرد؛ برای AdamW بهتر است weight_decay نیز تنظیم شود.
چرا روشهای مرتبه دوم معمولاً برای DNN مناسب نیستند؟
تمام روشهای بالا از مشتقهای مرتبه اول، یعنی Jacobianها، استفاده میکنند. الگوریتمهای مرتبه دوم از Hessian نیز بهره میبرند، اما برای مدل با n پارامتر تعداد مؤلفههای Hessian در مرتبه n² است، در حالی که Jacobian فقط n مؤلفه دارد. DNNها دهها هزار تا میلیونها پارامتر دارند؛ بنابراین نگهداری و محاسبه Hessian معمولاً از نظر حافظه و زمان غیرعملی است.
جدول ۱۱-۲ - مقایسه optimizerها؛ * ضعیف، ** متوسط، *** خوب
| کلاس | سرعت همگرایی | کیفیت همگرایی |
SGD | * | *** |
SGD(momentum=...) | ** | *** |
SGD(momentum=..., nesterov=True) | ** | *** |
Adagrad | *** | * - معمولاً خیلی زود متوقف میشود |
RMSprop | *** | ** یا *** |
Adam | *** | ** یا *** |
AdaMax | *** | ** یا *** |
Nadam | *** | ** یا *** |
AdamW | *** | ** یا *** |
این ترجمه برای استفادهٔ آموزشی تهیه شده است. انتشار عمومی، فروش یا بازنشر آن باید با رعایت حقوق مؤلف و ناشر و اخذ مجوزهای لازم انجام شود.