提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、算法相关介绍

    • 1.简介
    • 2.决策树直观表示
    • 3.ID3算法核心思想(含流程图)
  • 二、实例算法实现演示
    • 1.问题描述
    • 2.代码结构及其描述
    • 3.完整代码
  • 三、ID3算法讨论与分析
    • 1.优势
    • 2.缺点

一、算法相关介绍

     1.简介

决策树学习是应用最广的归纳推理算法之一。它是一种逼近离散函数的方法,且对噪声数据有很好的鲁棒性,能够学习析取表达式。相关算法包多为以ID3思想为内核。

决策树学习方法搜索完整表示的假设空间,从而避免了受限假设空间的不足。决策树学习的归纳偏置是优先选择较小的树。

     2.决策树直观表示

决策树通过把实例从根结点排列到某个叶子结点来分类实例,叶子结点即为实例所属的分类。树上的每一个结点指定了对实例的某个属性的测试,并且该结点的每一个后继分支对应于该属性的一个可能值。分类实例的方法是从这棵树的根结点开始,测试这个结点指定的属性,然后按照给定实例的该属性值对应的树枝向下移动。这个过程再在以新结点为根的子树上重复。

其本质是多个if-then有序规则的树状罗列,下图为教材中一棵典型的学习到的决策树:

   3.ID3算法核心思想

基本的 ID3 算法通过自顶向下构造决策树来进行学习。构造过程是从“哪一个属性将在树的根结点被测试?”这个问题开始的。然后为根结点属性的每个可能值产生一个分支,并把训练样例排列到适当的分支(也就是,样例的该属性值对应的分支)之下。然后重复整个过程,用每个分支结点关联的训练样例来选取在该点被测试的最佳属性。同时此贪婪搜索从不回溯重新考虑先前的选择。

故ID3算法主要围绕3个问题的解决来进行:

  • 如何选择最优属性
  • 结点数据如何拆分
  • 子树何时停止增长

3.1属性选择依据

在为树节点选择测试属性时,需要选择最有助于分类实例的属性(也即特征)。ID3定义了一个统计属性“信息增益”,用来衡量给定属性区分当前训练样例集的能力,在其增长树的每一步使用该信息增益标准从侯选属性集中选择属性。

3.1.1用熵度量样例的均一性的依据

3.1.2信息增益度量期望的熵降低

3.2结点数据拆分

依据所选特征(属性),依照不同的特征值将数据进行划分

3.3子树停止增长条件

满足以下条件之一:

  • 所有的属性均已被这条路径包括
  • 与该结点关联的所有样例具有相同的目标特征值(也即熵值为0)

3.4 ID3算法流程图

二、实例算法实现演示

1.问题描述

通过outlook、temperature,humidity,wind这四个特征值来判定该天(day)是否适宜打网球(playtennis)。数据以表格形式存于train_data.csv文件中。数据如下图所示。

2.代码结构及其描述

  • Outlook:sunny-1,rain-2,overcast-3
  • Temperature:hot-1,mild-2,cool-3
  • Humidity:high-1,normal-2
  • Wind:true-1,false-2

1.主要函数模块:

  • createDataset(file):将来自csv文件的数据集进行映射转换
  • majority_eigen(data_ls,eigen_idx): 获得“最通常值”
  • handle_incomplete(data_ls,incomplete_ls):对初始化的训练集进行不完整属性值填充(使用“最通常值”进行填充)
  • cal_gain(node_cls_ls):计算结点集信息增益(由于在选择测试结点时,依据公式Gain(A)=I(p,n)-E(A),知Gain与E(A)负相关,故只计算熵值)
  • choose_best_eigen(node_data,eigen_ls):求取最佳分类特征
  • create_tree(data,eigen_ls):构造决策树
  • make_predict(decision_tree,test_data):根据学习好的决策树对给定数据进行目标特征预测

2.函数调用关系图示如下:

3.完整代码

from math import log
import csv
import numpy as np#自动获取函数调用图示
from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput
from pycallgraph import Config
from pycallgraph import GlobbingFilter
config = Config()#不完整属性值先置0
default_fill=0 #特征列表
eigens=['outlook','temperature','humidity','wind','class',
]#属性值与代码映射字典
eigen_affine=[
{"sunny":1,"rain":2,"overcast":3,
},
{"hot":1,"mild":2,"cool":3,
},
{"high":1,"normal":2,
},
{"true":1,"false":2,
},
{"pos":"positive","neg":"negtive",
}
]#将来自csv文件的数据集进行映射转换
def createDataset(file):with open(file,encoding='utf-8') as f:f_handle=csv.reader(f)eigens=next(f_handle)data_ls=[]incomplete_ls=[]for row_idx,row in enumerate(f_handle):row_ls =[]for idx,value in enumerate(row):# print(idx,value)if value=="":row_ls.append(default_fill)incomplete_ls.append(row_idx)else:row_ls.append(eigen_affine[idx][value])data_ls.append(row_ls)return data_ls,incomplete_ls#对初始化的训练集进行不完整属性值填充(使用“最通常值”进行填充)
def handle_incomplete(data_ls,incomplete_ls):for idx in incomplete_ls:for eigen_idx,eigen in enumerate(data_ls[idx]):if eigen==0:value_dict={}for data_idx in range(idx):eigen_val=data_ls[data_idx][eigen_idx]if  eigen_val in value_dict:value_dict[eigen_val]+=1else:value_dict[eigen_val]=1count_ls=[]for val_count in value_dict.values():count_ls.append(val_count)data_ls[idx][eigen_idx]=max(count_ls)return data_ls#计算结点集信息增益
#由于在选择测试结点时,依据公式Gain(A)=I(p,n)-E(A),
#知Gain与E(A)负相关,故只计算熵值
def cal_gain(node_cls_ls):# cls_count=[0 for i in len(eigen_affine[-1])]cls_dict={}for cls_val in set(node_cls_ls):cls_dict[cls_val]=node_cls_ls.count(cls_val)entropy=0for cls_count in cls_dict.values():entropy=(-(cls_count/len(node_cls_ls))*log(cls_count/len(node_cls_ls)))return entropy#eigen_ls 特征序号列表
#返回最佳特征序号
def choose_best_eigen(node_data,eigen_ls):node_cls_ls=[data[-1] for data in node_data]# base_entropy=cal_entropy(node_cls_ls)best_gain=float('-inf')best_eigen=eigen_ls[0]for eigen in eigen_ls:cls_dict={}for data in node_data:if data[eigen] in cls_dict.keys():cls_dict[eigen].append(data[-1])else:cls_dict[eigen]=[]eigen_entropy = 0for data_ls in cls_dict.values():eigen_entropy+=cal_gain(data_ls)if eigen_entropy<best_gain:best_gain=eigen_entropybest_eigen=eigenreturn best_eigen#获得“最通常值”
def majority_eigen(data_ls,eigen_idx):eigen_dict={}for data in data_ls:if data[eigen_idx] in eigen_dict:eigen_dict[data[eigen_idx]]+=1else:eigen_dict[data[eigen_idx]]=1eigen_cnt=[count for count in eigen_dict.values()]return max(eigen_cnt)#eigen_ls
#特征idx列表
def create_tree(data,eigen_ls):#处理边界cls_ls=[data[-1] for data in data]if  len(set(cls_ls)) ==1:return cls_ls[0]if  len(eigen_ls)==0:return majority_eigen(data,-1)best_eigen_idx=choose_best_eigen(data,eigen_ls)best_eigen=eigens[best_eigen_idx]print(f'current step the beset eigen choosed is : {best_eigen}')decision_tree={best_eigen:{}}#根据测试属性划分子集data_dict={}# for eigen_label in range(len(eigen_affine[best_eigen_idx])):    for item in data:eigen_val=item[best_eigen_idx]if  eigen_val in data_dict.keys():data_dict[eigen_val].append(item)else:data_dict[eigen_val]=[item]#移除已经选取的特征eigen_ls.remove(best_eigen_idx)for eigen_val,child_data in data_dict.items():decision_tree[best_eigen][eigen_val]=create_tree(child_data,eigen_ls) return decision_tree #根据属性预测类别
def make_predict(decision_tree,test_data):pre_ls=[]for data in test_data:child_tree=list(decision_tree.values())[0]curr_eigen=list(decision_tree.keys())[0]curr_eigen_idx=eigens.index(curr_eigen)flag=False# print(data)for idx,eigen in enumerate(data):eigen=int(eigen)if idx==curr_eigen_idx:if eigen in child_tree.keys():if type(child_tree[eigen])==str:# print(eigen)# return child_tree[eigen]# print(child_tree[eigen])pre_ls.append(child_tree[eigen])flag=Truebreakelse:curr_eigen=list(child_tree[eigen].keys())[0]curr_eigen_idx=eigens.index(curr_eigen)child_tree=list(child_tree[eigen].values())[0]if flag==False:pre_ls.append('failured') return np.array(pre_ls)            # return 'failure'#程序入口
if __name__=='__main__':graphviz = GraphvizOutput()graphviz.output_file = 'graph.png'with PyCallGraph(output=graphviz, config=config):f_path='train_data.csv'data_ls,incomplete_ls=createDataset(f_path)#如果训练集有不完整属性,则使用‘最通常值法’进行填充if len(incomplete_ls)!= 0:data_ls=handle_incomplete(data_ls,incomplete_ls)decision_tree=create_tree(data_ls,list(range(len(eigens))))print(f'\nthie decision tree is {decision_tree}')#测试决策数是否与训练集一致并且覆盖训练集#注:转换为np.array后,数据类型统一变为strdata_arr=np.array(data_ls)train_data_arr=data_arr[:,:-1]# print(train_data_arr)true_cls_arr=data_arr[:,-1].reshape(-1)print(f'true_cls_arr:{true_cls_arr}')pre_arr=make_predict(decision_tree,train_data_arr)print(f'pre_arr:{pre_arr}')# print(true_cls_arr.shape,pre_arr.shape,train_data_arr.shape)print(f'\nfor training data, the accuracy is {np.sum(pre_arr==true_cls_arr)/pre_arr.size}')#测试用例test_data=[[1,1]]prediction=make_predict(decision_tree,np.array(test_data))print(f'the test predictions : {"    ".join(prediction.tolist())}')print('\nps: if the decision tree cannt handle the data, output "failured"')

三、ID3算法讨论与分析

作为一种最基础也最为核心的决策树算法,ID3算法从一个假设空间中搜索一个拟合训练样例的假设,通过观察ID3算法的搜索空间和搜索策略,我们可以看到这个算法的优势与不足

1.优势

  • ID3算法使用信息增益作为结点选择依据,从信息论的角度来进行学习,原理明晰、可解释性强
  • ID3算法操作简单,学习泛化能力强,考虑到ID3算法的归纳偏置:较短的树比较长的树优先,信息增益高的特征更靠近根节点的树优先,我们可以看到决策树所习得的规则是简单且易泛化到新数据的(符合奥卡姆剃刀原则)
  • 对于样例集中不充足属性的数据,可以有多种有效的方式进行填充,包括此次所用的“最通常值法”、“比例分配法”、“调换特征与目标属性角色法”等等。
  • ID3 算法在搜索的每一步都使用当前的所有训练样例,以统计为基础决定怎样精化当前的假设。这与那些基于单独的训练样例递增作出决定的方法(例如,Find-S或候选消除法)不同。使用所有样例的统计属性(例如,信息增益)的一个优点是大大减小了对个别训练样例错误的敏感性。

2.不足

  • ID3算法只能处理分类属性的数据,不适宜连续类型的数据
  • 不能判断有多少个其他的决策树也是与现有的训练数据一致的
  • ID3算法很容易出现过度拟合训练数据的问题(特别是当训练数据集合小的时候)。因为训练样例仅仅是所有可能实例的一个样本,向树增加分支可能提高在训练样例上的性能,但却降低在训练实例外的其他实例上的性能。因此,通常需要后修剪决策树来防止过度拟合训练集,一般来说,这可以通过划分一个验证集来观测修剪。

决策树ID3算法实现与讨论(完整代码与数据)相关推荐

  1. ++代码实现 感知机的原理_决策树ID3原理及R语言python代码实现(西瓜书)

    决策树ID3原理及R语言python代码实现(西瓜书) 摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则.分类决策树是由节点和有向边组成的树形结构,节点表示特 ...

  2. 机器学习算法—决策树(ID3)算法

    机器学习--决策树(ID3)算法 1.决策树(ID3)算法 1.1 算法引入 我们首先以一个分类问题开始,假设我们有这样一份样本数据: 我们的目标是想通过色泽.根蒂.敲声.纹理.脐部.触感来判断这是不 ...

  3. 决策树---ID3算法

    决策树---ID3算法   决策树: 以天气数据库的训练数据为例. Outlook Temperature Humidity Windy PlayGolf? sunny 85 85 FALSE no ...

  4. 决策树ID3算法[分类算法]

    ID3分类算法的编码实现 1 <?php 2 /* 3 *决策树ID3算法(分类算法的实现) 4 */ 5 6 7 8 /* 9 10 *求信息增益Grain(S1,S2) 11 12 */ 1 ...

  5. python决策树 value_机器学习之ID3算法详解及python代码实现

    在生活中我们经常会用到决策树算法,最简单的就是二叉树了:相信大家也会又同样的困扰,手机经常收到各种短信,其中不乏很多垃圾短信.此时只要设置这类短信为垃圾短信手机就会自动进行屏蔽.减少被骚扰的次数,同时 ...

  6. python决策树id3算法_python实现决策树ID3算法

    一.决策树概论 决策树是根据训练数据集,按属性跟类型,构建一棵树形结构.可以按照这棵树的结构,对测试数据进行分类.同时决策树也可以用来处理预测问题(回归). 二.决策树ID3的原理 有多种类型的决策树 ...

  7. python机器学习算法.mobi_机器学习之ID3算法详解及python代码实现

    在生活中我们经常会用到决策树算法,最简单的就是二叉树了:相信大家也会又同样的困扰,手机经常收到各种短信,其中不乏很多垃圾短信.此时只要设置这类短信为垃圾短信手机就会自动进行屏蔽.减少被骚扰的次数,同时 ...

  8. 机器学习——线性回归与决策树实验(附效果以及完整代码)(数据集、测试集开源)

    机器学习实验 实验名称:实验一.线性回归与决策树 一.实验目的 (1)掌握线性回归算法和决策树算法 ID3 的原理: (2)学会线性回归算法和决策树算法 ID3 的实现和使用方法. 二.实验内容 本次 ...

  9. 【Machine Learning in Action --3】决策树ID3算法

    1.简单概念描述 决策树的类型有很多,有CART.ID3和C4.5等,其中CART是基于基尼不纯度(Gini)的,这里不做详解,而ID3和C4.5都是基于信息熵的,它们两个得到的结果都是一样的,本次定 ...

  10. id3决策树_信息熵、信息增益和决策树(ID3算法)

    决策树算法: 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关的特征数据. 缺点:可能会产生过度匹配问题. 适用数据类型:数值型和标称型. 算法原理: 决策树是一个简单的为 ...

最新文章

  1. 【转】android的消息处理机制(图+源码分析)——Looper,Handler,Message
  2. MTDDL——美团点评分布式数据访问层中间件
  3. CMD是什么?(命令行提示符)如何使用python在windows上操作CMD?(python执行命令行)os.syste[m](执行的命令)、os.popen(执行的命令)
  4. ubuntu16.04 安装docker-ce,解决libltdl7版本过低的问题
  5. 【转】make makefile cmake qmake都是什么,有什么区别?
  6. tomcat调优的几个方面
  7. Mac安装metasploit-framework【亲测有用】
  8. (3)FPGA面试技能提升篇(TCL脚本)
  9. Chrome浏览器 开发者工具中的 Performance
  10. 评估数据库存储引擎的黄金三角
  11. HTTP基础(图解HTTP笔记)幕布
  12. 寄生电容/寄生电阻/寄生电感
  13. LSTM预测未来一天股票收盘价
  14. setenv设置环境变量_setenv命令教程在Linux中添加,删除和更改环境变量
  15. 利用python的turtle库绘制玫瑰的步骤_用python turtle画玫瑰
  16. 14、守护线程(thread.setDaemon(true))
  17. Android 10 Camera学习笔记:Camera Framework架构
  18. Ubuntu Kylin操作系统介绍及常用命令的使用
  19. C++按要求生成数据和文件操作
  20. 海思(三)Taurus的开发环境搭建

热门文章

  1. 【180629】VC++ QQ头像连连看游戏源码
  2. Android系统基础(03) Android系统源码下载
  3. Neo4j【有与无】【N6】Graph数据库内部
  4. likeshop搭建商城系统,一步到位
  5. 匹配区县代码_省份、城市、区县三级联动Html代码
  6. mysql 事务 库存_库存事务处理临时表
  7. 2018年,Windows Phone 8.1还能做什么
  8. xp系统打不开excel服务器,WinXP系统下XLSX文件怎么打开?
  9. 网络安全等级保护制度介绍
  10. PHP从入门到精通(数组运算符篇)