در مطلب قبلی که در ویرگول پست کردم با رگرسیون خطی ساده و نحوهی پیاده سازی آن از صفر آشنا شدیم (لینک) ، در این مطلب یک مدل یادگیری ماشین دیگر به نام رگرسیون لجستیک را بررسی میکنیم. رگرسیون لجستیک از دسته الگوریتمهای نظارت شده (Supervised) میباشد و برای دستهبندی (Classification) مورد استفاده قرار میگیرد. رگرسیون لجستیک یکی از پرکاربردترین الگوریتمهای یادگیری ماشین است که در ادامه به تفصیل آن را بررسی میکنیم.
در این مطلب هدف به دست آوردن الگوریتمی برای دستهبندی گروهی از دادهها میباشد. اما اول باید به این سوال پاسخ دهیم که چرا به الگوریتم جدیدی برای دستهبندی نیاز داریم، آيا نمیتوان از الگوریتم رگرسیون خطی برای این امر استفاده کرد؟ برای پاسخ به این سوال تلاش میکنیم تا به کمک الگوریتم رگرسیون خطی، دادههای زیر را دسته بندی کنیم. نمودار زیر نشاندهندهی رابطهی احتمال بیمار بودن و وزن شش (۶) موش مختلف میباشد، به این شکل که بر روی محور عرضها (y) احتمال بیمار بودن یا نبودن موش مورد نظر مشخص شده و بر روی محور طولها (x) وزن موش مورد نظر به واحد گِرم (g) نمایش داده شده است. نتایج به دست آمده در آزمایشگاه نشان میدهند که سه موش سنگین وزن شرکت کرده در این آزمایش بیمار هستند.
حال الگوریتم رگرسیون خطی ساده را با دادههای ارائه شده در بالا آموزش میدهیم و آستانهی انتخاب (Threshold) را ۰/۵ در نظر میگیریم. آستانهی انتخاب به این معنی است که اگر مدل رگرسیون خطی برای وزن یک موش، عددی بزرگتر از ۰/۵ پیشبینی کرد موش را بیمار در نظر میگیریم و اگر عددی کوچکتر از ۰/۵ را پیشبینی کرد موش را سالم در نظر میگیریم، در نمودار پایین خط نقطهچین مشکی نشاندهندهی آستانهی انتخاب یا مقدار ۰/۵ میباشد به عبارت دیگر اگر بر روی محور طولها (x) از خط نقطهچین به سمت راست حرکت کنیم، مقدار پیشبینی شده بزرگتر از ۰/۵ و موش، بیمار میباشد، ولی اگر به سمت چپ حرکت کنیم مقدار پیشبینی شده توسط مدل رگرسیون خطی ساده کوچکتر از ۰/۵ و موش مورد نظر، سالم میباشد.
واضح است که مدل رگرسیون خطی ساده در دسته بندی این موشها بسیار خوب و تا حدی بدون نقص عمل میکند. حال یک موش بسیار سنگین وزن به آزمایش اضافه میکنیم و رگرسیون خطی را دوباره اجرا میکنیم.
با اضافه شدن یک دادهی پرت، الگوریتم رگرسیون خطی نمیتواند عملیات دستهبندی را به درستی اجرا کند و یکی از موشهای بیمار را در دستهی سالم پیشبینی میکند. از طرفی میدانیم مقادیر به دست آمده از طریق الگوریتم رگرسیون خطی میتوانند بسیار بیشتر از یک و بسیار کمتر از صفر باشند فلذا نیاز به مدلی داریم که خروجی آن در بازهی ۰ تا ۱ باشد.
دو مشکل الگوریتم رگرسیون خطی ساده در دستهبندی، عبارتند از: ۱ـ عملکرد ضعیف و ۲ـ تولید مقادیری که تفسیر آنها مشکل است.
توابع سیگموئیدی به توابعی کراندار، مشتقپذیر و حقیقی گفته میشود که نمودار آنها شکل حرف s انگلیسی دارد. یکی از معروفترین این توابع، تابع لجستیک میباشد که مدل رگرسیون لجستیک نام خود را از این تابع وام گرفته است. نمودار این تابع را در شکل زیر میبینیم. این تابع اعداد حقیقی در بازهی (∞+،∞-) را به بازهی (۰،۱) نگاشت میکند. این کار باعث سادهسازی تفسیر خروجی مدل به عنوان احتمال میگردد و مشکل اعداد بزرگتر از یک (۱) و کوچکتر از صفر (۰) در رگرسیون خطی را برطرف میسازد.
این تابع به کمک معادلهی زیر محاسبه میگردد.
در مساله احتمال بیماری موشها که در بالا بررسی کردیم فقط یک عامل (وزن) را در بیمار بودن موشها موثر دانستیم و تاثیر آن را بررسی کردیم، در صورتی که در دنیای واقعی عوامل زیادی هستند که در نتیجهی یک اتفاق (Event) موثر هستند از طرفی هر عامل به اندازهی متفاوتی در نتیجه تاثیر دارد تاثیر این عوامل مختلف را با یک ضریب عددی وارد معادله کرده و آنها را وزن مینامیم. به این روش برای لحاظ کردن تاثیر وزنها بر مدل حاصلجمع وزندار گفته میشود که در پاراگراف بعدی آن را توضیح میدهم.
فرض کنید مجموعهی دادگانی دارای n ویژگی (Feature) باشد، همچنین در مجموعهی دادگان m داده داشته باشیم. این مجموعه داده را به شکل زیر میتوان نشان داد.
حاصلجمع وزندار برای هر عضو از مجموعهی دادگان نشان داده شده در بالا به شکل زیر محاسبه میگردد.
به منظور سادهسازی معادلات همچنین استفادهی حداکثری از توان کامپیوتر (موازی سازی) فرمول بالا را به کمک جبر خطی و به شکل برداری بازنویسی میکنیم. در صورتی که وزنها و متغیرها را به شکل دو بردار زیر نشان دهیم، حاصلجمع وزن دار را میتوانیم به شکل ضرب بردار نمایش دهیم که در آن T، ترانهادهی بردار میباشد.
مفهوم بایاس (Bias) و الزام استفاده از آن خارج از بحث این مطلب میباشد اما به طور خلاصه به منظور عملکرد بهتر مدل و یادگیری روابط پیچیدهتر، بایاس را نیز به عبارت بالا اضافه مینماییم و حاصل به دست آمده را z نامگذاری میکنیم.
حاصل عبارت بالا یک بردار از اعداد حقیقی خواهد بود که آن را به عنوان ورودی به تابع لجستیک میدهیم، در این گفتار تابع لجستیک را با نماد σ (سیگمای کوچک) نمایش میدهیم.
عبارت به دست آمده در بالا مدل (فرضیه، Hypothesis، h_θ(x)
) رگرسیون لجستیک میباشد. گفتنیاست که حاصل به دستآمده از طریق تابع لجستیک یک بردار به اندازهی m از اعداد در بازهی (۰،۱) میباشد. هر عدد به دست آمده از طریق این معادله (مدل) را میتوان به صورت عبارت زیر که یک احتمال شرطی یا برشی میباشد تفسیر کرد. به طور مثال در مورد موشها عدد حاصل شده از مدل احتمال بیمار بودن موش، به شرط وزن آن میباشد.
جهت ارزیابی عملکرد مدل همچنین بهبود آن به کمک الگوریتم گرادیانکاهشی که در ادامه به آن میپردازیم باید ابتدا یک تابع هزینه تعریف کنیم. تابع هزینهای که از آن استفاده میکنیم Cross Entropy Cost Function یا به اختصار CEC میباشد، تابع هزینه را برای رگرسیون لجستیک به شکل زیر تعریف میکنیم.
مفهوم گرادیان کاهشی را در مطلب قبلی که در ویرگول پست کردم (لینک)، توضیح دادم اما به طور خلاصه باید گفت که گرادیان کاهشی یک الگوریتم بهینه سازیست که در اینجا برای کمینه (Minimize) کردن تابع هزینه از آن استفاده میکنیم. شبه کد گرادیان کاهشی به شکل زیر میباشد.
برای استفاده از گرادیان کاهشی، نیاز به محاسبهی مشتق جزئی تابع هزینه نسبت به پارامتر θ داریم. این عملیات مشتقگیری نیاز به استفاده از قانون مشتق زنجیرهای (Chain Rule) دارد.
حال که همهی المانهای مورد نیاز را داریم آنها را به کد تبدیل میکنیم.
کد قابل اجرا و کامل این مطلب را میتوانید از این مخزن گیتهاب دریافت کنید (لینک).
مرحلهی اول import کردن کتابخانهی numpy میباشد که برای انجام محاسبات ریاضی از آن کمک میگیریم.
حال دادهها را وارد برنامه میکنیم، دادههای استفاده شده در این گفتار دادههای مربوط به سرطان سینه هستند که در کتابخانهی scikit موجود هستند. (لینک دادگان)
حال مجموعه دادگان وارد شده را به دو گروه test و train تقسیم میکنیم. ۲۵ درصد از دادگان را در مجموعهی test قرار داده و بقیه را در مجموعهی train همچنین اگر میخواهید نتایج به دست آمده در این گفتار را تکرار کنید میتوانید random_state را برابر با مقدار 42 قرار دهید، دقت کنید که در این امر اجباری نیست.
حال کلاس رگرسیون لجستیک را تعریف میکنیم، در تابع سازندهی این کلاس دو پارامتر max_iter و learning_rate را مقداردهی میکنیم، این دو پارامتر هردو مربوط به الگوریتم گرادیان کاهشی میباشند، دقت کنید که به منظور سادهسازی موضوع از شرط همگرایی در گرادیان کاهشی صرف نظر کردیم، اما در گیتهاب کد مربوط به اعمال شرط همگرایی نیز موجود است.
در متد fit ابتدا ابعاد مجموعهی دادگان را میگیریم و آن را در دو متغیر n_samples (تعداد اعضای مجموعه) و n_features تعداد ویژگیها میریزیم. سپس به کمک کتابخانهی numpy بردار theta را با مقدار صفر مقداردهی میکنیم.
در حلقهی تکرار در هر مرتبه ابتدا حاصلجمع وزن دار را محاسبه میکنیم، دقت کنید که چون کتابخانهی پانداس دادهها را به شکلی که ما در گفتار بالا بررسی کردیم، برنمیگرداند، در محاسبهی حاصلجمع وزندار مجبوریم مقادیر بردار دادگان (X) را نیز ترانهاده کنیم.
پس از محسابهی حاصلجمع وزن دار و محاسبهی مقدار لجستیک نوبت به اجرای گرادیان کاهشی میرسد. دقت کنید که با محاسبهی گرادیان بایاس متوجه میشویم، مقدار آن از رابطهی زیر محاسبه میشود.
حال که کلاس را داریم از آن استفاده کرده و دقت را محاسبه میکنیم.