【机器学习】监督学习算法之:决策树

news2024/11/13 11:26:57

决策树

  • 1、引言
  • 2、决策树
    • 2.1 定义
    • 2.2 原理
    • 2.3 实现方式
    • 2.4 算法公式
      • 2.4.1 信息增益公式
      • 2.4.2 信息增益率公式
    • 2.5 代码示例
  • 3、总结

1、引言

小屌丝:鱼哥,我被你骗了。
小鱼:… 别闹,我怎么可能骗你呢。
小屌丝:你上次说的去泡澡
小鱼:嗯,然后呢。
小屌丝:然后咱俩去的是啥地方
小鱼:…嗯… 这个… 是泡澡的地方啊
小屌丝:你可拉倒吧。
小鱼:那我问你,咱俩去没去泡澡。
小屌丝:去了啊。
小鱼:那咱俩泡澡的地方有没有汗蒸房
小屌丝: 有啊。
小鱼:那咱俩泡澡的地方,有没有提供饮料。
小屌丝:有啊
小鱼:那咱俩泡澡的地方,有没有敲背。
小屌丝:有啊…
小鱼: 那咱俩泡完澡,有没有吃夜宵。
小屌丝:… 也有啊
小鱼: 你看,你都说了,这个流程咱都有,你咋说我骗你呢。
小屌丝:…但不,咱去的泡澡的地方跟原来的不一样
小鱼: …哪不一样了。

在这里插入图片描述
小屌丝:你看,这就是你说你请我去的泡澡的地方。
小鱼:那你说,这次咱俩洗完澡,是不是比平时更舒服了
小屌丝:这么一说,确实是这样的。
小鱼:而且冬天了,咱也得感受一下东北的搓澡文化。
小屌丝:…这么一说,那下次,咱还去这搓澡。
小鱼:你这还喜欢上搓澡了。

2、决策树

2.1 定义

决策树算法是一种常用的机器学习算法,它主要用于分类和回归问题。

该算法通过构建一棵树状结构来对输入数据进行分类或预测。

决策树算法的核心思想是基于一系列的特征对数据集进行分割,使得每个分割后的子集能够更好地满足某种条件,从而逐步逼近最终的分类或预测结果。

2.2 原理

是通过对数据集进行递归地划分,使得每个划分子集中的数据尽可能地相似。

通过计算不同特征的信息增益或基尼不纯度等指标,选择最佳的划分特征。

在划分的过程中,会逐渐减小不确定性,使得每个子集内的数据更加纯净。

2.3 实现方式

决策树的实现通常包括以下几个步骤:

  • 特征选择:选择最优特征进行划分,常用的特征选择方法有信息增益、增益率、基尼不纯度等。
    决策树生成:递归地划分数据集,生成决策树。常用的划分准则是完全划分,即每个子集只包含同一类别的数据。
  • 剪枝:对生成的决策树进行剪枝,以提高模型的泛化能力。常见的剪枝策略有预剪枝和后剪枝。
  • 决策树评估:使用测试数据对决策树进行评估,常用的评估指标有准确率、精确率、召回率和F1分数等。

2.4 算法公式

决策树算法的实现方式可以有多种,包括:

  • ID3算法:ID3算法使用信息增益来选择最佳划分特征
  • C4.5算法:C4.5算法使用信息增益率来选择最佳划分特征
  • CART算法:CART算法则使用基尼不纯度来选择最佳划分特征

2.4.1 信息增益公式

信息增益公式如下:
G a i n ( D , A ) = E n t r o p y ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t r o p y ( D v ) Gain(D, A) = Entropy(D) - \sum_{v=1}^{V}\frac{|D_v|}{|D|}Entropy(D_v) Gain(D,A)=Entropy(D)v=1VDDvEntropy(Dv)
D D D表示原始数据集, A A A表示待选择的划分特征, V V V表示特征 A A A的取值集合, D v D_v Dv表示特征 A A A取值为 v v v的子集, ∣ D ∣ |D| D表示数据集的样本个数, ∣ D v ∣ |D_v| Dv表示子集 D v D_v Dv的样本个数。

2.4.2 信息增益率公式

信息增益率公式如下:
G a i n _ R a t i o ( D , A ) = G a i n ( D , A ) S p l i t _ I n f o ( D , A ) Gain\_Ratio(D, A) = \frac{Gain(D, A)}{Split\_Info(D, A)} Gain_Ratio(D,A)=Split_Info(D,A)Gain(D,A)

其中, S p l i t _ I n f o ( D , A ) Split\_Info(D, A) Split_Info(D,A)表示特征 A A A的分裂信息,用于避免对具有较多取值的特征偏好。

基尼不纯度公式如下:
G i n i ( D ) = 1 − ∑ k = 1 K ( p k ) 2 Gini(D) = 1 - \sum_{k=1}^{K}(p_k)^2 Gini(D)=1k=1K(pk)2
K K K表示类别的个数, p k p_k pk表示属于类别 k k k的样本在数据集 D D D中的比例。

2.5 代码示例

# -*- coding:utf-8 -*-
# @Time   : 2024-01-21
# @Author : Carl_DJ

'''
实现功能:
    实现了一个简单的决策树分类器,其中包含了
      信息熵和基尼指数的计算函数,
      构建决策树、预测的方法

'''


import numpy as np

# 定义熵函数,计算给定标签集合的熵(信息熵)
def entropy(y):
    # 获取y中所有唯一值及其出现次数
    _, counts = np.unique(y, return_counts=True)
    # 计算每个类别的概率
    probabilities = counts / len(y)
    # 根据香农熵公式计算熵值
    return -np.sum(probabilities * np.log2(probabilities))

# 定义基尼不纯度指数函数,计算给定标签集合的基尼指数
def gini(y):
    # 同样获取y中所有唯一值及其出现次数
    _, counts = np.unique(y, return_counts=True)
    # 计算每个类别的概率
    probabilities = counts / len(y)
    # 根据基尼指数公式计算基尼不纯度
    return 1 - np.sum(probabilities**2)

# 定义信息增益计算函数,基于某个特征列计算划分数据集的信息增益
def information_gain(X, y, feature_index):
    # 计算原始数据集的熵(或基尼指数)作为总熵
    total_entropy = entropy(y)
    # 获取特征列feature_index上所有唯一值及其出现次数
    values, counts = np.unique(X[:, feature_index], return_counts=True)
    # 计算每个特征值对应的子集熵,并加权求和得到信息增益
    weighted_entropies = []
    for value, count in zip(values, counts):
        subset_y = y[X[:, feature_index] == value]
        # 子集的熵
        subset_entropy = entropy(subset_y)
        # 加权后的熵
        weighted_entropies.append(subset_entropy * count / len(y))
    # 总熵减去加权子集熵之和即为信息增益
    return total_entropy - np.sum(weighted_entropies)

# 定义基尼指数增益计算函数,与信息增益类似,但使用基尼指数代替熵
def gini_index(X, y, feature_index):
    # 计算原始数据集的基尼指数作为总基尼指数
    total_gini = gini(y)
    # 获取特征列feature_index上所有唯一值及其出现次数
    values, counts = np.unique(X[:, feature_index], return_counts=True)
    # 计算每个特征值对应的子集基尼指数,并加权求和得到基尼指数增益
    weighted_ginis = []
    for value, count in zip(values, counts):
        subset_y = y[X[:, feature_index] == value]
        # 子集的基尼指数
        subset_gini = gini(subset_y)
        # 加权后的基尼指数
        weighted_ginis.append(subset_gini * count / len(y))
    # 总基尼指数减去加权子集基尼指数之和即为基尼指数增益
    return total_gini - np.sum(weighted_ginis)

# 定义决策树类
class DecisionTree:
    # 初始化方法,设置最大深度和分裂标准(默认为基尼指数)
    def __init__(self, max_depth=None, criterion='gini'):
        self.max_depth = max_depth
        self.criterion = criterion

    # 训练方法,构建决策树模型
    def fit(self, X, y):
        # 调用私有方法构建决策树
        self.tree = self._build_tree(X, y)

    # 预测方法,根据输入样本X预测类别
    def predict(self, X):
        # 对于每个样本x,遍历决策树进行预测,并将结果存放在数组中
        return np.array([self._traverse_tree(x, self.tree) for x in X])

    # 私有方法,递归构建决策树
    def _build_tree(self, X, y, depth=0):
        # 如果达到最大深度或者所有样本标签相同,则返回该标签作为叶子节点
        if depth == self.max_depth or len(np.unique(y)) == 1:
            return np.bincount(y).argmax()
        
        # 选择最优特征并根据最优特征划分数据集
        best_feature = self._select_best_feature(X, y)
        tree = {best_feature: {}}
        
        # 获取当前最佳特征的所有可能取值
        values = np.unique(X[:, best_feature])
        for value in values:
            # 根据特征值筛选出子集,并对子集继续构建子树
            subset_X = X[X[:, best_feature] == value]
            subset_y = y[X[:, best_feature] == value]
            tree[best_feature][value] = self._build_tree(subset_X, subset_y, depth + 1)
        
        # 返回当前结点及其包含的子树
        return tree

    # 私有方法,选择最优特征(根据信息增益或基尼指数)
    def _select_best_feature(self, X, y):
        # 根据设定的标准选取相应的评价函数
        if self.criterion == 'gini':
            criterion_func = gini_index
        elif self.criterion == 'entropy':
            criterion_func = information_gain
        else:
            raise ValueError("Invalid criterion.")
        
        # 遍历所有特征,找到具有最高信息增益/基尼指数增益的特征
        best_feature = None
        best_score = -np.inf
        for feature_index in range(X.shape[1]):
            score = criterion_func(X, y, feature_index)
            if score > best_score:
                best_score = score
                best_feature = feature_index
        
        # 返回最优特征索引
        return best_feature

    # 私有方法,遍历决策树进行预测
    def _traverse_tree(self, x, tree):
        # 如果当前结点是字典类型(非叶节点),则继续深入决策树
        if isinstance(tree, dict):
            feature_index = list(tree.keys())[0]
            value = x[feature_index]
            subtree = tree[feature_index][value]
            return self._traverse_tree(x, subtree)
        # 如果当前结点不是字典类型(叶节点),则返回预测类别
        else:
            return tree

3、总结

看到这里,监督爱学习的决策树就讲到这里了。
我们不仅要理解决策树的定义,还需要通过实例来掌握其原理,
因为只要在实践中,才能掌握其技能。

我是小鱼

  • CSDN 博客专家
  • 阿里云 专家博主
  • 51CTO博客专家
  • 51认证讲师等
  • 认证金牌面试官
  • 职场面试培训、职场规划师
  • 多个国内主流技术社区的认证专家博主
  • 多款主流产品(阿里云等)测评一、二等奖获得者

关注小鱼,学习机器学习领域的知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1424482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【GPU驱动开发】-LLVM和Clang环境部署

前言 不必害怕未知,无需恐惧犯错,做一个Creator! 一、下载LLVM源码 官网下载源码 https://github.com/llvm/llvm-project/releases/ 包含所有llvm版本的下载内容 win源码传到ubuntu 首先将虚拟机关机,在虚拟机设置中&#xff…

机器学习:梯度下降法(Python)

LinearRegression_GD.py import numpy as np import matplotlib.pyplot as pltclass LinearRegression_GradDesc:"""线性回归,梯度下降法求解模型系数1、数据的预处理:是否训练偏置项fit_intercept(默认True)&…

【Tomcat与网络8】从源码看Tomcat的层次结构

在前面我们介绍了如何通过源码来启动Tomcat,本文我们就来看一下Tomcat是如何一步步启动的,以及在启动过程中,不同的组件是如何加载的。 一般,我们可以通过 Tomcat 的 /bin 目录下的脚本 startup.sh 来启动 Tomcat,如果…

node.js(nest.js控制器)学习笔记

nest.js控制器: 控制器负责处理传入请求并向客户端返回响应。 为了创建基本控制器,我们使用类和装饰器。装饰器将类与所需的元数据相关联,并使 Nest 能够创建路由映射(将请求绑定到相应的控制器)。 1.获取get请求传参…

使用 Enigma Protector 无需管理员权限即可注册 ActiveX/COM 组件

我们的客户对如何保护 .NET 应用程序免遭破解和转储提出了许多问题。在本文中,我们将尝试描述保护此类特定文件的所有薄弱环节和细节。 The Enigma Protector 是一款专门设计用来为应用程序添加高强度保护的强大工具。它旨在防止非法复制、反编译和修改代码等操作&…

数据结构与算法面试系列-03

1. 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? 程序代码 package com.jingxuan.system;public class Sphere {public static void main(String[] args) {double s = 0;double t = 100;for (int i…

搜维尔科技:第九届元宇宙数字人大赛,参赛小组报名确认公告!

各位参赛选手大家好,近期已收到新增报名信息如下表,请各位参赛选手确认,如果信息有误或信息不完整请电话联系赛务组工作人员进行更正 随着元宇宙时代的来临,数字人设计成为了创新前沿领域之一。为了提高大学生元宇宙虚拟人角色策划…

多线程代码案例之线程池

作者简介: zoro-1,目前大二,正在学习Java,数据结构,javaee等 作者主页: zoro-1的主页 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 创建线程池 public class Poo…

Java面试题宝典(万字长文)

Java 基础 1. JDK 和 JRE 有什么区别? JRE是Java运行环境,即(Java Runtime Environment),也就是Java平台。所有的Java程序都要在JRE下才能运行。 JDK是开发工具包,即(Java Development Kit&am…

经典mysql实操和行专列操作

1.删除除了学号字段以外,其它字段都相同的冗余记录,只保留一条!(也就是要删除王五和赵六中一条重复数据只留一条) 要求的预期效果: 原始数据创建表结构: CREATE TABLE tb_student (id int(16) NOT NULL,na…

科技云报道:云原生PaaS,如何让金融业数字化开出“繁花”?

科技云报道原创。 在中国金融业数字化转型的历史长卷中,过去十年无疑是一部磅礴的史诗。 2017年,南京银行第一次将传统线下金融业务搬到了线上。那一年,它的互联网金融信贷业务实现了过去10年的业务总额。 2021年,富滇银行通过…

【大数据安全】数据管理安全安全分析隐私保护

目录 一、数据管理安全 (一)数据溯源 (二)数字水印 (三)策略管理 (四)完整性保护 (五)数据脱敏 二、安全分析 (一)大数据安全…

数据库技术栈 —— B树与B+树

数据库技术栈 —— B树与B树 一、复习二、MySQL中的B树应用 一、复习 B树是多路平衡查找树的意思 参考文章或视频链接[1] 【王道计算机考研 数据结构】 二、MySQL中的B树应用 这篇文章里的计算题还是讲的不错的。 参考文章或视频链接[1] 《探究MySQL的索引结构选型》

Wireshark网络协议分析 - Wireshark速览

在我的博客阅读本文 文章目录 1. 版本与平台2. 快速上手2.1. 选择网络接口进行捕获(Capture)2.2. 以Ping命令为例进行抓包分析2.3. 设置合适的过滤表达式2.4. 数据包详情2.5. TCP/IP 四层模型 3. 参考资料 1. 版本与平台 Wireshark是一个开源的网络数据…

IDEA的properties默认编码是UTF-8但是不显示中文

问题描述 今天打开IDEA项目,发现messages_zh_CN.properties不显示中文了 但奇怪的是target下的文件就是展示的中文 而且我IDEA已经配置了编码格式是UTF-8了 使用nodepad打开源文件,也是展示编码格式是UTF-8 (打开target下的文件,…

QWT开源库使用

源代码地址:Qwt Users Guide: Qwt - Qt Widgets for Technical Applications Qwt库包含GUI组件和实用程序类,它们主要用于具有技术背景的程序。除了2D图的框架外,它还提供刻度,滑块,刻度盘,指南针&#xf…

EDR、SIEM、SOAR 和 XDR 的区别

在一个名为网络安全谷的神秘小镇,居住着四位守护者,他们分别是EDR(艾迪)、SIEM(西姆)、SOAR(索亚)和XDR(艾克斯)。他们各自拥有独特的能力,共同守…

Android组件化中的Arouter学习

假设现在有两个业务组件登录和问答模块之间需要进行通信,可能会想到用反射的方式,是可以但是会影响性能,而写的代码比较多类名这些要记清楚。 路由可以看做表,每个map对应一张表 我们可以试着这么写,完成MainActivity跳…

03. 【Linux教程】安装虚拟机

前面小节介绍了 Linux 和 GUN 项目,本小节开始学习如何在 Windows 上安装虚拟机,虚拟机安装之后可以在虚拟机中安装 Linux 相关的操作系统,常见的虚拟机软件有 VirtualBox、VMware 等等,本教程使用 VMware 虚拟机软件来演示如何安…

【Linux取经路】进程控制——进程等待

文章目录 一、进程创建1.1 初识 fork 函数1.2 fork 函数返回值1.3 写时拷贝1.4 fork 的常规用法1.5 fork 调用失败的原因1.6 创建一批进程 二、进程终止2.1 进程退出场景2.2 strerror函数2.3 errno全局变量2.4 程序异常2.5 进程常见退出方法2.6 exit 函数2.7 _exit 函数和 exit…