机器学习02-决策树ID3算法
Posted Qunar_尤雪萍
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习02-决策树ID3算法相关的知识,希望对你有一定的参考价值。
决策树
概述:通过分析每个数据特征项在分类过程中所起到的所用比重,将数据划分为几个数据子集,如果某个数据子集数据同一类型,则无需再继续划分数据分类,如果不属于同一分类,则需要在对数据子集进行分割。
优点:计算复杂度不高。
缺点:可能会出现由于样本特征值对应的样本数量不统一导致结果偏向于数量多的样本对应的分类。
具体分类算法 ID3算法
在每次划分数据集时我们会取一个特征属性来进行划分,那么这里有一个问题,例如训练样本里面有20个特征值,我们如何从这些特征中选择当前用于划分的最适合的特征项呢?我们需要找到一个有效的量化方法来划分数据。
信息熵
样本id | 是否需要浮出水面 | 是否有脚蹼 | 属于鱼 |
---|---|---|---|
1 | 是 | 是 | 是 |
2 | 是 | 是 | 是 |
3 | 是 | 否 | 是 |
4 | 否 | 是 | 否 |
5 | 否 | 是 | 否 |
我们划分数据的原则是将无须的数据变得更加有序,这里有一个信息增益的概念:即数据在划分前后的信息发生的变化成为信息增益。因此我们需要计算每个特征值的数据划分之后的信息增益值,选取最大的信息增益特征值作为当前数据划分特征。集合信息的度量方式成为熵,我们需要计算我们的信息集合熵值。
熵的计算公式:
H=−log2p(xi)
对于集合的熵计算公式:
H=−∑ni=1p(xi)log2p(xi)
计算信息熵算法
#-*- coding=utf-8 -*-
from numpy import *
from math import log
import operator
def calcShannonEnt(dataSet):
labelCounts = #统计每个标签的次数
for line in dataSet:
label = line[-1]
labelCounts[label] = labelCounts.get(label, 0) + 1
shannonEnt = 0.0
#统计信息熵
for key in labelCounts:
prob = float(labelCounts[key])/len(dataSet)
shannonEnt -= prob * log(prob, 2)
return shannonEnt
数据划分code
由于是决策树因此我们需要将集合划分为不同的子集
#例如上面的通过是否浮出水面划分数据就能得到两个子集
#子集1
#是否有脚蹼|属于鱼类
#是 | 是
#是 | 是
#否 | 是
#子集2
#是 | 否
#是 | 否
#axis表示特征项,value表示需要匹配的特征值
def splitDataSet(dataSet, axis, value):
resultDataSet = []
for line in dataSet:
if line[axis] == value:
reduceValue = line[:axis]
reduceValue.extend(line[axis+1 : ])
resultDataSet.append(reduceValue)
return resultDataSet
选择最优的划分属性
由于有上面两个方法作为基础,我们可以通过下面的代码来寻找最适合划分的特征值
def chooseBestSplitFeature(dataSet):
featureCount = len(dataSet[0]) - 1
#计算当前的熵值
currentShannonEnt = calcShannonEnt(dataSet)
#定义信息增益
bestInfoGain = 0.0
#定义返回值
bestAxis = -1
#遍历每个特征项
for i in range(featureCount):
featureValues = set([value[i] for value in dataSet])
subShannonEnt = 0.0
for featureValue in featureValues:
subDataSet = splitDataSet(dataSet, i, featureValues)
subDataSetProb = float(subDataSet)/len(dataSet)
subShannonEnt += subDataSetProb * calcShannonEnt(subDataSet)
subInfoGain = currentShannonEnt - subShannonEnt
#判断当先最优的划分特征
if subInfoGain > bestInfoGain :
bestInfoGain = subInfoGain
bestAxis = i
return bestAxis
构建决策树
我们可以通过一个map来表示我们的决策树
def createTree(dataSet):
classList = [value[-1] for value in dataSet]
#如果所有的classList一致则直接返回
if classList.count(classList[0]) == len(classList):
return classList[0]
if len(dataSet[0]) == 1:
##这里的case场景是,已经没有可用的特征项时,针对剩余的分类如何决定目标分类
#return dataSet[0]
#这里采用取占比最多的值
return major(dataSet)
#选择分类属性
axis = chooseBestSplitFeature(dataSet)
#定义tree树 属性 index->Map
myTree = axis:
featureList = set([value[axis] for value in dataSet])
for feature in featureList :
mytree[axis][feature] = createTree(splitDateSet(dataSet, axis, feature))
return mytree
#去占比最多的分类值
def major(dataSet):
labelCount=
for line in dataSet:
labelCount[line[-1] = labelCount.get(line[-1], 0) + 1
#排序
return sorted(labelCount.iteritems(), key = operator.itemgetter(1), reverse=True)[0][0]
关于python的序列化
决策树构建完成之后,我们可以将决策树序列化到一个文件中,以便以后直接使用,这里就涉及到python的序列化模块pickle
import pickle
def storeTree(myTree, fileName):
fw = open(fileName, 'w')
pickle.dumps(myTree, fw)
fw.close()
def readTree(fileName):
fr = open(fileName)
return pickle.load(fr)
以上是关于机器学习02-决策树ID3算法的主要内容,如果未能解决你的问题,请参考以下文章