python决策树代码_机器学习_决策树Python代码详解

决策树优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据;

决策树缺点:可能会产生过度匹配问题。

决策树的一般步骤:

(1)代码中def 1,计算给定数据集的香农熵:

1503199-20181004165817853-94019632.png

其中n为类别数,D为数据集,每行为一个样本,pk表示当前样本集合D中第k类样本所占的比例,Ent(D)越小,D的纯度越高,即表示D中样本大部分属于同一类;反之,D的纯度越低,即数据集D中的类别数比较多。

(2)代码中def 2,选择最好的数据集划分方式,即选择信息增益最大的属性:

1503199-20181004170458769-992570205.png

其中

1503199-20181004170543326-816767190.png

这里V表示属性a的可能的取值数,Dv表示属性a上取值为av的样本。

(3)代码中 def 3,按照给定特征划分数据集:选取最优属性后,再从属性的各个取值中选取最优的属性,以此类推。

(4)代码中def 5,递归构造树,数的结束标志为:a、类别完全相同则停止划分;b、代码中def 4,如果数据集已经处理了所有属性,但是类标签依然不是唯一的,此时采用多数表决法,即遍历完所有特征时返回出现次数最多的类别。

from math import log

# 计算数据集的信息熵,熵越小,说明数据集的纯度越高

def calcShannonEnt(dataset): # def 1

numEntries = len(dataset) # 样本数,这里的dataSet是列表

labelCounts = {} #定义一个字典,key为类别,值为类别数

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 # 信息熵

# 选出最好的数据集划分方式,即找出具有最大信息增益的特征

def chooseBestFeatureToSplit(dataSet): #def 2

numFeatures = len(dataSet[0])-1 # 特征数

baseEntropy = calcShannonEnt(dataSet) #计算数据集的香农熵

bestInfoGain = 0.0; bestFeature = -1

for i in range(numFeatures):

featList = [example[i] for example in dataSet] #第i列特征的所有特征的取值

uniqueVals = set(featList) # 去掉重复的特征,每个特征值都是唯一的

newEntropy = 0.0

for value in uniqueVals:

subDataSet = splitDataSet(dataSet,i,value)

prob = len(subDataSet)/float(len(dataSet))

newEntropy += prob * calcShannonEnt(subDataSet)

infoGain = baseEntropy - newEntropy # 表示属性为value的信息增益

if (infoGain > bestInfoGain):

bestInfoGain = infoGain

bestFeature = i

return bestFeature # 具有最大信息增益的特征

# 按照给定特征维数划分数据集,数据集中一行为一个样本

# def 3

def splitDataSet(dataSet,axis,value): # axis可表示数据集的列,也就是特征为数,value表示特征的取值

retDataSet = []

for featVec in dataSet:

if featVec[axis] == value:

reducedFeatVec = featVec[:axis] # 在数据集中去掉axis这一列

reducedFeatVec.extend(featVec[axis+1:])

retDataSet.append(reducedFeatVec)

return retDataSet # 表示去掉在axis中特征值为value的样本后而得到的数据集

# 当处理了所有属性,但是类标签依然不是唯一的,此时采用多数表决法决定该叶子节点的分类

def majorityCnt(classList): # def 4

classCount = {}

for vote in classList:

if vote not in classCount.keys():

classCount[vote] = 0

classCount += 1

sortedClassCount = sorted(classCount.items(),key=lambda classCount: classCount[1],reverse = True)

return sortedClassCount[0][0]

# 创建树

def createTree(dataSet,labels): # def 5

classList = [example[-1] for example in dataSet] #类别列表

if classList.count(classList[0]) == len(classList): # 如果类别完全相同就停止划分

return classList[0]

if (len(dataSet[0]) == 1):

return majorityCnt(classList)

bestFeat = chooseBestFeatureToSplit(dataSet) # 选出最好的特征,也就是信息增益最大的特征

bestFeatLabel = labels[bestFeat]

myTree = {bestFeatLabel:{}}

del(labels[bestFeat]) # 每划分一层,特征数目就会较少

featValues = [example[bestFeat] for example in dataSet] # 最好的特征的特征值

uniqueVals = set(featValues) #去掉重复的特征

for value in uniqueVals:

subLabels = labels[:] # 减少后的特征名

myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels)

return myTree

def createDateSet():

dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]

labels = ['no surfacing','flippers'] #属性名

return dataSet,labels

myData,myLabel = createDateSet()

createTree(myData,myLabel)

print(createTree(myData,myLabel))

#print(chooseBestFeatureToSplit(myData))

# print(splitDataSet(myData,0,1))

# print(splitDataSet(myData,0,0))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值