پیاده سازی درخت تصمیم با پایتون
این آموزش یکی از پستهای زیرمجموعه آموزشهای مرتبط با پایتون میباشد، که به آموزش پیاده سازی درخت تصمیم با پایتون میپردازد. در صورتی که تمایل دارید کل آموزشهای مرتبط با پایتون را مشاهده کنید، از این لینک استفاده کنید. در ضمن اگه حوصله خوندن متن ندارید، میتونید از ویدیو آخر این پست استفاده کنید و از متن صرف نظر کنید. همچنین اگه با خواندن این مطلب سوالی برای شما پیش اومد، خوشحال میشم که اون را از طریق راههای ارتباطی که در همین وبسایت موجوده، باهام مطرح کنید.
پیشنیاز این آموزش تسلط بر پایتون هست.
درخت تصمیم چیه؟
درخت تصمیم یکی از زیرشاخههای یادگیری ماشین یا Machine Learning هست و در عین حال که الگوریتم سادهایه ولی به شدت کاربردی و مرسوم هم است. من خودم به شخصا خیلی این الگوریتم را دوست دارم و درکش برام خیلی راحته.
این الگوریتم به شما کمک میکنه که در رابطه با یک موضوع پیشبینی کنید یا اون موضوع را در دستهبندی مشخصی قرار بدید، اینکار را هم با کوچک و کوچکتر کردن محدوده تصمیم گیری میکنه تا شما را به یک تصمیم خاص برسونه. مثلا تصویر زیر که من از وبسایت کوئرا کالج دانلود کردم را در نظر بگیرید:
فرض کنید من قراره در یک شرکت استخدام بشم، اولویت اول من برای استخدام، حقوق بین 20 تا 50 میلیون تومان هست، پس اگه یک شرکت پایینتر از این مبلغ بهم پیشنهاد کنه، سریع ردش میکنم و تصمیم گیری در همینجا تموم میشه ولی حالا اگه حقوق 30 میلیون تومان بهم پیشنهاد بشه، اولویت اولم پاس میشه، بنابراین میرم سراغ اولویت دومم که نزدیک بودن شرکت به خانه هست، اگه اون شرکت این اولویت را پاس نکنه، حتی با اینکه حقوق مطلوب من را پیشنهاد داده، از طرف من رد میشه و فرایند تصمیم گیری همینجا تمومه. حالا اگه اولویت نزدیک خونه بودن هم پاس بشه، میرم سراغ اولویت بعدی… . این فرایند را اونقدر ادامه میدم تا به یک تصمیم مشخص برسم، یعنی برم داخل اون شرکت کار کنم یا نرم!
چالشهای درخت تصمیم در واقعیت
مثال قبل خیلی ساده بود چون من اولویتهای خودم را برای استخدام میدونم ولی در مسائل واقعی اینجوری نیست، یعنی شما نمیدونید که اولویت اولتون چیه. اجازه بدید با یک مثال برم جلو، فرض کنید قراره با درخت تصمیم نتیجه بازی منچستر یونایتد و اورتون را پیشبینی کنید. کدوم فاکتور اولویت اول باید باشه؟ مثلا باید استادیوم را بزارم اولویت اول یا آب و هوای روز مسابقه؟ فرض کنید استادیوم را در اولویت اول قرار میدم و میگم که اگه استادیوم الدترافورد بود، منچستر میبره و تصمیمگیری تمومه! چطور مطمئن بشم این الویت و این نتیجه گیری درسته؟ یکی از چالشهای درخت تصمیم همینه، وقتی تعداد فاکتورها زیاده، نمیتونیم به راحتی مثال استخدام اولویتبندی کنیم.
یکی دیگه از چالشهای پیادهسازی درخت تصمیم اینکه که وقتی یک اولویت پاس نشد، نمیشه به همین راحتی تصمیم گیری را متوقف کرد. برگردیم به مثال استخدام، یک شرکت به من پیشنهاد کار داده و اولویت اولم یعنی حقوق را پاس کرده ولی نزدیک به خونمون نیست، با منطقی که توضیح دادم باید تصمیم گیری همینجا تموم بشه و من شرکت را رد کنم ولی اگه حقوق پیشنهادی اون شرکت اینقدر بالا بود که حتی صرف کنه بخاطرش راه دور برم چی؟ اینم یکی دیگه از چالشهای درخت تصمیمه، وقتایی هست که یکی از اولویتها پاس نمیشه ولی نباید سریع تصمیم گیری را رها کرد و اولویتهای دیگه را هم باید چک کرد.
درخت تصمیم با پایتون
خب بریم سراغ پیادهسازی یک درخت تصمیم با پایتون:
مرحله اول: دیتا
مثل پیاده کردن خیلی از مدلهای هوش مصنوعی در اولین قدم به دیتا نیاز داریم. من یک دیتا دانلود کردم که برای شما هم در این لینک قرار میدم تا دانلود کنید. دیتا در رابطه با مشخصات افرادی هست که موفق شدهاند یا موفق نشدهاند از یک بانک خارجی وام بگیرند. تصویر زیر چند ردیف از این دیتا را نشون میده:
ستون Age سن درخواست کننده وام، Experience تعداد سال سابقه کاری اون شخص، ستون Income درآمد اون فرد و بقیه ستونها بجز ستون آخر، هر کدام یک فاکتور تاثیر گذار در قبول یا رد وام توسط بانک را نشون میده. ستون آخر یعنی ستون Personal.Loan در صورتی که برابر صفر باشه، یعنی بانک با درخواست وام اون شخص موافقت نکرده و در صورتی که برابر یک باشه، یعنی بانک با درخواست وام اون شخص موافقت کرده.
حالا فرض کنید من قراره به این بانک درخواست وام بدم ولی حال و حوصله ندارم که کلی کار اداری مربوط به درخواست وام را انجام بدم ولی در آخر هم بهم بگن به شما وام نمیدیم و من بمونم و کلی وقت و هزینه تلف شده! حالا قصد دارم با استفاده از این دیتا پیشبینی کنم که آیا بانک به من وام میده یا نه! اگه الگوریتم به من جواب مثبت داد، اون موقع میرم و کارهای اداری وام را میکنم ولی در غیر اینصورت وارد پروسه وام نمیشم.
مرحله دوم: وارد کردن کتابخانههای مورد نیاز
من از VS Code به عنوان محیط برنامه نویسی استفاده میکنم، البته روی VS Code خودم پلاگین Jupyter را نصب کردم تا محیطی شکل Jupyter Notebook بدست بیارم. دوباره یادآوری میکنم که اگه حوصله خوندن متن ندارید، میتونید از ویدیو آخر این پست استفاده کنید و متن را صرف نظر کنید.
کتابخانههای زیر را وارد کد خودم میکنم:
import pandas as pd
from sklearn.metrics import confusion_matrix, accuracy_score, classification_report
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
کتابخانه sklearn در حقیقت مهمترین کتابخانه این کد هست، چون با استفاده از این کتابخانه قراره درخت تصمیم را پیاده کنم.
مرحله سوم: وارد کردن دیتا
در این مرحله لازمه کدی بنویسم که فایل دیتا من را بخونه:
def readData():
data = pd.read_csv('bankloan.csv')
return data
فایل bankloan همون فایل csv حاوی دیتا من هست، این فایل را کنار فایل پایتون خودتون قرار بدید.
مرحله چهارم: بخشبندی کردن دیتا
تابع زیر را به کد اضافه میکنم:
def SplitData(data):
x = data.values[:, 1:13]
y = data.values[:, 13]
xTrain, xTest, yTrain, yTest = train_test_split(x, y, test_size=0.3, random_state=100)
return x, y, xTrain, xTest, yTrain, yTest
این تابع یک ورودی به نام data میگیره و اول اون را به دو بخش x و y تقسیم میکنه. x شامل ستونهای 1 تا 12 دیتا است که در حقیقت متغیرهای مستقل را شامل میشه و y شامل ستون 13 هست که متغیر وابسته یعنی ستون Personal.Loan را شامل میشه.
در خط 5 کد، با استفاده از تابع train_test_split از sklearn متغیرهای x و y را به 4 بخش تقسیم کردم. در ایجاد مدلهای هوش مصنوعی ما معمولا یک قسمت از دیتا را جدا میکنیم و با اون مدل را ایجاد میکنیم (اصطلاحا مدل را Train میکنیم) و با قسمت باقیمانده از دیتا، مدلی که ایجاد کردیم را تست میکنیم و دقتش را اندازه میگیریم. اینجا هم متغیرهای xTrain و yTrain برای ایجاد مدل قراره بکار بره و متغیرهای xTest و yTest برای ارزیابی مدل بکار میره.
پارامتر test_size مشخص میکنه که چقدر از دیتا را برای تست لازم داریم، من این پارامتر را روی 0.3 قرار دادم، یعنی 30 درصد دیتا را برای تست جدا کن. پارامتر random_state را برابر یک عدد دلخواه قرار میدم که هر بار که کد را اجرا میکنم، مقادیر متغیرهای xTest، xTrain و بقیه متغیرهای حاصل از این تابع، عوض نشه.
مرحله پنجم: ایجاد مدل
با تابع زیر مدل یا درخت تصمیم خودم را ایجاد میکنم:
def train_gini(xTrain, yTrain):
tree = DecisionTreeClassifier(criterion="gini", random_state=100, max_depth=13, min_samples_leaf=5)
tree.fit(xTrain, yTrain)
return tree
در این تابع با استفاده از سازنده کلاس DecisionTreeClassifier یک متغیر به نام tree ایجاد کردم. این متغیر در حقیقت شی اولیه درخت تصمیم ما هست. در خط بعدی هم این درخت تصمیم را با استفاده از متد fit و دیتاهایی که برای آموزش مدل کنار گذاشته بودم، train کردم.
چیزی که اینجا باید بگم اینه که اگه خط دوم کد را ببینید، یک پارامتر به نام criterion داریم. این پارامتر دو مقدار gini یا entropy را میتونه بگیره. حالا این دو تا چی هستند؟ اینها دو تا شاخص برای مشخص کردن اولویتهای مهمتر در درخت تصمیم هستند، مثلا برای مثال بانک، اینکه آیا شاخص درآمد در اولین نقطه (یا Node) از درخت باشه یا شاخص سن باید این جایگاه را بگیره، توسط این شاخصها محاسبه میشه. بسته به اینکه به پارامتر criterion مقدار gini را میدید یا entropy مدلتون ممکنه تغییر کنه، چون هر کدوم از این روشها، فرمول و محاسبات ریاضی مخصوص خودشون را دارند. میتونید یک بار مدلتون را با gini درست کنید و یک بار هم با entropy و بعد ببینید کدوم دقتش بیشتره.
مرحله پنجم: پیشبینی
الان کافیه یک تابع بنویسم که یک مقدار به همراه درخت تصمیم را بگیره و مقدار پیشبینی را بهم برگردونه. توجه کنید که شی tree یک متد به نام predict داره که اون برای من پیشبینی را انجام میده:
def prediction(xTest, tree):
yPred = tree.predict(xTest)
return yPred
مرحله ششم: سنجش دقت درخت
تابع زیر دقت مدل را با استفاده از متد accuracy_score که از متدهای sklearn هست اندازه میگیره:
def calAccuracy(yTest, yPred):
print("Accuracy : ", accuracy_score(yTest, yPred) * 100)
چیزی که شاید لازم باشه بگم اینه که من باید به عنوان پارامتر yTest و yPred را به تابع calAccuracy بدم، حالا yPred چیه؟ این متغیر، حامل مقادیر پیشبینی شده حاصل از پیشبینی xTest با تابع prediction هست که جلوتر بهش میرسیم. به زبان ساده ما مقادیر واقعی و مقادیر پیشبینی شده را به این تابع میدیم تا دقت درخت را برامون حساب کنه. دقیقا برای همین بود که اون اول کار، دیتا خودم را به چند بخش تقسیم کردم.
مرحله ششم: اجرای مدل
تا اینجا فقط یک مشت متد نوشتم، در کد زیر اونها را به کار میگیرم:
data = readData()
x, y, xTrain, xTest, yTrain, yTest = SplitData(data)
treeGini = train_gini(xTrain, yTrain)
preGini = prediction([[20, 0 , 130 , 92222 , 1 , 1.6 , 6 , 0, 1, 0, 0 ,0]] , treeGini)
print(preGini)
در خط چهارم کد، لازمه یک دیتا به تابع prediction بدهم تا برام پیشبینی را انجام بده. فرض کنید من 20 سالمه، هیچ سابقه کاری ندارم ولی درآمدم 130 هست (فرض کنید 130 هزار دلار یا 130 هزار تومان، واحد پولی اینجا مهم نیست)، کدپستی محل زندگی من 92222، تعداد افراد خانواده من 1 نفره، یعنی تنها زندگی میکنم و…، خلاصه تمام اطلاعات خودم را در قالب یک لیست به این تابع میدم و در پارامتر بعدی هم درخت تصمیم را بهش میدم. خروجی این تابع در متغیری به نام preGini ذخیره میشه و با دستور print از پایتون درخواست میکنم که این متغیر را بهم نشون بده:
[1.]
مدل بهم عدد یک را نشون میده، این یعنی درخت پیشبینی کرده که به من وام تعلق میگیره. خب الان میتونم با دلگرمی بیشتری برم بانک و تقاضا وام کنم ولی قبلش یکم صبر میکنم! دقت پیشبینی انجام شده چند درصده؟
کد زیر را هم به کدهای خودم اضافه میکنم تا دقت مدل را بدست بیارم:
yPred = prediction(xTest , treeGini)
calAccuracy(yTest , yPred)
در کد بالا، xTest که دیتا مربوط به تست مدل بود را به تابع prediction دادم تا برام مقادیر پیشبینی شده را بدست بیاره و بریزه داخل یک متغیر به نام yPred. بعدش مقادیر واقعی خودم یعنی yTest و مقادیر پیشبینی را به تابع calAccuracy دادم تا دقت درخت تصمیم را بدست بیاره. دقتی که بهم نشون میده به شکل زیره:
Accuracy : 97.86666666666667
الان میدونم که دقت جوابی که مدل بهم داده حدود 98 درصد هست پس دیگه وقتشه برم بانک و اقدام به درخواست وام کنم.
مرحله هفتم: رسم درخت
با کد زیر میتونم درخت تصمیم خودم را در قالب یک تصویر خروجی بگیرم:
def plotDecisionTree(tree, att, target):
plt.figure(figsize=(15, 10))
plot_tree(tree, filled=True, feature_names=att, class_names=target, rounded=True)
plt.show()
plotDecisionTree(treeGini, ['Age', 'Experience' , 'Income' , 'ZIPCode' , 'Family' , 'CCAvg' , 'Education', 'Mortgage' , 'SecuritiesAccount' , 'CDAccount' , 'Online' , 'CreditCard'] , ['Not Ok' , 'OK'])
تابع plotDecisionTree شی درخت را به همراه دو تا پارامتر att و target که به ترتیب برچسبهای مربوط به متغیرهای مستقل و متغیر وابسته مدل من هستند را ازم میگیره. این برچسبها در تصویری که این تابع به من خروجی میده به کار میروند:
بیشتر بدانید
اگه از الگوریتم درخت تصمیم خوشتون اومده، بهتون پیشنهاد میکنم آموزش جنگل تصادفی با پایتون را هم مطالعه کنید. جنگل تصادفی، الگوریتم مکمل درخت تصمیم هست که معمولا دقت بالاتری از درخت تصمیم را بهمون ارائه میده.
ویدیو آموزش پیادهسازی درخت تصمیم با پایتون
قبل اینکه ویدیو را ببینید، بگم که من ویدیوها را در چنل یوتوب خودم هم آپلود میکنم، خیلی خوشحال میشم که اونجا هم من را دنبال کنید.