决策树
kNN算法可以完成很多分类任务,但是它最大的缺点就是给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解
决策树的构造
- 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
- 缺点:可能会产生过度匹配问题。
适用数据类型:数值型和标称型。
创建分支的伪代码函数createBranch()
Check if every item in the dataset is in the same class:
If so return the class label
Else
find the best feature to split the data
split the dataset
create a branch node
for each split
call createBranch() and add the result to the branch node
return branch node
示例数据
海洋生物数据
不浮出水面是否可以生存 | 是否有脚蹼 | 属于鱼类 |
---|---|---|
是 | 是 | 是 |
是 | 是 | 是 |
是 | 否 | 否 |
否 | 是 | 否 |
否 | 是 | 否 |
信息增益 Information gain
划分数据集的大原则是:将无序的数据变得更加有序。
组织杂乱无章数据的一种方法就是使用 信息论 度量信息。
在划分数据集之前之后信息发生的变化称为 信息增益.
知道如何计算信息增益,就可以计算某个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。
冯 诺依曼 建议使用 熵 这术语
信息增益是熵(数据无序度)的减少,大家肯定对于将熵用于度量数据无序度的减少更容易理解。
集合信息的度量称为香农熵 或者 简称 熵(entropy)。(更多熵知识请移步至 What Is Information Entropy)
熵定义为信息的期望值
信息定义
如果待分类的事务可能划分在多个分类之中,则符号Xi的信息定义为
其中p(Xi)是选择该分类的概率。
为了计算熵,我们需要计算所有分类别所有可能值包含的信息期望值,通过下面的公式得到
计算给定数据集的香农熵
def calcShannonEnt(dataSet):
#实例总数
numEntries = len(dataSet)
labelCounts = {
}
#the the number of unique elements and their occurance
#统计目标变量的值出现的次数
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) #log base 2
return shannonEnt
创建数据集
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
#change to discrete values
return dataSet, labels
运行
# -*- coding: utf-8 -*-
import trees
dataSet, labels = trees.createDataSet()
print dataSet
#[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
print labels
#['no surfacing', 'flippers']
#计算熵
print trees.calcShannonEnt(dataSet)
#0.970950594455
#改变多一个数据
dataSet[0][-1] = 'maybe'
print dataSet
#[[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
print trees.calcShannonEnt(dataSet)
#1.37095059445
熵越大,则混合的数据越多
延伸:另一个度量集合无序程度的方法是基尼不纯度,简单地说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组的概率。
划分数据集
#axis表示第n列
#返回剔除第n列数据的数据集
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
#剔除第n列数据
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
运行
print dataSet
#[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
#划分数据集
#当第0列时,值为0 的实例
print trees.splitDataSet(dataSet, 0, 0)
#[[1, 'no'], [1, 'no']]
#当第0列时,值为1 的实例
print trees<