داستان ترنسفورمرها (۴): داستان برت
به نام خداوند بخشنده مهربان
اگر سر و کارتون با یادگیری عمیقه و به طور خاص علاقهمند به حوزه پردازش زبان هستید، قطعا نام پرآوازه "برت" به گوشتون خورده. تولد برت باعث انقلابی عظیم در حل مسائل زبانی شد و دونستن ساز و کارش بر هر محقق و مهندس پردازش زبان واجب عینی است. ما در انتشارات اورفیت در یک رشته پست تحت عنوان «داستان ترنسفورمرها»، ماجرای چرایی به وجود آمدن مکانیزم توجه و معماری ترنسفورمرها رو بیان کردیم. اگر با معماری ترنسفورمرها و توجه آشنایی ندارید میتونید خیلی مختصر و مفید سه پست قبلی رو بخونید و زودی برگردید همینجا. حالا بعد از حکایت مشکلات RNNها و ظهور مکانیزم توجه و معماری ترنسفورمری نوبت داستان برته.
نهضت انتقال یادگیری در پردازش زبان
با این که برت یک مدل با معماری ترنسفورمری است اما داستان رو میخوایم چند سال قبلتر از ۲۰۱۷ یعنی تولد ترنسفورمرها شروع کنیم. داستان از ۲۰۱۲ شروع میشه. در اون زمان شبکه های عمیق با معماری کانولوشنی در حوزه تصویر تازه ترکونده بودند. اما مشکل اساسی که وجود داشت این بود که به ازای هر تسک و مساله محققین مجبور بودند که یک شبکه عمیق رو از نو بر دادگان آموزشی اون مساله تعلیم بدهند. این قضیه هم وقتگیر بود و هم این که در خیلی اوقات به واسطه کمبود تعداد داده آموزشی برای مسائل کمتر مطرح، ناممکن بود. اینجا بود که یک ایده به ذهن محققین پردازش تصویر رسید و اون این بود که چطوره که بیایم شبکه های عمیق با ظرفیت بالا (معادل تعداد پارامتر زیاد) رو با تسک تشخیص کلاس تصویر و بر روی دادگان عظیم مثل ImageNet آموزش بدهیم و سپس در مسائل جدید از این شبکهها به عنوان یک نقطه شروع استفاده کنیم و صرفا وزنهای این شبکه های از پیش آموزش دیده رو تنظیم یا به اصطلاح Fine-Tune کنیم. این ایده در عمل هم موفقیت آمیز بود و باعث پیدایش شبکههایی نظیر VGG و AlexNet و بعدها ResNet شد. به بیانی دیگر این شبکهها به واسطه ظرفیت بالا و البته تعداد دادگان آموزشی زیاد که روی آنها پیشتعلیم میدیدند میتونستند بازنمایی از تصویر به دست بیارند که در روند حل مسائل تصویری دیگه نیز بشه از اونها استفاده کرد و به اصطلاح یادگیری رو انتقال داد.
اما از اونجایی که در پردازش متن دیتاست عظیمی همچون ImageNet وجود نداشت و جمع آوریش هم کار سختی بود داستان به نحو دیگه ای پیش رفت. در سال ۲۰۱۳ مدل معروف word2vec ابداع شد. این مدل یک شبکه عصبی با یک لایه نهان بود که وظیفه داشت با ورودی گرفتن یک کلمه، کلمات اطراف اون رو پیش بینی کنه (چیزی هم که زیاده متن و دنباله کلمات، فلذا نیازی به ساختن دیتاست عظیمی مثل ImageNet برای متن نیست). پس از پیشآموزش روی این تسک، بازنمایی لایه نهان شبکه w2v به عنوان یک بازنمایی معنایی از کلمه میتونست در وظایف مختلف پردازش زبان مورد استفاده قرار بگیره. در واقع ارزش اصلی w2v هم همین بود که میتونست کلماتی رو که قبل از اون به صورت بردارهای تک فعال (one-hot) با سایز بالا مدل میشدند رو به صورت یک بردار با سایز کوچکتر و البته روابط معنایی غنی، ارائه کنه. استفاده از بازنمایی w2v در شبکههای عصبی متنی باعث شد تا عملکرد و امتیاز این مدلها جهش جالب توجهی رو تجربه کنه. اما از اونجایی که کسی از جنبه یادگیری انتقالی به w2v نگاه نکرد، مساله انتقال یادگیری در پردازش زبان چند سال به خواب عمیقی رفت تا این که در سال ۲۰۱۸ مدل ELMO منتشر شد.
نکته ماجرا این جا بود که از اونجایی که شبکهنظیر w2v برای هر کلمه یک بردار بازنمایی تولید میکردند، وجود کلماتی مثل "شیر" که چند معنی دارند محققین رو به این فکر انداخت که بردار بازنمایی یک کلمه باید تابعی از محتوایی که آن کلمه در آن قرار گرفته نیز باشه. برای مثال بازنمایی کلمه شیر در دو عبارت "من شیر را خوردم" و یا "شیر سلطان جنگل است" باید متفاوت باشه و تابعی از جمله باشه. از طرفی در طی این چند سال معماریهای LSTM ای هم رونق گرفته بودند. اینجا بود که ELMO متولد شد. به طور مختصر مدل ELMO از دو شبکه LSTM چندلایه تشکیل شده که یکی از اونها تسک مدل زبانی (Language Model) را از سمت چپ دیگری نیز تسک مدل زبانی را از سمت راست روی دادگان متنی آموزش میبینند. ( تسک مدل زبانی یک از مسائل پایه ای اصلی پردازش زبانه، به این معنا که با دیدن یک سری کلمات از جمله بتونید بگید که کلمه بعدی چه میتونه باشه. برای مثال یعنی با دیدن "من تو را دوست ......." بتونید بگید که در جای خالی باید کلمه دارم قرار بگیره. در واقع توی w2v شما بایستی یک کلمه رو به شرط داشتن یک کلمه دیگر پیش بینی میکردید ولی اینجا باید یک کلمه رو با فرض داشتن یک عبارت پیش بینی کنید). مدل elmo در ابتدا با تسک مدل زبانی پیش آموزش میبینه و در مرحله بعدی وقتی که بخواهند از این شبکه به عنوان نقطه شروع یا شبکه استخراج کننده ویژگی از کلمات برای یک تسک دیگه استفاده کنند، ترکیب خطی بازنمایی کلمات از لایههای مختلف هر دو LSTM رو به عنوان بردار ویژگی آن کلمه در نظر میگیرند. نکته تاکتیکی ماجرا در w2v و مخصوصا elmo این بود که محققین پردازش زبان تونستند معادل و جایگزین تسک دستهبندی تصاویر و دیتاست ImageNet رو در دنیای متن هم پیدا کنند. تسک مدل زبانی به عنوان وظیفه مرحله پیش آموزش و دادگان متنی خام که همه جا فراوان ریخته (از جمله اینترنت) به عنوان دیتاست به کار رفته اند.
با کمک elmo میزان امتیاز مدل های عصبی در وظایف متنی نظیر دسته بندی متون و تشخیص موجودیتهای نامدار و ... دچار جهش قابل توجهی شدند و elmo یک شمع انقلابی نورانی رو در ظلمات شب پردازش متن روشن کرد. همه چیز به نظر برای المو رویایی بود اما از بخت بدش این قضایا با تولد معماری ترنسفورمری همزمان شد. شب وصلش دیر نپایید و آفتاب برت شمع elmo را خاموش کرد. این روزها کمتر کسی از elmo یاد میکنه و خیلی به ندرت ازش استفاده میشه ولی شما به یاد داشته باشید که شمع اول پارادایم مدلهای زبانی نظیر Bert و GPT توسط این بنده خدا روشن شده.
برت
بعد از ارائه معماری ترنسفورمری، توجهات زیادی به این معماری جلب شد و در اغلب مسائل مهاجرت از معماریهای بازگشتی به معماریهای نو شکل گرفت. طبعا این مهاجرتها محققین را به این فکر انداخت که مدلی با معماری ترنسفورمری و با کارکردی مشابه المو ارائه دهند. این ایده سرانجام منجر به انتشار مدل برت در ۲۰۱۸ شد. مدل برت از لحاظ ساختاری یک ترنسفورمری است که تنها قسمت انکودر را دارد و فاقد قسمت دیکودر است. برای یادآوری همانطور که میدانید (اگر قسمت های قبلی پستها رو خونده باشید حتما میدانید) انکودر ترنسفورمر یک دنباله به طول N توکن را گرفته و در خروجی خود برای هر یک از این توکنها یک بردار ویژگی تولید میکند، یعنی مثلا اگر سایز بردارهای ویژگی d باشد در خروجی دیکودر N تا بردار با سایز d خواهیم داشت. هدف کارکردی برت مشابه المو به دست آوردن یک بازنمایی معنایی قوی به وسیله آموزش روی دادگان فراوان متنی بدون برچسب است. دو تفاوتی که معماری برت را از المو متمایز میکند و به آن برتری میبخشند را میتوان اولا در سرعت بالاتر و آموزش سریع تر و راحت تر شبکه ترنسفورمری نسبت به بازگشتی دانست (موازی سازی در ترنسفورمر بیشتر است و دیگر شاهد ساختار بازگشتی نیستیم) و ثانیا امکان توجه توامان دوطرفه در هر کلمه نسبت به محتوای چپ و راست خود دید. به بیان بهتر در برت بردار بازنمایی یک کلمه میتواند همزمان به کلمات سمت چپ و راست خود توجه کند، در حالی که ما در المو با دو شبکه بازگشتی مواجه هستیم که هر یک به طور غیر توام توجه بردار بازنمایی کلمه را به سمت چپ و راست معطوف میکنند. نکته مهم دیگر در مورد برت سایز بزرگ آن است. برت در دو سایز Base و Large ارائه شده است که سایز Base آن دارای ۱۲ لایه در پشته انکودر خود و سایز Large نیز دارای ۲۴ لایه در پشته دیکودر خود است. اندازه بردارهای بازنمایی خروجی برای هر کلمه توسط این دو سایز نیز به ترتیب ۷۶۸ و ۱۰۲۴ است. در نهایت تعداد پارامترهای این دو سایز از برت به ترتیب ۱۱۰ میلیون و ۳۴۰ میلیون پارامتر است.
دو نکته مهم در مورد برت چگونگی پیش آموزش این شبکه و تنظیم و به اصطلاح فاین تیون آن روی وظایف مختلف پردازش زبان است که در قسمت بعدی آنها را بررسی میکنیم.
نحوه پیشآموزش برت
برت برای پیش آموزش خود سعی میکند تا دو تسک مدل زبانی ماسکشده (Masked Language Model) و تشخیص جمله بعدی را یاد بگیرد. در مساله مدل زبانی ماسکشده هدف این است که توزیع احتمال یک کلمه از روی کلمات قبل و بعدش یادگرفته شود. با توجه به معماری برت در امکان توجه توامان به چپ و راست، این تسک بیشترین استفاده را از پتانسیل این معماری میکند. در هنگام پیش آموزش برت با تسک مدل زبانی ماسکشده، به تصادف به جای پانزده درصد از توکنهای دنباله، توکن MASK قرار میگیرد. برای مثال جمله "رنگ آسمان آبی است" به "رنگ آسمان MASK است" تغییر پیدا میکند. این جمله تغییریافته به برت به عنوان ورودی داده میشود و برت برای هر کدام از چهار کلمه یک بردار بازنمایی با سایز مثالی ۷۶۸ تولید میکند. حال بر روی بردار بازنمایی مربوط به کلمه MASK یک لایه شبکه عصبی قرار میگیرد که تسک آن پیشبینی توزیع احتمال کلمات محتمل به جای MASK است. (فرض کنیم سایز دیکشنری کلمات برت ۳۰۰۰۰ باشد در این صورت اندازه این لایه بایستی ۷۶۸ به ۳۰۰۰۰ باشد. در واقع این لایه در خروجی خود توزیع احتمال بین تمامی کلمات ممکن در دیکشنری را تولید میکند)
پیش آموزش روی تسک مدل زبانی ماسکشده به برت کمک میکند تا برای هر کلمه بازنمایی موثری پیدا کند. اما برت برای انجام برخی وظایف پردازش زبان نیاز به ارائه بازنمایی مناسب در سطح جملات و کشف روابط بین جملات نیز دارد. برای نیل به این هدف برت بر روی تسک تشخیص جمله بعدی نیز پیش آموزش میبیند. نحوه طرح این تسک به این صورت است که جمله فرضی A از دیتاست متنهای بدون برچسب انتخاب میشود. سپس به احتمال ۵۰ درصد جمله پس از A در دیتاست به عنوان جمله B انتخاب میشود و یا به احتمال ۵۰ درصد یک جمله تصادفی دیگر به عنوان جمله B انتخاب میشود. حال مدل برت با ورودی گرفتن جملات A و B بایستی تشخیص بدهد و یادبگیرد که آیا جمله B پس از A آمده است و متوالی بودهاند و یا خیر.
ابتکار دیگر برت اضافه کردن توکنهای خاص CLS و SEP است. در پیادهسازی برت، در هنگام ورودی گرفتن یک رشته، یک توکن CLS افزوده میشود که بردار بازنمایی که برت برای آن تولید میکند در واقع بازنمایی از کل دنباله است. برای مثال یک کاربرد این بازنمایی این است که با اضافه کردن یک لایه عصبی softmax روی بازنمایی حاصل از CLS، در تسک تشخیص جمله بعدی برت قادر خواهد بود تا توزیع احتمال متوالی بودن جملات A و B را نشان دهد. همچنین در پایان هر زیردنباله در دنباله ورودی نیز یک توکن SEP اضافه میشود که جای خاتمه جملات و مرز بین آنها را نشان میدهد. علاوه بر این ابتکار، بردار تعبیهای قطعهای (segment embedding) قابل یادگیری نیز به زیر دنباله های اعمال میشود، به بیان دیگر به ازای کلمات در زیردنباله های مختلف، بردارهای تعبیه قطعهای متفاوتی بر آنها اعمال میشوند. در نهایت برت دارای سه مکانیزم تعبیه مکانی، قطعهای و کلمهای است که به ترتیب بر رشته ورودی اعمال میشوند. اگر گیج شدید میتوانید شکل زیر را مشاهده کنید.
نحوه تنظیم برت برای وظایف مختلف
داستان از این جا به بعد شبیه خانهسازی و لگوبازی است. شما ماژول یا شبکهای دارید که با یک دنباله از شما ورودی میگیرد و به ازای هر کلمه یک بردار بازنمایی در خروجی خود تولید میکند. این شبکه همچنین میتواند یک بردار بازنمایی از کل دنباله ورودی را نیز به وسیله بردار بازنمایی CLS تولید کند. تمام هنر شما باید این باشد که پس از درک و فهم مساله، بتوانید با اضافه کردن اندک عناصری بر روی برت، یک شبکه برای پاسخگوی به آن مساله به دست آورید.
برای مثال فرض کنید مسالهای دارید که در آن بایستی با ورودی گرفتن دو جمله تشخیص دهید که آیا این دو جمله با یکدگیر معادل معنایی هستند یا خیر (طبیعتا انشالله برای این مساله دیتاست هم دارید). یک طرح میتواند این باشد که این دو جمله را به یکدیگر بچسبانید و بین آنها توکن SEP را قرار دهید. سپس این دنباله را به عنوان ورودی به برت دهید و بردار بازنمایی CLS متعلق به این دنباله را به دست آورید (فرض کنید اندازه این بردار بازنمایی ۷۶۸ است). حال شما یک بازنمایی از این دنباله دارید و بایستی تعیین کنید که آیا این دو جمله معادل هستند یا نه. برای این کار یک لایه عصبی با اندازه ۷۶۸ به ۲ بر روی این بازنمایی اضافه میکنید. اکنون شما ساختاری دارید که میتواند با ورودی گرفتن دو جمله، توزیع احتمالی از معادل بودن یا نبودن این دو جمله تولید کند. حال نوبت وفقدادن و چکش کاری این ساختار است. در این جا دو استراتژی وجود دارد. در استراتژی اول از برت به عنوان شبکه استخراج ویژگی استفاده می کنیم (به اصطلاح برت را فریز میکنیم) و صرفا با استفاده از دادههای آموزشی صرفا لایه اضافه شده بر روی برت را آموزش میدهیم. در استراتژی دوم اما علاوه بر آموزش لایه اضافه شده بر روی برت به تنظیم وزنهای داخل خود برت نیز میپردازیم (این همان fine-tune کردن است). در واقع این کار باعث میشود تا با اندکی بالا پایین کردن وزنهای داخل برت، شبکه برت بردارهای بازنمایی بهتری برای تسک خاص خودمان تولید کند. استراتژی دوم معمولا جواب بهتری نسبت به استراتژی اول دارد اما از انجایی که نیازمند تغییرات در کل وزن های شبکه است و برت نیز شبکه عظیمی است پس نیاز به میزان حافظه و سخت افزار بیشتری نیز دارد. راهکار بینابینی نیز این وسط است که میتوان از ۲۴ لایه که برت دارد ۱۲ لایه پایینی را فریز کرد و مورد تنظیم قرار نداد و ۱۲ لایه بالا را مورد تنظیم قرار داد.
جمعبندی
در این پست پس از حکایتکردن داستان ایده انتقال یادگیری در پردازش زبان معماری های المو و سپس برت رو معرفی کردیم و نشون دادیم که چطوری این معماری ها بر روی وظایفی نظیر مدل زبانی ماسکشده و تشخیص جمله بعدی و بر روی دادگان عظیم متنی بدون برچسب (که به راحتی قابل دسترس هستند) پیش آموزش میدهند. برت شروع داستان انواع مدلهای زبانی ترنسفورمریه. انشالله در آینده ای نه چندان دور به سراغ بقیه این مدلها هم خواهیم رفت.
در تلگرام میتونید دنبالمون کنید و اگر هم متن خوبی در حوزهی هوش مصنوعی و پردازش زبان طبیعی داشتید که در انتشارات یا کانال بگذاریم، از همونجا ندا بدید.
بازخورد یادتون نره.
مطلبی دیگر از این انتشارات
داستان ترنسفورمرها (۲): attention برمیخیزد!
مطلبی دیگر از این انتشارات
تیپیکال سمپلینگ، تکه گمشده پازل تولید متن توسط رباتها
مطلبی دیگر از این انتشارات
متد gather در pytorch