机器学习-决策树

2024-10-01  本文已影响0人  阿凡提说AI

决策树详解

决策树是一种监督学习算法,它通过学习一组数据来构建一个树形结构,以用于预测新数据的类别或值。它类似于人类进行决策的过程,通过一系列的判断问题,最终得到结论。

1. 决策树的结构

决策树由以下部分组成:

2. 决策树的构建过程

决策树的构建过程主要包含以下步骤:

3. 选择最佳划分属性的标准

常用的属性选择标准有以下几种:

4. 停止条件

常用的停止条件有以下几种:

5. 决策树的优点

6. 决策树的缺点

7. 决策树的应用场景

决策树被广泛应用于各种机器学习任务中,例如:

8. 常用的决策树算法

9. 决策树的优缺点总结

优点 缺点
易于理解和解释 对噪声数据敏感
对缺失值不敏感 对连续型属性处理不佳
可以处理混合数据类型 不稳定性

总而言之,决策树是一种简单但有效的监督学习算法,它可以用于解决各种分类和回归问题。选择合适的属性选择标准和停止条件,以及使用剪枝技术来防止过拟合,可以提高决策树的性能。
下面是用 Python 实现决策树算法的代码,并包含注释解释。

import numpy as np
from collections import Counter

class DecisionTree:
    def __init__(self, criterion="gini", max_depth=None, min_samples_split=2):
        """
        初始化决策树模型。

        参数:
            criterion: 划分标准,可选 "gini" 或 "entropy",默认为 "gini"
            max_depth: 最大树深度,默认为 None (不限制)
            min_samples_split: 划分节点所需的最小样本数,默认为 2
        """
        self.criterion = criterion
        self.max_depth = max_depth
        self.min_samples_split = min_samples_split
        self.tree = None  # 存储决策树结构

    def fit(self, X, y):
        """
        训练决策树模型。

        参数:
            X: 训练数据特征,numpy 数组,形状为 (n_samples, n_features)
            y: 训练数据标签,numpy 数组,形状为 (n_samples,)
        """
        self.tree = self._build_tree(X, y)

    def predict(self, X):
        """
        对新数据进行预测。

        参数:
            X: 测试数据特征,numpy 数组,形状为 (n_samples, n_features)

        返回值:
            预测标签,numpy 数组,形状为 (n_samples,)
        """
        predictions = []
        for sample in X:
            prediction = self._predict_sample(sample, self.tree)
            predictions.append(prediction)
        return np.array(predictions)

    def _build_tree(self, X, y, depth=0):
        """
        递归构建决策树。

        参数:
            X: 当前节点的训练数据特征
            y: 当前节点的训练数据标签
            depth: 当前节点的深度

        返回值:
            决策树节点
        """

        # 停止条件
        if len(np.unique(y)) == 1 or depth == self.max_depth or len(y) < self.min_samples_split:
            return {"label": Counter(y).most_common(1)[0][0]}

        # 选择最佳划分属性
        best_feature = self._find_best_split(X, y)

        # 创建节点
        node = {"feature": best_feature}

        # 根据最佳划分属性划分数据
        for value in np.unique(X[:, best_feature]):
            X_subset = X[X[:, best_feature] == value]
            y_subset = y[X[:, best_feature] == value]
            node[value] = self._build_tree(X_subset, y_subset, depth + 1)

        return node

    def _find_best_split(self, X, y):
        """
        找到最佳划分属性。

        参数:
            X: 当前节点的训练数据特征
            y: 当前节点的训练数据标签

        返回值:
            最佳划分属性的索引
        """

        best_feature = None
        best_score = float("inf") if self.criterion == "gini" else float("-inf")

        # 遍历所有特征
        for feature in range(X.shape[1]):
            # 计算当前特征的划分分数
            score = self._calculate_split_score(X[:, feature], y)

            # 更新最佳划分属性和分数
            if (self.criterion == "gini" and score < best_score) or (self.criterion == "entropy" and score > best_score):
                best_feature = feature
                best_score = score

        return best_feature

    def _calculate_split_score(self, feature_values, y):
        """
        计算划分分数。

        参数:
            feature_values: 当前特征的值
            y: 当前节点的训练数据标签

        返回值:
            划分分数
        """

        if self.criterion == "gini":
            return self._gini_impurity(y) - self._weighted_gini_impurity(feature_values, y)
        else:
            return self._entropy(y) - self._weighted_entropy(feature_values, y)

    def _gini_impurity(self, y):
        """
        计算基尼不纯度。

        参数:
            y: 当前节点的训练数据标签

        返回值:
            基尼不纯度
        """

        counts = Counter(y)
        impurity = 1
        for count in counts.values():
            probability = count / len(y)
            impurity -= probability ** 2
        return impurity

    def _weighted_gini_impurity(self, feature_values, y):
        """
        计算加权基尼不纯度。

        参数:
            feature_values: 当前特征的值
            y: 当前节点的训练数据标签

        返回值:
            加权基尼不纯度
        """

        weighted_impurity = 0
        for value in np.unique(feature_values):
            y_subset = y[feature_values == value]
            weight = len(y_subset) / len(y)
            weighted_impurity += weight * self._gini_impurity(y_subset)
        return weighted_impurity

    def _entropy(self, y):
        """
        计算熵。

        参数:
            y: 当前节点的训练数据标签

        返回值:
            熵
        """

        counts = Counter(y)
        entropy = 0
        for count in counts.values():
            probability = count / len(y)
            entropy -= probability * np.log2(probability)
        return entropy

    def _weighted_entropy(self, feature_values, y):
        """
        计算加权熵。

        参数:
            feature_values: 当前特征的值
            y: 当前节点的训练数据标签

        返回值:
            加权熵
        """

        weighted_entropy = 0
        for value in np.unique(feature_values):
            y_subset = y[feature_values == value]
            weight = len(y_subset) / len(y)
            weighted_entropy += weight * self._entropy(y_subset)
        return weighted_entropy

    def _predict_sample(self, sample, node):
        """
        预测单个样本的类别。

        参数:
            sample: 测试样本特征
            node: 决策树节点

        返回值:
            预测类别
        """

        # 如果是叶子节点,返回类别
        if "label" in node:
            return node["label"]

        # 递归遍历决策树
        feature_value = sample[node["feature"]]
        return self._predict_sample(sample, node[feature_value])

使用方法:

# 导入必要的库
import numpy as np

# 创建训练数据
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
y = np.array([0, 0, 1, 1])

# 创建决策树分类器
dt_classifier = DecisionTree(criterion="gini", max_depth=2)

# 训练分类器
dt_classifier.fit(X, y)

# 创建测试数据
X_test = np.array([[1, 2, 3], [10, 11, 12]])

# 对测试数据进行预测
predictions = dt_classifier.predict(X_test)

# 打印预测结果
print(predictions)  # 输出:[0 1]

解释:

注意:

上一篇 下一篇

猜你喜欢

热点阅读