یه بار توی کامنتی از یکی از همین پست های ویرگولم، یه بنده خدایی منو به چالش توضیح دادن شبکه های عصبی مصنوعی (Artificial Neural Networks) دعوت کرد. بنده هم به مثال Barney توی سریال HIMYM، گفتم: «!!Challenge Accepted»?. احتمالا قراره این مطلب کمی طول بکشه ولی بهتون قول میدم که تاحالا این دیدگاه رو از شبکه های عصبی ندیدین! به جای شروع با توضیحات non-sense و گیج کننده مثل هر مطلب دیگه ای، باید یه مفهوم رو بهتون منتقل کنم! خب! بریم که رفتیم!
شبکه ی عصبی مصنوعی چیه؟ اگه بگم الگوریتم، درست گفتم، اگه بگم روش محاسباتی درست گفتم و اگه بگم تابع هم درست گفتم. ولی بیاین بچسبیم به همین تعریف تابع طور. شبکه ی عصبی یه تابع خیلی گنده اس که ورودی ایکس رو میگیره و یه سری محاسبات عجیب و غریب انجام میده و ایگرگ رو خروجی میده. مثل هر الگوریتم Supervised دیگه ای! حالا این ایگرگ میتونه یه مقداری رو پیش بینی کنه (یعنی Regression) یا یه تشخیصی رو انجام بده (یعنی Classification) که بیشتر با این مورد دومی کار داریم. خب فعلا این تعاریف رو همینجا نگه داریم و بریم با یه وسیله خیلی باحال آشنا شیم که کلید یاد گرفتن مفهوم شبکه های عصبیه!
تاحالا اسم تخته گالتون (Galton Board) به گوشتون خورده؟ اگه نه، گیف پایین رو نگاه کنین!
تخته گالتون یه دستگاهه مثل یه ساعت شنی، با این تفاوت که به جای دونه های شن، تعداد زیادی گوی فلزی داره. این توپ ها از بالا رها میشن و از یه مسیر مثل عکس پایین عبور میکنن:
گوی ها به اون موانع شیش ضلعی میخورن (موانع میتونن دایره ای یا مثلثی هم باشن) و مسیرشونو عوض میکنن و در نهایت میفتن توی یه سری مخزن. به طور کلی هم شکل قرارگیری نهایی گوی ها، توزیع گاوسی (Gaussian Distribution) یا همون توزیع نرمال (Normal Distribution) هست. اگه نمیدونین اینا چین، عیب نداره! اصن کاری با این دو عزیز نداریم! فقط کافیه بدونین که این دستگاه هم یه جور تابعه که گوی های ایکس رو از مسیرهایی میگذرونه و میریزه توی مخزن ایگرگ.
حالا ببینین این دستگاه نسبتا نامربوط چقد قشنگ شبکه های عصبی رو توضیح میده:
شبکه ی عصبی مجموعه ای از اون موانع شیش ضلعیه که میتونن گوی های فلزی ایکس رو دریافت کنن و پاس بدن به یه مانع شیش ضلعی دیگه توی لایه بعدی و اونقدر این پاس کاری رو ادامه بدن تا در نهایت بندازنش توی مخزن درست!
حالا بیاین تخته گالتون رو یکم پیشرفته تر کنیم. نظرتون چیه شکل یکی از موانع شیش ضلعی رو مقداری عوض کنیم:
طبق این عکس اگه تغییر کوچیکی توی شکل یه مانع ایجاد کنیم، میتونیم گوی های خاصی رو به جهتی که میخوایم هدایت کنیم. یه تغییر دیگه هم میتونیم ایجاد کنیم:
توی این نوع تغییر هم گوی هایی که مسیر مستقیم میرن و به مانع برخورد نمیکنن، با بزرگتر کردن ابعاد به مانع میخورن و مسیرشون عوض میشه. همینطور برعکس! ینی اگه مانع کوچیکتر بشه گوی های که قبلا به مانع میخوردن ممکنه مسیر مستقیم برن. حالا چی میشه اگه این دو نوع تغییر رو بر حسب نیاز روی تمام موانع ایجاد کنیم!؟ میتونیم به کمکش توابع پیچیده تری به غیر از توزیع گاوسی ایجاد کنیم!! مثل عکس زیر:
حالا هدف از بیان این ها چی بود؟ ما به کمک دو سوال ساده ی «گوی به مانع بخوره یا نه» و «اگه به مانع بخوره سمت چپ بره یا راست» میتونیم تصمیم بگیریم که چه نوع خروجی ای رو داشته باشیم. یه شبکه ی عصبی هم همین کار رو انجام میده. به کمک این دو سوال میتونیم دو تا مفهوم کلیدی توی شبکه های عصبی رو معنی کنیم. فرض کنید موانع همون نورون ها باشن. اولین مفهوم وزن (Weight) هست که یه عدده که میزان ارتباط هر نورون با نورون دیگه رو مشخص میکنه. با مثال تخته ی گالتون یعنی احتمال اینکه هر گوی بخوره به کدوم مانع توی لایه بعدی. هر چی این وزن بزرگتر باشه، ینی رفتن گوی از مسیری که ختم میشه به اون مانع، محتمل تره. این مفهومیه که میتونیم با تغییر شکل موانع تنظیمش کنیم. ینی مثلا یه بخش به سمت چپ مانع اضافه کنیم تا احتمال رفتن گوی ها به سمت راست بیشتر بشه و در نتیجه وزن مسیر های سمت راست. نکته ای که می مونه اینه که توی شبکه ی عصبی ممکنه از یه نورون بتونیم به هر نورونی توی لایه ی بعد بریم، درحالی که در عمل توی تخته ی گالتون، مانع میتونه فقط به مانع چپ یا راستی لایه بعدی منتهی بشه.
مفهوم دوم که مقداری پیچیده تره، فعالیت (Activation) هر نورونه. با توجه به اسمش هم یعنی چه میزان اون نورون فعاله (و چقد اون مانع توی تصمیم گیری برای تغییر جهت مسیر گوی تاثیرگذاره). به طور تقریبی میتونیم این مفهومو همون اندازه ی مانع تعبیر کنیم. هرچی اندازه ی مانع بزرگتر باشه میتونه روی گوی های بیشتری تاثیر بذاره و برای مسیرشون تصمیم گیری کنه. برای اینکه مثال تخته ی گالتونی رو شبیه تر به شبکه ی عصبی کنم:
طبق این عکس، مانع بزرگتر شده و مسیر یه گوی بیچاره رو جوری که ما میخوایم تغییر داده. اما این میزان فعالیت رو چجوری میتونیم تعریف کنیم؟ شبکه عصبی اینطور فعالیت هر نورون رو برامون تعریف میکنه:
هر وزن رو با فعالیت اون نورونی که وزن ازش خارج شده ضرب کنید. حاصل ضرب هارو جمع کنید. به جمع یه عدد به اسم بایاس (Bias) اضافه کنید. این جمع رو از توی یه تابع فعالساز بگذرونید. خروجی میشه فعالیت اون نورون!
خب. تعریف پیچیده ای شد. بیاین ساده ترش کنیم. به این عکس نگاه کنین:
توی مثال تخته ی گالتون، یعنی بیاین برای به دست آوردن بزرگی یا فعالیت مانع شماره ی فلان، به صورت بازگشتی، فعالیت های موانع لایه قبلی رو در وزن مسیرشون به مانع کنونی ضرب کنین و این ضرب ها رو با یه مقداری به اسم بایاس جمع کنین (توضیحشو میذارم واسه ی بعد) و این حاصل جمع رو ورودی بدین به یه تابع. ما پس تونستیم میزان بزرگی و تاثیرگذاری یه مانع رو برحسب وزن ها و بزرگی موانع قبلش به دست بیاریم. منطقی هم هست. اگه موانع قبلی فعالیتشون بالا باشه (برای مسیر تعداد زیادی از گوی های تصمیم گیری کنن) و از طرفی وزن های وارد شده به این مانع بزرگ باشن (گوی ها شانس زیادی برای برخورد با این مانع داشته باشن) پس این مانع بزرگی (تاثیرگذاری) زیادی داره. پس این دوتا عامل توی بزرگیِ بزرگی(!) تاثیر مستقیم دارن. حالا اون تابع فعالساز یا ()g چیکاره اس؟
اگه این تابع وجود نداشته باشه، شبکه ی عصبی ما عملا با رگراسیون خطی معادل میشه. ینی خروجی نهایی شبکه مون یه ترکیب خطی از ورودی میشه. توی مطلب بعدی با توضیح Forward Propagation میتونم کاملتر این مطلب رو توضیح بدم. فعلا بپذیرین که به شدتتت به این تابع نیاز داریم!?
توابع فعالساز دو دسته ان: خطی و غیر خطی. خطی ینی y = x و عملا ینی تابع فعالساز نداشته باشیم. دسته ی دوم هم که غیر خطی باشه، تابعیه مثل همین سیگموید. البته توی عمل میتونیم از توابع دیگه ای هم به عنوان تابع فعالساز استفاده کنیم که از سیگموید بهتر عمل میکنن. توابع غیر خطی مثل ReLU و Leaky ReLU و ... که خودتون میتونین بعدا راجبشون بخونین و اینجا بهتره بهشون نپردازم. کافیه بدونین که وظیفه ی این توابع غیر خطی، سازگار شدن با پیچیدگی های ورودیشونه.
حالا مقداری از نحوه ی عملکرد شبکه های عصبی بگم. یه سوال بزرگ که احتمالا توی ذهنتون شکل گرفته اینه که، مگه ما میتونیم یه کار خیلی پیچیده ای مثل هدایت گوی ها به مخزن درست رو انجام بدیم؟ اصن مگه میشه بیایم به ازای هر گوی، مسیرشو ببینیم و موانع رو جوری تغییر بدیم که گوی بره به جای درستش؟ متاسفانه خیر؛ ما نمیتونیم این کار رو انجام بدیم. اما شبکه ی عصبی این توانایی رو داره که خودش رو با توجه به خواسته ی ما وفق بده. اینجا باید گریز بزنم به مفاهیم پایه یادگیری نظارت شده ماشین (Supervised Machine Learning). اگه مطالب قبلیمو خوندین، توی تمام اون ها ما مقداری داده به سیستم میدادیم تا الگوریتمی رو ازشون کشف کنه و بتونه پیش بینی هایی بر حسب اون چه که یاد گرفته انجام بده. تو شبکه های عصبی هم همینجوریه. ما داده هایی رو به شبکه ی عصبی میدیم، و شبکه ی عصبی خودش رو با توجه به اون وفق میده و میتونه برای دیتاهای جدید، پیش بینی رو انجام بده.
خیلی راحت میشه این مفاهیم رو با مثال تخته ی گالتون توضیح داد. فرض کنین یه تخته ی گالتون ورژن 2023 داریم که میتونه شکل و اندازه ی موانعش رو تغییر بده! یه گوی قرمز رنگ میندازیم داخل و به تخته میگیم که این گوی باید بره تو مخزن شماره یک. تخته موانعش رو جوری تغییر میده که به ازای هر گوی قرمزی که میگیره، هدایتش کنه به مخزن شماره یک. حالا یه گوی آبی میندازیم و به تخته میگیم این گوی رو بنداز تو مخزن شماره 2. همین کار رو برای یه گوی زرد هم انجام میدیم و مشخص میکنیم که بره به مخزن شماره ی 3. حالا تخته ی گالتون «یاد گرفته» که گوی قرمز میره مخزن یک، آبی میره مخزن دو و زرد میره مخزن سه. ما به اصطلاح مرحله تمرین دادن (Training) رو انجام دادیم. حالا میتونیم یه گوی با هر رنگی رو بندازیم داخل تخته و تخته با توجه به اینکه مقدار قرمز یا آبی یا زرد توی اون رنگ بیشتره، میندازتش توی مخزن درستش! اینجا مدل تخته ای مون رو تست (Test) کردیم.
خب فکر میکنم برای این بخش کافی باشه چون میخواستم فقط به مفهومش بپردازم (= احتمالا یه مطلب دیگه هم بنویسم درباره ی Forward Propagation و Back Propagation که الگوریتمهایی هستن که باعث میشن شبکه عصبی بتونه وزن های خودشو تغییر بده و در نتیجه بتونه پیش بینی درستی رو انجام بده. منتظر بخش دوم باشین!