درختان تصمیم یکی از شهودی ترین و به طور گسترده ای الگوریتم های یادگیری ماشین برای هر دو طبقه بندی و رگرسیون هستند، آنها با تقسیم داده ها به شاخه ها بر اساس ارزش های ویژگی کار می کنند، تقلید از نحوه تصمیم گیری انسان ها، در حالی که کتابخانه هایی مانند Scikit-learn ساخت درختان تصمیم گیری را ناچیز می کنند، پیاده سازی یکی از ابتدا یک راه عالی برای مبتدیان برای درک کار داخلی الگوریتم است.

درخت تصمیم گیری چیست؟

یک درخت تصمیم یک ساختار شبیه به Flowchart است که در آن هر گره داخلی نشان دهنده یک آزمون بر روی یک ویژگی است (به عنوان مثال، "آیا سن" 30 است)، هر شاخه نشان دهنده نتیجه آن آزمون است و هر گره برگ دارای یک برچسب کلاس یا ارزش مداوم است. هدف ایجاد یک مدل است که پیش بینی یک متغیر هدف با یادگیری قوانین تصمیم گیری ساده از داده های تصمیم گیری ساده است زیرا آنها نیاز به تفسیر داده های ساده دارند.

درخت به طور بازگشتی ساخته شده است: از ریشه شروع، الگوریتم بهترین ویژگی و نقطه تقسیم را انتخاب می کند که داده ها را به طور تمیز جدا می کند. این فرایند در هر زیر مجموعه تکرار می شود تا زمانی که یک وضعیت توقف برای پس زمینه بیشتر، ویکی پدیا entry در تصمیم گیری یادگیری درخت یک مرور کلی جامد فراهم می کند.

مفاهیم اصلی که باید درک کنید

گره ها، شاخه ها و برگ ها

گره ریشه شامل تمام مجموعه داده های آموزشی است. گره های داخلی یک ویژگی را آزمایش می کنند و داده ها را به دو یا چند گره کودک تقسیم می کنند. Branchs اتصالاتی هستند که نشان دهنده نتیجه یک آزمون هستند. لیف ( گره های فاز) پیش بینی نهایی را تولید می کنند - رایج ترین کلاس در طبقه بندی یا ارزش معنی در رگرسیون.

تقسیم معیارهای

برای ساخت یک درخت، شما نیاز به یک راه برای اندازه گیری کیفیت یک تقسیم بالقوه دارید. متداول ترین معیارها عبارتند از:

  • ] کمبودگری - در طبقه بندی استفاده می شود تا اندازه گیری کند که چگونه اغلب یک عنصر تصادفی انتخاب شده است به اشتباه برچسب گذاری اگر آن را به طور تصادفی با توجه به توزیع کلاس در زیر مجموعه برچسب.
  • [FLT 1: 1] - اندازه گیری مقدار اختلال یا عدم اطمینان در یک مجموعه.
  • [[۱] [۱۰] کاهش تورم [[۱۰]] - برای درختان بازگشتی استفاده می شود، کاهش اختلاف (یا به معنای خطای مربعی) به دست آمده توسط تقسیم بندی محاسبه می شود.

الگوریتم هر تقسیم احتمالی را بر روی هر ویژگی ارزیابی می کند و یکی را انتخاب می کند که بیشترین کاهش در ناتوانی (یا کسب اطلاعات) را به دست می آورد.

کسب اطلاعات و به دست آوردن نسبت

به دست آوردن اطلاعات تفاوت بین ناتوانی گره والدین و مجموع وزن از ناخالصی های کودک است، در حالی که ساده است، آن را تمایل به علاقه به ویژگی های با بسیاری از ارزش ها است. نسبت به دست آوردن (استفاده در C4.5) این را طبیعی می کند. برای این آموزش ما با به دست آوردن اطلاعات استاندارد با استفاده از اختلال جینی، که به طور پیش فرض در CART (کلاس و Regression).

ساخت یک قدم درخت تصمیم گیری با قدم

۱- داده های خود را آماده کنید

شما نیاز به یک مجموعه داده با ویژگی ها و برچسب های هدف دارید، برای سادگی، از یک مجموعه داده های طبقه بندی باینری با ویژگی های عددی استفاده کنید.

  • [در این باره]: [[۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱]] [۱] [۱] [۱] [۱] [۵] [۱] [۹] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۹] [۱] [۹] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۹] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۹] [۹] [۱] [۹] [۱] [۱] [۱] [۱] [۵] [۹] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۹] [۱] [۹] [۹] [۹] [۱] [۹] [۱] [۱] [۹] [۹
  • (فَلَّهُمْهُمْهُمْهُمْهُمْهُمْهُمْهُمِهُمْهُمِهُواًاً)؛ یا [مِنِ ] [[[[[[[[[[[[[[ ] ] ] [[[[[[ ] ] ] [[[[[[[[ ] ] ] ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] ] ] [ ] [ ] [ ] ] ] ] ] ] ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] ] [ ] [ [ ] [ ] ] [ [ [ ] [ ] [ ] [ ] ] ] ] ] ] ] [ ] [ [ [ [ [ ] ] ] ] [ ] ] [ ] [ [ [ ] [ ] ] [ ] [ ] [ ] [ [ [ [ [ [ ] [ ] [ ] [ ] [ ] [ [ [ ] ] ] ] ] [ ] ] ] ] ] ] [ ] [ ] [ ]

داده ها را تمیز کنید: با ارزش های از دست رفته، تکرارها را حذف کنید و انواع عددی را تضمین کنید. درخت های تصمیم می توانند انواع داده های مختلف را کنترل کنند اما ما برای اجرای به عددی پایبند خواهیم بود.

۲) تعریف یک تابع تقسیم بندی Criterion

ما بدون شوری Gini را پیاده سازی می کنیم.شاخص جینی برای مجموعه ای از موارد:

[در این باره]

در جایی که p i نسبت اقلام کلاس i است، برای تقسیم دودویی، Gini کلی میانگین وزن گره های کودک است.

۳- پیاده سازی ارزیابی تقسیم بندی

برای هر ویژگی، ارزش های منحصر به فرد را اندازه گیری کنید.هر آستانه احتمالی (در میان ارزش های مرتب شده متوالی) برای هر آستانه کاندیدا، داده ها را به گروه های چپ و راست تقسیم کنید، Gini را محاسبه کنید و بهترین تقسیم را دنبال کنید.

۴- درخت را به طور ناگهانی بازسازی کنید

یک تابع ایجاد کنید که یک زیرمجموعه از داده ها و عمق فعلی را در نظر می گیرد.این شرایط را متوقف می کند (به عنوان مثال، حداکثر عمق به دست آمده، حداقل نمونه ها در هر گره یا بدون کسب اطلاعات) اگر یک وضعیت برآورده شده است، یک گره برگ با کلاس اکثریت ایجاد کنید، بهترین تقسیم را پیدا کنید و یک گره داخلی ایجاد کنید، سپس به طور بازگشتی تابع در سمت چپ و تقسیم راست.

۵- پیش بینی

هنگامی که درخت ساخته شده است، پیش بینی ساده است: شروع در ریشه، با ارزیابی تست های ویژگی بر روی نمونه جدید، شاخه ها را دنبال کنید و ارزش برگ را که بر روی آن فرود می آیید، بازگردانید.

اجرای کامل در پایتون

در زیر یک پیاده سازی کامل و حداقل یک درخت تصمیم برای طبقه بندی با استفاده از کمبود جینی است که این کد برای یادگیری به معنای آن است - آن را برای مجموعه داده های بزرگ بهینه سازی نمی شود.

import numpy as np
from collections import Counter

class DecisionTree:
 def __init__(self, max_depth=None, min_samples_split=2):
 self.max_depth = max_depth
 self.min_samples_split = min_samples_split
 self.tree = None

 def fit(self, X, y):
 dataset = np.column_stack((X, y))
 self.tree = self._grow_tree(dataset)

 def _grow_tree(self, dataset, depth=0):
 X, y = dataset[:, :-1], dataset[:, -1]
 n_samples, n_features = X.shape
 n_labels = len(np.unique(y))

 # Stopping conditions
 if (n_labels == 1 or depth == self.max_depth or n_samples < self.min_samples_split):
 leaf_value = Counter(y).most_common(1)[0][0]
 return {'leaf': True, 'value': leaf_value}

 best_feature, best_threshold = self._best_split(dataset, n_features)
 if best_feature is None:
 leaf_value = Counter(y).most_common(1)[0][0]
 return {'leaf': True, 'value': leaf_value}

 left_idx, right_idx = self._split(dataset[:, best_feature], best_threshold)
 left_subtree = self._grow_tree(dataset[left_idx], depth+1)
 right_subtree = self._grow_tree(dataset[right_idx], depth+1)
 return {'leaf': False,
 'feature': best_feature,
 'threshold': best_threshold,
 'left': left_subtree,
 'right': right_subtree}

 def _best_split(self, dataset, n_features):
 best_gini = float('inf')
 best_feature, best_threshold = None, None
 for feature in range(n_features):
 thresholds = np.unique(dataset[:, feature])
 for i in range(len(thresholds)-1):
 thresh = (thresholds[i] + thresholds[i+1]) / 2
 left_idx, right_idx = self._split(dataset[:, feature], thresh)
 if len(left_idx) == 0 or len(right_idx) == 0:
 continue
 gini = self._gini_gain(dataset, left_idx, right_idx)
 if gini < best_gini:
 best_gini = gini
 best_feature = feature
 best_threshold = thresh
 return best_feature, best_threshold

 def _split(self, values, threshold):
 left_idx = np.where(values <= threshold)[0]
 right_idx = np.where(values > threshold)[0]
 return left_idx, right_idx

 def _gini_gain(self, dataset, left_idx, right_idx):
 total = len(left_idx) + len(right_idx)
 gini_left = self._gini(dataset[left_idx, -1])
 gini_right = self._gini(dataset[right_idx, -1])
 return (len(left_idx)/total) * gini_left + (len(right_idx)/total) * gini_right

 def _gini(self, labels):
 _, counts = np.unique(labels, return_counts=True)
 p = counts / np.sum(counts)
 return 1 - np.sum(p**2)

 def predict(self, X):
 return np.array([self._predict_row(x, self.tree) for x in X])

 def _predict_row(self, x, node):
 if node['leaf']:
 return node['value']
 if x[node['feature']] <= node['threshold']:
 return self._predict_row(x, node['left'])
 else:
 return self._predict_row(x, node['right'])

تست درخت

از یک مجموعه داده ساده مانند مجموعه داده های کلاسیک آیریس (دو ویژگی برای طبقه بندی باینری) استفاده کنید (FLT:0) مجموعه داده های آیریس را یاد بگیرید به خوبی کار می کند.

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
X = data.data[:100] # take only first two classes (binary)
y = data.target[:100]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

tree = DecisionTree(max_depth=3)
tree.fit(X_train, y_train)
preds = tree.predict(X_test)
accuracy = np.mean(preds == y_test)
print(f'Accuracy: {accuracy:.2f}')

تکنیک های پیشرفته برای بهبود درخت

اجتناب از Overfit

یک درخت به طور کامل رشد می تواند سر و صدا را در داده های آموزشی حفظ کند. Pruning شاخه هایی را که قدرت پیش بینی کمی دارند حذف می کند. روش های رایج از پیش تعیین شده (که رشد را از طریق (FLT:4 یا و پس از اجرای (رشد درخت کامل پس از آن حذف شاخه ها با استفاده از یک مجموعه اعتباری یا هزینه های پیاده سازی ما پشتیبانی می کند).

مدیریت مستمر و ویژگی های کاتالیک

برای ویژگی های مداوم، ما از نقاط میانی بین مقادیر مرتب به عنوان آستانه استفاده کردیم.برای ویژگی های کاتالیک (به عنوان مثال، "رنگ = قرمز / سبز / آبی")، هر دسته می تواند به یک شاخه جداگانه (چندراه تقسیم) تبدیل شود یا شما می توانید آنها را دودویی کنید. اکثر پیاده سازی های مدرن (مانند Scikit-learn) از تقسیم باینری استفاده می کنند حتی برای ارزیابی تمام زیرمجموعه ها.

معامله با ارزش های از دست رفته

داده های دنیای واقعی اغلب دارای ارزش های از دست رفته است.یک رویکرد ساده این است که ارزش های از دست رفته را به شاخه های مکرر در میان نمونه های آموزشی که دارای ویژگی هستند اختصاص دهیم. C4.5 از یک روش احتمالاتی استفاده می کند.

مقایسه با کتابخانه ها و خواندن بیشتر

در حالی که ساخت از ابتدا آموزشی است، سیستم های تولیدی از کتابخانه هایی مانند Scikit-learn استفاده می کنند که پیاده سازی های C را بهینه سازی می کنند.شما می توانید بیشتر از رسمی کتابخانه های تصمیم گیری را یاد بگیرید برای نظریه عمیق تر، کتاب "The Elements Learning" توسط Hastie، Tibshi، و فریدمن یک کتاب مرجع معتبر دیگر است.

نتیجه گیری

ساخت یک درخت تصمیم گیری از ابتدا یکی از اساسی ترین الگوریتم ها در یادگیری ماشین را توجیه می کند، شما آموخته اید که چگونه یک روش تقسیم بندی ساده می تواند یک مدل قدرتمند را تولید کند. با نوشتن کد خود، شما درک عمیق تر از اقدامات خستگی ناپذیر، انتخاب تقسیم، و تجارت بین تعصب و تفاوت به عنوان یک گام بعدی، سعی کنید به اضافه کردن پشتیبان، یا تقویت ویژگی های پیچیده تر به عنوان شما به خوبی توسعه مهارت های حرکت می کند.