شبکه ترنسفورمر
شبکه ترنسفورمر یک شبکه عصبی مدرن است که با کمتر از ده سال سن غوغایی به پا کرده است. در یازدهمین جلسه از دوره یادگیری عمیق رایگان میخواهم به تشریح شبکه ترنسفورمر بپردازم. با آکادمی هوش مصنوعی هوسم همراه باشید…
تولد شبکه ترنسفورمر در گوگل
در سال 2017 مقالهای با نام Attention is All You Need توسط گوگل منتشر شد. بله، این مقالهای بود که در آن شبکه ترنسفورمر پیشنهاد شده بود. این شبکه برای اولین بار برای تسک ترجمه ماشینی یا Machine Translation ساخته شده بود. حرف حسابش چه بود؟
خانمها و آقایان، بیایید شبکههای بازگشتی پرزحمت را کنار بگذاریم!
عجب! یعنی LSTM و سایر دار و دستهاش پر؟! بله، پر! حالا کسانی که آموزش شبکه LSTM ما را خواندهاند، میگویند: “یعنی این همه گیت گیت کردی و مخ ما رو خوردی، الان میخوای بگی که اون رو بذاریم کنار؟!” خب LSTM و سایر شبکههای بازگشتی همچنان کاربرد دارند. اما در تسکهای بزرگ و سنگین، شبکه ترنسفورمر جایگزین شبکه LSTM شده است.
تا پیش از این، محققان گوگل کارهایی در زمینه استفاده از شبکه LSTM برای ترجمه ماشینی داشتند. اما زدند زیر میز و شبکه جدیدی را پیشنهاد کردند. البته، این زیر میز زدن، ناگهانی نبود! بلکه، آرام آرام پیشنهادهایی در راستای بهتر کردن شبکه LSTM، مانند شبکه LSTM با مکانیزم اتنشن ارائه شده بود که نهایتا شبکه ترنسفورمر متولد شد. انتشار این مقاله یک انقلاب بزرگ را در حوزه پردازش زبان طبیعی (NLP) رقم زد که به بهار NLP هم معروف است.
گرد و خاک بهپاکردن شبکه ترنسفورمر
پس از این مقاله، افراد مختلف از آن گفتند، نوشتند، مقاله منتشر کردند، کتابخانه ساختند و … بیایید باهم چند نمونه از کارهای کلیدی بر پایه شبکه ترنسفورمر را مرور کنیم:
- مجموعه هاگینگ فیس (Hugging Face) از همان زمان تولد ترنسفورمر بود که شروع کرد و یک پیادهسازی تروتمیز از شبکه ترنسفورمر در پایتورچ ارائه کرد. حالا دیگر هاگینگ فیس برای خودش شرکت هیولایی شده است.
- شبکه BERT بازهم توسط گوگل پیشنهاد شد که نحوه استفاده از شبکه ترنسفورمر در سایر تسکها مانند مدلسازی زبان، دستهبندی متن، پرسش و پاسخ و غیره را ارائه کرده بود. همچنین، بحث پریترین و فاین تیون کردن در ترنسفورمر هم مطرح شده بود. گفتیم که اولین بار ترنسفورمر برای ترجمه ماشینی ارائه شده بود.
- شبکههای GPT از شرکت OpenAI مطرح شد. همانهایی که باعث شدند ChatGPT جان ساخته شود. 🤗
- شبکه ViT توسط گوگل برای حوزه بینایی کامپیوتر مطرح شد. شبکهای که باعث ورود ترنسفورمرها به دنیای بینایی کامپیوتر شد. یعنی شبکه کانولوشنی هم پَر؟! 😬 نه!
طبیعتا، به همین شکل پیشرفتها ادامه پیدا کرد و این شبکه قرن بیست و یکمی وارد بسیاری از حوزهها مانند پردازش صوت و غیره هم شد. خب این از سرگذشت فوقالعاده ترنسفورمر…
قبل از اینکه تشریح شبکه ترنسفورمر را شروع کنیم، بیایید یک سناریو بسازیم و با آن سناریو پیش برویم.سناریوی دسته بندی متن به دو کلاس مثبت و منفی
فرض کنید، ما دیتاستی به نام IMDB داریم که شامل مجموعهای از کامنت کاربران سایت IMDB هست. میخواهیم این کامنتها را به دو کلاس مثبت و منفی دستهبندی کنیم. کاربری که کامنت خوب و رضایت از فیلم/سریال گذاشته، باید به عنوان کامنت/کلاس مثبت شناخته شود. کامنت منفی هم که مشخص هست. در شکل زیر، نمونههایی از دیتاست IMDB را مشاهده میکنید؛ ستون اول، کامنت کاربر و ستون دوم هم تارگت (Positive/Negative) هست. این دیتاست 49582 نمونه ندارد.
راستی حالا که صحبت از کامنت شد، باید از شما تشکر کنم. در پستهای قبلی آموزش یادگیری عمیق با کامنتها خیلی ما را خوشحال کردید و از شما ممنونیم.
حالا که دیتاست را شناختید، باید برویم سراغ پیشپردازش و آمادهسازی دیتاست! چرا متن ورودی باید پیشپردازش شود؟ چون شبکه عصبی تماما مبتنی بر اعداد و ریاضی هست و ما نمیتوانیم به آن متن بدهیم. باید به شکلی، این متنها را به عدد تبدیل کنیم. طبیعتا روی ستون تارگت هم مشکلی نداریم؛ چون صرفا دو کلمه مثبت و منفی داریم که بهجای آنها یک و صفر قرار میدهیم. در بخش بعدی، درمورد پیشپردازش و آمادهسازی دیتاست توضیح دادهام…
پیش پردازش و آماده سازی متن
رسیدیم به اینجا که متن ورودی را باید به اعداد تبدیل کنیم. حالا چگونه؟ یک ایده رایج این هست که بیاییم ابتدا جمله را به یکسری کلمه تبدیل کنیم. سپس، برای هر کلمه یک بردار ویژگی عددی بسازیم. همانطور که گفتم، ابتدا باید تک تک جملات به لیستی از کلمات تبدیل شوند. به این کار توکنایزیشن (Tokenization) گفته میشود. واقعیت این هست که جمله به لیستی از توکنها تبدیل میشود، نه کلمه! اما فعلا خودتان را درگیر جزییات کار نکنید. فعلا فکر کنید، توکنها تقریبا معادل با همان کلمهها هستند. در زیر نتیجه توکنایزیشن را برای یک نمونه میبینید:
تمرین آیا با پایتون میتوانید جملات بالا را به لیستهای بالا تبدیل کنید؟ یک خط کد نیاز دارد!بعد از توکنایز، باید عمل بردارسازی (Vectorization) انجام دهیم! این عمل، یعنی هر کلمه/توکن به یک بردار معنیدار تبدیل شود. خوشبختانه، امروزه یکسری مدل آماده داریم که به راحتی قابل دانلود و استفاده هستند. مثلا، GloVe که از ما یک کلمه/توکن میگیرد و در خروجی یک بردار به طول مشخص میدهد. مثلا، وقتی توکنهای نمونه بالا را به GloVe میدهیم، برای هرکدام یک بردار عددی به طول 50 میدهد. ببینید:
پس من یک جمله به طول 20 را تبدیل به 20 بردار به طول 50 کردم. کلا یک جمله به طول L را میتوان به یک تنسور به ابعاد LxF تبدیل کرد. L به همان طول جمله (تعداد توکنها) و F هم به طول بردار ویژگی اشاره دارد. حالا باید این بردار ورودی را باید در اختیار شبکه ترنسفورمر قرار دهیم.
طبیعتا، من خیلی خلاصه در مورد پیش پردازش و آماده سازی متن توضیح دادم. برای این پست، همین اندازه کافی است. جزئیات بیشتر را باید در یک آموزش اختصاصی پردازش زبان طبیعی بخوانید. تلاش میکنیم که یک پست مقدماتی خوب برای پردازش متن بنویسیم. بهصورت خلاصه، آنچه باید روی متن ورودی انجام شود این است که:
- دادههای متنی توکنایز شوند.
- هر توکن تبدیل به یک بردار شود. مثلا با word2vec.
قبل از اینکه معماری شبکه ترنسفورمر را توضیح دهم، باید کمی از تسک ترجمه ماشینی بگویم. چون، قبلا گفتم که اولین بار شبکه ترنسفورمر برای ترجمه ماشینی ارائه شد.
ترجمه ماشینی در پردازش زبان طبیعی
ترجمه ماشینی یا Machine Translation یعنی متنی از زبان A به زبان B ترجمه یا تبدیل شود. برای این کار معمولا از ساختار انکدر-دیکدر استفاده میکنند. ساختاری که در آن، یک شبکه به عنوان انکدر وظیفه انکد کردن یا استخراج ویژگی از زبان مبدا (A) را برعهده دارد. سپس، شبکه دیکدر، ویژگیهای استخراجی انکدر را به زبان مقصد (B) تبدیل میکند. ساختار کلی انکدر-دیکدر با تمرکز بر شبکههای بازگشتی در شکل زیر نشان داده شده است.
در شکل بالا، x-ها همان بردارهای توکن زبان A و y-ها هم بردارهای توکن زبان B هستند. ممکن هست، بگویید، چرا شبکه بازگشتی؟ نکته اینجاست که شبکه ترنسفورمر مبتنی بر همین ساختار انکدر-دیکدر کار ترجمه را انجام میدهد. با این تفاوت که در اینجا صرفا یک لایه انکدر و دیکدر داریم. اما در شبکه ترنسفورمر تعدادی زیادی لایه انکدر و دیکدر داریم. در ادامه، بیشتر در مورد این مطلب صحبت میکنم…
بالاخره بعد از کلی مقدمهچینی، رسیدیم به اصل مطلب، شبکه ترنسفورمر…
شبکه ترنسفورمر Transformer
اگر بجای بخش انکدر و دیکدر در شکل بالا، مجموعه لایههای انکدر و دیکدر شبکه ترنسفورمر را قرار دهیم، آنگاه شبکه ترنسفورمر ساخته میشود. در شکل زیر، بهصورت کلی این ساختار نشان داده شده است. مجموعهای لایه انکدر که بهصورت متوالی قرار گرفتهاند و بخش انکدر را ساختهاند. به صورت مشابه، مجموعهای لایه دیکدر بهصورت متوالی بخش دیکدر شبکه ترنسفورمر را ساختهاند.
نکته جالب اینجاست که خروجی بخش انکدر که ویژگی غنی و ارزشمند است، به تک تک لایههای دیکدر وارد میشود. چطوری؟ حالا فعلا جزئیات رو بگذار کنار و به کلیات توجه کن.
در شبکههای بازگشتی بخش انکدر و دیکدر کاملا یکی هستند. اما در شبکه ترنسفورمر، لایه انکدر و دیکدر یکی نیستند و باهم تفاوتهایی دارند. بنابراین، باید هرکدام بهصورت جداگانه بررسی شوند.
البته، نکته خوشحالکننده اینجاست که ساختار انکدر-دیکدر برای مسالههای دنباله به دنباله یا Sequence to Sequence (مثلا ترجمه ماشینی) کاربرد دارد. برای مسائلی مثل دستهبندی، رگرسیون و مدلسازی زبان همان بخش انکدر کافی است و اصلا به دیکدر نیازی نداریم. من هم اینجا میخواهم با سناریوی دستهبندی جلو بروم. پس فعلا فقط بخش انکدر را به شما توضیح بدهم. بعدا، خودتان میتوانید با دوره یادگیری عمیق هوسم یا به هر شکل دیگری بخش دیکدر را هم یاد بگیرید. برویم سراغ تشریح لایه انکدر در ترنسفورمر…
لایه انکدر در شبکه ترنسفورمر
همانطور که در شکل بالا نشان داده شد، بخش انکدر از تعدادی لایه انکدر تشکیل شده است. این لایهها باهم فرقی ندارند و صرفا بهصورت متوالی قرار گرفتهاند. چرا؟ اگر با سایر شبکههای عصبی آشنا باشید، انتظار دارم جوابش را بدانید. ما در همه شبکهها مثل شبکه MLP یا CNN یکسری لایه روی هم قرار میدادیم که ظرفیت یادگیری شبکه بالاتر رود و ویژگیهای ارزشمندتری استخراج کند. اینجا هم طبیعتا همین قاعده برقرار هست. حالا بیایید بزنیم به دل این لایههای انکدر…
در دل یک لایه انکدر ترنسفورمر دو ماژول اصلی قرار گرفته است:
- ماژول Multi-Head Attention
- ماژول Feed Forward
ماژول Feed Forward بسیار ساده هست و همان MLP است. اما ماژول Multi-Head Attention مهم هست و پیچیدگیهایی دارد. هرچه هست، زیر سر همین ماژول Multi-head Attention هست! اصلا برگردیم به ابتدای این پست! اسم مقاله شبکه ترنسفورمر چه بود؟ Attention is All You Need. میگوید اتنشن همه آن چیزی است که نیاز دارید. خب، تا همین جا فهمیدیم که قلب تپنده این شبکه Multi-head Attention هست. اتفاقا این ماژول در سمت دیکدر هم وجود دارد!
فان اسم مقاله چه بود؟ Attention is All You Need. علاوهبر محتوای علمی این مقاله، عنوان این مقاله هم جریانساز بود! بعد این مقاله، کلکسیونی از مقالات علمی منتشر شد که اسمشان به شکل زیر بود. دیگه واقعا جا داشت که بگوییم چه خبرتونه، چه خبرتونه؟! (لطفا با لحن دکتر بخونید!)
is All You Need …
قبل از اینکه وارد جزئیات هریک از ماژولها شویم، میخواهم جزئیات بیشتری از لایه انکدر را به شما نشان دهم. به شکل زیر نگاه کنید؛ همان بردارهای توکن که در بخش قبلی توضیح دادیم، باید وارد این لایه شوند. بهصورت کلی، ورودیهای X فرآیند زیر را طی میکنند:
- بردارهای X وارد ماژول Multi-Head Attention میشوند.
- سپس، خروجی Multi-Head Attention بدست میآید.
- خروجی Multi-Head Attention وارد ماژول Feed Forward میشوند.
- درنهایت، خروجی Feed Forward با نماد Z بدست میآید.
نکته به شکل بالا نگاه کنید؛ ما سه ورودی X1 X2 X3 داریم. تعداد خروجی هر ماژول به همان تعداد ورودی هست. یعنی درنهایت، سه خروجی Z1 Z2 Z3 داریم.
در ادامه میخواهم درباره Multi-head Attention و Feed Forward صحبت کنم. طبیعتا عمده صحبت ما معطوف به Multi-Head Attention خواهد بود.
ماژول Multi-Head Attention در شبکه ترنسفورمر
قبل از هرچیزی بگویم که از ساختار ماژول Multi-Head Attention نترسید! 😅 شاید ظاهرش سخت به نظر برسد، اما ته دلش چیزی نیست! ساختار این ماژول را در شکل زیر آوردهام.
به شکل بالا دقت کنید؛ یکسری بلوک وجود دارد که بهصورت موازی با هم قرار گرفتهاند. دو بلوک Concat و Linear (همان لایه فولی کانکتد) هم در آخر کار قرار گرفتهاند که فقط یکی هستند. کاملا واضح هست که بلوک Concat ورودیهای موازی و متعدد را بههم الحاق میکند. فعلا بیایید Concat و Linear آخر را کنار بگذاریم. برویم سراغ بلوکهای موازی…
این موازی بودن بلوکها به همان عبارت Multi-Head اشاره دارد. یعنی ما چند Head یا سر داریم که بهصورت موازی باهم قرار گرفتهاند. از قرار معلوم همه شبیه هم هستند، پس فعلا میتوانیم تعداد Head یا h را برابر با 1 درنظر بگیریم که شکل بالا بهصورت زیر ساده شود. حالا بهتر میتوانیم بلوکهای مختلف این ماژول را ببینیم.
نکته به این قسمت از شبکه ترنسفورمر که در شکل بالا نشان داده شده، ماژول Self-attention هم گفته میشود. بعد از پایان این وبلاگ، حتما این عبارت را گوگل کنید.
نکته جالب اینجاست که ورودی x در شکل بالا، به سه لایه Linear یا همان لایه فولی کانکتد مجزا میرود. سپس، سه خروجی V Q K ساخته میشود. این سه حرف نماینده سه کلمه معروف Value Query Key هستند. شاید قبلا جایی شنیده باشید. اگر هم نشنیدهاید که هیچ، مهم نیست… حالا سه تنسور V Q K وارد ماژولی بهنام Scaled Dot-Product Attnetion میشوند. برویم ببینیم در این زیرماژول چه خبر است…
زیرماژول Scaled Dot-Product Attnetion
همانطور که تا اینجا گفتیم، این زیرماژول در دل Multi-Head Attention قرار دارد. اما میخواهیم ببینیم چه بلایی سر سه ورودی V Q K میآورد؟ چیزی که از شکل مشخص است این هست که سه ورودی V Q K دریافت میکند و یک خروجی Z میدهد. بلوک دیاگرام زیرماژول Scaled Dot-Product Attnetion را در شکل زیر نشان دادهام. چیزی نیست جز ضرب ماتریسی و یکمی هم فلفل و نمک! عجب! این همه راه ما را کشانده و هی بلوکهای تودرتو را پشت سر گذاشتهایم تا به عملگر ضرب ماتریسی برسیم؟ بله! و چقدر این ضرب ماتریسی در یادگیری ماشین و یادگیری عمیق اهمیت دارد…
کل بلوک دیاگرام بالا معادل با فرمول زیر است:
نکته بعد از ضرب QKT باید scale که همان رایکال مخرج است را انجام دهیم. اتفاقا به همین خاطر هست که در این زیرماژول کلمه Scaled داریم. متغیر dK هم به طول بردار K اشاره میکند. همان F! چرا K؟ فرقی نمیکند. K و Q باهم برابرند. شاید در یادگیری ماشین دیده باشید؛ این مقیاس نقش Temperature را برای سافتمکس دارد. میتواند رفتار Softmax را به Argmax نزدیک کند یا از آن فاصله بگیرد و نسخه Soft ارائه دهد.
نکته ما میدانیم خروجی سافتمکس اعداد نرمالیزهشده بین 0 و 1 است. در واقع، ما از طریق K و Q یکسری Score یا وزن میسازیم و بردارهای موجود در V را وزندهی میکنیم.
بسیارخب، برگردیم به همان Multi-Head Attention… در همین بخش گفتیم که ما از همین Slef-Attention یکی نداریم، بلکه چندتا داریم که موازی باهم قرار گرفتهاند. بیایید این بار h را برابر با 3 درنظر بگیریم؛ در شکل زیر، این ماژولهای موازی را کنار هم نشان دادهام. اصل کلام این هست که ورودی LxF از بعد F باید به 3 تکه تقسیم (Split) شود و بعد هر تکه وارد یکی از این سه ماژول شود.
درنهایت، وقتی سه خروجی را بدست آوردیم، با همان Concat اینها رو دوباره از بعد F به هم میچسبانیم و تحویل لایه Linear میدهیم. تماممم!
به قول ژوله: “چقدر سخت بود، چقدر تلخ بود!” خسته شدم! 😫 وقتی از این کار آموزش دادن خسته میشم، عمیقا به بازنشستگی فکر میکنم! چند سال دیگه میتونم آموزش بدم؟! نمیدانم! واقعا نمیدانم!
ادامه دارد…
مطالب زیر را حتما مطالعه کنید
روش اعتبارسنجی متقابل یا cross validation چیست
مقایسه تنسورفلو و پایتورچ
شبکه عصبی GRU
یادگیری عمیق چیست
شبکه عصبی کانولوشن
آموزش matplotlib در پایتون
6 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
ممنون از آموزش بسیار عالی که ارائه کردید.
عاالی بود. فوق العاده بود. خیلی ممنون.
سلام. من نزدیک 15 سال هست که تدریس می کنم. تو تدریس یکی از ادعاهایی که دارم اینه که میتونم خیلی خوب و ساده مطلب رو توضیح بدم. اما وقتی سایت شما رو دیدم، کم آوردم و دیدم ماشالله شما خیلی کارت درسته و عالی توضیح میدی.
انشالله همیشه موفق باشی
سلام میثم عزیز،
از خوندن پیام شما خوشحال شدیم و انرژی گرفتیم.
موفق باشید.
سلام
مثل همه پست ها بسیار عالی و قابل فهم و در عین حال فنی توضیح می دهید. برعکس بسیاری از سایت ها که فقط یک کلیات می گویند.
لطفا این پست رو کامل کنید
با تشکر
سلام
ممنون سعید عزیز،
پست کمکم در حال تکمیل هست. چیزی تا تکمیل پست نمونده.