رگرسیون خطی
بهنام خدا، سلام… به چهارمین جلسه از آموزش یادگیری ماشین رایگان رسیدیم. در این جلسه میخواهم به توضیح رگرسیون بپردازم. درواقع، در این جلسه تازه طعم یادگیری ماشین را با مزه رگرسیون خطی خواهید چشید! البته، کار من خیلی سخت است. چون نباید یادگیری ماشین را به کام شما تلخ کنم! با آکادمی هوش مصنوعی هوسم همراه باشید…
رگرسیون در یادگیری ماشین
در جلسه دوم، رگرسیون را همراه با یک مثال ساده توضیح دادم. رگرسیون یکی از زیرشاخههای یادگیری باناظر (Supervised Learning) است. بهصورت خلاصه، میتوانیم رگرسیون را اینگونه تعریف کنیم:
رگرسیون، تخمین رابطه بین یک متغیر وابسته و یک یا چند متغیر مستقل است.
یعنی، درحالت ساده و یک متغیر مستقل، میخواهیم تابعی مانند f بهدست آوریم که از روی x ما را به y برساند. به تصویر زیر نگاه کنید؛ یک مجموعه نقطه دوبعدی (x,y) داریم. حالا یادگیری ماشین به ما کمک میکند که رابطه بین ورودی و خروجی (f) را پیدا کنیم. در این جلسه به شما یاد میدهم که چگونه این اتفاق میافتد.
رگرسیون مبحث جدیدی نیست. بسیاری از شما با این مفهوم در آمار دوم دبیرستان آشنا شدید. آنجا خبری از یادگیری ماشین نبود. اما تعدادی داده بهعنوان ورودی و خروجی داشتیم که باید یک خط به آن فیت میکردیم. خطی که از همه دادهها کمترین فاصله ممکن را داشته باشد. در شکل زیر، سه خط ترسیم شده است. از بین این سه خط، خط سیاه متعادلتر از بقیه است. اگرچه این خط دقیقا از بعضی دادهها رد نشده، اما بهترین خطی است که میتوانیم رسم کنیم. خطی که از همه نقاط موجود فاصله کمتری نسبت به سایر خطوط دارد.
بیایید مساله رگرسیون در یادگیری ماشین را خلاصه و جمعبندی کنیم. به بلوک دیاگرام زیر نگاه کنید؛ مجموعه داده ورودی x و برچسب y وجود دارد و در دستان ماست. میخواهیم تابعی مانند f داشته باشیم که از x ما را به y برساند. میخواهیم با استفاده از همین x و y، تابع f را پیدا کنیم. میتوانیم از یادگیری ماشین کمک بگیریم تا تابع f را برای ما پیدا کند.
وقتی دوم دبیرستان بودم، به پدرم گفتم سر کلاس، آمار رو نمیفهمم. پدرم گفت: سخته؟ اسم معلمت چیه؟ گفتم: آقای الف. گفت: آقای الف؟! معلم من هم بوده، خوب درس نمیده!! کمی خیالم راحت شد که مشکل از گیرنده نیست، بلکه گویا سالهاست فرستنده مشکل داشته و از دوران پدر به پسر هیچ پیشرفتی در تدریس نکرده! شنیدهها حاکی از این هست که ایشون الان وارد کسب و کار برنج شده و در این زمینه موفقه! خب از همون ابتدا وارد کاری میشدی که استعداد داری دیگه مَرد!
بسیارخب، مقدمات و خاطرهگویی کافی است. میخواهم سادهترین شکل از رگرسیون را به شما توضیح بدهم. رگرسیون خطی…
رگرسیون خطی
اگر داده ورودی و برچسب، یک ارتباط خطی باهم داشته باشند، میتوانیم از رگرسیون خطی استفاده کنیم. یعنی، یک معادله از درجه 1 که میتوانیم به شکل زیر آنرا تعریف کنیم:
خب، x و y که ورودی و برچسب هست. w و b هم پارامتر هستند. من نمیدانم چه مقداری برای این دو پارامتر مناسب است و در تلاشم که بهترین مقدار را با یادگیری ماشین بیابم. برای این کار نیاز است این مدل یادگیری ماشین (رگرسیون خطی) را آموزش دهم. یا به قول فرنگیها train کنم! بنابراین:
آموزش مدل یعنی، پارامترهای مدل را طوری تعیین کنیم که بهتر بر دادههای آموزش فیت شود!
تا اینجا به این رسیدیم که یک مدل رگرسیون خطی بهشکل (*) داریم که باید آنرا آموزش دهیم. برویم سراغ آموزش…
آموزش مدل یادگیری ماشین (رگرسیون خطی)
آموزش یک مدل یادگیری ماشین مانند رگرسیون خطی یک فرآیند بهینه سازی تکراری است که بارها از آن در زندگیمان استفاده میکنیم. به تصویر زیر نگاه کنید؛ مسابقه تیراندازی، بهترین مثال ممکن برای این کار است. یک تیرانداز همواره کارهای زیر را انجام میدهد:
- تیر میاندازد!
- فاصله بین مرکز سیبل تا محل برخورد تیر را میسنجد و تحلیل میکند.
- بازهم تیر میاندازد. سپس، فاصلهسنجی و تحلیل میکند. این فرآیند دومرحلهای بارها و بارها ادامه پیدا میکند.
مشابه همین فرآیند را برای آموزش مدل رگرسیون خطی باید انجام دهیم:
- مقادیر اولیه تصادفی برای w و b انتخاب میکنیم.
- همه داده های آموزشی x را به مدل رگرسیون خطی میدهیم و مقدار پیش بینی yp را بدست میآوریم.
- میزان خطا را میان yp و y محاسبه میکنیم.
- خطا را تحلیل میکنیم و دو مقدار جدید برای w و b بدست میآوریم.
- با مقادیر جدید w و b به مرحله 2 برمیگردیم. مدام این کار را تکرار میکنیم تا خطای مرحله 3 بسیار ناچیز شود.
بلوک دیاگرام همین فرآیند را در شکل زیر میتوانید مشاهده کنید.
حالا در ادامه به توضیح هریک از مراحل بالا میپردازم. اما، بیایید این توضیحات را با مثال پیش ببریم. تصور کنید، یک مجموعه نقطه داریم که اینها روی خط y=1+2x قرار گرفتهاند. ما میخواهیم از روی نقطهها به خط y=1+2x برسیم. این هم کد ساخت داده مصنوعی y=1+2x همراه با اندکی نویز:
x = np.random.rand(100, 1) y = 1 + 2 * x + 0.1 * np.random.randn(100, 1) idx = np.arange(100) np.random.shuffle(idx) train_idx = idx[:80] val_idx = idx[80:] x_train, y_train = x[train_idx], y[train_idx] x_val, y_val = x[val_idx], y[val_idx]
نویز اضافه کردم که کار کمی سخت شود. میدانیم که مدل رگرسیون خطی ما برای w و b باید به اعداد 2 و 1 برسد. این هم نمودار توزیع نقطههای Train و Test:
plt.scatter(x_train, y_train, c='b', s=200, edgecolors='w', label='Train') plt.scatter(x_val, y_val, c='r', s=200, edgecolors='w', label='Test') plt.legend()
تعیین مقدار اولیه برای پارامترهای w و b
اولین مرحله یا شاید بهتر باشد بگویم صفرمین مرحله، تعیین مقدار اولیه برای پارامترهای w و b است. بهصورت تصادفی دو مقدار … برای این دو پارامتر درنظر میگیریم.
w = np.random.randn(1) b = np.random.randn(1) print('w0={:.4f} , b0={:.4f}'.format(w.item(), b.item()))
w0=0.5029 , b0=-1.2453
تخمین مقدار yp برای داده ورودی x
برای مدل رگرسیون خطی دو مقدار 0.5029=w و 1.2453-=b درنظر گرفتیم. حالا باید مجموعه n داده آموزشی x را به مدل زیر بدهیم. سپس، خروجی yp را بهدست آوریم. ببینید:
yp = b + w * x_train
مقدار yp تخمین مدل رگرسیون ماست. میدانیم خیلی دقیق نیست، چون براساس پارامترهای تصادفی بهدست آمدهاند. یعنی پیش بینی بد است، اما چقدر بد؟ در بخش بعد خواهید دید…
تعیین مقدار خطا
ما یکسری برچسب یا لیبل داریم. از اینها میتوانیم کمک بگیریم تا مقدار خطا را محاسبه کنیم. یک تیرانداز برای بررسی میزان خطایش، کافی است موقعیت مرکز سیبل را منهای موقعیت اصابت تیر کند. اینجا هم همین کار را باید انجام دهیم. یعنی:
رابطه بالا میگوید، انتظار داشتیم مقدار تخمینی y باشد اما مدل رگرسیون yp تخمین زده است. حالا کافی است، خطای مربوط به تمامی مجموعه داده x را میانگین بگیریم:
رابطه بالا، نشان دهنده میانگین خطاست. اما یک ایراد بزرگ دارد؛ ممکن است برای بعضی نمونهها خطا مثبت و برای بعضی منفی باشد. ما باید اندازه خطای نمونهها را میانگین بگیریم تا به مقدار درستی از خطا برسیم. یعنی:
رابطه بالا Mean Absolute Error یا MAE نام دارد. MAE بسیار بسیار زیاد در یادگیری ماشین و رگرسیون استفاده میشود. علاوهبراین، معیار دیگری بهنام Mean Squared Error یا MSE هم برای محاسبه خطا در رگرسیون استفاده میشود. تفاوتش با رابطه بالا، تنها در توان 2 است. بجای اینکه اندازه اختلاف محاسبه شود، توان دوم اختلاف را محاسبه میکند. چه اهمیتی دارد؟ یعنی در خطا اغراق ایجاد میکند!
این دو فرمول را همراه با نامهایشان به خاطر بسپارید.
محاسبه مقدار خطا با MSE
بسیارخب، بیایید برای مثالمان مقدار خطا را محاسبه کنیم.
error = (yp - y_train) loss = (error ** 2).mean() print('Loss={:.4f}'.format(loss))
Loss=9.1824
بهبه! چقدر خطا داریم. نتیجه اینکه دو مقدار اولیه w و b بسیار بد بودند و وقت آن رسیده که دو مقدار جدید برایشان انتخاب کنیم و مراحل بالا را دوباره تکرار کنیم. بازهم اگر خطا کم نشد، آنقدر ادامه میدهیم که خطا کم شود.
تا اینجا فهمیدیم که باید مقادیر جدیدی برای پارامترهایمان انتخاب کنیم. اما چگونه؟ بازهم تصادفی انتخاب کنیم؟ واضح است که انتخاب پارامتر تصادفی، خروجی تصادفی هم میدهد! یعنی، بهتر است دنبال یک راهحل منطقی باشیم. به رابطه زیر نگاه کنید:
در رابطه بالا، بجای yp از معادله معروف yp=wx+b استفاده کردم. قبول دارید که رابطه loss نسبت به w و b توانی از 2 است. یعنی میتواند چنین شکلی داشته باشد:
سوال: منحنیهای بالا شما را یاد چه میاندازد؟ امیدوارم جلسه گرادیان کاهشی را خوانده باشید و جواب را فریاد بزنید:
گـــرادیــــان کـــاهــشـــی
در اینجا ما بهدنبال رسیدن به مینیموم هستیم. چون در اینجا رسیدن به مینیموم معادل با رسیدن به کمترین مقدار خطا، یعنی صفر است. با گرادیان کاهشی میتوانیم به منیمیوم محلی برسیم. پس، من با گرادیان کاهشی بهراحتی میتوانم دو مقدار جدید برای w و b بهدست بیاورم. چگونه؟ برویم در بخش بعد ببینیم…
تعیین مقادیر جدید برای پارامتر w و b با گرادیان کاهشی
در گرادیان کاهشی دیدیم که طی یک فرآیند تکراری، با مشتق از تابع و حرکت در جهت منفی شیب در هرلحظه میتوانیم به مینیموم محلی برسیم. پس باید مشتق بگیرم. اما مشتق را باید نسبت به دو پارامتر w و b بگیرم. آنهم جداگانه، چرا؟ چون دو پارامتر مستقل هستند. اگر 100 پارامتر مستقل هم داشته باشیم، باید جداگانه نسبت به تکتک آنها مشتق بگیریم. این شکلی:
و حالا از رابطه زیر برای بهدست آوردن نقطه جدید استفاده میکنم:
بیایید برای مثالمان، مقدار مشتق و پارامترهای جدید را حساب کنیم. بهاینصورت:
b_grad = -2 * error.mean() w_grad = -2 * (x_train * error).mean() print('grad_w={:.4f} , grad_b={:.4f}'.format(w_grad, b_grad))
grad_w=3.3557 , grad_b=5.9929
این هم از آپدیت:
lr = 0.1 b = b - lr * b_grad w = w - lr * w_grad print('w_new={:.4f} , b_new={:.4f}'.format(w.item(), b.item()))
w_new=-0.1683 , b_new=-2.4439
اجرای فرآیند تکراری برای کاهش خطا در رگرسیون خطی
حالا باید چند مرحله بالا را آنقدر تکرار کنیم تا به کمترین مقدار خطا برسیم. در کدهای زیر میبینید که همان تکه کدهای بالا را زیرهم گذاشتم و کلا همه را در یک حلقه برای 1000 بار تکرار قرار دادم.
np.random.seed(2) b = np.random.randn(1) w = np.random.randn(1) print('w0={:.4f} , b0={:.4f}'.format(w.item(), b.item())) lr = 0.1 n_epochs = 1000 for epoch in range(n_epochs): # Model yp = b + w * x_train # Loss error = (y_train - yp) loss = (error ** 2).mean() # Gradient b_grad = -2 * error.mean() w_grad = -2 * (x_train * error).mean() # Update b = b - lr * b_grad w = w - lr * w_grad print('wf={:.4f} , bf={:.4f}'.format(w.item(), b.item()))
w0=-0.0563 , b0=-0.4168 wf=2.0373 , bf=0.9732
خب به خروجی نگاه کنید؛ اول مقادیر کاملا پرتی برای w و b داشتیم. بعد از 1000 تکرار، توانستیم به مقدار w=2.03 و b=0.97 در مثالمان برسیم. این اعداد بسیار به مقادیر واقعی w=2 و b=1 نزدیک هستند. یعنی یادگیری ماشین، تابع زیر را بعد از آموزش پیشنهاد داده است:
من مقدار اتلاف و پارامترها را در هرمرحله ذخیره کردم تا بتوانم نحوه حرکت بهسمت پارامترهای بهینه را به شما نشان دهم.
خب، حالا چطوری مدل رگرسیون خطی را ارزیابی کنیم؟! مرحله بعدی لطفا…
ارزیابی مدل رگرسیون خطی
در بخش قبلی دیدید که چگونه مدل رگرسیون خطی را آموزش دادیم و به پارامترهای بهینه w و b رسیدیم. اما چگونه این مدل آموزش دیده را ارزیابی کنیم؟ چگونه متوجه شویم که این مدل واقعا خوب کار میکند؟ جواب سوالها این ساده هست.
ما در بخش قبل دیدیم که مدل ما خیلی شیک روی نقاط x آموزشی فیت شده است. خطا هم روی این دادهها بسیار کم بود. اما آیا اگر مجموعهای داده داشته باشیم که مدل آنها را در فرآیند آموزش ندیده باشد، بازهم جواب خوبی میدهد؟ درواقع، الان در شرایطی هستیم که یک دانشآموزی داریم که برای درس ریاضی یک عالمه درس خوانده و همه سوالهای داخل کتاب را سهسوته حل میکند. اما آیا میتوانیم بگوییم که حتما در امتحان به سادگی به همه سوالات جواب میدهد؟ خیر، ممکن است امتحان بدهد و 3.75 شود! کافی است بجای فهمیدن درس ریاضی، فقط سوالات و جوابها را حفظ کرده باشد. بنابراین، ما باید یک مجموعه داده برای ارزیابی داشته باشیم که مدل ما روی آنها آموزش ندیده باشد.
من یک مجموعه داده ارزیابی بهنام test دارم. میخواهم مدل یادگیری ماشین را روی این مجموعه داده ارزیابی کنم. اما بیایید معادله (**) را روی دادههای شکل 1 بیندازیم و ببینیم اوضاع چطور است.
حالا چگونه ارزیابی روی داده تست را انجام دهم؟ کافی است، یکییکی ورودیهای داده تست را به رابطه (**) بدهم و بعد هم خروجی پیش بینی را مشاهده کنم و لذت ببرم.
yp = b + w * x_val error = (yp - y_val) loss = (error ** 2).mean() print('Loss=', loss)
Loss=0.00880
حدود 0.009 خطا داریم و این بسیار کم است! اولین مدلمان را بهراحتی آموزش دادیم. 😎
نکته معیار در مسائل رگرسیون از دو معیار MSE و MAE برای ارزیابی عملکرد استفاده میشود.
به پایان جلسه رگرسیون در یادگیری ماشین رسیدیم. یک نمونه مدل رگرسیون معروف بهنام رگرسیون خطی را بررسی کردیم. همچنین، کاربرد گرادیان کاهشی را که در جلسه قبلی با آن آشنا شدید را در اینجا دیدید. طبیعتا انواع مدل رگرسیون داریم که صحبت درباره آنها در این مقال نمیگنجد. مثلا:
- رگرسیون چندجمله ای
- رگرسیون Ridge
- رگرسیون Lasso
- رگرسیون ElasticNet
در جلسه درباره دسته بندی یا کلاسبندی در یادگیری ماشین صحبت خواهیم کرد. لطفا حالا شما بگویید این جلسه چطور بود؟ لطفا نظر و پیشنهادتان را برای ما کامنت کنید. با هوسم همراه باشید…
مطالب زیر را حتما مطالعه کنید
آموزش یادگیری ماشین رایگان
الگوریتم k means
نرمال سازی داده در یادگیری ماشین
یادگیری گروهی
ماشین بردار پشتیبان
الگوریتم KNN
28 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
سلام ممنون از آموزش خوبتون
سلام
ممنون 🌹🙏
سلام خیلی عالی بود heart
کاش میشد آخر آموزش چندتا آزمون تستی از آموزش می گرفتید
و لینک دانلود کد کامل رو هم میگذاشتید
سلام
بله، سعی میکنیم آزمون هم بذاریم. لینک کدها رو هم اضافه میکنیم.
ممنون 🌹🙏
سلام روزتون بخیر کدتون یه ایرادی داره .فرمول w_grad , b_grad درست نیست
سلام منم احساس کردم مشکل داره به کمک Gemini گوگل یکم کد رو بهتر کردم ولی آخرش خودم فهمیدم که باید مثل زیر باشه تا همگرا بشه وگرنه هی بد تر و بد تر میشه
w_grad = 2 * (xtrain * error).mean()
b_grad = 2 * error.mean()
b -= lr*b_grad
w -= lr*w_grad
و یا اینطوری بنویسی:
w_grad = -2 * (xtrain * error).mean()
b_grad = -2 * error.mean()
b += lr*b_grad
w += lr*w_grad
بسیار عالی، شیوا و جذاب …
بسیار خوب و مفید و روشن
ممنون. برای من بسیار مفید بود
واقعاً عالی آموزش هاتون
همین طور ادامه بدید
موفق باشید
عالی هستید.
سپاس🌹
عالی بود. خیلی واضح و شیرین تدریس میکنید.
سلام، روز بخیر
ممنونم بابت توضیحات عالیتون
یک سوال داشتم، اگر یکسری داده رو بدیم به رگرسیون و نتایج رو برامون پیشبینی کنه، چطور باید تابعی که کد ماشین لرنینگ بر اساس اون داره پیشبینی رو انجام میده از کد بگیریم؟ منظورم تابع ریاضی هست
خیلی خوب بود
ولی چون من هشتمم فرمول های ریاضیش رو اصلا متوجه نمیشم
فقط کلیاتش رو متوجه شدم
سلام
خیلی ممنون از آموزش خوبتان، توضیحات عالیییییی بود.
فقط اینکه چرا در بخش تعیین مقادیر جدید برای پارامتر w و b با گرادیان کاهشی، وقتی از تابع نسبت به w یا b مشتق گرفتین، علامت منفی پشت 2/n گذاشتین ولی در جلسه ی 02 یادگیری عمیق رایگان این منفی را نگذاشتین (که باعث شده جهت حرکتw برعکس شود)؟ چه چوری باید تشخیص بدیم که باید منفی بگذاریم یا نه؟
عالی بود
ممنونم ازتون
یک توصیه به نگارنده ی این مطلب:
(سایز فونت نوشته ها و توضیحات) رو با (سایز فونت کد) یکسان کنید لطفا.
متشکرم
خیلی ممنون، خدا خیرتون بده
ممنون، خیلی ساده و کاربردی بود برای من
سلام فوق العاده بود.
توی آموزش هایی که گذاشتین توضیح دادن که تابع loss شخصی سازی شده رو چطور میشه به تنسور تبدیل کرد.که بتونیم توی کتابخانه keras از استفاده کنیم
واقعا عالی توضیح میدید همینجوری ادامه بدید
سلام
انشالله ادامه میدیم.
ممنون از اینکه کامنت میذارید و انرژی میدید 🌹🙏
ممنون اموزش خوبتون
خیلی شفاف و کاربردی تدریس شده 🙏
سلام آموزش بسيار جالب و قابل درکي رو ارائه داديد بي نهايت سپازگزارم اميدوارم بيقه مباحث يادگيري ماشين رو هم ارائه بدبد .
سلام
سپاس 🌹🙏
بله ادامه داره. درحال آمادهسازی آموزش رگرسیون لاجستیک هستم…
توضیحات عالی بود.
اگر کل دیپ لرنینگ علاوه بر کلاس آنلاین و آفلاین به این صورت هم مدل شود بی نهایت عالی می شود.(هرچند کار ساده ای نیست)
فقط کدهای پایتورچ نوشته شده بدون مطالعه قبلی پایتورچ قابل درک نبودند.که اگر در کنار آنها یک لینک آموزشی جداگانه ای گذاشته شود بنظرم بد نیست.
مجدد از توضیحات فوق العاده شما سپاسگزارم.
سلام
از شما ممنونیم بابت کامنت و البته پیشنهادها 🌹🙏
تلاش میکنیم مفاهیم پیچیده رو هم به این شکل بیان کنیم. سعی کردیم در بخش آموزش یادگیری عمیق رایگان این کار رو انجام بدیم.
کدهای این بخش با نامپای نوشته شده. حق با شماست، برای کسانی که با نامپای آشنایی ندارند، ممکن هست این کدها قابل درک نباشه. آموزش نامپای درحال آمادهسازی هست و به زودی منتشر میشه.