خیلی تعریف دوره Machine Learning Specialization از Andrew Ng رو شنیده بودم، بالاخره گفتم بشینم ببینمش و یه خلاصه از نکات مهمش بنویسم. تصمیم گرفتم از هفته اول کورس «Supervised Machine Learning: Regression and Classification» که سال 2022 توی کورسرا برگزار شده، شروع کنم.
این دوره Machine Learning Specialization کلاً از سه تا بخش اصلی تشکیل شده:
حالا قراره تو اینجا خلاصه نکات هفته اول از کورس اول رو باهاتون به اشتراک بذارم.
خب، بریم سراغ اصل مطلب. دو نوع اصلی از یادگیری ماشین داریم: Supervised Learning و Unsupervised Learning. البته یه نوع سوم هم هست به اسم Reinforcement Learning، ولی دو تا دسته اول بیشتر توی کارای روزمره استفاده میشن. از بین اینا، Supervised Learning بیشتر مورد توجه و استفاده است و خیلی سریع هم داره توسعه پیدا میکنه.
شاید شنیده باشیم که Supervised Learning توی خیلی از جاها کاربرد داره. مثلا تو تبلیغات آنلاین، ترجمه ماشینی یا تشخیص صدا. قشنگیش اینه که توی این روش، ما به ماشین یه سری داده (ورودی) و جواب صحیح میدیم، و اون با این اطلاعات یاد میگیره تا برای دادههای جدید، جواب درست پیدا کنه.
حالا اولین چیزی که توی دسته Supervised Learning بررسی میکنیم، Regression هست. توی رگرسیون، وظیفه اصلی ماشین اینه که یه عدد رو پیشبینی کنه. مثلا با کشیدن یه خط یا منحنی، یا حتی با رسم یه تابع، میفهمیم که اون عدد چیه.
بعد از رگرسیون، میرسیم به دسته دوم Supervised Learning که اسمش Classification هست. تو این روش، کار ما دستهبندی دادههاست. مثلا یه کاربردش توی تشخیص غدههای سرطانیه. اینجوری که میایم میگیم اگر غده سرطانی باشه، عدد 1 و اگه نباشه، عدد 0 رو بهش میدیم. یعنی برخلاف Regression که با بینهایت عدد سروکار داشتیم، اینجا فقط با چند تا دسته مشخص سر و کار داریم، مثل همون 0 و 1.
در کل، Classification یعنی پیشبینی دستهبندیها. خروجیهاش هم همیشه محدوده و به همون دستههایی که تعریف کردیم، خلاصه میشه.
حالا بریم سراغ دسته دوم یادگیری ماشین که Unsupervised Learning هست. همونطور که قبلاً گفتم، تو Supervised Learning ما جواب درست رو از قبل به ماشین میدادیم که یاد بگیره. ولی تو Unsupervised Learning دیگه نیازی به این کار نیست. اینجا ما به دادهها برچسب نمیزنیم که مثلا این غده سرطانیه یا نه. هدف اینه که دادههای خام رو به ماشین بدیم و خودش بیاد الگو پیدا کنه یا دستهبندیهای جالب از توی اون دادهها استخراج کنه.
حالا که Unsupervised Learning رو فهمیدیم، میرسیم به اولین دستهاش که اسمش Clustering هست. توی Clustering، الگوریتم میاد و دادهها رو خودش گروهبندی میکنه. مثلاً Google News رو در نظر بگیر؛ وقتی میخوای چیزی درباره پاندا بخونی، برات همه خبرهایی که به پاندا، دوقلوهاش یا باغ وحش مربوط میشه رو کنار هم قرار میده. این یعنی الگوریتم بدون اینکه بهش بگی کدوم خبر مهمه یا مربوط به چیه، خودش دستهبندی میکنه.
یه مثال دیگه اینکه الگوریتم بیاد بگه شما ۳ نوع مشتری داری: دسته اول اونایی که دنبال ارتقای شغلیان، دسته دوم کسایی که میخوان با هوش مصنوعی آشنا بشن، و دسته سوم اونایی که برای کاربردهای شخصی دنبال اطلاعات میان. یعنی دادهها رو میگیریم و الگوریتم بهشون برچسب (label) میزنه و دستهبندیشون میکنه.
البته Clustering تنها حالت Unsupervised Learning نیست. یه حالت دیگه اینه که الگوریتم به جای اینکه به دادهها برچسب بزنه، دنبال پیدا کردن یه الگو توی دادهها باشه. این روشا هم خیلی کاربردیان.
مثلاً توی Anomaly Detection (تشخیص ناهنجاری)، الگوریتم میتونه نقلوانتقالات غیرمعمول بانکی رو تشخیص بده یا بحران مالی رو شناسایی کنه. اینجوری میشه که دادههایی که از رفتار طبیعی فاصله گرفتن، سریع تشخیص داده میشن.
یه روش دیگه هم داریم به اسم Dimensionality Reduction که هدفش فشرده کردن دادههای خیلی بزرگه. مثلا وقتی با دیتاستهای عظیم طرفیم، این روش میاد حجم اطلاعات رو کم میکنه، ولی در عین حال، بخش زیادی از اطلاعات اصلی رو حفظ میکنه. این باعث میشه که پردازش دادهها راحتتر و سریعتر بشه، بدون اینکه ارزش اصلی دادهها از دست بره.
خب، حالا که رسیدیم به اینجای بحث، یه مرور کلی کنیم. Classification برای دستهبندی دادههای گسسته استفاده میشه، مثل همون 0 و 1 که گفتیم. از طرف دیگه، Regression برای دادههای پیوسته هست، مثل پیشبینی قیمت یه خونه.
توی ماشین لرنینگ، به مجموعه دادههایی که برای آموزش مدل استفاده میکنیم، میگیم Training Set. ورودیهامون رو با xxx نشون میدیم که بهش Feature هم میگیم. خروجی یا همون هدف مدل رو با yyy نشون میدیم، و متغیری که ماشین قراره پیشبینی کنه، y^\hat{y}y^ هست. به این توابع هم میگیم Model.
حالا بریم سراغ یه قسمت مهم تو یادگیری ماشین: تابع هزینه یا همون Cost Function. برای رگرسیون خطی، رایجترین تابع هزینه Squared Error Cost Function هست که فرمولش اینه:
اون ضریب 1/2 هم برای اینکه بعداً وقتی مشتق میگیریم، راحتتر بشه محاسبات رو ساده کرد.
کل این فرمول داره میزان خطایی که مدلمون در پیشبینی دادهها مرتکب شده رو اندازهگیری میکنه. یعنی هر چی فاصله بین پیشبینیو مقدار واقعی کمتر باشه، خطا یا هزینه کمتر میشه. هدف ما اینه که این مقدار خطا، یعنی Cost Function، رو به حداقل برسونیم.
حالا هر چی ضرایب w و b (یا همون وزنها) رو بهتر انتخاب کنیم، مقدار Cost Function کمتر میشه و مدل دقیقتر میشه. کل هدف اینه که ضرایب رو جوری پیدا کنیم که مقدار Cost Function یا همون Jکمینه بشه.
اگه تو رگرسیون خطی مقدار b رو صفر در نظر بگیریم، Cost Function یه نمودار سهمی شکل (parabola) میشه. اما اگه b صفر نباشه، اون وقت شکل سهبعدی تابع هزینه مثل یه Hammock (ننو) درمیاد، که نشوندهنده پیچیدگی بیشتری توی جستجو برای کمینه کردن تابع هزینه است.
خب، یکی از راههایی که به جای نمایش سهبعدی تابع هزینه استفاده میکنیم، Contour Plot یا نمودار همتراز هست. توی این روش، به جای اینکه سهبعدی با ارتفاع و پیچیدگی طرف باشیم، میایم و همه نقاطی که مقدار J یکسان دارن رو روی یه منحنی قرار میدیم. این منحنیها مثل دایرههای هممرکز میمونن. هرچی به مرکز این دایرهها نزدیکتر بشیم، مقدار J یا همون خطا کمتر میشه و هرچی از مرکز دور بشیم، J بزرگتر میشه.
تو حالت سهبعدی، ارتفاع نمایانگر مقدار J بود. ولی توی این نمودار دوبعدی، ارتفاعهای مختلف توسط منحنیهای همتراز نمایش داده میشن. اینجوری کار ما خیلی سادهتر میشه، چون میتونیم توی یه نمودار دوبعدی تغییرات J رو دنبال کنیم.
حالا سؤال اینه: چطوری ضرایب w و b رو جوری تنظیم کنیم که J کمینه بشه؟ خب، اگه خودمون بخوایم دستی این کار رو انجام بدیم، هم زمانبره و هم بهصرفه نیست. اینجاست که الگوریتم گرادیان کاهشی (Gradient Descent) وارد عمل میشه.
خب، Gradient Descent بهصورت اتوماتیک مقدارهای بهینه برای w و b رو پیدا میکنه و از این الگوریتم برای آموزش مدل استفاده میشه. طوری کار میکنه که با هر بار حرکت، ضرایب رو طوری تغییر میده که مقدار J کمتر و کمتر بشه، تا جایی که به کمینه یا همون پایینترین مقدارش برسه.
در واقع، Gradient Descent نهتنها برای رگرسیون خطی کاربرد داره، بلکه برای کمینه کردن هر نوع تابعی میتونه استفاده بشه، حتی توی یادگیری عمیق (Deep Learning) هم یکی از اصلیترین روشهاست.
خب، توی الگوریتم گرادیان کاهشی، اول از همه باید یه حدس اولیه برای ضرایب w و b بزنیم. نکته مهم اینه که برای رگرسیون خطی، اهمیتی نداره حدس اولیهمون چی باشه. برای سادگی، معمولاً مقدار w و b رو برابر صفر قرار میدیم. بعدش شروع میکنیم به مقداردهی دوباره به این ضرایب تا به کمینه تابع هزینه J برسیم.
حالا ممکنه بسته به تابع هزینهای که داریم، چندین نقطه کمینه موضعی (Local Minimum) وجود داشته باشه. ولی اینو نباید فراموش کنیم که برای تابع رگرسیون خطی، همیشه یه نقطه کمینه گلوبال (Global Minimum) داریم؛ یعنی نقطهای که پایینترین مقدار J رو داره و الگوریتم همیشه به اون میرسه.
یه جورایی میتونیم این الگوریتم رو اینطوری تجسم کنیم: فرض کن بالای یه سری تپه ایستادی و هدفت اینه که بری به پایینترین نقطه دره. قدم به قدم حرکت میکنی و هر بار اطراف رو بررسی میکنی که ببینی باید به کدوم سمت بری تا به پایینترین نقطه برسی. بسته به حدس اولیهای که زده بودی، ممکنه به نقاط کمینه مختلفی برسی، ولی توی رگرسیون خطی، همیشه یه نقطه اصلی داریم که همون کمینه گلوبال هست.
حالا بریم سراغ فرمول گرادیان کاهشی:
توی این فرمول:
هدف اینه که این دو معادله برای w و b رو همزمان حل کنیم. این کار رو اونقدر ادامه میدیم تا به نقطه همگرایی برسیم؛ یعنی جایی که تغییرات توی ضرایب دیگه محسوس نیست و به کمینه تابع هزینه رسیدیم.
همزمان حل کردن دو معادله به این معنی که w قدیمی توی معادله b استفاده میشه.
اینجوری هم میتونیم بگیم، ما قراره Cost Function رو کمینه کنیم ، پس اگه مشتق مقدار مثبت داشته باشه به این معنی هست که اگه w رو زیاد کنیم مقدار J هم زیاد میشه. پس جهت غلطه (چون می خوایم مقدار کمینه رو پیدا کنیم) و باید اون رو تو یه مقدار منفی ضرب کنیم تا w فعلی کوچیک بشه.
خب، حالا بریم سراغ اهمیت اندازه آلفا. آلفا (learning rate) یه نقش خیلی مهم تو عملکرد الگوریتم گرادیان کاهشی داره. اگه یه مقدار خیلی کوچک برای آلفا انتخاب کنیم، قدمها خیلی کوچیک میشن و برای رسیدن به نقطه کمینه، به تعداد زیادی تکرار نیاز داریم. این یعنی الگوریتم بهشدت آهسته میشه و زمانبره.
از طرف دیگه، اگه آلفا رو خیلی بزرگ انتخاب کنیم، الگوریتم ممکنه به جای نزدیک شدن به کمینه، از اون رد بشه و بهجای کاهش، مقدار تابع هزینه افزایش پیدا کنه. این حالت رو Overshooting میگن. اگه این اتفاق بیفته، الگوریتم ممکنه هیچوقت به کمینه نرسه و Diverge (واگرا) بشه، یعنی اصلاً جواب نده.
حالا این سوال پیش میاد که آیا ثابت بودن آلفا میتونه مشکلساز بشه؟ واقعیت اینه که وقتی به نقطه بهینه نزدیک میشیم، شیب تابع هزینه کم میشه، مقدار مشتق هم کمتر میشه و در نتیجه قدمهایی که برمیداریم بهصورت خودکار کوچکتر میشن. این یعنی نیاز خاصی به آلفای متغیر نداریم، چون گرادیان کاهشی به شکل طبیعی این کار رو برای ما انجام میده.
اما یه نکته مهم توی گرادیان کاهشی اینه که این الگوریتم اگه به یه کمینه موضعی برسه، همونجا متوقف میشه و نمیتونه سراغ کمینه گلوبال بره. با این حال، خوشبختانه در رگرسیون خطی چنین مشکلی نداریم، چون تابع هزینهمون چند تا local minimum نداره. تابع هزینه برای رگرسیون خطی یه تابع محدب یا همون Convex هست که فقط یه global minimum داره. بنابراین، اگه مقدار آلفا رو درست انتخاب کنیم، تضمین میشه که الگوریتم حتماً به کمینه گلوبال میرسه.
حالا بریم سراغ یه مبحث مهم دیگه: Batch Gradient Descent.
تو این روش، هر بار که میخوایم ضرایب w و b رو آپدیت کنیم، از کل دادههای Training Set استفاده میکنیم. به همین خاطر اسمش شده "Batch Gradient Descent"، چون از کل دادهها بهعنوان یه دسته (batch) استفاده میکنه. این روش مخصوصاً توی رگرسیون خطی خیلی استفاده میشه.
البته روشهای دیگهای هم هستن که بهجای استفاده از کل دادهها، فقط از بخشی از Training Set استفاده میکنن. یکی از این روشها Stochastic Gradient Descent (SGD) هست که بهجای استفاده از کل دادهها، در هر مرحله فقط با یک نمونه کار میکنه.