مقدمه‌ای بر شبکه‌های عصبی بازگشتی (RNNs) - جلسهٔ اول

در اولین جلسه از دوره‌ی «مقدمه‌ای بر شبکه‌های عصبی بازگشتی (RNN)» به بررسی ماهیت این شبکه‌ها و سلول‌های تشکیل‌دهنده‌ آن‌ها می‌پردازیم.تطبیق با دوره ویدئوییقسمت اول (۱۸ دقیقه) – مقدمات شبکه‌های بازگشتیتوجهدر مطالب این دوره تصور شده که خواننده آشنایی مقدماتی با زبان پایتون و شبکه‌های عصبی و پیاده‌سازی آن‌ها با فریم‌ورک‌های Tensorflow و Keras دارد.مقدمهشمایی ساده از یک شبکه بازگشتیتا اینجا تمامی شبکه‌های عصبی عمیق (DNNs) که بررسی کردیم به‌خصوص شبکه‌های عصبی کانولوشنی (CNNs) داده‌های آموزشی را با یک پیش‌فرض مشخص پردازش می‌کردند: «اینکه هیچ ارتباطی بین داده‌های آموزشی وجود ندارد»؛ در واقع هر کدام از داده‌های ورودی شبکه تنها عنصر استخراج ویژگی بودند. در مقابل، شبکه‌های عصبی بازگشتی (Recurrent Neural Networks [RNNs]) نوعی از شبکه‌های عصبی هستند که برای پردازش توالی‌ها و ترتیب‌ها استفاده و در تشخیص الگوهایی که نیازمند چندین مرحله داده‌آزمایی باشند، برای مثال تشخیص الگوها در فریم‌های ویدیو -دنباله‌ای از تصاویر- و یا پردازش‌های زبان طبیعی (NLP) -دنباله‌ای از کلمات- کاربرد فراوانی دارند [۱].مثالبه‌عنوان مثال‌هایی از کاربردهای شبکه‌های بازگشتی، می‌شود به Image Captioning، OCR و Video Classification اشاره کرد. در صورت تمایل در مورد این موضوعات جست‌وجو کنید.روش پردازش توالی‌ها در شبکه‌های بازگشتی با استفاده از یک حلقه در گراف شبکه عصبی است که بازخوردی از خروجی نهایی حالت قبل (خروجی به ازای ورودی قبلی) را ذخیره می‌کند. در شبکه‌های عصبی ساده و شبکه‌های کانولوشنی (CNN) که شبکه‌های پیش‌خور (Feed Forward) هستند، ورودی‌های هر لایه تنها از لایه قبلی بوده و داده‌ها فقط در یک جهت -و با گذشت از لایه‌های میانی- به سمت لایه‌های خروجی حرکت می‌کنند. در این شبکه‌ها، خروجی شبکه به‌ازای هر ورودی به حافظه سپرده نمی‌شود؛ اما در شبکه‌های عصبی بازگشتی (RNN) خروجی مدل (model) در مرحله‌ی قبل به‌عنوان یک حافظه‌ی نهان (Hidden State) همراه ورودی به شبکه بازگردانده می‌شود. این ویژگی باعث می‌شود که الگوریتم بتواند رفتار پویای موقتی را به نمایش بگذارد [۱-۲].حافظه ترتیبیاین نحوه‌ی پردازش ترتیبی داده‌ها، به‌صورت طبیعی در مغز نیز اتفاق می‌افتد؛ برای مثال نحوه‌ی به حافظه سپردن و یادآوری حروف الفبا (به‌عنوان یک توالی از داده‌ها) را در‌نظر بگیرید:الف ب پ ت ث ج چ ح خ د ذ ر ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن و ه یاگر از شما خواسته شود که دنباله‌ی الفبا را پشت‌سرهم بیان کنید به‌سرعت این‌کار را انجام می‌دهید، اما تصور کنید که بخواهیم این دنباله را به‌صورت وارونه بیان کنیم:ی ه و ن م ل گ ک ق ف غ ع ظ ط ض ص ش س ژ ز ر ذ د خ ح چ ج ث ت پ ب الفمتوجه می‌شوید که -اگر از قبل تمرین نکرده باشید- این کار به‌صورت قابل‌توجهی از حالت اول سخت‌تر است و در واقع نیازمند مرور چند باره‌ی دنباله‌ی اصلی‌ست. این نیاز به مرور دنباله در ذهن، هنگامی که بخواهیم از میانه‌ی دنباله، برای مثال از حرف «ط» به بعد را بیان کنیم هم اتفاق می افتد:الف ب ... ط ظ ع غ ف ... ن و ه یدر این حالت، احتمال زیاد در ابتدا با چند حرف اول شروع کرده و پس از آنکه مغز الگوی (pattern) دنباله را به‌خاطر آورد، ادامه‌دادن آن به آسانی قابل انجام خواهد بود.اینکه چرا یادآوری دنباله‌ی الفبا -یا هر دنباله مشابه دیگری- در حالت اصلی و فرمی که اولین‌بار به حافظه سپرده شده ساده‌تر است، ارتباط مستقیمی با حافظه ترتیبی مغز یعنی مکانیزمی که مغز از آن برای شناسایی و یادآوری سریع الگو‌ها (پترن‌ها) استفاده می‌کند، دارد [۱].انواع شبکه‌های بازگشتییک تفاوت دیگر شبکه‌های عصبی بازگشتی نسبت به شبکه‌های عصبی ساده و شبکه‌های عصبی کانولوشنی این است که این شبکه‌ها با داده‌هایی با سایز مشخص کار کرده و ورودی‌های با سایز ثابت (مانند یک تصویر) گرفته و خروجی‌های با سایز ثابت (یک آرایه با طول ثابت از احتمالات هر دسته) تولید می‌کنند؛ به علاوه، این مدل‌ها نگاشت میان ورودی و خروجی را در تعداد مراحل مشخصی (تعداد لایه‌های مدل) انجام می‌دهند.در مقابل شبکه‌های بازگشتی اجازه می‌دهند ورودی‌ها و خروجی‌هایی با توالی‌های متغیر داشته باشیم، از این رو شبکه‌های عصبی بازگشتی از نگاه ورودی/خروجی‌ها به دسته‌های زیر تقسیم می‌شوند:ورودی‌ها قرمز، شبکه RNN سبز و خروجی‌های ممکن آبی. برای مثال،ترجمه ماشین (مانند Google Translator) با استفاده از شبکه‌های «many to many» پیاده‌سازی می‌شود. متن زبان مبدأ به‌صورت یک توالی به شبکه خوراک شده و شبکه متن ترجمه شده را در خروجی برمی‌گرداند.تحلیل احساسات (مانند تشخیص این که آیا این نظر مثبت است یا منفی) در اکثر مواقع با شبکه‌های «many to one» پیاده‌سازی می‌شود. متن مورد تحلیل به شبکه خوراک شده و یک دسته (کلاس [class]) (مثبت یا منفی بودن متن) به‌عنوان خروجی مشخص می‌شود [۳].انواع مختلف شبکه‌های عصبی بازگشتی و تقسیم‌بندی‌های آن‌ها بر اساس ورودی/خروجی را در ادامه دوره به تفصیل بررسی خواهیم کرد.پیش از شروع بررسی شبکه‌های RNN به‌صورت دقیق‌تر و جزئی‌تر، اجازه بدید با یک مثال ساده، نحوه کار این شبکه‌ها و تفاوت‌های آن با شبکه‌های غیر بازگشتی را مرور کنیم:یک مثال ساده - چراغ راهنماییمثال کنترل چراغ راهنمایی توسط شبکه عصبیفرض کنید می‌خواهیم شبکه‌ای آموزش دهیم تا وضعیت یک چراغ راهنمایی را در هر دقیقه تعیین کند، این شبکه باید به این صورت عمل کند که با بررسی وضعیت راه تصمیم به نمایش چراغ با رنگ مناسب بگیرد.وضعیت راهباز بودنبسته بودنوضعیت چراغسبز: اجازه‌ی عبورزرد: کاهش سرعتقرمز: توقف (عدم اجازه‌ی عبور)حالت اولدر اولین حالت، شبکه با بررسی وضعیت راه تصمیم می‌گیرد که چراغ سبز را روشن کند یا چراغ قرمز را. اگر راه باز باشد چراغ سبز و اگر بسته باشد چراغ قرمز روشن خواهند شد:رابطه ورودی‌ها و خروجی‌های مسئله در حالت اول همانطور که مشخص است، وضعیت نهایی شبکه که مشخص‌کننده‌ی وضعیت چراغ راهنمایی خواهد بود کاملاً بستگی به ورودی‌های شبکه که وضعیت راه‌ است دارد. چنین مسئله‌ای، به سادگی توسط یک شبکه پیش‌خور (برای مثال یک شبکه MLP یا هر شبکه‌‌ی دیگری با لایه‌های تمام-متصل) قابل حل است و می‌توانیم هر کدام از وضعیت‌های ورودی و خروجی خود را توسط یک بردار one-hot نمایش بدهیم:بردارهای one-hot ورودی‌ها و خروجی‌هامشخص‌است که برای پیاده‌سازی همچین شبکه‌ای به دو نورون (neuron) در لایه‌ی ورودی و ۳ نورون در لایه‌ی خروجی احتیاج خواهیم داشت.نکتهشبکه در این مسئله، می‌تواند لایه‌های پنهان داشته یا نداشته باشد.(چرا که وزن‌های شبکه قابلیت نگاشت این مقادیر را دارا هستند)چنین شبکه تمام-متصلی را می‌توانیم به‌صورت یک ضرب ماتریسی در نظر بگیریم، با فرض اینکه شبکه‌ی یادگرفته شده (Train شده) است، یک ماتریس وزن (مانند ماتریس تصویر پایین) وجود خواهد داشت که با ضرب کردن آن در ورودی‌ها، خروجی شبکه بر اساس هرکدام قابل محاسبه باشد.نمایش شبکه حالت اول به‌صورت یک ضرب ماتریسی همچنین، می‌توانیم این شبکه را به‌صورت گراف زیر تصویر کنیم. در این گراف دو گره ورودی و سه گره خروجی داریم که یال‌های وزن‌های آن مقادیر ۰ (یال‌های کم‌رنگ) و یا ۱ (یال‌های پررنگ) را خواهند داشت:تصویرسازی ساده‌ای از شبکه در حالت اول، یال‌های تیره ۱ و یال‌های کم‌رنگ ۰حالت دومدر این حالت رویکرد دیگری از مسئله را در نظر گرفته و نحوه‌ی تصمیم‌گیری را کمی تغییر می‌دهیم، حال می‌خواهیم چراغ راهنمایی ما تنها وابسته به وضعیت قبلی خود از چراغ سبز به زرد و سپس به قرمز تغییر وضعیت دهد:رابطه ورودی‌ها و خروجی‌های مسئله در حالت دوم همانطور که مشخص است، وضعیت نهایی شبکه که مشخص‌کننده‌ی وضعیت چراغ راهنمایی خواهد بود، تنها وابسته به وضعیت قبلی شبکه (خروجی قبلی شبکه) است.یادآوریتصویر بالا را با تصویر ابتدای بخش «مقدمه» مقایسه کنید.بنابراین برای پیاده‌سازی همچین مدلی، به شبکه‌ای احتیاج داریم که به‌صورت بازگشتی عمل کرده و خروجی مرحله قبلی خود را به‌عنوان ورودی دریافت کند:نمایش شبکه حالت دوم به‌صورت بازگشتی (RNN)برای پیاده‌سازی همچین شبکه‌ای، از آنجایی که هر وضعیت را با یک بردار one-hot کد می‌کردیم به سه نرون در لایه‌های ورودی و خروجی احتیاج خواهیم داشت.چنین شبکه‌ای را نیز می‌توانیم به‌صورت یک ضرب ماتریسی در نظر گرفته و با فرض اینکه شبکه یادگرفته شده (Train شده) است، یک ماتریس وزن (مانند ماتریس تصویر پایین) وجود خواهد داشت که با ضرب کردن آن در ورودی‌ها، خروجی شبکه بر اساس هرکدام قابل محاسبه باشد.نمایش شبکه حالت دوم به‌صورت یک ضرب ماتریسی چنین شبکه‌ای را می‌توانیم به‌صورت گراف زیر تصویر کنیم که در آن سه گره ورودی و سه گره خروجی داریم و گره‌های ورودی شبکه در واقع همان حالت‌های قبلی شبکه هستند. همچنین، در این تصویرسازی تنها یال‌های با وزن ۱ نمایش داده شده‌اند:تصویرسازی ساده‌ای از شبکه در حالت دوم، شبکه تمام-متصل بوده و تنها یال‌های با وزن ۱ نمایش داده شدهحالت سومحال، حالتی را در نظر بگیرید که تنها وابسته به وضعیت راه (حالت اول) و یا وضعیت قبلی چراغ‌ها (حالت دوم) نباشیم و در واقع در حالتی نزدیک‌تر به واقعیت برای تصمیم‌گیری وضعیت چراغ‌ها وابسته به هم وضعیت راه و هم حالت قبلی چراغ‌ها باشیم. این‌بار قصد رسم شبکه و بررسی آن را نداریم اما بررسی این وضعیت به شناخت شبکه‌های عصبی بازگشتی کمک بسیاری می‌کند:بنابراین، به‌عنوان‌مثال، به‌این صورت عمل می‌کنیم که اگر راه باز است و وضعیت قبلی چراغ قرمز است، چراغ سبز را نشان می‌دهیم، اما اگر راه بسته‌است و وضعیت چراغ اگر سبز بود به زرد و اگر زرد بود به قرمز تغییر می‌کند.نکتهفرض می‌کنیم که هر تغییر وضعیت بین باز یا بسته بودن راه‌ها بیشتر از یک دقیقه طول می‌کشد.یادآوریفواصل زمانی تغییر وضعیت چراغ یک دقیقه هستند.پس در هر مرحله از خوراک این شبکه، علاوه بر ورودی متشکل از وضعیت راه (باز یا بسته بودن) به ورودی دیگری که خروجیِ قبلیِ شبکه را نمایش دهد نیز نیاز داریم. به دلیل پیچیدگی زیاد (ورودی‌ها و وزن‌های هر کدام باعث پیچیدگی زیاد گراف خواهد شد) از رسم شبکه مربوط به حالت سوم خودداری می‌کنیم. اما نکته مهمی که نیاز بود در این مثال فرا بگیریم -علاوه‌بر مشاهده‌ی یک نمونه ساده از شبکه‌هایی بازگشتی در عمل- چرایی نیاز به شبکه‌های دارای اتصالات بازگشتی و چگونگی رفتار آن‌هاست.در این جلسه ابتدا با کلیّات شبکه‌های بازگشتی، انواع و موارد استفاده‌‌ی آن‌ها آشنا شده و همراه یک مثال ساده به‌صورت ابتدایی با یک سلول (گره) شبکه‌های بازگشتی آشنا شدیم و دریافتیم این واحدها دارای دو ورودی هستند. یک ورودی، مانند شبکه‌های پیش‌خور از داده‌های ورودی شبکه گرفته شده ورودی دیگر از وضعیت قبلی واحد.در جلسه بعدی به بررسی دقیق‌تر این واحدهای تشکیل دهنده شبکه‌های بازگشتی پرداخته و در ادامه یک شبکه ساده برای تخمین یک تابع سینوسی پیاده‌سازی می‌کنیم.برای پیاده‌سازی در جلسات آینده از کتابخانه‌ی Keras و زبان پایتون استفاده می‌کنیم.اگر با این کتابخانه یا کتابخانه‌‌های دیگری مثل numpy یا Matplotlib آشنایی ندارید، تا جلسه‌ی آینده فرصت خوبیست مرور کلی‌ای بر آن‌ها داشته باشید.می‌توانید لیست جلسات دوره را در این پست مشاهده کنید.جلسه قبلیجلسه بعدیاین دوره به کوشش علی‌رضا اخوان‌پور به‌صورت ویدئویی تهیه شده و به قلم محمدحسن ستاریان با نظارت ایشان به‌صورت متنی نگارش و توسط بهار برادران افتخاری ویرایش شده‌ست.در صورت تمایل به خرید دوره به صورت ویدئویی می‌توانید با استفاده از کد تخفیف shenasablog_intro از ۲۰ درصد تخفیف بهره‌مند شوید.منابعدر انتهای هر پاراگراف این پست شماره‌ی منبع یا منابعی که در نگارش آن قسمت از آن‌ها کمک گرفته شده ذکر شده، در لیست زیر می‌توانید هر کدام از این منابع را مشاهده و مطالعه کنید:[۱] (با دخل و تصرف) راهنمای مصوری بر شبکه‌های عصبی بازگشتی - Towards Data Science[۲] (خط آخر) ویکی‌پدیا - مقاله «شبکه‌های عصبی بازگشتی»[۳] وبلاگ آندره کارپاسی