رگرسیون با mlp و تنسورفلو
در جلسه قبل از آموزش یادگیری عمیق توانستیم یک شبکه mlp برای دسته بندی پایگاه داده fashion-mnist آموزش دهیم. در این بخش میخواهیم یک پروژه رگرسیون با mlp و تنسورفلو انجام دهیم. در پروژه ای که انجام خواهیم داد، میخواهیم یک شبکه رگرسیون برای تخمین قیمت خانه بسازیم. با هوسم همراه باشید…
استفاده از شبکه عصبی mlp برای رگرسیون
از شبکههای mlp میتوان برای رگرسیون استفاده کرد. مثلا برای تخمین قیمت یک خانه، ویژگیهای آن خانه را به شبکه میدهیم. سپس شبکه تخمین میزند که قیمت آن خانه چقدر است. در چنین مسائلی ما فقط یک نورون خروجی خواهیم داشت. که خروجی آن نورون، مقدار پیشبینی شده برای قیمت خانه است. در رگرسیون چندمتغیره به ازای هر متغیر یک نورون خروجی خواهیم داشت. به عنوان مثال برای تخمین مرکز یک دایره به 2 عدد نیاز است. که مختصات مرکز در فضای دوبعدی مشخص شود. چنین مسئلهای نیاز به شبکهای دارد که دو نورون خروجی داشته باشد.
به طور کلی برای استفاده از mlp در رگرسیون، نیاز نیست نورنهای خروجی تابع فعالساز داشته باشند. در این صورت نورونهای خروجی آزاد هستند که هر رنج عددی را تخمین بزنند. اگر بخواهید که خروجی شبکه همیشه مثبت باشد، آنگاه میتوانید از یک تابع فعالسازی مانند ReLU استفاده کنید. اگر هم میخواهید خروجی در یک رنج خاص باشد، میتوانید از توابع فعالسازی مانند سیگموید استفاده کنید. این توابع فعالسازی رنج خروجی را محدود به یک بازه میکنند. مثلا سیگموید رنج خروجی را بین 0 و 1 قرار خواهد داد.
طرح مسئله
در این جلسه ما میخواهیم یک شبکه رگرسیون با mlp و تنسورفلو بسازیم. وظیفه شبکهای که میسازیم این است که ویژگیهای یک خانه را بگیرد و قیمت آن را تخمین بزند. ویژگی خانه میتواند عمر ساختمان، تعداد اتاقها و … باشد. برای آموزش این شبکه از پایگاه داده California Housing Prices استفاده خواهیم کرد. برای پیادهسازی این پروژه از فریمورک تنسورفلو 2 و کراس استفاده میکنیم. همچنین مانند جلسه قبل، کدنویسی در گوگل کولب انجام خواهد شد.
فراخوانی پایگاه داده
گفتیم پایگاه دادهای که استفاده خواهیم کرد، California Housing Prices خواهد بود. در این پایگاه داده ویژگیهای هر خانه به شکل زیر مشخص شده است:
- طول جغرافیایی
- عرض جغرافیایی
- قدمت بنا
- تعداد اتاقها
- تعداد اتاق خوابها
- میران آلودگی منطقه
- صاحب خانهها
- میزان درآمد
- قیمت بنا
- نزدیکی به اقیانوس
گفتیم ما میخواهیم یک شبکه رگرسیون با mlp و تنسورفلو بسازیم. که با استفاده از ویژگیهایی که در بالا گفتیم، مقدار قیمت بنا را تخمین بزند. برای این کار ابتدا باید این پایگاه داده را دانلود و فراخوانی کنیم. کتابخانه معروف یادگیری ماشین یعنی Scikit-Learn امکان دانلود این پایگاه داده را فراهم آورده است. برای فراخوانی داده با Scikit-Learn، ابتدا باید این کتابخانه را import کنیم. ما کُل کتابخانه را فراخوانی نمیکنیم. بلکه فقط ابزارهایی از کتابخانه که به آنها نیاز داریم را فراخوانی میکنیم:
from sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler
پس از import کردن Scikit learn، نوبت به فراخوانی داده میرسد. ابتدا دادهها را فراخوانی میکنیم:
housing = fetch_california_housing() x_train_full, x_test, y_train_full, y_test = train_test_split(housing.data, housing.target) x_train, x_valid, y_train, y_valid = train_test_split(x_train_full, y_train_full)
مشاهده میکنیده که در پایگاه داده California Housing Prices، دادههای آموزش ، اعتبارسنجی و تست جدا نشدهاند. پس همین اول با کمک دستور train_test_split، دادهها را به train و تست تقسیم میکنیم. سپس دادههای train را باز هم با کمک دستور train_test_split به train و validation تقسیم میکنیم.
نکته دستور train_test_split یک ورودی اضافی نیز قبول میکند. این ورودی اضافی مشخص میکند که چند درصد از دادهها به آموزش و چند درصد دیگر به ارزیابی اختصاص داده شود. مثلا اگر بخواهید 50 درصد از دادهها را به ارزیابی اختصاص دهید کافی است بنویسید: train_test_split( x_train, y_train, test_size=0.5) . مقدار پیشفرض برای test_size، مقدار 0.25 است. یعنی اگر test_size اصلا در ورودی نباشد، 25 درصد از دادهها برای ارزیابی جدا خواهند شد.
اگر دادهها را print کنید، متوجه خواهید شد که ویژگیها رنجهای متفاوتی دارند. بنابراین باید مقدار ویژگیها را استاندارد کنیم. مقادیر را با استفاده از Scikit-Learn به میانگین صفر و انحراف معیار یک استاندارد میکنیم:
scaler = StandardScaler() x_train = scaler.fit_transform(x_train) x_valid = scaler.transform(x_valid) x_test = scaler.transform(x_test)
مشاهده میکنید که ما به کمک توابع StandardScaler و fit_transform از کتابخانه Scikit-Learn توانستیم مقادیر را به میانگین صفر و انحراف معیار یک استاندارد کنیم. حتما مقادیر دادهها را قبل و بعد از استانداردسازی print کنید. و ببینید که چه تغییراتی در دادهها رخ میدهد.
ساختن شبکه mlp برای رگرسیون
بعد از import دادهها و استانداردسازی، نوبت به تعریف شبکه میرسد. فرآیند تعریف شبکه مشابه با جلسه قبل با استفاده از model.sequential انجام خواهد شد. تنها تفاوت در ساختار شبکهها و تابع اتلاف است. در جلسه قبل دیدیم که یک کلاسیفایر mlp، در لایه خروجی تابع فعالسازی softmax دارد. دلیل استفاده از softmax هم این بود که برای هر کلاس یک احتمال بدست بیاید. از آنجایی که مجموع مقادیر خروجی softmax یک است، هر کلاسی که بیشترین احتمال را داشت، به عنوان پیشبینی شبکه انتخاب میشد. اما در شبکه رگرسیون، لایه خروجی هیچ تابع فعالسازی نخواهد داشت. زیرا ما میخواهیم که شبکه یک عدد را تخمین بزند. همچنین در مسئله رگرسیون از تابع اتلاف MSE استفاده خواهیم کرد. این تابع اتلاف میزان فاصله از مقدار واقعی را به ما نشان میدهد. شبکه رگرسیون را به شکل زیر تعریف میکنیم:
model = keras.models.Sequential([ keras.layers.Dense(30, activation="relu", input_shape=x_train.shape[1:]), keras.layers.Dense(1) ])
همانطور که مشاهده میکنید، شبکه، یک لایه fully connected با 30 نورون دارد. این لایه با دستور keras.layers.Dense ساخته شده است. که در آن ورودی اول، تعداد نورونها را نشان میدهد. ورودی دوم نشان میدهد که تابع فعالسازی ReLU برای این لایه انتخاب شده است. ورودی سوم اما ابعاد ورودی لایه را نشان میدهد. متغیر x_train تعداد 11610 سطر و 8 ستون دارد. در واقع 8 ستون از داده داریم و باید این 8 ستون را به شبکه بدهیم. عبارت input_shape=x_train.shape[1:] میگوید که ابعاد ورودی 8 است! درست همان چیزی که میخواستیم. در نهایت لایه خروجی هم یک نورون دارد.
قدم بعدی نوبت به compile کردن شبکه است. یعنی باید تعیین کنیم که شبکه چه تابع اتلافی دارد. برای این شبکه از MSE استفاده خواهیم کرد. همچنین باید تعیین شود الگوریتم بهینهسازی آن چیست. برای این شبکه از گرادیان کاهشی استفاده میکنیم. در کلاسبندی معیار ارزیابی را هم مشخص کردیم. وقتی بحث رگرسیون میشود، معیار ارزیابی را همان فاصله میتوان در نظر گرفت. در اینجا ما معیار ارزیابی تعریف نمیکنیم. زیرا تابع اتلاف یعنی همان MSE، معیار ارزیابی نیز هست. برای compile کردن شبکه کد زیر را بنویسید:
model.compile(loss="mean_squared_error", optimizer="sgd")
آموزش شبکه رگرسیون
تا اینجا توانستیم یک شبکه رگرسیون با mlp و تنسورفلو 2 بسازیم و کامپایل کنیم. الان نوبت به آموزش دادن شبکه است. برای آموزش شبکه، کد زیر را بنویسید:
history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid))
مشاهده میکنید دستوری که برای آموزش شبکه نوشتیم، model.fit است. ابتدا دادههای آموزشی و برچسب آنها را به عنوان ورودی به model.fit میدهیم. سپس با کمک epochs=20 مشخص میکنیم که تعداد تکرارها 20 تا باشد. در نهایت هم دادههای اعتبارسنجی را به صورت validation_data=(X_valid, y_valid( به دستور model.fit میدهیم. با اجرای کد بالا خواهیم داشت:
Epoch 1/20
363/363 [==============================] - 1s 2ms/step - loss: 0.9365 - val_loss: 0.6358
Epoch 2/20
363/363 [==============================] - 1s 2ms/step - loss: 0.6851 - val_loss: 0.4733
Epoch 3/20
363/363 [==============================] - 1s 2ms/step - loss: 0.4735 - val_loss: 0.4293
.
.
.
Epoch 19/20
363/363 [==============================] - 1s 2ms/step - loss: 0.3649 - val_loss: 0.3592
Epoch 20/20
363/363 [==============================] - 1s 2ms/step - loss: 0.3653 - val_loss: 0.3610
مشاهده میکنید که مقدار اتلاف رفته رفته کاهش یافته است.
رسم نمودار loss
برای رسم نمودار اتلاف کافی است بنویسید:
import pandas as pd import matplotlib.pyplot as plt pd.DataFrame(history.history).plot(figsize=(8, 5)) plt.grid(True) plt.gca().set_ylim(0, 1) # set the vertical range to [0-1] plt.show()
با اجرای کد بالا خواهیم داشت:
مشاهده میکنید که همانطور که گفتیم مقدار اتلاف از آغاز آموزش تا پایانِ 20 تکرار، کاهش یافته است. و اگر دقت کنید میبینید که کماکان تمایل به کم شدن دارد. یعنی اگر فرآیند آموزش را ادامه میدادید چه بسا که کمتر هم میشد!
ارزیابی شبکه رگرسیون
در این قسمت میخواهیم ببینیم شبکه روی دادههای تست چه عملکردی دارد. برای این کار کافی است از دستور model.evaluate استفاده کنید:
se_test = model.evaluate(x_test, y_test)
با اجرای کد بالا مقدار اتلاف MSE برای دادههای تست به شکل زیر به دست خواهد آمد:
162/162 [==============================] - 0s 1ms/step - loss: 0.3865
مشاهده میکنید که مقدار اتلاف MSE برای دادههای تست، 0.38 به دست آمد.
خب تبریک میگویم! شما موفق شدید پروژه را به پایان برسانید😎. شما توانستید یک شبکه رگرسیون با mlp و تنسورفلو 2 بسازید. و این شبکه را آموزش دادید تا بتواند بر اساس ویژگیهایی که دریافت میکند، قیمت یک خانه را تخمین بزند.
منابع آموزش یادگیری عمیق
در فهرست زیر، تعدادی از منابع خوب آموزش یادگیری عمیق را معرفی کردهایم.
- کتاب Hands on Machine Learning
- کتاب Pattern Recognition and Machine Learning
- کتاب Neural Networks for Pattern Recognition
- کتاب شبکه عصبی Haykin
در این پست یک شبکه رگرسیون با mlp و تنسورفلو 2 ساختیم. سپس شبکه را روی پایگاه داده California Housing Prices، آموزش دادیم. امیدوارم این آموزش مورد توجه شما قرار گرفته باشد. نظرات و سوالات خود را پایین 👇 برایمان کامنت کنید. حتما سوالات شما پاسخ داده خواهد شد.
مطالب زیر را حتما مطالعه کنید
شبکه عصبی mlp
شبکه ترنسفورمر
مدل MobileLLM
یادگیری عمیق چیست
آموزش یادگیری عمیق رایگان
شبکه عصبی کانولوشن
7 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
سلام
چجوری میشه قیمت پیش بینی چند تا خونه از داده ها رو دید؟
سلام
ضمن تشکر از شما. قرار شد مدل قیمت خانه ارائه کند. قیمت خانه ای ندیدم ولی زدید پروژه انجام شد.
سلام
در بخش ارزیابی شبکه رگرسیون، مدل به ازای ورودی x_test، پیشبینی انجام داده (قیمت خونه تخمین زده) و این پیشبینی با y_test مقایسه شده…
اگه میخوایید اعداد تخمینی رو ببینید، بنویسید: model.predict(x_test)
سلام
اول تشکر میکنم انقدر خوب و روان تدریس میکنین …
دوم اینکه من سوال برام پیش اومده تفاوت fit.transform با transform چی هست ؟
وplt.gca() چه کاری انجام میده ؟
سلام
دو دستور fit_transform و transform مربوط به فریمورک سایکیت لرن هستن و خب اینجا توضیح دادنش کمی مشکله. بهصورت خلاصه، اگر داده آموزش رو مثلا میخوایید نرمالیزه کنید، باید هم فیت کنید و هم ترنسفورم (پس میشه fit_transform). اگر داده ارزیابی رو میخوایید نرمالیزه کنید، فقط باید ترنسفورم بشه (پس میشه transform).
توضیح خلاصه سوال دومتون هم سخته 😅 plt.gca یعنی get current axes. در واقع axes جاری رو به عنوان آبجکت میگیره و بعد ما میتونیم روی این آبجکت تنظیماتی رو اعمال کنیم. مثلا تغییر بازه محور عمودی و افقی، گذاشتن لیبل برای محور افقی و عمودی و …
ممنون از اموزشهای بسیار خوبتون
فقط میشه لطفا جلسات بعد رو هم درسایت قرار بدین
سلام
بله حتما. جلسه بعدی کانولوشن هست که بخشی از اون نگارش شده و درحال آمادهسازی هست.