机器学习实战第三章学习笔记
使用决策树分类的一般步骤:准备数据à构建决策树(该决策树可以被存成文件,便于二次利用)à使用决策树决策
【准备数据】
有n组数据,每一组有m个元素,前m-1个元素为分类标签即特征,最后一个元素为决策结果。
【构建决策树】
首先选择最优的分类特征。
输入:数据集dataSet,假设该数据集有k个特征,1个决策结果。
方法:从第一个特征到第k个特征,每次使用一个特征去划分数据集dataSet成dataSet1、dataSet2、dataSet3…。挨个计算每一个子数据集的熵值n1、n2、n3…,并求和(dataSet1/dataset)*n1+(dataSet2/dataset)*n2+(dataSet3/dataset)*n3+….。总的熵值最小的那个特征便是最优分类特征。
ps:所有代码的依赖包
from math import log
import operator
import matplotlib.pyplot as plt
import numpy
[具体代码如下]
########
##计算输入数据集的熵值
########
def calcShannonEnt(dataSet): #####计算数据集dataSet的熵
numEntries = len(dataSet) ###统计数据集的行数
labelCounts = {}
for featVec in dataSet :
currentLabel = featVec[-1] ####提取数据集中最后一列的内容,即数据标签。除去数据标签外的每一列都是该行数据的一个特征
if currentLabel not in labelCounts.keys(): ###统计每一种标签出现的次数,并将其存储在一个字典中格式为:{标签名, 出现次数}
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0.0
for key in labelCounts: ###计算当前数据集的熵
prob = float(labelCounts[key])/numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt
使用key-value格式的数据结构创建决策树。
输入:数据集dataSet, 标签序列
方法:从数据集dataSet中选择最优分类特征feature1。以该特征值为key创建空的键值对。通过在数据集中计算该feature1所在列有多少个取值,就可以知道以该feature1为父结点的子节点有多少个。假设该feature1有i个子节点值分别为temp1、temp2、temp3…tempi,则循环i次,每次从当前数据集dataSet中删除feature1所在列值为tmpi行,并以余下的数据作为一个新的数据集创建子树。【递归调用】
[具体代码如下]
########
##从数据集dataSet中删除第axis列,值为value的那行,并返回剩余的数据集
########
def splitDateSet(dataSet, axis, value): ###从数据集合dataSet中选出第axis+1列内容等于value的数据行,且选出的数据不再包含第axis+1列的内容
retDataSet = []
for featVec in dataSet :
if featVec[axis] == value:
reduceFeatVec = featVec[:axis] #featVec[:axis]选去featVec中从第0到第axis列的内容
reduceFeatVec.extend(featVec[axis+1:]) #featVec[axis+1:]选去featVec中第axis+1列之后的内容
retDataSet.append(reduceFeatVec)
return retDataSet
########
##从输入的数据集中挑选取分类效果最好的特征
########
def chooseBestFeatureToSplit(dataSet): ##选择最优的数据划分方式
numFeatures = len(dataSet[0]) - 1 ###计算每组数据中除去最后一个数据类型标签标示外总共有多少个特征,这些特征描述该组数据
baseEntropy = calcShannonEnt(dataSet) #判断数据集合dataSet之中是否有多种类型的数据,即判断数据集的熵值是否为零
bestInfoGain = 0.0
bestFeature = -1
for i in range(numFeatures): #从第1列开始(即第一个特征,每一行各有一个特征值),每次选取一个特征去划分数据集合
featList = [example[i] for example in dataSet] ###i表示特征所在列的索引,featList存放该列的每一个具体的值
uniqueVals = set(featList) ####删除重复的值
newEntorpy = 0.0
for value in uniqueVals:
subDataSet = splitDateSet(dataSet, i, value) ####从dataSet中筛选出第i列值为value的那些行,并把这些行划分为同一类
prob = len(subDataSet)/float(len(dataSet)) ###计算当前划分出的子数据集合所拥有的数据行数占总数据行的比值
newEntorpy += prob * calcShannonEnt(subDataSet) ####用上一步的比值乘以子数据集合的熵,newEntorpy中存储每个子数据集合的熵的累加值
infoGain = baseEntropy - newEntorpy ##由于熵的值为负数,为了比较大小,取整
if infoGain > bestInfoGain : ####上面的步骤是从第i列下手,计算在此列中划分的各子数据集熵值的累加和
bestInfoGain = infoGain ####使用冠军法选取最小的那个熵值下的特征列
bestFeature = i ##返回最优分类特征的索引值
return bestFeature
<pre name="code" class="python">########
##定义这个方法的主要作用是用于处理特殊情况:当数据集已经处理了所有的属性,但是类标签依然不是唯一的,此时我们需要决定如何定义该叶节点,在这种情况下,我们通常会采用多数表决的方法决定该叶子结点的分类
########