Python实现决策树(Decision Tree)

💥 项目专栏:【探索机器学习之旅】原理与实践,Python算法实现


前言

🚀 欢迎莅临本专栏!在这里,我们将为机器学习的新手和初次尝试 sklearn 的用户群体提供一系列有趣的原生Python机器学习算法实现。我们的目标是让您轻松入门机器学习,并深入探索算法的内部奥秘。💡

在这个专栏中,我们专注于使用原生Python实现一些经典机器学习算法,比如决策树、逻辑回归等。通过自己亲手复现算法,我们将理论与实践紧密结合,让您对这些算法有更深入的理解。每篇文章都会附带完整的代码和详细讲解,助您逐步掌握算法的核心概念和运行原理。🔍📝

哪怕您是零基础,也不必担心!本专栏旨在为您提供一条通向机器学习世界的清晰路径。我们坚信,通过这些实践和理论指导,您将快速掌握机器学习的精髓,并在未来的学习和探索中展翅高飞!🌈🌟

来吧!让我们一起踏上机器学习之旅,探索这个神奇领域,畅游在算法的海洋中,感受数据科学的魅力吧!🌊💻🔬


🚨 欢迎来到我的机器学习探索项目环境!📊🐍

  • 平台:Windows 11 🖥️
  • 语言环境:Python 3.7 🐍
  • 编译器:Jupyter Lab 📘🔬
  • 数据处理:Pandas 1.3.5 🐼📈
  • 数值计算:Numpy 1.19.3 🔢🧮
  • 科学计算:Scipy 1.7.3 🧪📚
  • 数据可视化:Matplotlib 3.1.3 📊🎨

在这个酷炫的项目环境里,我们将使用强大的Python语言,搭配Jupyter Lab编译器,为您带来一流的机器学习学习体验。Pandas将为我们处理数据,Numpy则助力高效的数值计算,而Scipy则为我们的科学计算保驾护航。

让数据更加生动的秘密武器是Matplotlib,它将以图表的形式展现复杂的信息,让您轻松洞悉数据的特征和趋势。📊📈🔍

让我们一起在这个有趣的机器学习之旅中探索新的可能性吧!🚀🌟💻


让我们一起启程,探索机器学习的奇妙世界!🚀💡🤖

💥 项目专栏:【探索机器学习之旅】原理与实践,Python算法实现

在这里插入图片描述


一、基于原生Python实现决策树(Decision Tree)

🌳📊决策树,是机器学习的魔法般工具!它可以帮助我们进行分类和回归,无论是二元还是多元,连续还是离散,统统搞定!决策树的构建过程就像在寻宝一样,我们递归地挑选最优特征,然后根据这些特征将数据分割,直到发现宝藏——满足某种条件为止,这时,一颗美丽的决策树就呈现在我们面前!✨🏆

常见的决策树算法有三种: ID3C4.5CART。它们各有特色:ID3喜欢用信息增益来挑选特征,C4.5热衷于信息增益比,而CART则钟情于基尼指数。

决策树的魔法不仅在于它易于理解和解释,还能用可视化的图形展示模型。它还有神奇的本领,能处理各种类型的数据,连缺失值都能大胆面对,毫不畏惧!🧙‍♂️📈

当然,决策树也有一些小小的缺点:有时候它会变得有点过度自恋,容易过拟合。特别是当决策树变得太深,有点“自我作古”的感觉。此外,它对于特征的选择也是挑剔的,选个不合适的特征,它可是会生气的,影响预测性能哦!😱💔

不过别担心!我们还有Python来拯救我们!本篇文章将用Python语言实现经典的决策树算法 Decision Tree,让你轻松驾驭这项魔法!🐍🌟

在这里插入图片描述

二、决策树的算法原理

💡🌳 决策树,一个神奇的算法,让我们来揭开它的魔法面纱!✨

首先,决策树的核心就是选择最优的特征,它像在挑选漂亮衣服一样,找到最适合的特征来把数据集分割成小块。步骤可不简单哦:

  • 1️⃣ 首先要计算每个特征的“魔法值”——信息增益或信息增益比,就像测量魔法力量一样。信息增益是看特征分割后带来的信息变化,而信息增益比是对信息增益的绝妙评价。

  • 2️⃣ 然后,根据最优特征,把数据集变成小小的子集,每个子集对应一个特征取值,就像用魔法棒将数据分割成不同颜色的小球一样。🎈

  • 3️⃣ 接下来,咱们要递归地应用魔法,对每个子集重复步骤1和步骤2,直到找到宝藏——满足终止条件为止。✨🏰

  • 4️⃣ 最后,咱们大功告成,可以得到一颗漂亮的决策树,就像是一颗光芒四射的魔法树!🌳🌟在分类预测时,只需要按照魔法路线从根节点出发,逐渐找到对应的叶子节点,咦,原来这个叶子节点就是预测结果呢!🎁

🌈 哇,真是太有趣了!决策树有很多种实现方式,就像不同魔法一样,有ID3、C4.5和CART等,每种都有自己独特的魅力哦!❤️

决策树算法可不止魅力,它还有许多优点:易于理解和解释,处理离散和连续数据,而且不怕缺失值,真是万能魔法师!🧚‍♀️💖当然啦,每个魔法都有小小的缺点:有时候会过拟合,有时候对特征挑剔,但这都不影响它的魅力!

三、算法实现

💡🌳 欢迎来到决策树算法的魔法学院!✨🎓 今天我们要学习的是如何用原生Python来亲手实现决策树算法,这样你就能亲身感受算法内部的奥秘啦!🧚‍♀️💖

别担心,我们不会一口气把所有细节都告诉你,而是采用阉割版的决策树算法,让你轻松入门!😉 相比于sklearn框架的复杂实现,我们只保留了算法的核心部分,就像是为你准备了一颗炫酷的决策树小样本!🌲✨

你知道吗?掌握算法的主干才是最重要的,小细节和优化策略可以在日后再来考虑哦!所以,让我们一起开启决策树算法的奇幻冒险之旅吧!🚀💫

在这里,我们注重你的学习体验,就像你在魔法学院里学习一样,我们会用可爱的语言和简洁的步骤带你一步步深入理解算法的精髓,就像和好友一起探索决策树的魅力!🌟🤗

咱们不急,一起走进决策树的魔法森林,感受每一步决策的魔力,为你量身打造的决策树小样本,带你掌握决策树算法的精华!🎉🧙‍♀️

让我们手牵手,一起踏上决策树之旅吧!💞🌳✨

3.1 导包

🌟 我们的工具箱里准备了一些超酷的第三方库,都是些相当常见且厉害的小伙伴们哦!🔧🤩

  • 首先,我们要请来最可爱的小数学家——“numpy”!它可是我们的得力助手,擅长解决各种科学计算难题,就像一个小小的数学精灵!🧚‍♀️🧮

  • 当然,我们还有一位超级绘图专家——“matplotlib”!🎨✨ 它是我们的美术指导,能够帮我们绘制出绚丽多彩的图像,让我们的数据更有生气!🌈🖌️

  • 为了让我们的训练更加顺利,我们还有两位不可或缺的训练伙伴——“sklearn.datasets"和"train_test_split”!👥🔍 它们能够帮我们导入和划分训练数据,确保我们的决策树旅程顺利无阻!🛤️🗺️

  • 别忘了还有一个重要的小助手——“Counter”!🔢🤖 它是我们的计数器,可以帮我们统计各种事情,让我们的数据更加井井有条!📊📋

  • 最后,当然少不了我们的好朋友"math"!🎉🧙‍♀️ 它是我们的魔法计算师,擅长处理各种数学问题,让我们的算法更加神奇!✨🔮

嘿嘿~我们的小伙伴们组成了一支超级强大的决策树团队,将带领我们一起踏上决策树冒险之旅!🌲🚀

让我们齐心协力,用这些可爱的工具一起展开决策树的奇妙冒险吧!💖🌈✨

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter
import math

3.2 定义随机数种子

🎲🌈 在机器学习的大冒险中,随机数种子可谓是一把神奇的魔法棒!✨🪄 它的使命是确保我们的实验结果可爱又可重复,就像魔法一样,每次运行都能得到一样的结果!🌟🔁

你知道吗?机器学习的世界充满了各种神秘的随机性~🧙‍♀️ 比如那些调皮的随机初始化参数,捣蛋的随机选择训练样本等,它们总是让我们的实验结果五花八门~🌪️🙈

但是,有了可爱的随机数种子,一切都变得不一样了!🌈🤗 它就像是实验的守护精灵,每次都保持着相同的魔法节奏,让我们的结果一致又可靠~🎉✨

小小的随机数种子,却有着非常重要的使命哦~💖 它是我们实验的稳定器,消除了随机性的魔咒,让我们的算法评估更加精准可靠~🧚‍♀️🎯

但是记住哦~🌸🌟 使用随机数种子时,要保证所有条件都是一模一样的~🔍👯‍♀️ 这样,我们的实验结果才能如期而至,稳稳地掌握在我们手中!🤝📈

让我们握紧魔法棒,带上可爱的随机数种子,一起探索机器学习的奇幻世界吧!🚀💕🔮

# 设置随机种子
seed_value = 2023
np.random.seed(seed_value)

3.3 定义决策树模型

为了更容易理解,本文定义决策树模型的方式和 sklearn 封装的算法一致,都是定义 fitpredictscore 接口。

构建一棵决策树的详细过程可以分为以下几个步骤:

  1. 首先,我们要创建一棵神奇的决策树,它的根节点包含着所有的特征和标签🌿🏠 这个根节点就像是一片神奇的土地,等待着我们去探索

  2. 接着,我们要选择最优特征,这可是个重要的任务哦~🔍💡 我们要遍历所有特征,计算它们的信息增益,然后找出最最最大的那个,就是我们的划分标准啦!🌟🎯

  3. 一旦找到最优特征,我们就要用它来划分数据集~🎈📦 每个特征不同的取值,都会给我们带来一份神奇的子集,它们里面的数据样本特别特别有趣哦!🎁🎉

  4. 接下来,我们要让这个神奇的过程不停地进行下去🔄💫 对于每个子集,我们都要重复上面的步骤,直到它们变得越来越小,最后都变成同一个类别了,或者达到了我们预先设定的小目标

  5. 最终,我们将会构建出一颗充满魔力的决策树!🌳🏰 里面的每个非叶子节点都代表一个特征,每个叶子节点都闪闪发光,代表一个特别的类别~🌟💖

🌳💕 哇,剪枝策略就像是给决策树一把小剪刀,让它变得更聪明更可爱啦!✂️🌟

首先,我们有两种超酷的剪枝方式:预剪枝和后剪枝~🌿🌱

预剪枝是个超级聪明的小策略哦!在我们构建决策树的时候,每次遇到一个节点,我们会想一想:如果划分这个节点,会不会让测试集的准确率变得不怎么样呢?如果不会大大提升准确率,那我们就决定不划分啦!因为不划分反而更可爱!😊🎈

接着,我们还有后剪枝~这个剪枝策略可是超级神奇哦!🌟🌠 我们在决策树构建完成后,会从底部开始往上看,发现有一些非叶子节点,其实可以把它们变成更可爱的叶子节点哦!这样会让测试集的准确率更高~🌱🍃

你看,剪枝策略就像是为了让我们的决策树变得更加聪明和可爱!它们可以避免过拟合的麻烦,让我们的决策树更有用!🌳💖

构建一颗决策树需要注意以下问题:

  1. 特征选择问题:选择合适的特征作为决策树的划分标准是决策树算法的核心。常用的特征选择方法包括信息增益、信息增益比、基尼指数等。
  2. 过拟合问题:决策树容易对训练数据过度拟合,导致泛化性能差。通过剪枝、限制树的深度等方法可以缓解过拟合现象。
  3. 缺失值处理问题:在实际数据中经常会存在缺失值,如何处理缺失值对决策树的构建影响很大。常用的处理方法包括忽略带有缺失值的数据样本、使用平均值、中位数等填充缺失值、使用最近邻样本进行填充等。
  4. 类别不平衡问题:在实际应用中,可能存在不同类别样本数量差异较大的情况。针对这种情况,可以采用过采样、欠采样等方法平衡数据样本分布,或者在构建决策树时引入加权误差等方法。

总体而言,决策树算法的构建过程需要结合具体问题具体分析,对不同问题选择合适的特征选择方法、剪枝方法、缺失值处理方法等。

3.3.1 模型训练

基于训练数据和选择的分类标准,使用决策树算法训练出一颗决策树模型。训练过程包括以下步骤:

  • (1)计算数据集的熵,用于度量数据集的无序程度。

  • (2)对每个特征计算信息增益,选择信息增益最大的特征作为划分数据集的标准。

  • (3)按照选定的特征划分数据集,递归地对子集进行上述操作,直到所有数据集都为同一类别或者不能再划分为止。

首先,我们有一个超级神奇的 Node 类,它就像是决策树的一个小小节点~每个节点都有着自己的特征索引,一个阈值,还有左边的小伙伴 left 和右边的小伙伴 right,当然还有一个值 value~如果 value 不为空,那就说明这个节点是个可爱的叶子节点哦!🍃🌟

然后,还有我们的 DecisionTreeClassifier 类,这可是个大魔法师哦~在 fit 方法里,我们会拿着数据集 X 和标签 y,然后在决策树森林中一边逛一边训练我们的决策树!当然要记得记录分类的数量和特征数量哦!🌳🌈

接下来,在 predict 方法里,我们会像探险家一样勇敢地遍历决策树,来预测输入数据的标签~我们会用魔法查找正确的路径,找到宝藏一样的结果!💖🗺️

让我们穿上可爱的冒险装,一起来训练决策树吧!🎒🌳💪

  • _grow_tree :首先检查是否达到了最大深度、是否只有一个标签或者是否只有一个样本,如果是的话,我们返回一个叶节点。否则,我们计算每个特征和阈值的信息增益,并选择信息增益最大的特征和阈值进行分裂。我们再递归地构建左右子树,直到叶节点。
  • _best_criteria :计算每个特征和阈值的信息增益,并返回信息增益最大的特征和阈值。
  • _information_gain :计算分裂前和分裂后的熵,并返回信息增益。
  • _entropy :计算标签的熵。
  • _split :根据给定的特征列和阈值将数据集拆分成两个子集。
  • _most_common_label :返回最常见的标签。

这个实现中可能还有一些需要改进的地方,但是这个代码可以用来实现简单的决策树分类任务。

3.3.1.1 构建一颗决策树

决策树的构建是一个递归的过程,其基本思路可以概括为以下几个步骤:

嘿嘿决策树的构建过程其实就像是在探险,我们需要勇敢地选择最优特征,就像是挑选最闪闪发光的宝石一样!💎✨ 这些宝石可以是信息增益、信息增益比、还有基尼系数等每个宝石都代表着不同的特征选择方法,我们要根据不同的问题来选择哦~🤩🗝️

然后,我们会用这些宝石来划分数据集,把数据集分成好多小小的子集,每个子集都是特征的不同取值哦~就像是探险队伍分成了好几个小组,分别去寻找宝藏一样!🗺️🌳

接着,我们会勇敢地递归构建子树,就像是一层一层探险下去,直到找到宝藏或者满足终止条件~🚀🌈 然后,我们就可以把这些子树拼成一棵完整的决策树,每个子树就是一个节点,通过宝藏的特征值,我们可以把数据分配到不同的子树中~🌳🍃

不过,冒险途中还有个问题要注意哦就是过拟合和欠拟合问题,我们得小心翼翼避免掉进这些坑里~😱🚫 还有要好好准备特征选择、数据预处理等工作,就像是装备准备要充分哦!🛡️🧰

让我们戴上可爱的冒险帽,踏上决策树的奇妙冒险之旅吧!💕🎒🌟

# 生成树
def _grow_tree(self, X, y, depth=0):
    n_samples, n_features = X.shape
    n_labels = len(set(y))

    if depth >= self.max_depth or n_labels == 1 or n_samples < 2:
        leaf_value = self._most_common_label(y)
        return Node(value=leaf_value)

    feature_indices = range(n_features)
    best_feature, best_threshold = self._best_criteria(X, y, feature_indices)
    left_indices, right_indices = self._split(X[:, best_feature], best_threshold)

    left = self._grow_tree(X[left_indices, :], y[left_indices], depth + 1)
    right = self._grow_tree(X[right_indices, :], y[right_indices], depth + 1)
    return Node(best_feature, best_threshold, left, right)
3.3.1.2 计算每个特征的信息增益

信息增益其实就是一个特征带给我们的"惊喜"程度,它告诉我们如果用某个特征来分割数据集,会让我们对数据有更多的了解,就像是解开谜题一样~🧩🕵️‍♀️

当我们找到信息增益最大的那个特征时,就像是找到了藏在森林深处的一颗珍贵宝石,我们会选择这个特征作为我们的划分标准,然后继续探索下去,找到更多宝藏!💎💫

通过计算信息增益,我们不仅可以得到一颗宝石,还可以得到整个决策树的构建方案!🌳🗺️ 就像是解开了一个个谜题,揭开了一幅幅冒险地图,我们可以一步一步构建出一棵精美的决策树!🧭🗝️

# 信息增益最大的特征和阈值
def _best_criteria(self, X, y, feature_indices):
    best_gain = -1
    split_index, split_threshold = None, None
    for i in feature_indices:
        column = X[:, i]
        thresholds = set(column)
        for threshold in thresholds:
            gain = self._information_gain(y, column, threshold)
            if gain > best_gain:
                best_gain = gain
                split_index = i
                split_threshold =
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Natasha❀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值