1. 实现决策树的前提:信息增益
信息增益:
数据集合在被处理的之前之后,其信息发生的变化称为信息增益。
香农熵或熵:
集合信息的度量方式称为香农熵或者简称为熵。
熵被定义为信息的期望值:
-
信息的定义
如果存在有多个分类(分类1、分类2...)的条件下,待分类的事务可能被划分为其中某个分类,则该事务($$x_i$$)的信息定义为:
\[l(x_i) = -log_2P(x_i) \] -
信息的期望值
\[H = -{\textstyle \sum_{i=1}^{n}}P(x_i)log_2P(x_i) \]- n是分类的数目
计算给定集合中特征的熵:
-
假定集合为:
dataSet = [[1,1,"yes"], [1,1,"yes"], [1,0,"no"], [0,1,"no"], [0,1,"no"]]
共三个特征
-
python计算该集合的熵
import math def calculateShannonEntropy(dataSet): # 计算数据集中实例的总数 numRows = len(dataSet) # 创建存储标签的字典,方便计数 labelCounts = {} for data in dataSet: # 取数据集的最后一个特征 currentLabel = data[-1] # 如果特征不存在,则赋予默认值,否则计数+1 if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 # 初始化熵值 shannonEntropy = 0.0 for currentLabel in labelCounts: # 计算当前类别标签的发生频率,即该类别出现的概率 probability = float(labelCounts[currentLabel])/numRows # 计算所有特征的所有可能值包含的信息期望值 shannonEntropy -= probability * math.log(probability,2) # 返回香农熵 return shannonEntropy
-
结果
2. 实现决策树的前提:划分数据集
抽取符合给定特征的数据集:
def splitDataSet(dataSet, feature_seq : int = 0, feature_value=None):
'''
抽取符合要求的值,形成一个新的集合
:param dataSet: 数据集
:param feature_seq: 特征在数据集中的位置,默认从0开始
:param feature_value: 指定特征的值
:return:
'''
# 创建一个新集合,防止对源数据集合的修改
resultDataSe t = list()
for data in dataSet:
# 获取新集合,新集合中排除目标特征
if data[feature_seq] == feature_value:
# 选择在feature_seq之前的特征
reduceFeature = data[:feature_seq]
# 选择在feature_seq之后的特征
reduceFeature.extend(data[feature_seq + 1:])
resultDataSet.append(reduceFeature)
return resultDataSet
找到最好的特征划分方式:
需要满足两个条件:
- 数据必须时一种由列表元素组成的列表,而且所有的列表元素都要具有相同的数据长度
- 数据的最后一列或者每个实例的最后一个元素是当前实例的类别标签
def chooseBestFeatureToSplit(dataSet):
'''
选择源数据集中的最好特征
信息增益是熵的减少或者是数据无序度的减少。
:param dataSet:
:return: 比较所有特征中的信息增益,返回最好特征划分的索引值
'''
# 获取特征的长度
numFeatures = len(dataSet[0])
# 计算源数据的最后一个特征的香农熵(最初的无序度量值)
baseEntropy = calculateSh