提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
1.简介
决策树学习是应用最广的归纳推理算法之一。它是一种逼近离散函数的方法,且对噪声数据有很好的鲁棒性,能够学习析取表达式。相关算法包多为以ID3思想为内核。
决策树学习方法搜索完整表示的假设空间,从而避免了受限假设空间的不足。决策树学习的归纳偏置是优先选择较小的树。
2.决策树直观表示
决策树通过把实例从根结点排列到某个叶子结点来分类实例,叶子结点即为实例所属的分类。树上的每一个结点指定了对实例的某个属性的测试,并且该结点的每一个后继分支对应于该属性的一个可能值。分类实例的方法是从这棵树的根结点开始,测试这个结点指定的属性,然后按照给定实例的该属性值对应的树枝向下移动。这个过程再在以新结点为根的子树上重复。
其本质是多个if-then有序规则的树状罗列,下图为教材中一棵典型的学习到的决策树:
3.ID3算法核心思想
基本的 ID3 算法通过自顶向下构造决策树来进行学习。构造过程是从“哪一个属性将在树的根结点被测试?”这个问题开始的。然后为根结点属性的每个可能值产生一个分支,并把训练样例排列到适当的分支(也就是,样例的该属性值对应的分支)之下。然后重复整个过程,用每个分支结点关联的训练样例来选取在该点被测试的最佳属性。同时此贪婪搜索从不回溯重新考虑先前的选择。
故ID3算法主要围绕3个问题的解决来进行:
3.1属性选择依据
在为树节点选择测试属性时,需要选择最有助于分类实例的属性(也即特征)。ID3定义了一个统计属性“信息增益”,用来衡量给定属性区分当前训练样例集的能力,在其增长树的每一步使用该信息增益标准从侯选属性集中选择属性。
3.1.1用熵度量样例的均一性的依据
3.1.2信息增益度量期望的熵降低
3.2结点数据拆分
依据所选特征(属性),依照不同的特征值将数据进行划分
3.3子树停止增长条件
满足以下条件之一:
3.4 ID3算法流程图
通过outlook、temperature,humidity,wind这四个特征值来判定该天(day)是否适宜打网球(playtennis)。数据以表格形式存于train_data.csv文件中。数据如下图所示。
1.主要函数模块:
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]+=1
else:
value_dict[eigen_val]=1
count_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=0
for 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 = 0
for data_ls in cls_dict.values():
eigen_entropy+=cal_gain(data_ls)
if eigen_entropy
作为一种最基础也最为核心的决策树算法,ID3算法从一个假设空间中搜索一个拟合训练样例的假设,通过观察ID3算法的搜索空间和搜索策略,我们可以看到这个算法的优势与不足
1.优势
2.不足