فهرست

پیاده سازی Linear Regression در Julia

نویسنده یا مترجم :‌ امیرعباس اسدی ‌

توضیح مسئله

در این مطلب قصد داریم یکی از مدل های ساده اما کارآمد یادگیری ماشین را برای پیشبینی پیاده سازی کنیم. با رجوع به این لینک می توانید یک دیتاست حاوی اطلاعات کانگورو های خاکستری را دانلود کنید. این داده ها حاوی دو ستون X و Y است. این دو متغیر به ترتیب نشان دهنده‌ی طول و عرض بینی کانگورو ها به میلی متر هستند.این فایل حاوی داده های مذکور برای ۴۵ کانگورو است. هدف ما در این مثال کشف یک رابطه‌ی خطی بین Y و X است. با کشف این رابطه می توانیم عرض بینی این کانگورو ها را بر اساس طولش پیشبینی کنیم.

بررسی وجود یک رابطه‌ی خطی

اولین پرسشی که مطرح می شود این است که اصلا Linear Regression برای این داده ها قابل استفاده است؟ برای پاسخ به این پرسش لازم است بررسی کنیم که آیا رابطه ای خطی بین X و Y وجود دارد یا نه.یک روش برای بررسی این موضوع رسم نمودار پراکندگی X و Y است.ابتدا دیتاست را دانلود و برای استفاده آسانتر آن را در قالب csv ذخیره میکنیم.یکی از پکیج های Julia که کار با داده ها را تسهیل می کند DataFrames است.همچنین برای خواندن فایل دیتاست که از نوع CSV است از پکیج CSV استفاده می کنیم.ابتدا این پکیج ها را نصب میکنیم:

using Pkg
Pkg.add("DataFrames")
Pkg.add("CSV")

با استفاده از پکیج CSV فایل دیتاست را فراخوانی می کنیم:

using CSV
data = CSV.read("dataset.csv")

در کد بالا ورودی تابع read نام فایل دیتاست است.خروجی این تابع از نوع DataFrame است.اگر با استفاده از تابع print متغیر data را چاپ منیم نتیجه به صورت زیر خواهد بود:

print(data)
45×2 DataFrames.DataFrame
│ Row │ X     │ Y     │
│     │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1   │ 609   │ 241   │
│ 2   │ 629   │ 222   │
│ 3   │ 620   │ 233   │
│ 4   │ 564   │ 207   │
│ 5   │ 645   │ 247   │
│ 6   │ 493   │ 189   │
│ 7   │ 606   │ 226   │
│ 8   │ 660   │ 240   │
│ 9   │ 630   │ 215   │
│ 10  │ 672   │ 231   │
│ 11  │ 778   │ 263   │
│ 12  │ 616   │ 220   │
│ 13  │ 727   │ 271   │
│ 14  │ 810   │ 284   │
│ 15  │ 778   │ 279   │
│ 16  │ 823   │ 272   │
│ 17  │ 755   │ 268   │
│ 18  │ 710   │ 278   │
│ 19  │ 701   │ 238   │
│ 20  │ 803   │ 255   │
│ 21  │ 855   │ 308   │
│ 22  │ 838   │ 281   │
│ 23  │ 830   │ 288   │
│ 24  │ 864   │ 306   │
│ 25  │ 635   │ 236   │
│ 26  │ 565   │ 204   │
│ 27  │ 562   │ 216   │
│ 28  │ 580   │ 225   │
│ 29  │ 596   │ 220   │
│ 30  │ 597   │ 219   │
│ 31  │ 636   │ 201   │
│ 32  │ 559   │ 213   │
│ 33  │ 615   │ 228   │
│ 34  │ 740   │ 234   │
│ 35  │ 677   │ 237   │
│ 36  │ 675   │ 217   │
│ 37  │ 629   │ 211   │
│ 38  │ 692   │ 238   │
│ 39  │ 710   │ 221   │
│ 40  │ 730   │ 281   │
│ 41  │ 763   │ 292   │
│ 42  │ 686   │ 251   │
│ 43  │ 717   │ 231   │
│ 44  │ 737   │ 275   │
│ 45  │ 816   │ 275   │

برای دسترسی به ستون های این دیتاست می توانیم از data.X یا data.Y استفاده کنیم که خروجی آن ها از نوع آرایه های زبان Julia است. برای رسم نمودار در Julia میتوانیم از پکیج Plots استفاده کنیم. این پکیج از تعدادی پکیج دیگر به عنوان Backend برای رسم نمودار استفاده کند. ابتدا این پکیج و plotly را به عنوان Backend برای رسم نمودار نصب می کنیم:

Pkg.add("Plots")
Pkg.add("PyPlot")

اکنون این پکیج را فراخوانی و plotly را بعنوان Backend رسم نمودار انتخاب میکنیم:

using Plots
pyplot(size = (300,300), legend = false)

اکنون با استفاده از تابع scatter نمودار پراکندگی X و Y را رسم میکنیم:

scatter(data.X, data.Y)

نتیجه به صورت زیر خواهد بود: نمودار پراکندگی رسم شده از شکل بالا می توان گفت مدل کردن رابطه‌ی بین X و Y غیرمنطقی نیست. البته می توانیم قیق تر باشیم. به عنوان یک روش دیگر برای بررسی همبستگی خطی، از کتابخانه Statistics برای محاسبه ماتریس همبستگی استفاده میکنیم.Statistics جز Standard Library زبان Julia بوده و نیازی به نصب ندارد.برای محاسبه ماتریس همبستگی به این شیوه عمل می کنیم:

using Statistics
cor(hcat(data.X, data.Y))

در کدبالا تابع hcat دو ماتریس data.X و data.Y را به یکدیگر متصل می کند. تابع cor ماتریس همبستگی را محاسبه می کند.نتیجه بدین صورت خواهد بود:

2×2 Array{Float64,2}:
 1.0       0.881414
 0.881414  1.0     

ضریب همبستگی 0.881414 هم نشان می دهد استفاده از Linear Regression فکر بدی نیست.

محاسبه ضرایب Linear Regression

اکنون که به این نتیجه رسیدیم رابطه‌ی بین X و Y را با یک خط تخمین بزیم، بایستی این خط را بدست آوریم.به عبارت دیگر هدف ما محاسبه پارامتر های این خط است.

می توانیم این مسئله را در قالب یه معادله‌ی ماتریسی بیان کنیم:

ماتریس های بالا را به اختصار بدین صورت نام گذاری می کنیم:

هدف محاسبه‌ی بردار است.می توان نشان داد پاسخ خوبی برای این معادله به صورت زیر محاسبه می گردد:

ابتدا ماتریس را محاسبه می کنیم.ستون اول این ماتریس است.میتوانیم با استفاده از تابع hcat یک بردار با 45 عنصر را به صورت افقی به ماتریس data.X الحاق کنیم.

A = hcat(ones(length(data.X), 1), data.X)

برای محاسبه‌ی ترانهاده و وارون ماتریس از کتابخانه LinearAlgebra استفاده می کنیم. این کتابخانه هم جزیی از Standard Library زبان جولیا است.

using LinearAlgebra
AT = transpose(A)
p = inv(AT*A)*AT*data.Y

بعد از اجرای این کد، بردار به صورت زیر بدست می آید:

2-element Array{Float64,1}:
 46.45081362636087 
  0.2876123682414831

رسم خط بدست آمده

حال که پارامتر های خط مورد نظر را بدست آوردیم، می توانیم آن را رسم کنیم. توجه کنید که نشان دهنده‌ی مقادیر پیش بینی شده توسط این مدل برای داده های دیتاست است.می توانیم برای رسم خط از تابع plot استفاده کنیم. اما این تابع نمودار را از نو رسم می کند.به جای آن می توانیم از تابع plot! استفاده کنیم.این تابع نمودار را بر روی نمودار قبلی رسم می کند.

scatter(data.X, data.Y)
plot!(data.X, A*p)

در نهایت خواهیم داشت: خط برازش شده بر روی داده ها