نرمالسازی لایه (Layer norm)
جواب کوتاه
نرمالسازی لایه عددهای بردار هر کلمه رو هممقیاس میکنه: میانگینشون رو حساب میکنه و از همه کم میکنه، بعد همه رو بر پراکندگیشون تقسیم میکنه؛ نتیجه میانگین صفر و پراکندگی یک داره. بعد برای هر خونه یه ضریب و یه جابهجایی یادگرفته اعمال میشه، تا مدل اگه لازم داشت مقیاس رو عوض کنه. این کار برای هر کلمه جدا انجام میشه، نه روی چند نمونه با هم؛ برای همین به اندازهی دسته بستگی نداره. سال ۲۰۱۶ معرفی شد و ترنسفورمر ۲۰۱۷ بعد از هر جمع میانبر ازش استفاده کرد. یه نسخهی سادهترش، RMSNorm، فقط تقسیم میکنه و میانگین رو کم نمیکنه.
یعنی چی
عددهای هر کلمه رو، هر بار، به یه مقیاس استاندارد برمیگردونیم.
مثلا فرض کنید یه معلم از ۲۰ نمره میده و یکی دیگه از ۱۰۰. یه ۱۸ و یه ۹۰ رو نمیشه همینطوری مقایسه کرد؛ اول باید هممقیاسشون کنید. توی درس نرمالسازی داده همین رو برای ستونهای یه جدول دیدیم. نرمالسازی لایه همین کار رو داخل مدل، برای بردار هر کلمه، بعد از هر بخش انجام میده.
چرا لازمه
توی درس اتصال باقیمانده دیدیم هر بخش یه چیزی به بردار کلمه اضافه میکنه. حالا اگه دهها بخش پشت سر هم چیز اضافه کنن، عددها ممکنه کمکم خیلی بزرگ یا خیلی کج بشن، و هر لایه مجبور بشه با عددهایی کار کنه که هر بار یه مقیاس دیگه دارن. این آموزش رو سخت و ناپایدار میکنه. پژوهش ۲۰۱۶ که نرمالسازی لایه رو معرفی کرد، نشون داد زمان آموزش رو کم میکنه.
سه قدم
یه بردار ساختگی با چهار عدد: ۲، ۴، ۶ و ۸. قدم اول، میانگین: جمعشون میشه ۲۰، تقسیم بر ۴ میشه ۵. قدم دوم، ۵ رو از همه کم میکنیم: منفی ۳، منفی ۱، ۱ و ۳. حالا میانگین صفره. قدم سوم، پراکندگی رو حساب میکنیم، که اینجا حدود ۲٫۲۴ میشه، و همه رو بر اون تقسیم میکنیم. نتیجه میشه حدود منفی ۱٫۳۴، منفی ۰٫۴۵، ۰٫۴۵ و ۱٫۳۴. ترتیب و فاصلهی نسبی عددها همون مونده؛ فقط دور صفر و توی یه اندازهی استاندارد نشستن.
دو عدد یادگرفته
شاید مدل همیشه میانگین صفر و پراکندگی یک رو نخواد. برای همین بعد از نرمالسازی، برای هر خونه دو عدد یادگرفته هست: یه ضریب که در عدد ضرب میشه، و یه جابهجایی که بهش اضافه میشه. اینها مثل بقیهی وزنها موقع آموزش یاد گرفته میشن. پس مدل هر بار از یه نقطهی مرتب شروع میکنه، ولی آزاده مقیاس رو هر جور که لازم داره تنظیم کنه.
روی یه کلمه
اسم «لایه» از اینه که میانگین و پراکندگی روی همهی خونههای یه لایه، برای یه کلمه، حساب میشه؛ یعنی یه سطر از جدول. پیش از اون، یه روش ۲۰۱۵ به اسم نرمالسازی دستهای معروف بود که هر خونه رو روی چند نمونهی یه دسته نرمال میکرد؛ یعنی یه ستون. اون روش به اندازهی دسته بستگی داره و برای جملههایی با طولهای مختلف دردسر داره. نرمالسازی لایه هر کلمه رو تنها حساب میکنه و موقع آموزش و استفاده یکسان کار میکنه.
بزرگ یا کوچیک، یه جواب
یه خاصیت مهم نرمالسازی لایه اینه که بزرگی کل بردار براش مهم نیست.
همون ۲، ۴، ۶، ۸ رو ده برابر کنید: ۲۰، ۴۰، ۶۰، ۸۰. میانگین هم ده برابر میشه، پراکندگی هم ده برابر، و وقتی تقسیم میکنیم، دهها با هم میرن. نتیجه دقیقا همون منفی ۱٫۳۴، منفی ۰٫۴۵، ۰٫۴۵ و ۱٫۳۴ هست. حالا به جاش به همه صد تا اضافه کنید: ۱۰۲، ۱۰۴، ۱۰۶، ۱۰۸. این بار میانگین صد تا جلو میره و کم کردنش، صد رو برمیداره؛ باز همون جواب. مقالهی ۲۰۱۶ همین رو نوشت: نرمالسازی لایه به بزرگتر شدن کل عددهای یه نمونه حساس نیست. برای همین اگه عددها توی لایههای پشت سر هم کمکم بزرگ یا کوچیک بشن، این بخش دوباره مرتبشون میکنه.
نسخهی سادهتر
یه پژوهش ۲۰۱۹ پرسید: واقعا لازمه میانگین رو کم کنیم؟ و یه نسخهی سادهتر ساخت به اسم RMSNorm، که فقط عددها رو بر «ریشهی میانگین مربعها» تقسیم میکنه. برای همون ۲، ۴، ۶، ۸، این عدد حدود ۵٫۴۸ میشه و نتیجه حدود ۰٫۳۷، ۰٫۷۳، ۱٫۱ و ۱٫۴۶. حساب کمتری داره و نتیجهش نزدیکه. یه خانوادهی مدل باز ۲۰۲۳ همین رو به کار برد و خیلی از مدلهای بعدی هم.
وقتی همه یکیان
یه حالت خاص هم هست که باید حواسمون بهش باشه: اگه همهی عددها یکی باشن چی؟
فرض کنید بردار ۵، ۵، ۵، ۵ باشه. میانگین ۵ هست، کم کردنش همه رو صفر میکنه، و پراکندگی هم صفره. قدم سوم میگه تقسیم بر پراکندگی، یعنی تقسیم بر صفر، که جواب نداره. برای همین توی عمل، زیر رادیکال کنار پراکندگی یه عدد خیلی کوچیک، مثلا ۰٫۰۰۰۰۱، اضافه میکنن. این عدد برای بردارهای معمولی تقریبا هیچ فرقی نمیکنه، ولی نمیذاره تقسیم بر صفر پیش بیاد. کل کار توی چند خط پایتون:
import math
def layer_norm(v, eps=1e-5):
m = sum(v) / len(v)
var = sum((x - m) ** 2 for x in v) / len(v)
return [round((x - m) / math.sqrt(var + eps), 2) for x in v]
print(layer_norm([2, 4, 6, 8]))
# [-1.34, -0.45, 0.45, 1.34]
print(layer_norm([20, 40, 60, 80]))
# [-1.34, -0.45, 0.45, 1.34]
print(layer_norm([5, 5, 5, 5]))
# [0.0, 0.0, 0.0, 0.0]اون دو عدد یادگرفته، ضریب و جابهجایی، اینجا نیستن؛ توی مدل واقعی بعد از همین خروجی میان.
چند نکته
- ترتیب عددها عوض نمیشه؛ فقط مقیاسشون.
- برای هر کلمه جدا، نه روی چند نمونه.
- ضریب و جابهجایی رو مدل یاد میگیره.
- توی مقالهی ۲۰۱۷، بعد از هر جمع میانبر.
«بعد از هر جمع»؟ بعدها خیلیها این جا رو عوض کردن. درس بعد: نرمالسازی پیش یا پس از هر بخش.
جمعبندی. آنچه از این درس با خودتان میبرید.
- منهای میانگین، تقسیم بر پراکندگی.
- نتیجه: میانگین صفر، پراکندگی یک.
- بعد ضریب و جابهجایی یادگرفته.
- برای هر کلمه جدا.
- RMSNorm: فقط تقسیم.
خودتون رو بسنجید
۱۵ پرسش، هر بار تازه از میان ۳۰ پرسش این درس. آخرش فقط کارنامه رو میبینید: چند تا درست، چند تا نادرست.