ID3算法原理及Python实践

2024-09-01 01:36
文章标签 python 算法 实践 原理 id3

本文主要是介绍ID3算法原理及Python实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、ID3算法原理

ID3(Iterative Dichotomiser 3)算法是一种用于分类和预测的决策树学习算法,由Ross Quinlan在1986年提出。该算法的核心原理基于信息论中的信息增益概念,通过选择信息增益最大的属性来构建决策树。以下是ID3算法原理的详细解释:

1. 信息熵与信息增益

信息熵:信息熵是度量数据集中不确定性的一个指标。在ID3算法中,信息熵用于表示数据集在分类前的混乱程度。信息熵的值越大,表示数据集的不确定性越高,即数据集中的样本类别越分散。

信息增益:信息增益是指在选择某个属性进行划分后,数据集不确定性的减少程度。具体来说,信息增益是划分前数据集的信息熵与划分后所有子数据集加权平均信息熵之差。信息增益越大,表示该属性对于分类的贡献越大。

2. ID3算法步骤

ID3算法通过以下步骤构建决策树:

计算信息熵:首先计算整个数据集的信息熵,这表示了数据集在分类前的混乱程度。

选择最优属性:对于数据集中的每个属性,计算其信息增益。选择信息增益最大的属性作为当前节点的最优划分属性。

划分数据集:根据最优属性的不同取值,将数据集划分为若干个子集。

递归构建决策树:对每个子集重复步骤1至3,直到满足停止条件(如所有子集都属于同一类别或没有更多属性可供划分)。

构建决策树:根据选择的属性和划分结果构建决策树,每个节点表示一个属性,每个分支表示一个属性值,每个叶节点表示一个类别。

3. 优缺点

优点:

原理简单,易于理解。

对于类别较少的分类问题效果较好。

生成的决策树规模较小,查询速度快。

缺点:

只能处理离散型数据,对于连续型数据需要预先进行离散化处理。

倾向于选择取值较多的属性作为划分属性,这可能导致决策树过于复杂,出现“过拟合”现象。

没有考虑缺失值处理,对于含有缺失值的数据集需要预处理。

4. 应用场景

ID3算法适用于数据集属性较少,数据类型为离散型的分类问题。它常被用于解决文本分类、垃圾邮件过滤、医学诊断、金融风险评估等问题。

总的来说,ID3算法是一种经典的决策树学习算法,通过信息增益来选择最优属性进行数据集划分,从而构建出用于分类和预测的决策树。

二、ID3算法的Python实践

在Python中实现ID3算法,我们首先需要定义几个关键的功能:计算信息熵、计算信息增益,以及根据这些概念来构建决策树。以下是一个简化的ID3算法实现,假设我们只处理离散特征且数据已经是清洁的(没有缺失值)。

首先,我们需要安装或确认安装了numpy库,虽然在这个简单实现中我们可能不直接使用它,但它对于更复杂的数据处理任务是有用的。

下面是一个简单的ID3算法实现:

from collections import Counter

from math import log2

def calc_entropy(target_counts):

    """计算信息熵"""

    total = sum(target_counts.values())

    entropy = 0.0

    for count in target_counts.values():

        p = count / total

        if p > 0:

            entropy -= p * log2(p)

    return entropy

def split_dataset(dataset, axis, value):

    """根据给定特征和值分割数据集"""

    ret_dataset = []

    for feature_vec in dataset:

        if feature_vec[axis] == value:

            reduced_feature_vec = feature_vec[:axis]

            reduced_feature_vec.extend(feature_vec[axis+1:])

            ret_dataset.append(reduced_feature_vec)

    return ret_dataset

def choose_best_feature_to_split(dataset):

    """选择最佳特征进行分割"""

    num_features = len(dataset[0]) - 1  # 假设最后一列是目标变量

    base_entropy = calc_entropy(Counter(row[-1] for row in dataset))

    best_info_gain = 0.0

    best_feature = -1

   

    for i in range(num_features):

        feat_values = [example[i] for example in dataset]

        unique_vals = set(feat_values)

        new_entropy = 0.0

       

        for value in unique_vals:

            sub_dataset = split_dataset(dataset, i, value)

            prob = len(sub_dataset) / float(len(dataset))

            new_entropy += prob * calc_entropy(Counter(row[-1] for row in sub_dataset))

       

        info_gain = base_entropy - new_entropy

       

        if (info_gain > best_info_gain):

            best_info_gain = info_gain

            best_feature = i

   

    return best_feature

def create_tree(dataset, labels):

    """创建决策树"""

    class_list = [row[-1] for row in dataset]

    if class_list.count(class_list[0]) == len(class_list):

        return class_list[0]  # 完美分类,所有项属于同一类

   

    if len(dataset[0]) == 1:  # 没有更多特征

        return Counter(class_list).most_common(1)[0][0]

   

    best_feat = choose_best_feature_to_split(dataset)

    best_feat_label = labels[best_feat]

    my_tree = {best_feat_label:{}}

    del(labels[best_feat])

    feat_values = [example[best_feat] for example in dataset]

    unique_vals = set(feat_values)

   

    for value in unique_vals:

        sub_labels = labels[:]

        my_tree[best_feat_label][value] = create_tree(split_dataset(dataset, best_feat, value), sub_labels)

   

    return my_tree

# 示例用法

# 假设有这样一个数据集

# 注意:这个数据集是简化的,实际应用中数据集会更加复杂

data = [

    ['no surfacing', 1, 'flippers'],

    ['no surfacing', 1, 'flippers'],

    ['surfacing', 1, 'flippers'],

    ['no surfacing', 0, 'flippers'],

    ['no surfacing', 1, 'no flippers']

]

labels = ['surfacing', 'fish', 'flippers']

# 注意:我们需要将数据集中的目标变量(在这个例子中是'fish')转换为整数值

# 为了简化,我们假设'1'代表'yes'(比如是鱼),'0'代表'no'(比如不是鱼)

# 但在这个例子中,我们保持原始值

# 构建决策树

tree =继续构建决策树的示例,我们不需要修改`data`中的数据来将目标变量转换为整数值,因为在这个例子中我们直接使用了字符串`'1'`和`'0'`来表示分类结果。但是,在更复杂的应用中,将目标变量编码为整数可能会更方便处理。

现在,我们将使用之前定义的函数来构建决策树:

```python

# 构建决策树

tree = create_tree(data, labels)

# 打印决策树

def print_tree(tree, indent=''):

    for feat, sub_tree in tree.items():

        print('{}{} ->'.format(indent, feat))

        if isinstance(sub_tree, dict):

            for next_feat, next_tree in sub_tree.items():

                print_tree(next_tree, indent + '  ')

        else:

            print('{}{} {}'.format(indent + '  ', next_feat if isinstance(sub_tree, list) else '', sub_tree))

print_tree(tree)

但是,请注意,由于我们的示例数据集非常小且不完全代表真实世界的复杂性,因此生成的决策树可能不是很有用或直观。此外,由于我们没有将目标变量'1'和'0'转换为整数,create_tree函数中的某些部分可能需要调整才能正确处理字符串类标签。

不过,为了保持示例的简单性,我们将假设一切工作正常,并打印出生成的决策树。

然而,在实际应用中,您可能需要处理更复杂的情况,如处理缺失值、连续特征、不平衡的数据集等。此外,对于大型数据集,ID3算法可能不是最高效的选择,因为它可能会倾向于生成非常深的树,这可能导致过拟合。在这种情况下,您可能需要考虑使用C4.5(ID3的改进版本)或CART等其他决策树算法。

另外,请注意,上面的create_tree函数中的sub_tree[value] = create_tree(...)行假设了value是唯一的,这在实际应用中可能不是总是成立的。对于具有多个相同value的情况,您可能需要稍微修改该函数以确保它正确处理这些情况(尽管在这个简单的示例中它可能仍然可以工作)。

最后,请确保您的数据集是正确格式化的,并且labels列表中的标签与数据集中的特征顺序相匹配。如果数据集很大或很复杂,您可能需要编写额外的代码来预处理数据。

这篇关于ID3算法原理及Python实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125572

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal