3.22【机器学习】决策树作业代码实现

news2025/1/15 15:49:25

4.1由于决策树只在样本同属于一类或者所有特征值都用完或缺失时生成叶节点,同一节点的样本,在路径上的特征值都相同,而训练集中又没有冲突数据,所以必定存在训练误差为0的决策树

4.2使用最小训练误差会导致过拟合,使得学习模型泛化能力下降。

4.3

青绿0,乌黑1,浅白2

蜷缩0,稍蜷1,硬挺2

浊响0,沉闷1,清脆2

清晰0,烧糊1,模胡2

凹陷0,稍凹1,平坦2

硬滑0,软粘1

import numpy as np
import treePlotter
np.random.seed(100)
class DecisionTreeClassifier:
    def __init__(self,tree_type='ID3',k_classes=2):
        self.tree_type=tree_type
        self.k_classes=k_classes
        if tree_type=='ID3':
            self.gain_func=self.Gain
        elif tree_type=='CART':
            self.gain_func=self.GiniIndex
        elif tree_type=='C45':
            self.gain_func=self.GainRatio
        else:
            raise ValueError('must be ID3 or CART or C45')
        self.tree=None

    def fit(self,X,y):
        D={}
        D['X']=X
        D['y']=y
        A=np.arange(X.shape[1])
        aVs={}
        for a in A:
            aVs[a]=np.unique(X[:,a])
        self.tree=self.TreeGenerate(D,A,aVs)

    def predict(self,X):
        if self.tree is None:
            raise RuntimeError('cant predict before fit')
        y_pred=[]
        for i in range(X.shape[0]):
            tree = self.tree
            x=X[i]
            while True:
                if not isinstance(tree,dict):
                    y_pred.append(tree)
                    break
                a=list(tree.keys())[0]
                tree=tree[a]
                if isinstance(tree,dict):
                    val = x[a]
                    tree = tree[val]
                else:
                    y_pred.append(tree)
                    break
        return np.array(y_pred)

    def TreeGenerate(self,D,A,aVs):
        X=D['X']
        y=D['y']
        # 情形1
        unique_classes=np.unique(y)
        if len(unique_classes)==1:
            return unique_classes[0]
        flag=True
        for a in A:
            if(len(np.unique(X[:,a]))>1):
                flag=False
                break
        # 情形2
        if flag:
            return np.argmax(np.bincount(y))

        gains=np.zeros((len(A),))
        if self.tree_type=='C45':
            gains=np.zeros((len(A),2))
        for i in range(len(A)):
            gains[i]=self.gain_func(D,A[i])
        #print(gains)
        subA=None
        if self.tree_type=='CART':
            a_best=A[np.argmin(gains)]
            subA=np.delete(A,np.argmin(gains))
        elif self.tree_type=='ID3':
            a_best=A[np.argmax(gains)]
            subA=np.delete(A,np.argmax(gains))
        elif self.tree_type=='C45':
            gain_mean=np.mean(gains[:,0])
            higher_than_mean_indices=np.where(gains[:,0]>=gain_mean)
            higher_than_mean=gains[higher_than_mean_indices,1][0]
            index=higher_than_mean_indices[0][np.argmax(higher_than_mean)]
            a_best=A[index]
            subA=np.delete(A,index)

        tree={a_best:{}}

        for av in aVs[a_best]:
            indices=np.where(X[:,a_best]==av)
            Dv={}
            Dv['X']=X[indices]
            Dv['y']=y[indices]
            if len(Dv['y'])==0:
                tree[a_best][av]=np.argmax(np.bincount(y))
            else:
                tree[a_best][av]=self.TreeGenerate(Dv,subA,aVs)
        return tree
    @classmethod
    def Ent(cls,D):
        y=D['y']
        bin_count=np.bincount(y)
        total=len(y)
        ent=0.
        for k in range(len(bin_count)):
            p_k=bin_count[k]/total
            if p_k!=0:
                 ent+=p_k*np.log2(p_k)
        return -ent

    @classmethod
    def Gain(cls,D,a):
        X=D['X']
        y=D['y']
        aV=np.unique(X[:,a])
        sum=0.
        for v in range(len(aV)):
            Dv={}
            indices=np.where(X[:,a]==aV[v])
            Dv['X']=X[indices]
            Dv['y']=y[indices]
            ent=cls.Ent(Dv)
            sum+=(len(Dv['y'])/len(y)*ent)
        gain=cls.Ent(D)-sum
        return gain

    @classmethod
    def Gini(cls,D):
        y = D['y']
        bin_count = np.bincount(y)
        total = len(y)
        ent = 0.
        for k in range(len(bin_count)):
            p_k = bin_count[k] / total
            ent+=p_k**2
        return 1-ent

    @classmethod
    def GiniIndex(cls,D,a):
        X = D['X']
        y = D['y']
        aV = np.unique(X[:, a])
        sum = 0.
        for v in range(len(aV)):
            Dv = {}
            indices = np.where(X[:, a] == aV[v])
            Dv['X'] = X[indices]
            Dv['y'] = y[indices]
            ent = cls.Gini(Dv)
            sum += (len(Dv['y']) / len(y) * ent)
        gain = sum
        return gain

    @classmethod
    def GainRatio(cls,D,a):
        X = D['X']
        y = D['y']
        aV = np.unique(X[:, a])
        sum = 0.
        intrinsic_value=0.
        for v in range(len(aV)):
            Dv = {}
            indices = np.where(X[:, a] == aV[v])
            Dv['X'] = X[indices]
            Dv['y'] = y[indices]
            ent = cls.Ent(Dv)
            sum += (len(Dv['y']) / len(y) * ent)
            intrinsic_value+=(len(Dv['y'])/len(y))*np.log2(len(Dv['y'])/len(y))
        gain = cls.Ent(D) - sum
        intrinsic_value=-intrinsic_value
        gain_ratio=gain/intrinsic_value
        return np.array([gain,gain_ratio])

if __name__=='__main__':
    watermelon_data = np.array([[0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0],
                                [1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0],
                                [2, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 1],
                                [1, 1, 0, 1, 1, 1], [1, 1, 0, 0, 1, 0],
                                [1, 1, 1, 1, 1, 0], [0, 2, 2, 0, 2, 1],
                                [2, 2, 2, 2, 2, 0], [2, 0, 0, 2, 2, 1],
                                [0, 1, 0, 1, 0, 0], [2, 1, 1, 1, 0, 0],
                                [1, 1, 0, 0, 1, 1], [2, 0, 0, 2, 2, 0],
                                [0, 0, 1, 1, 1, 0]])
    label = np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0])
    X_test=np.array([[0, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0],
                        [1, 1, 0, 1, 1, 0], [1, 0, 1, 1, 1, 0],
                     [1, 1, 0, 0, 1, 1], [2, 0, 0, 2, 2, 0],
                     [0, 0, 1, 1, 1, 0]])

    decision_clf=DecisionTreeClassifier(tree_type='ID3')
    decision_clf.fit(watermelon_data,label)
    print(decision_clf.tree)
    treePlotter.createPlot(decision_clf.tree)

    y_pred=decision_clf.predict(X_test)
    print('y_pred:',y_pred)
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong'] 
mpl.rcParams['axes.unicode_minus'] = False 
decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")

def plotNode(nodeTxt, centerPt, parentPt, nodeType):
    createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', \
                            xytext=centerPt, textcoords='axes fraction', \
                            va="center", ha="center", bbox=nodeType, arrowprops=arrow_args)

def getNumLeafs(myTree):
    numLeafs = 0
    firstStr = list(myTree.keys())[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            numLeafs += getNumLeafs(secondDict[key])
        else:
            numLeafs += 1
    return numLeafs

def getTreeDepth(myTree):
    maxDepth = 0
    firstStr = list(myTree.keys())[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            thisDepth = getTreeDepth(secondDict[key]) + 1
        else:
            thisDepth = 1
        if thisDepth > maxDepth:
            maxDepth = thisDepth
    return maxDepth

def plotMidText(cntrPt, parentPt, txtString):
    xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0]
    yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1]
    createPlot.ax1.text(xMid, yMid, txtString)

def plotTree(myTree, parentPt, nodeTxt):
    numLeafs = getNumLeafs(myTree)
    depth = getTreeDepth(myTree)
    firstStr = list(myTree.keys())[0]
    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalw, plotTree.yOff)
    plotMidText(cntrPt, parentPt, nodeTxt)
    plotNode(firstStr, cntrPt, parentPt, decisionNode)
    secondDict = myTree[firstStr]
    plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalD
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            plotTree(secondDict[key], cntrPt, str(key))
        else:
            plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalw
            plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
            plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
    plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalD

def createPlot(inTree):
    fig = plt.figure(1, facecolor='white')
    fig.clf()
    axprops = dict(xticks=[], yticks=[])
    createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)
    plotTree.totalw = float(getNumLeafs(inTree))
    plotTree.totalD = float(getTreeDepth(inTree))
    plotTree.xOff = -0.5 / plotTree.totalw
    plotTree.yOff = 1.0
    plotTree(inTree, (0.5, 1.0), '')
    plt.show()

4.5

import numpy as np
import treePlotter
import sklearn.datasets as datasets
from sklearn.metrics import mean_squared_error
import sklearn.tree as tree
import graphviz

class DecisionTreeRegressor:
    def __init__(self, min_samples_split=3,min_samples_leaf=1,random_state=False):
        self.min_samples_split=min_samples_split
        self.min_samples_leaf=min_samples_leaf
        self.random=random_state
        self.tree = None

    def fit(self, X, y):
        D = {}
        D['X'] = X
        D['y'] = y
        A = np.arange(X.shape[1])
        self.tree = self.TreeGenerate(D, A)

    def predict(self, X):
        if self.tree is None:
            raise RuntimeError('cant predict before fit')
        y_pred = []
        for i in range(X.shape[0]):
            tree = self.tree
            x = X[i]
            while True:
                if not isinstance(tree, dict):
                    y_pred.append(tree)
                    break
                a = list(tree.keys())[0]
                tree = tree[a]
                if isinstance(tree, dict):
                    val = x[a]
                    split_val=float(list(tree.keys())[0][1:])
                    if val<=split_val:
                        tree=tree[list(tree.keys())[0]]
                    else:
                        tree=tree[list(tree.keys())[1]]
                else:
                    y_pred.append(tree)
                    break
        return np.array(y_pred)

    def TreeGenerate(self, D, A):
        X = D['X']
        y = D['y']
        if len(y)<=self.min_samples_split:
            return np.mean(y)
        split_j=None
        split_s=None
        min_val=1.e10
        select_A=A
        if self.random is True:
            d=len(A)
            select_A=np.random.choice(A,size=int(d//2),replace=False)
        for j in select_A:
            for s in np.unique(X[:,j]):
                left_indices=np.where(X[:,j]<=s)[0]
                right_indices=np.where(X[:,j]>s)[0]
                if len(left_indices)<self.min_samples_leaf or len(right_indices)<self.min_samples_leaf:
                    continue
                val=np.sum((y[left_indices]-np.mean(y[left_indices]))**2)+np.sum((y[right_indices]-np.mean(y[right_indices]))**2)
                if val<min_val:
                    split_j=j
                    split_s=s
                    min_val=val

        if split_j is None:
            return np.mean(y)
        tree = {split_j: {}}
        left_indices=np.where(X[:,split_j]<=split_s)[0]
        right_indices=np.where(X[:,split_j]>split_s)[0]
        D_left, D_right = {},{}
        D_left['X'],D_left['y'] = X[left_indices],y[left_indices]
        D_right['X'],D_right['y']=X[right_indices],y[right_indices]
        tree[split_j]['l'+str(split_s)]=self.TreeGenerate(D_left,A)
        tree[split_j]['r'+str(split_s)]=self.TreeGenerate(D_right,A)
        # 当前节点值
        tree[split_j]['val']=np.mean(y)
        return tree


if __name__=='__main__':
    breast_data = datasets.load_boston()
    X, y = breast_data.data, breast_data.target
    X_train, y_train = X[:200], y[:200]
    X_test, y_test = X[200:], y[200:]


    decisiontree_reg=DecisionTreeRegressor(min_samples_split=20,min_samples_leaf=5)
    decisiontree_reg.fit(X_train,y_train)
    print(decisiontree_reg.tree)
    treePlotter.createPlot(decisiontree_reg.tree)
    y_pred=decisiontree_reg.predict(X_test)
    print('tinyml mse:',mean_squared_error(y_test,y_pred))


    sklearn_reg=tree.DecisionTreeRegressor(min_samples_split=20,min_samples_leaf=5,random_state=False)
    sklearn_reg.fit(X_train,y_train)
    print(sklearn_reg.feature_importances_)
    sklearn_pred=sklearn_reg.predict(X_test)
    print('sklearn mse:',mean_squared_error(y_test,sklearn_pred))
    dot_data=tree.export_graphviz(sklearn_reg,out_file=None)
    graph=graphviz.Source(dot_data)

4.9

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

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

相关文章

数字IC后端实现之PR工具中如何避免出现一倍filler的缝隙?

在数字IC后端实现中&#xff0c;由于有的工艺foundary不提供Filler1&#xff0c;所以PR工具Innovus和ICC2在做标准单元摆放时需要避免出现两个标准单元之间的缝隙间距是Filler1。为了实现这个目的&#xff0c;我们需要给PR工具施加一些特殊的placement constraint&#xff08;典…

群控系统服务端开发模式-应用开发-前端短信配置开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下sms文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;"><el…

111.有效单词

class Solution {public boolean isValid(String word) {if(word.length()<3){return false;}int countV0,countC0;//分别统计原音和辅音for(int i0;i<word.length();i){if(Character.isLetterOrDigit(word.charAt(i))){if(word.charAt(i)a||word.charAt(i)e||word.charA…

python图像彩色数字化

效果展示&#xff1a; 目录结构&#xff1a; alphabets.py GENERAL {"simple": "%#*-:. ","complex": "$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_~<>i!lI;:,\"^. " } # Full list could be found here…

欧科云链研究院:比特币还能“燃”多久?

出品&#xff5c; OKG Research 作者&#xff5c;Hedy Bi 本周二&#xff0c;隔夜“特朗普交易” 的逆转趋势波及到比特币市场。比特币价格一度冲高至约99,000美元后迅速回落至93,000美元以下&#xff0c;最大跌幅超6%。这是由于有关以色列和黎巴嫩有望达成停火协议的传闻引发…

Unity之一键创建自定义Package包

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之一键创建自定义Package包 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01; …

E2、UML类图顺序图状态图实训

一、实验目的 在面向对象的设计里面&#xff0c;可维护性复用都是以面向对象设计原则为基础的&#xff0c;这些设计原则首先都是复用的原则&#xff0c;遵循这些设计原则可以有效地提高系统的复用性&#xff0c;同时提高系统的可维护性。在掌握面向对象七个设计原则基础上&…

【Java基础入门篇】一、变量、数据类型和运算符

Java基础入门篇 一、变量、数据类型和运算符 1.1 变量 计算机中的数据表示方式是&#xff1a;“二进制(0/1)”&#xff0c;但是同时也可以兼容其他进制&#xff0c;例如八进制、十进制、十六进制等。 Java变量的本质是&#xff1a;存储在固定空间的内容&#xff0c;变量名是…

前端学习笔记之文件下载(1.0)

因为要用到这样一个场景&#xff0c;需要下载系统的使用教程&#xff0c;所以在前端项目中就提供了一个能够下载系统教程的一个按钮&#xff0c;供使用者进行下载。 所以就试着写一下这个功能&#xff0c;以一个demo的形式进行演示&#xff0c;在学习的过程中也发现了中文路径…

【力扣】387.字符串中的第一个唯一字符

问题描述 思路解析 对于这种个数有限的问题&#xff0c;我的第一想法是使用桶排序来解决因为s中只有小写英文单词&#xff0c;所以我只需要一个26个单位的数组就好了通过 charAt() 来提取单个字符&#xff0c;然后通过 -‘a’ 来将其映射到 0~25&#xff0c;不然数组长度就被超…

数据采集中,除了IP池的IP被封,还有哪些常见问题?

在数据采集的过程中&#xff0c;代理IP池的使用无疑为我们打开了一扇通往信息宝库的大门。然而&#xff0c;除了IP被封禁这一常见问题外&#xff0c;还有许多其他问题可能影响数据采集的效果。本文将探讨在数据采集中&#xff0c;除了IP被封之外&#xff0c;还可能遇到的一些常…

【笔记】自动驾驶预测与决策规划_Part8_数据驱动的规划方法

文章目录 0. 前言1.生成模型1.1 Diffusion-ES1. Diffusion-ES算法介绍2. Diffusion-ES算法具体流程Diffusion Model 是什么&#xff1f;Diffusion-ES: Evolutionary StrategiesDiffusion-ES MethodDiffusion-ES Mapping Language instructions to reward functions with LLM pr…

里氏替换原则:Java面向对象设计的基石

在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;继承是一个强大的工具&#xff0c;它允许我们创建新的类&#xff08;子类&#xff09;来复用和扩展现有类&#xff08;父类&#xff09;的功能。然而&#xff0c;继承也带来了复杂性&#xff0c;特别是在确保子类能够正…

C++笔记之单例模式与静态方法的使用辨析及代码规范

C++笔记之单例模式与静态方法的使用辨析及代码规范 code review! 文章目录 C++笔记之单例模式与静态方法的使用辨析及代码规范一.示例代码二.讲解2.1.代码规范2.1.1.单例模式实现2.1.2.静态方法实现2.1.3.单例模式结合静态方法2.2.总结一.示例代码 // 使用 set 方法设置值(通…

18:(标准库)DMA二:DMA+串口收发数据

DMA串口收发数据 1、DMA串口发送数据2、DMA中断串口接收定长数据包3、串口空闲中断DMA接收不定长数据包4、串口空闲中断DMA接收不定长数据包DMA发送数据包 1、DMA串口发送数据 当串口的波特率大于115200时&#xff0c;可以通过DMA1进行数据搬运&#xff0c;以防止数据的丢失。如…

加载不同本地gltf模型,模型内容不更新的解决方案

相关链接 http://mars3d.cn/editor-vue.html?keyex_6_2_2&idlayer-graphic/draw/draw-model 问题内容 加载本地gltf模型的时候&#xff0c;不clear图层&#xff0c;再打开其他本地gltf&#xff0c;gltf的内容就不更新 重现步骤 进入官网示例&#xff0c;贴入以下代码…

可视化建模以及UML期末复习篇----相关软件安装

作为一个过来人&#xff0c;我的建议是别过来。 一、可视化建模 <1>定义: 官方&#xff1a;一种使用图形符号来表示系统结构和行为的建模技术。 我&#xff1a;其实说白了就是把工作流程用图形画出来。懂不&#xff1f; <2>作用: 提高理解和分析复杂系统的能力。促…

AI开发 - GPT之魂 用Python 演示chatGPT的自注意力机制 - 机器学习

自注意力机制&#xff08;Self-Attention&#xff09;就是让模型在处理每个词时&#xff0c;学会“关注重点”&#xff0c;而不是平均地对每个词一视同仁。这种机制让 GPT 能更聪明地理解句子的上下文和语义之间的关系。 自注意力机制是 GPT 的核心&#xff0c;它帮助模型在理解…

Web 表单开发全解析:从基础到高级掌握 HTML 表单设计

文章目录 前言一、什么是 Web 表单?二、表单元素详解总结前言 在现代 Web 开发中,表单 是用户与后端服务交互的重要桥梁。无论是用户登录、注册、搜索,还是提交反馈,表单都无处不在。在本文中,我们将从基础入手,全面解析表单的核心知识点,并通过示例带你轻松掌握表单开…

HCIE:详解OSPF,从基础到高级特性再到深入研究

目录 前言 一、OSPF协议基本原理 简介 基本原理 OSPF路由器类型 OSPF网络类型 OSPF报文类型和封装 OSPF邻居的建立的维护 DR和BDR的选举 伪节点 LSDB的更新 OSPF的配置 二、OSPF的高级特性 虚连接&#xff08;Virtual-Link&#xff09; OSPF的LSA和路由选择 OSPF…