通俗易懂的机器学习——根据CART算法使用python构建决策树(效果和sklearn类似)

本文详细介绍如何用Python实现CART算法构建决策树,包括依赖包导入、信息熵计算、树结点定义、决策树类及其关键函数解读,以及通过make_circles、make_moons和iris数据集的实际应用展示。

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

前言

之前曾经实现过可以应用在离散取值区间的简易决策树,前天突发奇想仿照sklearn的实现效果写了一个取值范围可以是连续区间的通用决策树。
如果对之前的简易决策树了解不深可以先复习一下:简易决策树地址

代码介绍

依赖包

import numpy as np
from collections import Counter
from math import log2
import matplotlib.pyplot as plt
from sklearn import datasets

在这里我们为了方便直接选用了sklearn里面的数据集(仅选用数据集,算法具体实现不依赖于sklearn)。
对于依赖包的解释也可以翻阅之前的简易决策树一文。

计算损失

def entropy(y_label):
    counter = Counter(y_label)
    ent = 0.0
    for num in counter.values():
        p = num / len(y_label)
        ent += -p * log2(p)
    return ent

在本博客中我们选用的是信息熵,也可以选用基尼系数。

树结点

class TreeNode:
    def __init__(self, acc, imin=None, minD=None):
        self.acc = list(acc)  # 不同类别的精度
        self.imin = imin  # 最小分割的特征
        self.minD = minD  # 分割点

树的结点中包含的信息有:在当前结点不同类别的精度、该结点损失最小分割特征、和按照损失最小分割特征分割的损失最小的分割值。

决策树类

class DecisionTree:
    def __init__(self, maxentropy=1e-10, max_depth=20, min_samples=0.1):
        self.tree = {
   
   }
        self.maxentropy = maxentropy  # 最大信息熵(分割条件:小于这个信息熵可以分割)
        self.max_depth = max_depth  # 递归树深度
        self.min_samples = min_samples  # 最小样本数

    # 训练决策树
    def fit(self, X, y):
        if self.min_samples < 1 and self.min_samples > 0:
            # 如果min_samples是小数则按照输入数据的数据量的比例确定min_samples,如果>1则给定的数值作为min_samples
            self.min_samples *= len(X)
        cols = list(range(X.shape[1]))
        # 对X得每一列数据,计算分割后得信息熵
        ylen = len(set(y))
        self.tree = self._genTree(cols, X, y, ylen, 1)

    # 递归生成决策树
    def _genTree(self, cols, X, y, ylen, depth):
        # 计算最小信息熵得特征
        imin = cols[0]  # 最下熵得列
        leftemin = 100  # 最小左熵值
        rightemin = 100  # 最小右熵值
        minD = None
        for i in cols:
            coli = X[:, i]  # 拿到第i个特征数据
            sortedcoli = coli
            sorted(sortedcoli)
            divide = []
            divide.append(coli[0])
            for j in range(len(sortedcoli)):
                # 划分分界线
                if j == len(sortedcoli) - 1:
                    divide.append(sortedcoli[j])
                else:
                    divide.append((sortedcoli[j] + sortedcoli[j+1]) / 2)
            for d in divide:
                # 选择不同特征的不同值所产生的最小信息熵
                leftenti = entropy(y[coli < d])
                rightenti = entropy(y[coli >= d])
                if leftenti + rightenti < leftemin + rightemin:
                    imin = i
                    leftemin = leftenti
                    rightemin = rightenti
                    minD = d
        # 求划分精度
        coli = X[:, imin]
        Acc = np.zeros(ylen)
        leftAcc = np.zeros(ylen)
        rightAcc = np.zeros(ylen)

        for idx in set(y):
            # print(y[coli < minD] == idx)
            leftAcc[idx] = np.sum(y[coli < minD] == idx) / len(y[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

艾醒(AiXing-w)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值