机器学习实验二——决策树(肉食性动物与草食性动物的区分)

决策树是一种强大的机器学习模型,用于分类、回归和特征选择。文章详细介绍了ID3、C4.5和CART的构建方法,以及信息增益、信息增益比和基尼不纯度等指标。通过实例展示了如何用Python实现决策树,包括预测草食性与肉食性动物的区分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是决策树

决策树是一种基于树形结构的机器学习模型,用于进行分类和回归任务。它通过一系列的决策节点和分支来对数据进行分类或预测。决策树的每个节点表示一个特征,每个分支表示该特征可能的取值,而每个叶子节点则表示一个类别(对于分类任务)或一个数值(对于回归任务)。

在分类任务中,决策树通过对数据进行分裂,将其划分为不同的类别。在每个节点上,决策树根据某个特征的取值将数据分割成子集,然后递归地对每个子集进行进一步的分裂,直到满足停止条件,例如节点中的样本都属于同一类别或达到了树的最大深度。

在回归任务中,决策树通过对数据进行分裂,预测连续型的数值。与分类任务类似,决策树根据特征的取值将数据分割成子集,并递归地对每个子集进行进一步的分裂,直到满足停止条件,例如达到了树的最大深度或分裂后的子集样本数量不足。

决策树的优点包括易于理解和解释,对缺失值不敏感,并且能够处理各种类型的数据(例如数值型、类别型等)。然而,决策树也容易过拟合训练数据,特别是在处理复杂的问题时。因此,通常会通过剪枝等技术来避免过拟合。

二、决策树的作用

  1. 分类:决策树可以用于分类任务,即根据输入数据的特征将其分到不同的类别中。例如,可以使用决策树来判断一封电子邮件是否为垃圾邮件。

  2. 回归:除了分类,决策树还可以用于回归任务,即预测连续型的数值。例如,可以使用决策树来预测房屋的销售价格。

  3. 特征选择:决策树可以根据特征的重要性来选择最相关的特征,从而帮助理解数据并提高模型性能。

  4. 数据探索:通过可视化决策树,可以直观地了解数据的结构和特征之间的关系,从而发现数据中的模式和规律。

  5. 集成学习:决策树是许多集成学习算法的基础,如随机森林和梯度提升树。这些算法通过组合多个决策树来提高整体模型的性能和稳定性。

总的来说,决策树是一种灵活而强大的机器学习模型,可以用于各种类型的任务,包括分类、回归、特征选择和数据探索。

三、构建决策树的方法

(一)ID3 (Iterative Dichotomiser 3)

特征选择:ID3算法使用信息增益来选择最佳的特征进行分裂。信息增益衡量了选择某个特征进行分裂后,对于减少数据的不确定性所做的贡献。具体而言,算法计算每个特征的信息增益,选择具有最大信息增益的特征作为当前节点的分裂特征。
树的构建:根据信息增益进行递归地构建树形结构,直到满足停止条件,例如节点中的样本都属于同一类别,或者达到了树的最大深度。


(二)C4.5

特征选择:C4.5算法使用信息增益比来选择最佳的特征进行分裂。信息增益比考虑了特征的取值数目对信息增益的影响,避免了偏向取值较多的特征。具体而言,算法计算每个特征的信息增益比,选择具有最大信息增益比的特征作为当前节点的分裂特征。
树的构建:根据信息增益比进行递归地构建树形结构,直到满足停止条件,例如节点中的样本都属于同一类别,或者达到了树的最大深度。


(三)CART (Classification and Regression Trees)

特征选择:对于分类任务,CART算法使用基尼不纯度来选择最佳的特征进行分裂。基尼不纯度衡量了从数据集中随机抽取两个样本,它们属于不同类别的概率。具体而言,算法计算每个特征的基尼不纯度,选择具有最小基尼不纯度的特征作为当前节点的分裂特征。对于回归任务,CART算法使用均方差(Mean Squared Error)来衡量分裂的效果。
树的构建:根据基尼不纯度或均方差进行递归地构建树形结构,直到满足停止条件,例如节点中的样本都属于同一类别或达到了树的最大深度。

四、基于原理的具体公式实现

(一)信息熵

(二)信息增益

(三)信息增益率

五、实验代码呈现(肉食性与草食性动物的区分)

(一)实验总体代码

(有自己实现构建树的函数,后半部分使用了库中函数)

import numpy as np
import math

class Node:
    def __init__(self, attribute=None, value=None, result=None):
        self.attribute = attribute  # 属性名
        self.value = value          # 分裂值(如果是叶节点则为None)
        self.result = result        # 类别结果(如果是内部节点则为None)
        self.children = {}          # 子节点字典,键为属性值,值为子节点

class DecisionTree:
    def __init__(self):
        self.root = None

    def fit(self, X, y):
        attributes = [i for i in range(len(X[0]))]  # 特征属性列表
        self.root = self._build_tree(X, y, attributes)

    def _entropy(self, y):
        # 计算给定数据集y的熵
        classes = set(y)
        entropy = 0
        total = len(y)
        for c in classes:
            p = list(y).count(c) / total
            entropy -= p * math.log2(p)
        return entropy

    def _information_gain(self, X, y, attribute):
        # 计算使用给定属性attribute对数据集X进行划分所得的信息增益
        values = set(X[:, attribute])
        gain = self._entropy(y)
        total = len(y)
        for value in values:
            subset_y = [y[i] for i in range(total) if X[i][attribute] == value]
            gain -= len(subset_y) / total * self._entropy(subset_y)
        return gain

    def _build_tree(self, X, y, attributes):
        # 递归构建决策树
        if len(set(y)) == 1:  # 如果所有样本属于同一类别,则创建叶节点并返回
            return Node(result=y[0])

        if len(attributes) == 0:  # 如果没有可用属性,则创建叶节点并返回
            return Node(result=int(np.argmax(np.bincount(y))))

        best_attribute = max(attributes, key=lambda a: self._information_gain(X, y, a))
        node = Node(attribute=best_attribute)

        values = set(X[:, best_attribute])
        for value in values:
            subset_indices = [i for i in range(len(X)) if X[i][best_attribute] == value]
            subset_X = X[subset_indices]
            subset_y = [y[i] for i in subset_indices]
            if len(subset_X) == 0:  # 如果子集为空,则创建叶节点并返回
                node.children[value] = Node(result=int(np.argmax(np.bincount(y))))
            else:
                subset_attributes = [a for a in attributes if a != best_attribute]
                node.children[value] = self._build_tree(subset_X, subset_y, subset_attributes)

        return node

    def predict(self, X):
        # 对输入的数据集X进行预测
        predictions = []
        for instance in X:
            predictions.append(self._predict_instance(instance, self.root))
        return predictions

    def _predict_instance(self, instance, node):
        # 对单个实例instance进行预测
        if node.result is not None:  # 如果是叶节点,则返回类别结果
            return node.result
        else:
            value = instance[node.attribute]
            if value in node.children:
                return self._predict_instance(instance, node.children[value])
            else:  # 如果实例的属性值在训练集中未出现,则返回叶节点中出现频率最高的类别
                return int(np.argmax(np.bincount(node.result)))

# 构建样本数据
X = np.array([
    [1, 1, 1, 1],  # 有尖牙,是哺乳动物,有爪子,是大型动物,是肉食动物
    [1, 1, 0, 1],  # 有尖牙,是哺乳动物,无爪子,是大型动物,是肉食动物
    [0, 1, 1, 1],  # 无尖牙,是哺乳动物,有爪子,是大型动物,是肉食动物
    [0, 1, 0, 1],  # 无尖牙,是哺乳动物,无爪子,是大型动物,是草食动物
    [0, 0, 1, 0],  # 无尖牙,不是哺乳动物,有爪子,不是大型动物,是草食动物
    [0, 0, 0, 0]   # 无尖牙,不是哺乳动物,无爪子,不是大型动物,是草食动物
])

y = np.array([1, 1, 1, 0, 0, 0])

# 创建并训练决策树模型
model = DecisionTree()
model.fit(X, y)

new_samples = np.array([
    [1, 0, 1, 1],  # 有尖牙,不是哺乳动物,有爪子,是大型动物
    [1, 1, 0, 0],  # 有尖牙,是哺乳动物,无爪子,是大型动物
    [0, 1, 0, 0]   # 无尖牙,是哺乳动物,无爪子,不是大型动物
])
predictions = model.predict(new_samples)
print("预测结果:", predictions)

(二)实验结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值