فهرست مطالب
در این مقاله یاد می گیریم چطور یک مدل یادگیری ماشین با پایتون بسازیم. با اینکه انتخابهای متنوعی برای زبان برنامهنویسی وجود دارد (مقاله زبان های برنامه نویسی یادگیری ماشین را بخوانید)، برای این تمرین از پایتون استفاده میکنیم چرا که یادگیری آن سریع است و برای تغییر و کار با مجموعهدادههای بزرگ، مفید و مناسب است.
اگر هیچ تجربهای در برنامهنویسی یا پایتون ندارید، اصلاً لازم نیست نگران باشید. هدف اصلی این قسمت، درک روش و قدمهای لازم برای ساخت یک مدل یادگیری ماشین با پایتون است.
. . . .
یادگیری ماشین با پایتون
در این تمرین و طی 6 گام، سیستم ارزشگذاری قیمت خانه با استفاده از gradient boosting را طراحی میکنیم:
- آمادهسازی محیط کدنویسی
- بارگذاری مجموعهداده
- پاکسازی مجموعهداده
- تقسیم داده به دو بخش آموزشی و آزمایشی
- انتخاب الگوریتم و تنظیم ابرپارامترها
- ارزیابی نتایج
1) آمادهسازی محیط کدنویسی
قدم اول، آمادهکردن محیط کدنویسی است. برای این تمرین، از Jupyter Notebook استفاده میکنیم که یک وب اپلیکیشن متنباز است که اجازه ویرایش و به اشتراک گذاشتن notebookها را میدهد.
Jupyter Notebook از آدرس http://jupyter.org/install.html قابل دانلود است. این وب اپلیکیشن با استفاده از توزیع آناکوندا (Anaconda Distribution) یا سامانه مدیریت بسته پایتون (pip: Python Package Manager ) نصب میشود.
برای افراد مبتدی، نصب از طریق Anaconda پیشنهاد میشود که بسیار ساده بوده و در حد چند کلیک است.
با این شیوه نصب، به سایت Anaconda هدایت میشوید. سپس میتوانید نسخه ویندوز، macOS یا لینوکس را انتخاب کنید. همچنین دستورالعملهای نصب (متناسب با سیستمعامل مورد انتخابتان) بر روی وبسایت Anaconda در دسترس است.
پس از نصب Anaconda بر روی سیستم خود، به تعدادی از برنامههای علم داده از جمله rstudio، Jupyter Notebook و graphicviz دسترسی خواهید داشت. برای انجام این تمرین، باید در داخل سربرگ Jupyter Notebook، روی دکمه “launch” کلیک کنید.
برای شروع کار با Jupyter Notebook، دستور زیر را از ترمینال (برای مک یا لینوکس و برای ویندوز داخل cmd) اجرا کنید:
“jupyter notebook”
سپس داخل ترمینال یک URL ایجاد میشود. کافی است آن را کپی و در مرورگر وارد کنید مثل:
http://localhost:8888
بهمحض اینکه Jupyter Notebook در مرورگرتان باز شد بر روی “new” در گوشه بالا سمت راست وب اپلیکیشن، کلیک کنید تا یک “Notebook”جدید ساخته شود.
قدم نهایی در این بخش از ساخت مدل یادگیری ماشین با پایتون نصب کتابخانههای ضروری مورداستفاده برای تکمیل این تمرین است. نیاز دارید که Pandas و تعدادی از کتابخانهها از جمله Scikit-learn را نصب کنید.
هر پروژه در یادگیری ماشین با پایتون، از نظر کتابخانههای موردنیاز برای بارگذاری، متفاوت خواهد بود. برای این تمرین خاص، از gradient boosting و از میانگین قدرمطلق خطا برای ارزیابی کارایی استفاده میکنیم.
باید هرکدام از کتابخانهها و توابع زیر را با واردکردن دقیق همین دستورات در Jupyter Notebook بارگذاری کنید:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import ensemble
from sklearn.metrics import mean_absolute_error
from sklearn.externals import joblib
اگر هرکدام از کتابخانههای بارگذاری شده در قطعه کد بالا را نمیشناسید نگران نباشید. در قدمهای بعدی، به این کتابخانهها اشاره خواهد شد.
2)بارگذاری مجموعهداده یا دیتاست
قدم بعدی برای پروژه یادگیری ماشین با پایتون بارگذاری مجموعهداده است. برای این تمرین، یک مجموعهداده رایگان از kaggle را انتخاب کردهام که شامل خانه، تعداد واحد و قیمت خانه در ملبورن استرالیا میشود. مجموعهداده شامل لیست 14242 ملک و 21 متغیر شامل آدرس، اندازه زمین، تعداد اتاقها، قیمت، طول جغرافیایی، عرض جغرافیایی، کد پستی و غیره است.
لطفاً دقت داشته باشید که ارزش ملک در این مجموعهداده به دلار استرالیا – یک دلار استرالیا تقریباً 0.77 دلار آمریکا است (از 2017)- بیان شده است.
مجموعهداده بازار ملک ملبورن (the Melbourne Housing Market) را از لینک زیر دانلود کنید:
https://www.kaggle.com/anthonypino/melbourne-housing-market
پس از ساخت یک اکانت رایگان و ورود به سایت kaggle، مجموعهداده را به شکل یک فایل zip دانلود کنید. سپس، فایل دانلود شده را unzip کنید و در Jupyter Notebook بارگذاری کنید. برای بارگذاری مجموعهداده، از تابع read_csv استفاده کنید.
df = pd.read_csv('~/Downloads/Melbourne_housing_FULL-26-09-2017.csv')
این دستور مجموعهداده را مستقیماً بارگذاری میکند. بااینحال، دقت داشته باشید که آدرس دقیق فایل به محل ذخیره مجموعهداده بستگی دارد. برای مثال، اگر فایل csv را بر روی دسکتاپ خود ذخیره کردهاید، لازم است فایل csv. را با استفاده از دستور زیر بخوانید:
df = pd.read_csv('~/Desktop/Melbourne_housing_FULL-26-09-2017.csv')
پس از پیشروی در یادگیری ماشین و علم داده، مهم است که مجموعهداده و پروژهها را در فولدرهایی مستقل و با نام مناسب، برای دسترسی منظم، ذخیره کنید. اگر تصمیم گرفتید که فایل csv. را در همان فولدر Jupyter Notebook خود ذخیره کنید، نیازی ندارید که اسم directory یا “~/” را اضافه کنید.
سپس، برای نمایش dataframe در Jupyter Notebook، دستور زیر را وارد کنید که “n” نشاندهنده تعداد ردیفهایی است که نمایش داده میشود.
df.head(n=5)
کلیک راست کنید و “Run” را انتخاب کنید یا از منوی Jupyter Notebook مسیر زیر را جستجو کنید:
Cell > Run All
این کار اجباری نیست ولی تکنیک مفیدی برای نمایش مجموعهدادهتان و آشنایی بیشتر با آن است.
3) پاکسازی داده یا Data Cleaning
قدم بعدی ساخت مدل یادگیری ماشین با پایتون، تمیزکردن مجموعهداده و بهبود آن است. این فرایند شامل تغییر یا حذف دادههای ناکامل، نامربوط یا تکراری است. این فرایند ممکن است شامل تبدیل داده متنی به مقادیر عددی و بازسازی ویژگیها بشود.
فرایند پاکسازی ممکن است قبل یا بعد از بارگذاری مجموعهداده در Jupyter Notebook انجام بپذیرد. برای مثال، سازنده مجموعهداده بازار ملک ملبورن دو عنوان ستون “Longitude” و “Latitude” را با املای غلط نوشته است. از آنجایی که این دو متغیر را در این تمرین مورد بررسی قرار نمی دهیم، نیازی به تغییر و اصلاح نیست. بااینحال، اگر قصد داشتیم که این دو متغیر را وارد مدلمان کنیم، معقولانه بود که این خطا را برطرف کنیم.
از دیدگاه برنامهنویسی، غلط املایی در عنوان این ستونها، تا زمانی که از همین املا برای انجام دستورات استفاده کنیم، هیچ خطایی به وجود نمیآورد. بااینحال، این نامگذاری غلط ستونها ممکن است باعث خطای انسان بشود، بهخصوص اگر کدتان را با اعضای تیم به اشتراک میگذارید.
برای پیشگیری از هرگونه سردرگمی احتمالی، بهتر است تا غلطهای املایی و دیگر خطاهای ساده در فایل منبع، قبل از بارگذاری دادهمحور y Notebook اصلاح شوند. کافی است فایل CSV محور y excel(یا برنامه معادل دیگر) بازکرده سپس اصلاحات لازم انجام شده و در نهایت دوباره در قالب یک فایل CSV ذخیره شوند.
درحالیکه خطاهای ساده را میتوان در فایل منبع اصلاح کرد، تغییرات ساختاری بزرگ بر روی مجموعهداده مثل مهندسی ویژگی، در محیط کدنویسی بهتر صورت میپذیرد – برای انعطافپذیری بیشتر و برای حفظ مجموعهداده برای استفادههای آینده. برای مثال، در این تمرین، مهندسی ویژگی در قالب حذف تعدادی از ستونهای مجموعهداده پیادهسازی میشود ولی ممکن است بعداً نظرمان درباره اینکه کدام ستونها را میخواهیم استفاده کنیم، عوض بشود.
اگر ستونها را در فایل منبع حذف کرده بودیم، دیگر قابل برگشت نبود ولی وقتی در محیط توسعه و کدنویسی ستونها را حذف کنیم، امکان تغییر و برگشت وجود دارد. بهطورکلی تغییرات در محیط کدنویسی، سریعتر و آسانتر هستند.
پاکسازی داده ها چیست و چه مراحلی دارد؟
ابتدا ستونهایی را که نمیخواهیم در مدل استفاده کنیم با استفاده از تابع del و واردکردن عنوان ستون حذف میکنیم.
del df[‘Address’]
del df[‘Method’]
del df[‘SellerG’]
del df[‘Date’]
del df[‘Postcode’]
del df[‘Lattitude’]
del df[‘Longtitude’]
del df[‘Regionname’]
del df[‘Propertycount’]
ستونهای Address، Regionname و Propertycount حذف شدند چون موقعیت ملک در دیگر ستونها (Suburb و CouncilArea) پوشش داده شده است و همینطور میخواهیم اطلاعات غیر عددی را به حداقل برسانیم (مثل Address و Regionname). Postcode، Latitude و Longitude نیز حذف شدند چون همانطور که گفته شد، موقعیت ملک در ستونهای Suburb و CouncilArea وجود دارد.
فرض اولیه این است که احتمالاً در ذهن خریدار ستونهای Suburb و CouncilArea اهمیت بیشتری نسبت به Postcode، Latitude و Longitude دارند.
Method، SellerG و Date نیز حذف شدند چون فرض شده که در مقایسه با دیگر متغیرها، ارتباط کمتری باهدف مسئله داشته باشند. البته به این معنی نیست که این متغیرها بر قیمت ملک تأثیرگذار نیستند، بلکه به معنی این است که یازده متغیر مستقل دیگر، برای ساخت یک مدل ساده کافی هستند. در آینده یا همینالان میتوانید هرکدام از این متغیرها را به مدل اضافه کنید.
یازده متغیر مستقل باقیمانده در مجموعهداده (که با X نمایش داده میشوند) Suburb، Rooms، Type، Distance، Bedroom2، Bathroom، Car، Landsize، BuildingArea، YearBuilt و CouncilArea هستند. متغیر دوازدهم که در ستون پنجم از مجموعهداده وجود دارد، متغیر وابسته یعنی قیمت است (با y نمایش داده میشود).
همانطور که اشاره شد، درختهای تصمیم (از جمله gradient boosting و جنگل تصادفی) در مدیریت مجموعهدادههای بزرگ (ابعاد بالا و تعداد متغیرهای زیاد) عملکرد خوبی دارند.
قدم بعدی در پاکسازی مجموعهداده برای مدل یادگیری ماشین با پایتون، حذف مقادیر ناموجود است. با اینکه روشهای زیادی برای مدیریت مقادیر ناموجود وجود دارد (مثلاً محاسبه میانگین، میانه و حذف تمام مقادیر ناموجود) اما برای این تمرین، میخواهیم تاحدامکان آن را ساده نگهداریم پس ردیفهای دارای مقادیر ناموجود را در نظر نمیگیرم. نکته منفی واضح آن، این است که داده کمتری برای تحلیل داریم.
متأسفانه، در مجموعهداده تعداد زیادی مقادیر ناموجود داریم! بااینوجود، تعداد ردیفهای در دسترس برای ساخت مدل یادگیری ماشین با پایتون کافی است.
تابع زیر از کتابخانه Pandas برای حذف ردیفهای دارای مقادیر ناموجود استفاده میشود:
df.dropna(axis=0, how=’any’, thresh=None, subset=None, inplace=True)
بعد از اجرای دستور del df، باید ردیفهای دارای مقادیر ناموجود را حذف کنید (همانطور که در قدم قبلی نشان داده شد). از این طریق، احتمال وجود ردیفهای بیشتر از مجموعهداده اصلی بیشتر میشود. در نظر بگیرید یک ردیف بهخاطر اینکه یک مقدار ناموجود دارد بهکلی حذف شود مثل post code درصورتیکه بعداً در مدل از این متغیر استفاده نکرده و حذف میشود و یک ردیف از دادهها کم شده است.
سپس، ستونهایی که داده غیرعددی دارند را با استفاده از رمزگذاری one-hot به مقادیر عددی تبدیل میکنیم. با استفاده از تابع get_dummies از کتابخانه Pandas، رمزگذاری one-hot را پیاده میکنیم:
features_df = pd.get_dummies(df, columns=[‘Suburb’, ‘CouncilArea’, ‘Type’])
این دستور مقادیر ستونهای Suburb، CouncilArea و Type را به کمک رمزگذاری one-hot به مقادیر عددی تبدیل میکند.
سپس، چون ستون price بهعنوان متغیر وابسته خواهد بود حذف میکنیم – در حال حاضر تنها یازده متغیر مستقل (X) را بررسی خواهیم کرد.
del features_df[‘Price’]
در نهایت، ازروی مجموعهداده با استفاده از as_matrix، آرایههای X و y را میسازیم. آرایه X شامل متغیرهای مستقل و آرایه y شامل متغیر وابسته قیمت است.
X=features_df.as_matrix()
y=df[‘Price’].as_matrix4()
دوره آموزشی: میخواهید دادههایتان را خودتان جمع آوری کنید و یک دیتاست برای خودتان بسازید؟ پس دوره آموزش رایگان وب اسکرپینگ را در کانال یوتیوب دیتاهاب ببینید.
4)تقسیم مجموعهداده
در ادامه مسیر یادگیری ماشین با پایتون، الان در مرحلهی تقسیم داده به دو قسمت آموزشی و آزمایشی هستیم. برای این تمرین، با استاندارد تقسیم 70/30 عمل میکنیم. برای این کار تابع زیر از کتابخانهی Scikit-learn را با ورودی “0.3” فراخوانی میکنیم. ردیفهای مجموعهداده با استفاده از تابع random_state تصادفی جابهجا شدهاند تا از بایاس جلوگیری شود.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
5)انتخاب الگوریتم و تنظیم ابر پارامترها
همانطور که به یاد دارید، از الگوریتم gradient boosting برای این تمرین استفاده میکنیم.
model = ensemble.GradientBoostingRegressor(
n_estimators=150,
learning_rate=0.1,
max_depth=30,
min_samples_split=4,
min_samples_leaf=6,
max_features=0.6,
'loss='huber)
خط اول مربوط به الگوریتم است (gradient boosting) که فقط یک خط کد است. خط کدهای زیر آن، ابرپارامترهای این الگوریتم را مشخص میکنند.
- n_estimators نشان میدهد چند درخت تصمیم ساخته شود. به یاد دارید که بهطورکلی تعداد زیاد درختها دقت را بهبود میبخشد (تا یک نقطه خاص)، البته مدتزمان پردازش مدل را افزایش میدهد. در بالا، 150 درخت تصمیم را بهعنوان یک نقطه شروع ابتدایی انتخاب کردهام.
- learning_rate میزان اثرگذاری هر یک از درختهای تصمیم بر پیشبینی کلی را کنترل میکند. با تنظیم learning_rate، میزان تأثیر هر درخت کم میشود. مقدار کمی مثل 0.1 برای این پارامتر، باید دقت را بهبود ببخشد.
- max_depth حداکثر تعداد لایهها (عمق) را برای هر درخت تصمیم تعریف میکند. اگر “None” انتخاب بشود، تمام گرهها تا جایی که تمام برگها خالص شوند (انشعابپذیر نباشند) یا زمانی که تمام برگها کمتر از min_sample_leaf شوند، گسترش مییابند. در اینجا، یک مقدار زیاد برای حداکثر تعداد لایهها (30) را انتخاب کردهام که تأثیر بسیار زیادی بر روی نتیجه نهایی خواهد داشت، همانطور که بعداً خواهیم دید.
- min_sample_split حداقل نمونة موردنیاز برای انجام یک تقسیم دودویی جدید را تعیین میکند. برای مثال، min_sample_split = 10 به معنی این است که برای ساخت یک شاخه جدید، باید 10 نمونه در دسترس باشد.
- min_sample_leaf حداقل نمونههای موردنیاز که باید در هر فرزند گره (برگ)، قبل از ایجاد یک شاخه جدید، وجود داشته باشد را نشان میدهد. این ویژگی تأثیر نقاط پرت و آنومالی را کم میکند – مثل وقتی که تعداد نمونههای یافت شده در یک برگ در یک تقسیم دودویی کم باشد. برای مثال، min_sample_leaf=4 یعنی برای ساخت یک شاخه جدید، باید در داخل هر برگ، حداقل 4 نمونه موجود باشد.
- max_features تعداد کل ویژگیهای ارائه شده به مدل در زمان تعیین بهترین تقسیم است. همانطور که در فصلهای قبلی گفته شد، جنگلهای تصادفی و gradient boosting تعداد کل ویژگیهای داده شده به هر درخت را محدود میکنند تا چندین نتیجه بسازند تا بعداً بتوانند روی آنها رأیگیری کنند.
- اگر مقدار max_features عدد صحیح باشد، مدل در هر تقسیم (شاخه) تعداد max_features را در نظر میگیرد.
- اگر مقدار آن عدد اعشاری باشد (مثل 0.6) پس max_features درصدی از کل ویژگیها است که بهتصادف انتخاب شدهاند.
- Loss نرخ خطای مدل را محاسبه میکند. برای این تمرین، از Huber استفاده میکنیم که در برابر نقاط پرت و آنومالیها مقاوم است. نرخ خطاهای دیگر، شامل ls(حداقل مربع رگرسیون، Least square regression)، lad (حداقل قدرمطلق مشتقها، Least absolute deviations) و quantile (رگرسیون quantile) هستند. Huber در واقع ترکیبی از ls و lad است. برای اینکه درباره ابر پارامترهای gradient boosting بیشتر یاد بگیرید، میتوانید به وبسایت Scikit-learn مراجعه کنید:
http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html
پس از مقداردهی ابر پارامترهای مدل، تابع fit از کتابخانه Scikit-learn را فراخوانی میکنیم تا فرایند آموزش مدل یادگیری ماشین با پایتون شروع شود.
model.fit(X_train, y_train)
در انتها، باید با استفاده از تابع joblib.dump مدل آموزشدیده را بهعنوان یک فایل ذخیره کنیم که در قدم 1 در Jupyter Notebook بارگذاری شد. این کار این امکان را به ما میدهد تا مدل آموزشدیده را در آینده برای پیشبینی ارزش املاک مجدداً استفاده کنیم، بدون اینکه نیاز باشد تا مدل را از نو بسازیم.
joblib.dump(model, ‘house_trained_model.pkl’)
دوره آموزشی: برای یادگیری کار با دیتاستها در پروژههای واقعی یادگیری ماشین با پایتون و ساخت مدلهای مختلف، آموزش رایگان یادگیری ماشین را در کانال یوتیوب دیتاهاب ببینید.
6)روش ها و معیارهای ارزیابی الگوریتم یادگیری ماشین
همانطور که قبلاً اشاره شد، برای این تمرین از میانگین قدرمطلق خطا استفاده میکنیم تا صحت مدل را ارزیابی کنیم.
mse = mean_absolute_error(y_train, model.predict(X_train))
print(“Training Set Mean Absolute Error: %.2f” % mse)
در اینجا، مقدار y که نشاندهنده نتایج صحیح از مجموعهداده آموزشی است را وارد میکنیم. تابع model.predict بر روی مجموعه آموزشی X صدا زده میشود و یک پیشبینی تا دو رقم اعشار انجام میدهد. سپس، تابع میانگین قدرمطلق خطا، اختلاف بین پیشبینی مورد انتظار مدل و مقدار واقعی را مقایسه خواهد کرد. همین فرایند برای داده آزمایشی نیز تکرار خواهد شد.
mse = mean_absolute_error(y_test, model.predict(X_test))
print(“Test Set Mean Absolute Error: %.2f” % mse)
حالا برای اجرای کل مدل، کلیک راست کرده و “Run” را انتخاب کنید یا در منوی Jupyter Notebook مسیر مقابل را بروید:
Cell> Run All
چند ثانیه صبر کنید تا کامپیوتر مدل آموزشدیده را پردازش کند. نتایج، همانطور که در زیر نشاندادهشده است، در پایین notebook ظاهر خواهد شد.
Training Set Mean Absolute Error: 27157.02
Test Set Mean Absolute Error: 169962.99
برای این تمرین، میانگین قدرمطلق خطای مجموعه آموزشی 27157.02 دلار است و میانگین قدرمطلق خطای مجموعه آزمایشی 169962.99 دلار است. این به آن معنی است که به طور متوسط، مجموعه آموزشی ارزش واقعی ملک را به مقدار 27157.02 دلار اشتباه محاسبه کرده است.
بااینحال، مجموعه آزمایشی را به طور متوسط، 169962.99 دلار اشتباه محاسبه کرده است یعنی مدل آموزشدیده در پیشبینی ارزش واقعی ملکهای موجود درداده آموزشی بسیار خوب عمل میکند. البته 27157.02 دلار ممکن است پول زیادی به نظر بیاید، اما این مقدار میانگین خطا باتوجهبه حداکثر قیمت در مجموعهداده که 8 میلیون دلار است، مقدار کمی است.
باتوجهبه اینکه ملکهای موجود در مجموعهداده بیش از 1000000 دلار هستند، 27157.02 دلار یک نرخ خطای پایین و منطقی میباشد.
نتایج مدل برای دادههای آزمایشی، صحت کمتری دارد. داده آزمایشی با میانگین نرخ خطای 169962.99 دلار، پیشبینیهای صحیح کمتری ارائه داد. اختلاف زیاد بین داده آموزشی و آزمایشی یک شاخص کلیدی برای تشخیص بیشبرازش است.
وقتی که مدل با داده آموزشی متناسب و سازگار میشود، ممکن است در زمان پیشبینی داده آزمایشی دچار مشکل شود – احتمالاً داده آزمایشی، شامل الگوهای جدیدی است که مدل برای آنها آموزش ندیده است. البته ممکن است، داده آزمایشی، شامل الگوهای کمی متفاوت و همچنین نقاط پرت و آنومالی جدید بشود.
بااینحال، در این حالت، اختلاف بین داده آموزشی و آزمایشی به دلیل اینکه مدل را طوری تنظیم کردیم که نسبت به داده آموزشی دچار بیشبرازش بشود، تشدید میشود. مثالی از این مشکل قراردادن max_depth به مقدار “30” بود. با اینکه قراردادن یک مقدار زیاد برای max_depth شانس یافتن الگوها درداده آموزشی را بهبود میبخشد، ولی امکان بیشبرازش را تقویت میکند.
دلیل احتمالی دیگر، تقسیم نامناسب داده آموزشی و آزمایشی است -ولی برای این مدل، داده با استفاده از Scikit-learn به شکل تصادفی جابهجا شد. در انتها، لطفاً در نظر داشته باشید که بهاینعلت که دادههای آموزشی و آزمایشی به طور تصادفی جابهجا شدهاند، زمانی که این مدل را بر روی ماشین خودتان تکرار کنید، نتایجتان کمی متفاوت خواهد شد.
و در انتها…
تبریک… شما اولین مدل یادگیری ماشین با پایتون خود را ساختید.
یک گام نهایی باقی مانده است تا مفاهیم یادگیری ماشین را کامل بدانید. گام آخر این است که مدلی که ساخته ایم را بهینه کرده و دقت آن را افزایش دهیم. پس با مقاله روش های بهینه سازی یادگیری ماشین به عنوان آخرین مقاله یادگیری ماشین با ما همراه باشید.
دوره آموزشی: از بقیه شنیدید برای یادگیری هوش مصنوعی باید ریاضیات بلد باشید و نگرانید که ریاضی را فراموش کردید؟ آموزش سریع جبر خطی را در کانال یوتیوب دیتاهاب ببینید تا خیالتان راحت شود.