در این مطلب ما از روش "Ordinary Least Squares (OLS)" یا «کمترین مربعات معمولی» استفاده می کنیم.
فرض می کنیم که جدول زیر نشان دهنده متراژ و قیمت چند خانه است.
ستون Area در این جدول نشان دهنده متراژ و ستون Price نشان دهنده قیمت آن خانه است. برای مثال قیمت خانه 1 متری 1 تومان، خانه 2 متری 3 تومان است.
اگر مقادیر جدول بالا را بر روی نمودار رسم کنیم، متوجه وجود یک رابطه خطی بین متراژ و قیمت می شویم، به طوری که در نتیجه افزایش متراژ، قیمت نیز افزایش می یابد.
برای رسم این نمودار از کد زیر استفاده شده است:
import matplotlib.pyplot as plt Area = [1,2,4,3,5] Price = [1,3,3,2,5] plt.scatter(Area, Price, color='blue') plt.xlabel('Area') plt.ylabel('Price')
در چنین مواردی که یک رابطه خطی بین متغیرها وجود دارد، می توانیم برای پیش بینی مقادیر جدید، از رگرسیون خطی استفاده کنیم.
در رگرسیون خطی (Linear Regression)، به طور کلی دو نوع متغیر وجود دارد:
اگر یک نوع متغیر مستقل داشته باشیم، رگرسیون خطی از نوع ساده (Simple Linear Regression) و در صورتی که چند نوع متغیر مستقل داشته باشیم، رگرسیون خطی چندگانه (Multiple Linear Regression) است. برای مثال قیمت نهایی خانه برگرفته از عواملی نظیر: متراژ، عمر بنا و محله باشد.
با استفاده از این فرمول ما می توانیم به ازای هر ورودی x، خروجی y را محاسبه کنیم. با در نظر گرفتن مثال بالا، می خواهیم پیش بینی کنیم قیمت یک خانه 6 متری چقدر است.
بدین ترتیب، در فرمول معرفی شده، مقدار x، 6 خواهد بود و با محاسبه B1 و B0 می توانیم Y که همان قیمت این خانه است را پیش بینی کنیم.
مشخص است که ابتدا باید B1 را حساب کنیم و سپس B0 را به دست بیاوریم.
برای محاسبه صورت کسر فرمول B1، برای هر ردیف، مقدار ستون x را از میانگین x ها کم می کنیم، مقدار ستون y را از میانگین y ها کم می کنیم، حاصل را در هم ضرب می کنیم.
برای تمامی ردیف ها این فرآیند را انجام می دهیم و در پایان تمامی این مقادیر را با هم جمع می کنیم.
کد زیر، مربوط محاسبه B1 است.
Area = [1,2,4,3,5] Price = [1,3,3,2,5] input_size = len(Area) x = Area y = Price def avg(avg_input): my_temp = 0 for i in range (0, input_size): my_temp = my_temp + avg_input[i] return(my_temp/input_size) avg_x = avg(x) avg_y = avg(y) print("Average of x: ", avg_x) print("Average of y: ", avg_y) def beta1(): beta1_numerator = 0 beta1_denumerator = 0 for i in range (0, input_size): beta1_numerator = beta1_numerator + ((x[i] - avg_x)*(y[i] - avg_y)) beta1_denumerator = beta1_denumerator + ((x[i] - avg_x)**2) return(beta1_numerator/beta1_denumerator) print("Beta1 = ", beta1())
در نتیجه اجرای این کد مقادیر زیر به دست می آیند:
Average of x: 3.0
Average of y: 2.8
Beta1 = 0.8
در مرحله بعد، Beta0 را محاسبه می کنیم.
beta0 = avg_y - (beta1() * avg_x) print("Beta0 = ", avg_y , "-" , "(" , beta1() , "*" , avg_x , ") =" , beta0)
در نتیجه اجرای این کد مقدار Beta0 به صورت زیر محاسبه می شود:
Beta0 = 2.8 - ( 0.8 * 3.0 ) = 0.39999999999999947
پس از محاسبه Beta1 و Beta0 می توانیم معادله خط رگرسیون را به دست بیاوریم:
Y = Beta0 + Beta0 x
Beta1 = 0.8
Beta0 = 0.399
Y = 0.8 + ( 0.399 * x)
در این معادله x، مقدار ورودی کاربر (با توجه به مثال، متراژ خانه) و Y نیز پاسخ نهایی یا همان قیمت خانه مورد نظر است.
def capital_y(user_input): return(beta0 + (beta1() * user_input))
پس از به دست آوردن معادله خط رگرسیون، نوبت به ارزیابی آن می رسد. برای این کار متراژ خانه ها را به تابع ساخته شده می دهیم و قیمت های محاسبه شده را با قیمت های اصلی مقایسه می کنیم.
ستون Predicted price در جدول قیمت های محاسبه شده را نشان می دهد. همانطور که مشخص است، مدل ساخته شده دارای خطا است. برای محسابه این بخش از کد زیر استفاده می شود:
user_input = [1,2,4,3,5] predicted_y = [] for i in range(0, len(user_input)): predicted_y.append(capital_y(user_input[i])) print("Predicted values are: ", predicted_y)
حاصل اجرای کد بالا نیز به صورت زیر است:
Predicted values are: [1.1999999999999995, 1.9999999999999996, 3.5999999999999996, 2.8, 4.3999999999999995]
که همان مقادیر ستون Predicted price هستند.
در نمودار زیر نقاط آبی رنگ، قیمت های اصلی و نقاط قرمز رنگ قیمت های پیش بینی شده هستند.
فاصله هر نقطه آبی تا نقطه نارنجی در همان عرض، نشان دهنده میزان خطای مدل در پیش بینی قیمت ها است.
نمودار بالا با استفاده از کد زیر رسم شده است:
plt.scatter(Area, Price, color='blue') plt.scatter(Area, predicted_y, color='red') plt.xlabel('Area') plt.ylabel('Price') plt.plot(Area, predicted_y, color='orange')
محاسبه میزان خطای جذر میانگین مربعات (RMSE)
همانطور که گفته شده مشخص است مدل ساخته شده دارای خطا است، اما میزان خطای این مدل چقدر است؟
یکی از رایج ترین معیارهای سنجش خطا در مدل های رگرسیون و به طور کلی در مباحث ماشین لرنینگ، خطای Root Mean Squared Error است که به صورت زیر محاسبه می شود.
def my_RMSE(y,predicted_y): my_temp = 0 for i in range(0, input_size): my_temp = my_temp + ((y[i] - predicted_y[i])**2) my_temp = my_temp / input_size my_temp = my_temp **(1/2) return(my_temp) print("RMSE = ", my_RMSE(y,predicted_y))
قطعه کد بالا، RMSE را برای مقادیر مثال مطرح شده محاسبه می کند.
RMSE = 0.692820323027551
تمامی کدهای نوشته شده در این مطلب، به صورت یکجا از لینک زیر قابل دریافت هستند:
https://github.com/alifallahi/Regression/blob/master/Simple_Linear_Regression.py
همانطور که گفته شد ما در این مطلب از روش کمترین مربعات معمولی (به انگلیسی: Ordinary Least Squares) (به اختصار OLS) استفاده کردیم. این روش برای مسایلی که تعداد متغیرهای وابسته و مستقل کم است و به طور کلی مسئله ساختار ساده ای دارد می تواند استفاده شود، اما در مسایل پیچیده تر که حجم داده ها و تعداد متعیرها بیشتر می شود نیاز است تا از روش هایی مثل «گرادیان کاهشی» استفاده کنیم که به صورت تکرار شونده و در چند مرحله بهترین مقدار را برای Beta1 و Beta0 به دست بیاورم تا در نهایت خط رگرسیون در مطلوبترین حالت رسم شود.
لینک های تکمیلی:
https://fa.wikipedia.org/wiki/خطای_جذر_میانگین_مربعات