شجرة القرار في R: شجرة التصنيف مع مثال
ما هي أشجار القرار؟
أشجار القرار تعد خوارزميات التعلم الآلي متعددة الاستخدامات التي يمكنها تنفيذ مهام التصنيف والانحدار. وهي خوارزميات قوية للغاية، وقادرة على استيعاب مجموعات البيانات المعقدة. علاوة على ذلك، تعد أشجار القرار مكونات أساسية للغابات العشوائية، والتي تعد من بين أقوى خوارزميات التعلم الآلي المتاحة اليوم.
التدريب وتصور أشجار القرار في R
لبناء شجرة القرار الأولى في مثال R، سنتبع ما يلي في هذا البرنامج التعليمي لشجرة القرار:
- الخطوة 1: استيراد البيانات
- الخطوة 2: تنظيف مجموعة البيانات
- الخطوة 3: إنشاء مجموعة تدريب/اختبار
- الخطوة 4: بناء النموذج
- الخطوة 5: قم بالتنبؤ
- الخطوة 6: قياس الأداء
- الخطوة 7: ضبط المعلمات الفائقة
الخطوة 1) استيراد البيانات
إذا كنت مهتمًا بمصير التايتنك، يمكنك مشاهدة هذا الفيديو على يوتيوب . الغرض من مجموعة البيانات هذه هو التنبؤ بالأشخاص الذين من المرجح أن يبقوا على قيد الحياة بعد الاصطدام بالجبل الجليدي. تحتوي مجموعة البيانات على 13 متغيرًا و1309 ملاحظة. يتم ترتيب مجموعة البيانات بواسطة المتغير X.
set.seed(678) path <- 'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/titanic_data.csv' titanic <-read.csv(path) head(titanic)
الإخراج:
## X pclass survived name sex ## 1 1 1 1 Allen, Miss. Elisabeth Walton female ## 2 2 1 1 Allison, Master. Hudson Trevor male ## 3 3 1 0 Allison, Miss. Helen Loraine female ## 4 4 1 0 Allison, Mr. Hudson Joshua Creighton male ## 5 5 1 0 Allison, Mrs. Hudson J C (Bessie Waldo Daniels) female ## 6 6 1 1 Anderson, Mr. Harry male ## age sibsp parch ticket fare cabin embarked ## 1 29.0000 0 0 24160 211.3375 B5 S ## 2 0.9167 1 2 113781 151.5500 C22 C26 S ## 3 2.0000 1 2 113781 151.5500 C22 C26 S ## 4 30.0000 1 2 113781 151.5500 C22 C26 S ## 5 25.0000 1 2 113781 151.5500 C22 C26 S ## 6 48.0000 0 0 19952 26.5500 E12 S ## home.dest ## 1 St Louis, MO ## 2 Montreal, PQ / Chesterville, ON ## 3 Montreal, PQ / Chesterville, ON ## 4 Montreal, PQ / Chesterville, ON ## 5 Montreal, PQ / Chesterville, ON ## 6 New York, NY
tail(titanic)
الإخراج:
## X pclass survived name sex age sibsp ## 1304 1304 3 0 Yousseff, Mr. Gerious male NA 0 ## 1305 1305 3 0 Zabour, Miss. Hileni female 14.5 1 ## 1306 1306 3 0 Zabour, Miss. Thamine female NA 1 ## 1307 1307 3 0 Zakarian, Mr. Mapriededer male 26.5 0 ## 1308 1308 3 0 Zakarian, Mr. Ortin male 27.0 0 ## 1309 1309 3 0 Zimmerman, Mr. Leo male 29.0 0 ## parch ticket fare cabin embarked home.dest ## 1304 0 2627 14.4583 C ## 1305 0 2665 14.4542 C ## 1306 0 2665 14.4542 C ## 1307 0 2656 7.2250 C ## 1308 0 2670 7.2250 C ## 1309 0 315082 7.8750 S
من مخرجات الرأس والذيل، يمكنك ملاحظة عدم خلط البيانات. هذه قضية كبيرة! عندما تقوم بتقسيم بياناتك بين مجموعة القطار ومجموعة الاختبار، ستختار فقط الراكب من الفئتين 1 و2 (لا يوجد راكب من الفئة 3 ضمن أعلى 80 بالمائة من الملاحظات)، مما يعني أن الخوارزمية لن ترى أبدًا ميزات راكب الفئة 3. سيؤدي هذا الخطأ إلى سوء التنبؤ.
للتغلب على هذه المشكلة، يمكنك استخدام الدالة Sample().
shuffle_index <- sample(1:nrow(titanic)) head(shuffle_index)
شرح رمز شجرة القرار R
- Sample(1:nrow(titanic)): إنشاء قائمة عشوائية من الفهرس من 1 إلى 1309 (أي الحد الأقصى لعدد الصفوف).
الإخراج:
## [1] 288 874 1078 633 887 992
سوف تستخدم هذا الفهرس لخلط مجموعة البيانات العملاقة.
titanic <- titanic[shuffle_index, ] head(titanic)
الإخراج:
## X pclass survived ## 288 288 1 0 ## 874 874 3 0 ## 1078 1078 3 1 ## 633 633 3 0 ## 887 887 3 1 ## 992 992 3 1 ## name sex age ## 288 Sutton, Mr. Frederick male 61 ## 874 Humblen, Mr. Adolf Mathias Nicolai Olsen male 42 ## 1078 O'Driscoll, Miss. Bridget female NA ## 633 Andersson, Mrs. Anders Johan (Alfrida Konstantia Brogren) female 39 ## 887 Jermyn, Miss. Annie female NA ## 992 Mamee, Mr. Hanna male NA ## sibsp parch ticket fare cabin embarked home.dest## 288 0 0 36963 32.3208 D50 S Haddenfield, NJ ## 874 0 0 348121 7.6500 F G63 S ## 1078 0 0 14311 7.7500 Q ## 633 1 5 347082 31.2750 S Sweden Winnipeg, MN ## 887 0 0 14313 7.7500 Q ## 992 0 0 2677 7.2292 C
الخطوة 2) تنظيف مجموعة البيانات
يوضح هيكل البيانات أن بعض المتغيرات لها NA. يتم تنظيف البيانات على النحو التالي
- قم بإسقاط المتغيرات home.dest وcabin وname وX والتذكرة
- إنشاء متغيرات عامل لـ pclass ونجا
- إسقاط NA
library(dplyr) # Drop variables clean_titanic <- titanic % > % select(-c(home.dest, cabin, name, X, ticket)) % > % #Convert to factor level mutate(pclass = factor(pclass, levels = c(1, 2, 3), labels = c('Upper', 'Middle', 'Lower')), survived = factor(survived, levels = c(0, 1), labels = c('No', 'Yes'))) % > % na.omit() glimpse(clean_titanic)
شرح الكود
- حدد(-c(home.dest, Cabin, name, X, Ticket)): قم بإسقاط المتغيرات غير الضرورية
- pclass = عامل(pclass,levels = c(1,2,3), labels= c('Upper', 'Middle', 'Lower')): أضف تسمية إلى المتغير pclass. 1 يصبح علويًا، 2 يصبح متوسطًا و3 يصبح أقل
- عامل(survived,levels = c(0,1), labels = c('No', 'Yes')): أضف تسمية للمتغير الذي نجا. 1 يصبح لا و 2 يصبح نعم
- na.omit(): إزالة ملاحظات NA
الإخراج:
## Observations: 1,045 ## Variables: 8 ## $ pclass <fctr> Upper, Lower, Lower, Upper, Middle, Upper, Middle, U... ## $ survived <fctr> No, No, No, Yes, No, Yes, Yes, No, No, No, No, No, Y... ## $ sex <fctr> male, male, female, female, male, male, female, male... ## $ age <dbl> 61.0, 42.0, 39.0, 49.0, 29.0, 37.0, 20.0, 54.0, 2.0, ... ## $ sibsp <int> 0, 0, 1, 0, 0, 1, 0, 0, 4, 0, 0, 1, 1, 0, 0, 0, 1, 1,... ## $ parch <int> 0, 0, 5, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 4, 0,... ## $ fare <dbl> 32.3208, 7.6500, 31.2750, 25.9292, 10.5000, 52.5542, ... ## $ embarked <fctr> S, S, S, S, S, S, S, S, S, C, S, S, S, Q, C, S, S, C...
الخطوة 3) إنشاء مجموعة تدريب/اختبار
قبل تدريب النموذج الخاص بك، تحتاج إلى تنفيذ خطوتين:
- إنشاء قطار ومجموعة اختبار: يمكنك تدريب النموذج على مجموعة القطار واختبار التنبؤ على مجموعة الاختبار (أي البيانات غير المرئية)
- قم بتثبيت rpart.plot من وحدة التحكم
الممارسة الشائعة هي تقسيم البيانات بنسبة 80/20، حيث يعمل 80 بالمائة من البيانات على تدريب النموذج، و20 بالمائة في عمل التنبؤات. تحتاج إلى إنشاء إطارين منفصلين للبيانات. لا تريد لمس مجموعة الاختبار حتى تنتهي من بناء النموذج الخاص بك. يمكنك إنشاء اسم دالة create_train_test() الذي يأخذ ثلاث وسائط.
create_train_test(df, size = 0.8, train = TRUE) arguments: -df: Dataset used to train the model. -size: Size of the split. By default, 0.8. Numerical value -train: If set to `TRUE`, the function creates the train set, otherwise the test set. Default value sets to `TRUE`. Boolean value.You need to add a Boolean parameter because R does not allow to return two data frames simultaneously.
create_train_test <- function(data, size = 0.8, train = TRUE) { n_row = nrow(data) total_row = size * n_row train_sample < - 1: total_row if (train == TRUE) { return (data[train_sample, ]) } else { return (data[-train_sample, ]) } }
شرح الكود
- الوظيفة (البيانات، الحجم = 0.8، القطار = TRUE): أضف الوسائط في الوظيفة
- n_row = nrow(data): حساب عدد الصفوف في مجموعة البيانات
- Total_row = size*n_row: قم بإرجاع الصف n لإنشاء مجموعة القطار
- Train_sample <- 1:total_row: حدد الصف الأول من الصفوف n
- if (train ==TRUE){ } else { }: إذا تم ضبط الشرط على true، قم بإرجاع مجموعة القطار، وإلا قم بإرجاع مجموعة الاختبار.
يمكنك اختبار وظيفتك والتحقق من البعد.
data_train <- create_train_test(clean_titanic, 0.8, train = TRUE) data_test <- create_train_test(clean_titanic, 0.8, train = FALSE) dim(data_train)
الإخراج:
## [1] 836 8
dim(data_test)
الإخراج:
## [1] 209 8
تحتوي مجموعة بيانات القطار على 1046 صفًا بينما تحتوي مجموعة بيانات الاختبار على 262 صفًا.
يمكنك استخدام الدالة Prop.table() مع table() للتحقق من صحة عملية التوزيع العشوائي.
prop.table(table(data_train$survived))
الإخراج:
## ## No Yes ## 0.5944976 0.4055024
prop.table(table(data_test$survived))
الإخراج:
## ## No Yes ## 0.5789474 0.4210526
وفي كلتا مجموعتي البيانات، فإن عدد الناجين هو نفسه، حوالي 40 بالمائة.
قم بتثبيت rpart.plot
rpart.plot غير متوفر من مكتبات conda. يمكنك تثبيته من وحدة التحكم:
install.packages("rpart.plot")
الخطوة 4) بناء النموذج
أنت جاهز لبناء النموذج. بناء جملة وظيفة شجرة القرار Rpart هو:
rpart(formula, data=, method='') arguments: - formula: The function to predict - data: Specifies the data frame- method: - "class" for a classification tree - "anova" for a regression tree
يمكنك استخدام طريقة الفصل لأنك تتنبأ بالفصل.
library(rpart) library(rpart.plot) fit <- rpart(survived~., data = data_train, method = 'class') rpart.plot(fit, extra = 106
شرح الكود
- rpart(): الدالة التي تناسب النموذج. الحجج هي:
- نجا ~.: صيغة أشجار القرار
- البيانات = data_train: مجموعة البيانات
- الطريقة = 'الفئة': تناسب النموذج الثنائي
- rpart.plot(fit, extra= 106): ارسم الشجرة. يتم تعيين الميزات الإضافية على 101 لعرض احتمالية الفئة الثانية (مفيدة للاستجابات الثنائية). يمكنك الرجوع إلى المقالة القصيرة لمزيد من المعلومات حول الاختيارات الأخرى.
الإخراج:
تبدأ من العقدة الجذرية (العمق 0 على 3، أعلى الرسم البياني):
- في الأعلى، هو الاحتمال العام للبقاء على قيد الحياة. ويبين نسبة الركاب الذين نجوا من الحادث. نجا 41 بالمائة من الركاب.
- تسأل هذه العقدة ما إذا كان جنس الراكب ذكرًا. إذا كانت الإجابة بنعم، فانتقل إلى العقدة الفرعية اليسرى للجذر (العمق 2). 63% منهم ذكور مع احتمال البقاء على قيد الحياة بنسبة 21%.
- في العقدة الثانية، تسأل ما إذا كان عمر الراكب الذكر أكبر من 3.5 سنة. إذا كانت الإجابة بنعم، فإن فرصة البقاء على قيد الحياة هي 19 بالمائة.
- عليك أن تستمر على هذا المنوال لفهم الميزات التي تؤثر على احتمالية البقاء على قيد الحياة.
لاحظ أن إحدى الخصائص العديدة لأشجار القرار هي أنها تتطلب القليل جدًا من إعداد البيانات. وعلى وجه الخصوص، فهي لا تتطلب تغيير حجم الميزة أو توسيطها.
بشكل افتراضي، تستخدم الدالة rpart() جيني قياس النجاسة لتقسيم المذكرة. كلما ارتفع معامل جيني، زادت الحالات المختلفة داخل العقدة.
الخطوة 5) قم بالتنبؤ
يمكنك التنبؤ بمجموعة بيانات الاختبار الخاصة بك. للقيام بالتنبؤ، يمكنك استخدام وظيفة التنبؤ (). بناء الجملة الأساسي للتنبؤ بشجرة قرار R هو:
predict(fitted_model, df, type = 'class') arguments: - fitted_model: This is the object stored after model estimation. - df: Data frame used to make the prediction - type: Type of prediction - 'class': for classification - 'prob': to compute the probability of each class - 'vector': Predict the mean response at the node level
تريد التنبؤ بالركاب الذين من المرجح أن ينجووا بعد الاصطدام من مجموعة الاختبار. يعني أنك ستعرف من بين هؤلاء الركاب الـ 209 من منهم سينجو أم لا.
predict_unseen <-predict(fit, data_test, type = 'class')
شرح الكود
- توقع (fit، data_test، type = 'class'): توقع الفئة (0/1) لمجموعة الاختبار
اختبار الراكب الذي لم ينجح ومن فعل.
table_mat <- table(data_test$survived, predict_unseen) table_mat
شرح الكود
- table(data_test$survived,predict_unseen): قم بإنشاء جدول لحساب عدد الركاب المصنفين كناجين ومتوفين مقارنة بتصنيف شجرة القرار الصحيح في R
الإخراج:
## predict_unseen ## No Yes ## No 106 15 ## Yes 30 58
تنبأ النموذج بشكل صحيح بمقتل 106 راكبًا، لكنه صنف 15 ناجيًا على أنهم موتى. وعلى سبيل القياس، أخطأ النموذج في تصنيف 30 راكبًا على أنهم ناجين بينما تبين أنهم ماتوا.
الخطوة 6) قياس الأداء
يمكنك حساب مقياس الدقة لمهمة التصنيف باستخدام الارتباك مصفوفة:
تشير الارتباك مصفوفة هو خيار أفضل لتقييم أداء التصنيف. الفكرة العامة هي حساب عدد المرات التي يتم فيها تصنيف المثيلات الحقيقية على أنها خاطئة.
يمثل كل صف في مصفوفة الارتباك هدفًا فعليًا، بينما يمثل كل عمود هدفًا متوقعًا. يأخذ الصف الأول من هذه المصفوفة الركاب الموتى (الفئة الخاطئة): تم تصنيف 106 منهم بشكل صحيح على أنهم أموات (صحيح سلبي)، بينما تم تصنيف الباقي خطأً على أنه ناجٍ (إيجابية كاذبة). الصف الثاني يعتبر الناجين، الفئة الإيجابية كانت 58 (صحيح إيجابي)، في حين أن صحيح سلبي كان 30.
يمكنك حساب اختبار الدقة من مصفوفة الارتباك :
إنها نسبة الإيجابية الحقيقية والسالبة الحقيقية إلى مجموع المصفوفة. باستخدام R، يمكنك البرمجة على النحو التالي:
accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
شرح الكود
- sum(diag(table_mat)): مجموع القطر
- sum(table_mat): مجموع المصفوفة.
يمكنك طباعة دقة مجموعة الاختبار:
print(paste('Accuracy for test', accuracy_Test))
الإخراج:
## [1] "Accuracy for test 0.784688995215311"
لقد حصلت على 78 بالمائة في مجموعة الاختبار. يمكنك تكرار نفس التمرين مع مجموعة بيانات التدريب.
الخطوة 7) ضبط المعلمات الفائقة
تحتوي شجرة القرار في R على معلمات مختلفة تتحكم في جوانب الملاءمة. في مكتبة شجرة القرار rpart، يمكنك التحكم في المعلمات باستخدام الدالة rpart.control(). في الكود التالي، يمكنك تقديم المعلمات التي ستقوم بضبطها. يمكنك الرجوع إلى المقالة القصيرة لمعلمات أخرى.
rpart.control(minsplit = 20, minbucket = round(minsplit/3), maxdepth = 30) Arguments: -minsplit: Set the minimum number of observations in the node before the algorithm perform a split -minbucket: Set the minimum number of observations in the final note i.e. the leaf -maxdepth: Set the maximum depth of any node of the final tree. The root node is treated a depth 0
سنتصرف على النحو التالي:
- إنشاء وظيفة لإرجاع الدقة
- ضبط الحد الأقصى للعمق
- قم بضبط الحد الأدنى لعدد العينات التي يجب أن تحتوي عليها العقدة قبل أن تتمكن من الانقسام
- ضبط الحد الأدنى لعدد العينة التي يجب أن تحتوي عليها العقدة الورقية
يمكنك كتابة وظيفة لعرض الدقة. يمكنك ببساطة تغليف الكود الذي استخدمته من قبل:
- توقع: توقع_غير مرئي <- توقع (مناسب، data_test، اكتب = 'class')
- إنتاج الجدول: table_mat <- table(data_test$survived,predict_unseen)
- دقة الحساب: اختبار الدقة <- sum(diag(table_mat))/sum(table_mat)
accuracy_tune <- function(fit) { predict_unseen <- predict(fit, data_test, type = 'class') table_mat <- table(data_test$survived, predict_unseen) accuracy_Test <- sum(diag(table_mat)) / sum(table_mat) accuracy_Test }
يمكنك محاولة ضبط المعلمات ومعرفة ما إذا كان بإمكانك تحسين النموذج على القيمة الافتراضية. للتذكير، عليك الحصول على دقة أعلى من 0.78
control <- rpart.control(minsplit = 4, minbucket = round(5 / 3), maxdepth = 3, cp = 0) tune_fit <- rpart(survived~., data = data_train, method = 'class', control = control) accuracy_tune(tune_fit)
الإخراج:
## [1] 0.7990431
مع المعلمة التالية:
minsplit = 4 minbucket= round(5/3) maxdepth = 3cp=0
تحصل على أداء أعلى من النموذج السابق. تهنئة!
الملخص
يمكننا تلخيص الوظائف لتدريب خوارزمية شجرة القرار في R
المكتبة | الهدف | الوظيفة | مبوبة | المعلمات | التفاصيل |
---|---|---|---|---|---|
rpart | شجرة تصنيف القطارات في R | ربارت () | فئة | الصيغة، مدافع، الطريقة | |
rpart | تدريب شجرة الانحدار | ربارت () | أنوفا | الصيغة، مدافع، الطريقة | |
rpart | ارسم الأشجار | rpart.plot() | نموذج مناسب | ||
قاعدة | تنبأ | تنبؤ() | فئة | النموذج المجهز، النوع | |
قاعدة | تنبأ | تنبؤ() | غالبا | النموذج المجهز، النوع | |
قاعدة | تنبأ | تنبؤ() | ناقلات | النموذج المجهز، النوع | |
rpart | المعلمات السيطرة | rpart.control() | com.minsplit | قم بتعيين الحد الأدنى لعدد الملاحظات في العقدة قبل إجراء الخوارزمية للتقسيم | |
com.minbucket | قم بتعيين الحد الأدنى لعدد الملاحظات في الملاحظة النهائية، أي الورقة | ||||
أقصى عمق | قم بتعيين الحد الأقصى لعمق أي عقدة من الشجرة النهائية. تتم معالجة العقدة الجذرية بعمق 0 | ||||
rpart | نموذج القطار مع معلمة التحكم | ربارت () | الصيغة، df، الطريقة، التحكم |
ملاحظة: قم بتدريب النموذج على بيانات التدريب واختبار الأداء على مجموعة بيانات غير مرئية، أي مجموعة الاختبار.