1. 理解决策树的基本概念
决策树是一种监督学习算法,可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征,节点之间的分支表示特征的可能取值,叶节点表示分类或回归结果。
2. 决策树的构建过程
2.1. 特征选择
特征选择是构建决策树的第一步,通常使用信息增益、基尼指数或增益率等指标。
- 信息增益(Information Gain)
信息增益表示通过某个特征将数据集划分后的纯度增加量,公式如下:
其中:
D 是数据集。
A 是特征。
V(A) 是特征 A 的所有可能取值。
Dv 是数据集中特征 A 取值为 v 的子集。
∣Dv∣ 是 Dv 中样本的数量。
∣D∣ 是数据集 D 中样本的总数量。
Entropy(D) 是数据集 D 的熵,表示数据集本身的纯度。
选择信息增益最大的特征作为当前节点的划分特征。
熵的计算公式为:
其中:
c 是类别的数量。
pi 是数据集中属于第 i 类的样本所占的比例。
以下代码展示了如何计算熵、信息增益,并选择最优特征。
import numpy as np
from collections import Counter
from sklearn.datasets import load_iris
def entropy(y):
hist = np.bincount(y)
ps = hist / len(y)
return -np.sum([p * np.log2(p) for p in ps if p > 0])
def information_gain(X, y, feature):
# Entropy before split
entropy_before = entropy(y)
# Values and counts
values, counts = np.unique(X[:, feature], return_counts=True)
# Weighted entropy after split
entropy_after = 0
for v, count in zip(values, counts):
entropy_after += (count / len(y)) * entropy(y[X[:, feature] == v])
return entropy_before - entropy_after
def best_feature_by_information_gain(X, y):
features = X.shape[1]
gains = [information_gain(X, y, feature) for feature in range(features)]
return np.argmax(gains), max(gains)
# Load dataset
iris = load_iris()
X = iris.data
y = iris.target
# Find best feature
best_feature, best_gain = best_feature_by_information_gain(X, y)
print(f'Best feature: {
iris.feature_names[best_feature]}, Information Gain: {
best_gain}')
- 基尼指数(Gini Index)
也称为基尼不纯度(Gini Impurity),是一种衡量数据集纯度的指标。基尼指数越小,数据集的纯度越高。
基尼指数的计算公式:
对于一个包含 k 个类别的分类问题,基尼指数 G(D) 定义如下:
其中:
D 是数据集。
k 是类别的数量。
pi 是数据集中属于第 i 类的样本所占的比例。
条件基尼指数:
在某个特征 A 的条件下,数据集 D 的条件基尼指数 G(D∣A) 定义如下:
其中:
values(A) 是特征 A 的所有可能取值。
Dv 是数据集中特征 A 取值为 v 的子集。
∣Dv∣ 是 Dv 中样本的数量。
∣D∣ 是数据集 D 中样本的总数量。
G(Dv) 是子集 Dv 的基尼指数。
基尼增益(Gini Gain):
基尼增益 GG(D,A) 是通过特征 A 划分数据集 D 后基尼指数的减少量。计算公式如下:
参数解释
D:整个数据集,包含了所有的样本。
A:某个特征,用于划分数据集。
G(D):数据集 D 的基尼指数,表示数据集本身的纯度。
G(D∣A):在特征 A 的条件下,数据集 D 的条件基尼指数,表示在特征 A 的条件下数据集的纯度。
选择基尼增益最大的特征及其分割点作为当前节点的划分特征。
以下代码展示如何使用上述步骤来选择基尼增益最大的特征:
import numpy as np
from sklearn.datasets import load_iris
def gini(y):
hist = np.bincount(y)
ps = hist / len(y)
return 1 - np.sum([p**2 for p in ps if p > 0])
def gini_gain(X, y, feature):
# Gini index before split
gini_before = gini(y)
# Values and counts
values, counts = np.unique(X[:, feature], return_counts=True)
# Weighted gini after split
gini_after = 0
for v, count in zip(values, counts):
gini_after += (count / len(y)) * gini(y[X[:, feature] == v])
return gini_before - gini_after
def best_feature_by_gini_gain(X, y):
features = X.shape[1]
gains = [gini_gain(X, y, feature) for feature in range<