决策树之python实现C4.5算法
时间: 2023-09-28 21:11:14 浏览: 139
C4.5算法是一种决策树算法,其主要特点是可以处理连续型和离散型的属性,并且能够自动地进行特征选择。下面是用Python实现C4.5算法的步骤:
1. 数据预处理
首先需要将数据集处理成合适的格式,通常将数据集表示成一个二维数组或DataFrame的形式,其中每一行表示一个样本,每一列表示一个特征。如果数据集中存在缺失值,需要进行处理,通常可以使用均值、中位数或众数等方法来填充缺失值。
2. 特征选择
C4.5算法使用信息增益比来选择最佳的特征。信息增益的定义为:样本集合的熵减去在特定特征条件下样本集合的条件熵,即:
$Gain(A) = Ent(D) - Ent(D|A)$
其中,$A$ 表示一个特征,$D$ 表示样本集合,$Ent(D)$ 表示样本集合的熵,$Ent(D|A)$ 表示在特定特征条件下样本集合的条件熵。
信息增益比定义为信息增益除以特征的固有值,即:
$Gain\_ratio(A) = \frac{Gain(A)}{IV(A)}$
其中,$IV(A)$ 表示特征 $A$ 的固有值,计算公式为:
$IV(A) = -\sum_{i=1}^{n}\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|}$
其中,$n$ 表示特征 $A$ 的取值个数,$D_i$ 表示在特征 $A$ 取值为 $i$ 的样本集合,$|D|$ 表示样本集合的大小。
在选择最佳特征时,需要计算每个特征的信息增益比,选择信息增益比最大的特征作为当前节点的划分特征。
3. 决策树生成
从根节点开始,按照最佳特征进行划分,将样本集合划分成若干个子集合,对每个子集合递归生成子树,直到所有叶节点的样本集合属于同一类别或样本集合为空。
4. 决策树剪枝
为了避免过拟合,需要对决策树进行剪枝。一般采用预剪枝或后剪枝方法。预剪枝在生成决策树的过程中,如果某个节点的划分增益小于某个阈值,则不再进行划分;后剪枝则是在生成完整的决策树后,对决策树进行剪枝,将某些节点转换为叶节点。
下面是一个简单的C4.5算法的Python实现,其中使用了pandas库来处理数据集:
```python
import pandas as pd
import numpy as np
class C45DecisionTree:
def __init__(self, epsilon=0.1):
self.epsilon = epsilon
def fit(self, X, y):
self.classes = np.unique(y)
self.root = self._build_tree(X, y)
def predict(self, X):
return np.array([self._predict(x, self.root) for x in X])
def _build_tree(self, X, y):
if len(np.unique(y)) == 1:
return y[0]
if len(X) == 0:
return self._majority_vote(y)
if len(X.columns) == 0:
return self._majority_vote(y)
best_feature = self._choose_feature(X, y)
tree = {best_feature: {}}
for value in np.unique(X[best_feature]):
subset_X = X[X[best_feature] == value].drop(best_feature, axis=1)
subset_y = y[X[best_feature] == value]
subtree = self._build_tree(subset_X, subset_y)
tree[best_feature][value] = subtree
return tree
def _choose_feature(self, X, y):
n_features = len(X.columns)
entropy = self._entropy(y)
max_gain_ratio = 0
best_feature = None
for col in X.columns:
subset_entropy = 0
iv = 0
for value in np.unique(X[col]):
subset_y = y[X[col] == value]
subset_entropy += len(subset_y) / len(y) * self._entropy(subset_y)
iv -= len(subset_y) / len(y) * np.log2(len(subset_y) / len(y))
gain_ratio = (entropy - subset_entropy) / iv
if gain_ratio > max_gain_ratio:
max_gain_ratio = gain_ratio
best_feature = col
if max_gain_ratio < self.epsilon:
return None
return best_feature
def _entropy(self, y):
entropy = 0
for cls in self.classes:
p = len(y[y == cls]) / len(y)
if p > 0:
entropy -= p * np.log2(p)
return entropy
def _majority_vote(self, y):
max_count = 0
most_common = None
for cls in self.classes:
count = len(y[y == cls])
if count > max_count:
max_count = count
most_common = cls
return most_common
def _predict(self, x, tree):
if isinstance(tree, str):
return tree
for feature, subtree in tree.items():
if x[feature] in subtree:
return self._predict(x, subtree[x[feature]])
return self._majority_vote(y)
```
在实际使用时,可以使用sklearn的API来加载数据集,然后使用C4.5算法进行训练和预测:
```python
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
clf = C45DecisionTree()
clf.fit(pd.DataFrame(X_train), y_train)
y_pred = clf.predict(pd.DataFrame(X_test))
print('Accuracy:', accuracy_score(y_test, y_pred))
```
阅读全文