当前位置:首页 > AI > 正文内容

根据信息增益和基尼指数的二叉决策树

邻居的猫1个月前 (12-09)AI1038
# coding: UTF-8
'''
依据信息增益和基尼指数的二叉决议计划树的完成。
该决议计划树能够用于分类问题,经过挑选适宜的特征来区分样本。
'''

from collections import Counter

class biTree_node:
    '''
    二叉树节点界说
    每个节点能够是叶子节点或内部节点。
    '''

    def __init__(self, f=-1, fvalue=None, leafLabel=None, l=None, r=None, splitInfo="gini"):
        '''
        类初始化函数
        para f: int, 切分的特征,用样本中的特征次第表明
        para fvalue: float or int, 切分特征的决议计划值
        para leafLabel: int, 叶节点的标签
        para l: biTree_node指针, 当时节点的左子树
        para r: biTree_node指针, 当时节点的右子树
        para splitInfo: string, 切分的规范, 可取值'infogain'和'gini', 别离表明信息增益和基尼指数。
        每个节点都保存了其用于区分的特征以及该特征的详细值,而且指向其左右子树。
        假如是叶子节点,则保存了该节点的标签。
        '''
        self.f = f  # 特征索引,即样本中的特征次第
        self.fvalue = fvalue  # 特征切分值,用于决议样本走向左子树仍是右子树
        self.leafLabel = leafLabel  # 假如是叶节点,则保存对应的类别标签
        self.l = l  # 左子树,指向当时节点的左子节点
        self.r = r  # 右子树,指向当时节点的右子节点
        self.splitInfo = splitInfo  # 切分规范,用于决议运用何种方法来核算最佳特征和特征值


def gini_index(samples):
    '''
    核算基尼指数。
    para samples: list, 样本列表,每个样本的最终一个元素是标签。
    return: float, 基尼指数。
    '''
    label_counts = sum_of_each_label(samples)
    total = len(samples)
    gini = 1.0
    for label in label_counts:
        prob = label_counts[label] / total
        gini -= prob ** 2
    return gini

def info_entropy(samples):
    '''
    核算信息熵。
    para samples: list, 样本列表,每个样本的最终一个元素是标签。
    return: float, 信息熵。
    '''
    label_counts = sum_of_each_label(samples)
    total = len(samples)
    entropy = 0.0
    for label in label_counts:
        prob = label_counts[label] / total
        entropy -= prob * (prob * 3.321928094887362)  # 以2为底的对数
    return entropy

def split_samples(samples, feature, value):
    '''
    依据特征和值切割样本集。
    para samples: list, 样本列表。
    para feature: int, 特征索引。
    para value: float or int, 特征值。
    return: tuple, 两个列表,别离为左子集和右子集。
    '''
    left = [sample for sample in samples if sample[feature] < value]
    right = [sample for sample in samples if sample[feature] >= value]
    return left, right

def sum_of_each_label(samples):
    '''
    核算样本中各类别标签的散布。
    para samples: list, 样本列表。
    return: dict, 标签及其呈现次数的字典。
    '''
    labels = [sample[-1] for sample in samples]
    return Counter(labels)

def build_biTree(samples, splitInfo="gini"):
    '''构建二叉决议计划树
    para samples: list, 样本的列表,每样本也是一个列表,样本的最终一项为标签,其它项为特征。
    para splitInfo: string, 切分的规范,可取值'infogain'和'gini', 别离表明信息增益和基尼指数。
    return: biTree_node, 二叉决议计划树的根节点。
    该函数递归地构建决议计划树,每次挑选一个最佳特征和其值来切分样本集,直到无法有用切分停止。
    '''
    # 假如没有样本,则返回空节点
    if len(samples) == 0:
        return biTree_node()

    # 查看切分规范是否合法
    if splitInfo != "gini" and splitInfo != "infogain":
        return biTree_node()

    bestInfo = 0.0  # 最佳信息增益或基尼指数减少数
    bestF = None  # 最佳特征
    bestFvalue = None  # 最佳特征的切分值
    bestlson = None  # 左子树
    bestrson = None  # 右子树

    # 核算当时调集的基尼指数或信息熵
    curInfo = gini_index(samples) if splitInfo == "gini" else info_entropy(samples)

    sumOfFeatures = len(samples[0]) - 1  # 样本中特征的个数
    for f in range(0, sumOfFeatures):  # 遍历每个特征
        featureValues = [sample[f] for sample in samples]  # 提取特征值
        for fvalue in featureValues:  # 遍历当时特征的每个值
            lson, rson = split_samples(samples, f, fvalue)  # 依据特征及其值切分样本
            # 核算割裂后两个调集的基尼指数或信息熵
            if splitInfo == "gini":
                info = (gini_index(lson) * len(lson) + gini_index(rson) * len(rson)) / len(samples)
            else:
                info = (info_entropy(lson) * len(lson) + info_entropy(rson) * len(rson)) / len(samples)

            gain = curInfo - info  # 核算增益或基尼指数的减少数

            # 找到最佳特征及其切分值
            if gain > bestInfo and len(lson) > 0 and len(rson) > 0:
                bestInfo = gain
                bestF = f
                bestFvalue = fvalue
                bestlson = lson
                bestrson = rson

    # 假如找到了最佳切分
    if bestInfo > 0.0:
        l = build_biTree(bestlson, splitInfo)  # 递归构建左子树
        r = build_biTree(bestrson, splitInfo)  # 递归构建右子树
        return biTree_node(f=bestF, fvalue=bestFvalue, l=l, r=r, splitInfo=splitInfo)
    else:
        # 假如没有有用切分,则生成叶节点
        label_counts = sum_of_each_label(samples)
        return biTree_node(leafLabel=max(label_counts, key=label_counts.get), splitInfo=splitInfo)


def predict(sample, tree):
    '''
    对给定样本进行猜测
    para sample: list, 需求猜测的样本
    para tree: biTree_node, 构建好的分类树
    return: int, 猜测样本所属的类别
    '''
    if tree.leafLabel is not None:  # 假如当时节点是叶节点
        return tree.leafLabel
    else:
        # 不然依据特征值挑选子树
        sampleValue = sample[tree.f]
        branch = tree.r if sampleValue >= tree.fvalue else tree.l
        return predict(sample, branch)  # 递归下去


def print_tree(tree, level='0'):
    '''简略打印树的结构
    para tree: biTree_node, 树的根节点
    para level: str, 当时节点在树中的深度,0表明根,0L表明左子节点,0R表明右子节点
    '''
    if tree.leafLabel is not None:  # 假如是叶节点
        print('*' + level + '-' + str(tree.leafLabel))  # 打印标签
    else:
        print('+' + level + '-' + str(tree.f) + '-' + str(tree.fvalue))  # 打印特征索引及切分值
        print_tree(tree.l, level + 'L')  # 打印左子树
        print_tree(tree.r, level + 'R')  # 打印右子树


if __name__ == "__main__":

    # 示例数据集:或人相亲的数据
    blind_date = [[35, 176, 0, 20000, 0],
                  [28, 178, 1, 10000, 1],
                  [26, 172, 0, 25000, 0],
                  [29, 173, 2, 20000, 1],
                  [28, 174, 0, 15000, 1]]

    print("信息增益二叉树:")
    tree = build_biTree(blind_date, splitInfo="infogain")  # 构建信息增益的二叉树
    print_tree(tree)  # 打印树结构
    print('信息增益二叉树对样本进行猜测的成果:')

    test_sample = [[24, 178, 2, 17000],
                   [27, 176, 0, 25000],
                   [27, 176, 0, 10000]]

    # 对测验样本进行猜测
    for x in test_sample:
        print(predict(x, tree))

    print("基尼指数二叉树:")
    tree = build_biTree(blind_date, splitInfo="gini")  # 构建基尼指数的二叉树
    print_tree(tree)  # 打印树结构
    print('基尼指数二叉树对样本进行猜测的成果:')

    # 再次对测验样本进行猜测
    for x in test_sample:
        print(predict(x, tree))  # 猜测并打印成果

输出成果:


扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=378

标签: 人工智能
分享给朋友:

“根据信息增益和基尼指数的二叉决策树” 的相关文章

Ollma本地布置Qwen2.5 14B(不运用docker)

Ollma本地布置Qwen2.5 14B(不运用docker)

布置机器硬件状况:内存 :32GB显卡 :3060 为什么不运用docker: 1.网上教程大多以docker为主 2.装置docker的时刻太长,在等候的时分趁便测验一下不必docker的布置 1.装置Ollama 下载地址:https://ollama.com/ 下载好之后默许装置即可。 Oll...

激情综合色ai,激情与综合色的碰撞

激情综合色ai,激情与综合色的碰撞

AI换脸技术:激情与综合色的碰撞一、AI换脸技术的原理与优势AI换脸技术,又称“deepfakes”,是一种基于深度学习算法的视频处理技术。它通过分析源视频和目标视频中的面部特征,实现人脸的实时替换或静态替换。相较于传统的视频处理技术,AI换脸具有以下优势: 高精度:AI换脸技术能够实现高度逼真的...

机器学习算法决策树

机器学习算法决策树

决策树(Decision Tree)是一种非常流行的机器学习算法,它通过一系列规则对数据进行分类或回归。决策树是一种监督学习算法,这意味着它需要训练数据来学习如何对数据进行分类或回归。决策树的工作原理如下:1. 首先,选择一个特征作为根节点,该特征将数据分为两个或多个子集。2. 对每个子集重复上述过...

ai换头,突破传统界限,引领视觉革命

ai换头,突破传统界限,引领视觉革命

AI换头技术,通常指的是利用人工智能技术,尤其是深度学习技术,将一个人的头部替换到另一张照片或视频中的人的头部上。这种技术通常涉及到图像识别、图像处理和生成模型等技术。AI换头技术的应用非常广泛,例如在娱乐、影视制作、游戏开发等领域,都可以看到它的身影。通过这种技术,可以创造出更加真实、生动的角色形...

机器学习数据湖,定义与重要性

机器学习数据湖,定义与重要性

机器学习数据湖是一个集中存储、管理和处理大量数据的系统,用于支持机器学习模型的训练和部署。它通常包括以下关键组件:1. 数据存储:数据湖支持多种数据格式的存储,包括结构化、半结构化和非结构化数据。数据可以存储在Hadoop分布式文件系统(HDFS)、Amazon S3、Azure Data Lake...

ai软件有哪些,2024年必备的智能助手

ai软件有哪些,2024年必备的智能助手

1. 机器学习平台和框架: TensorFlow PyTorch scikitlearn Keras MXNet Caffe Theano2. 自然语言处理(NLP)工具: spaCy NLTK Stanford NLP Gensi...