logistic regression

تو پست های قبلی درباره ی الگوریتم linear regression خیلی مفصل و کامل حرف زدیم، یه پیاده سازی خیلی مقدماتی از این الگوریتم دیدیم و در نهایت هم با vectorize کردن آشنا شدیم. تو این پست میریم سراغ اولین الگوریتم classification که در ادامه با استفاده از همین الگوریتم شبکه های عصبی رو میسازیم.طرح مسئلهفرض کنید اطلاعات یک سری بیمار سرطانی (سرطان سینه) رو به عنوان ورودی به ما دادن و به ازای هر بیمار مشحص شده که نوع سرطان خوش خیم هست یا بدخیم. هدف ما اینه که با این داده ها یک الگوریتم classification بسازیم که اگر داده ی جدیدی به ما دادن بتونیم نوع سرطان اون رو تشخیص بدیم.تو این مسئله به جای اینکه label های ما یک مقدار پیوسته باشن، دو مدل هستند، سرطان خوش‌خیم/سرطان بدخیم، میتونیم بیایم و به هر کدوم از این کلاس ها یک عدد نسبت بدیم. مثلا اگر مریض سرطان خوش‌خیم داشت بگیم label بشه 1 و اگر خوش‌خیم بود بشه 0. (البته اینکه این اعداد رو 0 و 1 گذاشتیم خیلی هم بی دلیل نیست.)کاری که میخوایم بکنیم اینه که بیایم و یک تابع h بسازیم که خروجی اون این مدلی باشه که اگر سرطان خوش‌خیم بود خروجی بشه 1 و اگر نه بشه 0. (نیاز داریم حتما خروجی تابع بین 0 و 1 باشه)بیاید و یک سری داده ی تصادفی در نظر بگیریم، مثلا:تو این داده اگر x کمتر از 10 بود داده مال کلاس 0 و در غیر این صورت مال کلاس 1 هست.اگر بخوایم و این مسئله رو با الگوریتم قبلی که داشتیم حل کنیم یکی از مشکلاتی که داریم اینه که خروجی همیشه بین 0 و 1 نیست. (و یک سری مشکلات دیگه). در واقع اون الگوریتم سعی میکرد که بیاد و یک خطی پیدا کنه کنه که از داده ها رد بشه، تو این الگوریتم میخوایم خطی پیدا کنیم که داده ها رو جدا کنه، یعنی دوست داریم خطی که پیدا میشه این شکلی باشه:تابع h جدیدبرای اینکه خروجی ما این مدلی باشه، باید تابع h رو تغییر بدیم. فرض کنید ورودی ما n تا فیچر داشته باشه و فیچر صفرام مثل الگوریتم قبلی برابر با 1 باشه، در این صورت تابع h رو به صورت زیر تعریف میکنیم:در واقع اومدیم و همون خروجی الگوریتم قبلی رو دادیم به یک تابع جدید که اینجا با سیگما نشونش دادیم. این تابع اسمش sigmoid هست و به این صورت تعریف میشه:اگر نمودار این تابع رو رسم کنیم این شکلی میشه:آخرین نکته درباره ی تابع h اینکه تو این مسئله و با توجه به اینکه از تابع sigmoid برای خروجی استفاده کردیم، میشه یک سری دلیل آماری آورد که این تابع h درواقع داره احتمال اینکه خروجی ما متعلق به کلاس 1 باشه رو پیشبینی میکنه.تابع J جدیدتابع J باید مقدار خطا رو مشخص کنه، تو این مسئله دوست داریم که کلاسی که برای ورودی (x) پیشبینی میکنیم، مساوی کلاس خروجی باشه. یا از دید احتمالاتی دوست داریم اگر یک ورودی مال کلاس 1 باشه، مدل ما احتمال اینکه اون ورودی مال کلاس 1 باشه رو زیاد تشخیص بده.میدونیم که احتمال یک مقدار بین 0 و 1 هست و ما دوست داریم اگر ورودی متعلق به کلاس 1 باشه، خروجی مدل نزدیک 1 باشه و در غیر این صورت نزدیک 0 باشه. میتونیم اینجوری بگیم که اگر ورودی متعلق به کلاس 1 بود دوست داریم احتمال تعلق داشتن اون به کلاس 1 زیاد باشه و اگر متعلق به 1 نبود (مال کلاس 0 بود) دوست داریم احتمال تعلق نداشتن اون به کلاس 1 زیاد باشه، یعنی یک منهای احتمال تعلق داشتنش به کلاس 1 زیاد باشه.بازم به یک سری دلایل ریاضیاتی که فعلا نمیخوام واردش بشم، اگر متغییر مربوط به هر کلاسی بود، فرقی نداره که بگیم احتمال تعلق داشتنش به اون کلاس زیاد بشه یا لگاریتم تعلق داشتنش به اون کلاس. پس میتونیم بگیم اگر label برابر با 1 بود دوست داریم log(h(x)) زیاد بشه و اگر متعلق به کلاس 0 بود دوست داریم log(1 - h(x)) زیاد بشه. میتونیم این دو تا معادله رو به این صورت کنار هم بنویسیم:تو این معادله، اگر label مساوی با 1 باشه، بخش دوم صفر میشه و فقط بخش اولش میمونه یعنی:y*log(h(x))و اگر label مساوی 0 باشه، بخش اول صفر میشه و فقط بخش دومش میمونه، یعنی:(1-y)*log(1-h(x))پس اگر تابع h ما تابع خوبی باشه، این مقدار باید زیاد بشه. از اونجایی که تابع J رو باید minimum کنیم پس تابع J رو برابر با منفی این عبارت قرار میدیم. (در واقع منفی میانگین این عبارت برای تمام داده هایی که داریم):برای پیدا کردن بهترین مقدار تتا (بردار تتا) میتونیم از الگوریتم gradient descent استفاده کنیم. (چون خیلی با جزئیاتش کار نداریم، اینجا توضیح نمیدم. در ادامه برای پیاده سازی این الگوریتم از کتابخونه های آماده استفاده میکنیم.)