决策树(Decison Tree)—有监督学习方法、概率模型、生成模型、非线性模型、非参数化模型、批量学习

定义

ID3算法

输入:训练数据集(T= { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) } \left\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\right\} {(x1,y1),(x2,y2),⋯,(xN,yN)}),特征集A阀值 ε \varepsilon ε

输出:决策树T

(1)若D中所有实例属于同一类 C k C_k Ck,则T为单节点树,并将 C k C_k Ck作为该节点的类标记,返回T;

(2)若A= ∅ \varnothing ∅,则T为单节点树,并将D中实例数最大的类 C k C_k Ck作为该节点的类标记,返回T;

(3)否则,需要计算A中各特征对D的信息增益,选择信息增益最大的特征 A g A_g Ag;

(4)如果 A g A_g Ag的信息增益小于阀值 ε \varepsilon ε,则置T为单节点树,并将D中实例数最大的类 C k C_k Ck作为该节点的类标记,返回T;

(5)否则,对 A g A_g Ag的每一可能值 a i a_i ai,依 A g = a i A_g=a_i Ag=ai将D分割为若干非空子集 D i D_i Di,将 D i D_i Di中实例最大的类作为标记,构建子节点,由节点及其子节点构成树T,返回T;

(6)对第i个字节点,以 D i D_i Di为训练集,以 A − A g A-{A_g} A−Ag为特征集,递归地调用步骤(1)~(5),得到子树 T i T_i Ti,返回 T i T_i Ti

输入空间

T= { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ... , ( x N , y N ) } \left\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)\right\} {(x1,y1),(x2,y2),...,(xN,yN)}

python 复制代码
import numpy as np

def loadData(fileName,lines=60000):
    '''
    加载文件
    :param fileName:要加载的文件路径 下载地址:https://download.csdn.net/download/nanxiaotao/89720991)
    :return: 数据集和标签集
    '''
    #存放数据及标记
    dataArr = []; labelArr = []
    #读取文件
    fr = open(fileName)
    #遍历文件中的每一行
    for line in fr.readlines():
        curLine = line.strip().split(',')
        dataArr.append([int(int(num) > 128) for num in curLine[1:]])
        labelArr.append(int(curLine[0]))
    #返回数据集和标记
    return dataArr, labelArr
python 复制代码
# 获取训练集
trainDataList, trainLabelList = loadData('../Mnist/mnist_train.csv')
python 复制代码
np.shape(trainDataList)
python 复制代码
Epsilon = 0.1

特征空间(Feature Space)

python 复制代码
trainDataList[0][0:784]

统计学习方法

模型

决策树 T T T

策略

m a x ( g ( D , A ) ) max(g(D,A)) max(g(D,A))

算法

H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ l o g 2 ∣ C k ∣ ∣ D ∣ H(D)=-\sum_{k=1}^K \dfrac{ \left| C_k \right| }{ \left| D \right|}log_2 \dfrac{ \left| C_k \right| }{ \left| D \right|} H(D)=−∑k=1K∣D∣∣Ck∣log2∣D∣∣Ck∣

python 复制代码
def calc_H_D(trainLabelArr):
    '''
    计算数据集D的经验熵
    :param trainLabelArr:当前数据集的标签集
    :return: 经验熵
    '''
    #初始化为0
    H_D = 0
    trainLabelSet = set([label for label in trainLabelArr])
    #遍历每一个出现过的标签
    for i in trainLabelSet:
        p = trainLabelArr[trainLabelArr == i].size / trainLabelArr.size
        #对经验熵的每一项累加求和
        H_D += -1 * p * np.log2(p)
    #返回经验熵
    return H_D

H ( D ∣ A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) H(D|A)=\sum_{i=1}^n \dfrac{ \left| D_i \right| }{ \left| D \right|}H(D_i) H(D∣A)=∑i=1n∣D∣∣Di∣H(Di)

python 复制代码
def calcH_D_A(trainDataArr_DevFeature, trainLabelArr):
    '''
    计算经验条件熵
    :param trainDataArr_DevFeature:切割后只有feature那列数据的数组
    :param trainLabelArr: 标签集数组
    :return: 经验条件熵
    '''
    #初始为0
    H_D_A = 0
    #在featue那列放入集合中,是为了根据集合中的数目知道该feature目前可取值数目是多少
    trainDataSet = set([label for label in trainDataArr_DevFeature])

    #对于每一个特征取值遍历计算条件经验熵的每一项
    for i in trainDataSet:
        #计算H(D|A)
        #trainDataArr_DevFeature[trainDataArr_DevFeature == i].size / trainDataArr_DevFeature.size:|Di| / |D|
        #calc_H_D(trainLabelArr[trainDataArr_DevFeature == i]):H(Di)
        H_D_A += trainDataArr_DevFeature[trainDataArr_DevFeature == i].size / trainDataArr_DevFeature.size \
                * calc_H_D(trainLabelArr[trainDataArr_DevFeature == i])
    #返回得出的条件经验熵
    return H_D_A

g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)=H(D)-H(D|A) g(D,A)=H(D)−H(D∣A)

m a x ( g ( D , A ) ) max(g(D,A)) max(g(D,A))

python 复制代码
def majorClass(labelArr):
    '''
    找到当前标签集中占数目最大的标签
    :param labelArr: 标签集
    :return: 最大的标签
    '''
    #建立字典,用于不同类别的标签技术
    classDict = {}
    #遍历所有标签
    for i in range(len(labelArr)):
        if labelArr[i] in classDict.keys():
            # 若在字典中存在该标签,则直接加1
            classDict[labelArr[i]] += 1
        else:
            #若无该标签,设初值为1,表示出现了1次了
            classDict[labelArr[i]] = 1
    #对字典依据值进行降序排序
    classSort = sorted(classDict.items(), key=lambda x: x[1], reverse=True)
    #返回最大一项的标签,即占数目最多的标签
    return classSort[0][0]
python 复制代码
def getSubDataArr(trainDataArr, trainLabelArr, A, a):
    '''
    更新数据集和标签集
    :param trainDataArr:要更新的数据集
    :param trainLabelArr: 要更新的标签集
    :param A: 要去除的特征索引
    :param a: 当data[A]== a时,说明该行样本时要保留的
    :return: 新的数据集和标签集
    '''
    #返回的数据集
    retDataArr = []
    #返回的标签集
    retLabelArr = []
    #对当前数据的每一个样本进行遍历
    for i in range(len(trainDataArr)):
        #如果当前样本的特征为指定特征值a
        if trainDataArr[i][A] == a:
            #那么将该样本的第A个特征切割掉,放入返回的数据集中
            retDataArr.append(trainDataArr[i][0:A] + trainDataArr[i][A+1:])
            #将该样本的标签放入返回标签集中
            retLabelArr.append(trainLabelArr[i])
    #返回新的数据集和标签集
    return retDataArr, retLabelArr
python 复制代码
def calcBestFeature(trainDataList, trainLabelList):
    '''
    计算信息增益最大的特征
    :param train_dataSet: 数据集
    :return: 信息增益最大的特征及最大信息增益值
    '''
    #将数据集和标签集转换为数组形式
    trainDataArr = np.array(trainDataList)
    trainLabelArr = np.array(trainLabelList)

    #获取当前特征数目,也就是数据集的横轴大小
    featureNum = trainDataArr.shape[1]

    #初始化最大信息增益
    maxG_D_A = -1
    #初始化最大信息增益的特征
    maxFeature = -1
    
    #1.计算数据集D的经验熵H(D)
    H_D = calc_H_D(trainLabelArr)
    #对每一个特征进行遍历计算
    for feature in range(featureNum):
        trainDataArr_DevideByFeature = np.array(trainDataArr[:, feature].flat)
        #计算信息增益
        G_D_A = H_D - calcH_D_A(trainDataArr_DevideByFeature, trainLabelArr)
        #不断更新最大的信息增益以及对应的feature
        if G_D_A > maxG_D_A:
            maxG_D_A = G_D_A
            maxFeature = feature
    return maxFeature, maxG_D_A

创建决策树 T T T

python 复制代码
def createTree(*dataSet):
    '''
    递归创建决策树
    :param dataSet
    :return:新的子节点或该叶子节点的值
    '''
    trainDataList = dataSet[0][0]
    trainLabelList = dataSet[0][1]

    classDict = {i for i in trainLabelList}

    if len(classDict) == 1:
        return trainLabelList[0]

    if len(trainDataList[0]) == 0:
        #返回当前标签集中占数目最大的标签
        return majorClass(trainLabelList)

    Ag, EpsilonGet = calcBestFeature(trainDataList, trainLabelList)

    #如果Ag的信息增益比小于阈值Epsilon,则置T为单节点树,并将D中实例数最大的类Ck
    #作为该节点的类,返回T
    if EpsilonGet < Epsilon:
        return majorClass(trainLabelList)

    #否则,对Ag的每一可能值ai,依Ag=ai将D分割为若干非空子集Di,将Di中实例数最大的
    # 类作为标记,构建子节点,由节点及其子节点构成树T,返回T
    treeDict = {Ag:{}}
    #特征值为0时,进入0分支
    #getSubDataArr(trainDataList, trainLabelList, Ag, 0):在当前数据集中切割当前feature,返回新的数据集和标签集
    treeDict[Ag][0] = createTree(getSubDataArr(trainDataList, trainLabelList, Ag, 0))
    treeDict[Ag][1] = createTree(getSubDataArr(trainDataList, trainLabelList, Ag, 1))

    return treeDict
python 复制代码
# 获取测试集
testDataList, testLabelList = loadData('../Mnist/mnist_test.csv')

#创建决策树
tree = createTree((trainDataList, trainLabelList))
print('tree is:', tree)

假设空间(Hypothesis Space)

{ f ∣ f ( x ) = m a x ( g ( D , A ) ) } \left\{f|f(x) = max(g(D,A)) \right\} {f∣f(x)=max(g(D,A))}

输出空间

y {\tt y} y = { c 1 , c 2 , ⋯   , c k } = \{c_1,c_2,\cdots,c_k \} ={c1,c2,⋯,ck}

模型评估

训练误差(Training Error)

python 复制代码
testDataList, testLabelList = loadData('../Mnist/mnist_test.csv')
python 复制代码
np.shape(testDataList)
python 复制代码
def predict(testDataList, tree):
    '''
    预测标签
    :param testDataList:样本
    :param tree: 决策树
    :return: 预测结果
    '''

    while True:
        (key, value), = tree.items()
        #如果当前的value是字典,说明还需要遍历下去
        if type(tree[key]).__name__ == 'dict':
            dataVal = testDataList[key]
            del testDataList[key]
            tree = value[dataVal]
            if type(tree).__name__ == 'int':
                #返回该节点值,也就是分类值
                return tree
        else:
            #如果当前value不是字典,那就返回分类值
            return value
python 复制代码
def model_test(testDataList, testLabelList, tree):
    '''
    测试准确率
    :param testDataList:待测试数据集
    :param testLabelList: 待测试标签集
    :param tree: 训练集生成的树
    :return: 准确率
    '''
    errorCnt = 0
    for i in range(len(testDataList)):
        if testLabelList[i] != predict(testDataList[i], tree):
            errorCnt += 1
    #返回准确率
    return 1 - errorCnt / len(testDataList)
python 复制代码
accur = model_test(testDataList, testLabelList, tree)
print('the accur is:', accur)

测试误差(Test Error)

模型选择

过拟合

正则化

泛化能力

相关推荐
泰迪智能科技012 小时前
高校深度学习视觉应用平台产品介绍
人工智能·深度学习
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
Eric.Lee20213 小时前
Paddle OCR 中英文检测识别 - python 实现
人工智能·opencv·计算机视觉·ocr检测
cd_farsight3 小时前
nlp初学者怎么入门?需要学习哪些?
人工智能·自然语言处理
AI明说3 小时前
评估大语言模型在药物基因组学问答任务中的表现:PGxQA
人工智能·语言模型·自然语言处理·数智药师·数智药学
Focus_Liu3 小时前
NLP-UIE(Universal Information Extraction)
人工智能·自然语言处理
PowerBI学谦3 小时前
使用copilot轻松将电子邮件转为高效会议
人工智能·copilot
audyxiao0013 小时前
AI一周重要会议和活动概览
人工智能·计算机视觉·数据挖掘·多模态
Jeremy_lf4 小时前
【生成模型之三】ControlNet & Latent Diffusion Models论文详解
人工智能·深度学习·stable diffusion·aigc·扩散模型