【大数据】机器学习------决策树

一、基本流程

决策树是一种基于树结构的分类和回归方法,它通过对特征空间进行划分,每个内部节点表示一个特征测试,每个分支代表一个测试输出,每个叶节点代表一个类别或回归值。

  1. 特征选择:根据某种准则(如信息增益、信息增益比、基尼指数等)选择最优特征进行划分。
  2. 决策树生成:从根节点开始,根据选定的特征对样本进行划分,生成子节点,递归地构建决策树。
  3. 决策树剪枝:通过剪枝处理防止过拟合,提高决策树的泛化能力。

二、划分选择

1. 信息增益(ID3 算法)

信息增益表示得知特征 X X X 的信息而使得类 Y Y Y 的信息不确定性减少的程度。

设数据集 D D D 的信息熵为:

其中 C k C_k Ck 是类别 k k k 的样本集合, ∣ C k ∣ |C_k| ∣Ck∣ 是类别 k k k 的样本数量, ∣ D ∣ |D| ∣D∣ 是数据集 D D D 的样本总数。

对于特征 A A A,信息增益为:

2. 信息增益比(C4.5 算法)

信息增益比克服了信息增益偏向于选择取值较多的特征的问题,定义为:

3. 基尼指数(CART 算法)

基尼指数表示集合的不确定性,对于数据集 D D D:

其中

对于特征 A A A 的基尼指数:

三、剪枝处理

1. 预剪枝

在决策树生成过程中,对每个节点在划分前进行估计,如果当前节点的划分不能带来决策树泛化性能的提升,则停止划分。

2. 后剪枝

先生成完整的决策树,然后自底向上对非叶节点进行考察,若将其替换为叶节点能提高泛化性能,则进行剪枝。

四、连续与缺失值处理

1. 连续值处理

对于连续特征,通常将其离散化,如采用二分法,将连续特征的取值排序,取相邻值的平均值作为划分点,计算不同划分点的信息增益(或其他指标),选择最优划分点。

2. 缺失值处理

  • 样本权重调整:对于含有缺失值的样本,根据无缺失值样本中该特征的取值分布,将其以一定权重划分到不同子节点。
  • 属性值填充:使用一些策略(如均值、中位数、众数)填充缺失值。

五、多变量决策树

多变量决策树不是为每个节点寻找一个最优划分属性,而是试图建立一个线性组合作为划分属性,如:

六、代码示例

1. 使用 sklearn 实现决策树分类

python 复制代码
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score


# 加载鸢尾花数据集
iris = load_iris()
X = iris.data
y = iris.target


# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)


# 初始化决策树分类器,使用信息增益(默认)
clf = DecisionTreeClassifier(criterion='entropy')


# 训练模型
clf.fit(X_train, y_train)


# 预测
y_pred = clf.predict(X_test)


# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")

2. 自定义决策树(使用信息增益)

python 复制代码
import numpy as np


def entropy(y):
    """计算信息熵"""
    unique_labels = np.unique(y)
    entropy = 0
    for label in unique_labels:
        p = np.mean(y == label)
        entropy -= p * np.log2(p)
    return entropy


def information_gain(X, y, feature_index):
    """计算信息增益"""
    base_entropy = entropy(y)
    values = np.unique(X[:, feature_index])
    new_entropy = 0
    for value in values:
        sub_y = y[X[:, feature_index] == value]
        p = len(sub_y) / len(y)
        new_entropy += p * entropy(sub_y)
    return base_entropy - new_entropy


class Node:
    """决策树节点类"""
    def __init__(self, feature_index=None, threshold=None, left=None, right=None, value=None):
        self.feature_index = feature_index
        self.threshold = threshold
        self.left = left
        self.right = right
        self.value = value


def build_tree(X, y, depth=0, max_depth=5):
    """构建决策树"""
    if len(np.unique(y)) == 1:
        return Node(value=y[0])
    if depth >= max_depth:
        return Node(value=np.bincount(y).argmax())
    n_features = X.shape[1]
    best_gain = 0
    best_feature = None
    best_threshold = None
    for feature_index in range(n_features):
        gain = information_gain(X, y, feature_index)
        if gain > best_gain:
            best_gain = gain
            best_feature = feature_index
    if best_gain == 0:
        return Node(value=np.bincount(y).argmax())
    feature_values = np.unique(X[:, best_feature])
    best_threshold = (feature_values[:-1] + feature_values[1:]) / 2
    best_threshold = best_threshold[np.argmax([information_gain(X, y, best_feature, t) for t in best_threshold])]
    left_indices = X[:, best_feature] <= best_threshold
    right_indices = X[:, best_feature] > best_threshold
    left = build_tree(X[left_indices], y[left_indices], depth + 1, max_depth)
    right = build_tree(X[right_indices], y[right_indices], depth + 1, max_depth)
    return Node(feature_index=best_feature, threshold=best_threshold, left=left, right=right)


def predict_sample(node, sample):
    """预测单个样本"""
    if node.value is not None:
        return node.value
    if sample[node.feature_index] <= node.threshold:
        return predict_sample(node.left, sample)
    else:
        return predict_sample(node.right, sample)


def predict(tree, X):
    """预测多个样本"""
    return np.array([predict_sample(tree, sample) for sample in X])


# 示例数据
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 0])


# 构建决策树
tree = build_tree(X, y, max_depth=3)


# 预测
y_pred = predict(tree, X)
print(y_pred)

代码解释

1. 使用 sklearn 实现决策树分类

  • load_iris() 加载鸢尾花数据集。
  • DecisionTreeClassifier(criterion='entropy') 初始化一个使用信息熵作为划分准则的决策树分类器。
  • clf.fit(X_train, y_train) 训练模型。
  • clf.predict(X_test) 对测试集进行预测。
  • accuracy_score(y_test, y_pred) 计算准确率。

2. 自定义决策树(使用信息增益)

  • entropy(y) 函数计算信息熵。
  • information_gain(X, y, feature_index) 计算信息增益。
  • Node 类定义决策树的节点。
  • build_tree(X, y, depth=0, max_depth=5) 递归构建决策树,使用信息增益选择特征和阈值进行划分。
  • predict_sample(node, sample) 对单个样本进行预测。
  • predict(tree, X) 对多个样本进行预测。
相关推荐
在猴站学算法2 小时前
机器学习(西瓜书) 第二章 模型评估与选择
人工智能·机器学习
Edingbrugh.南空6 小时前
Flink自定义函数
大数据·flink
gaosushexiangji7 小时前
利用sCMOS科学相机测量激光散射强度
大数据·人工智能·数码相机·计算机视觉
无级程序员9 小时前
大数据平台之ranger与ldap集成,同步用户和组
大数据·hadoop
lifallen10 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
TDengine (老段)11 小时前
TDengine 数据库建模最佳实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
张先shen11 小时前
Elasticsearch RESTful API入门:全文搜索实战(Java版)
java·大数据·elasticsearch·搜索引擎·全文检索·restful
Elastic 中国社区官方博客11 小时前
Elasticsearch 字符串包含子字符串:高级查询技巧
大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
张先shen12 小时前
Elasticsearch RESTful API入门:全文搜索实战
java·大数据·elasticsearch·搜索引擎·全文检索·restful
2401_8786247912 小时前
pytorch 自动微分
人工智能·pytorch·python·机器学习