您的位置:首页 > 编程语言 > Python开发

机器学习:决策树python实现

2016-03-14 21:19 519 查看
机器学习:决策树python实现源码笔记

打算今天开始回顾一下ml的经典算法,就去按照书上实现了决策树。其实,ml代码模式有很大的相似之处,特征的划分等等。

def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
# 下面的标签labels主要是对应dataset上的1和0,yes和no代表的是标签
labels = ['no surfacing','flippers']
return dataSet, labels

//计算数据集的信息熵
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet: //主要是实现对标签的计数
currentLabel = featVec[-1]//这里对应数据标签
if currentLabel not in labelCounts.keys():
//当前的标签还不存在在labelcounts中
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

//按照不同的属性列划分数据 axis--列索引,value--当前的列所对应的数据
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
//属性列中不同的数据进行不同的划分
if featVec[axis] == value:
//数据的从新组合--去掉当前的value。
//[1,2,3]-->[1,3]-->用数值2去划分
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet

//选择最好的划分属性所对应的索引-->也就是选择划分前后entory变化最大的划分
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1//特征的个数
baseEntropy = calcShannonEnt(dataSet)//计算当前data的entory
bestInfoGain = 0.0; bestFeature = -1
for i in range(numFeatures)://对不同的特征进行遍历
featList = [example[i] for example in dataSet]//找出当前特征下所对应的数值
uniqueVals = set(featList)//去掉相同的数值
newEntropy = 0.0
for value in uniqueVals:
//对特征i下不同的value进行划分数据,在计算划分之后的entory
subDataSet = splitDataSet(dataSet, i, value)
//划分之后每个数据集所占的比例
prob = len(subDataSet)/float(len(dataSet))
//计算划分之后的entory
newEntropy += prob * calcShannonEnt(subDataSet)
//计算划分前后entory的差
infoGain = baseEntropy - newEntropy
if (infoGain > bestInfoGain):
bestInfoGain = infoGain
bestFeature = i
return bestFeature

//考虑到存在就算划分到最后,有些节点的还会存在两种以上的label
//那就找出划分之后节点中label最多的那个label
def majorityCnt(classList):
classCount={}
for vote in classList://计算每个label所对应的个数
if vote not in classCount.keys(): classCount[vote] = 0
classCount[vote] += 1
//进行排序
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]

def createTree(dataSet,labels):
//找出当前数据中存在的labels
classList = [example[-1] for example in dataSet]
//只有一种label的话也就代表当前的data停止划分
if classList.count(classList[0]) == len(classList):
return classList[0]
//当前的data中只有一个特征,就不要再划分了。
if len(dataSet[0]) == 1:
return majorityCnt(classList)
//找出最好的划分特征索引
bestFeat = chooseBestFeatureToSplit(dataSet)
//得到特征
bestFeatLabel = labels[bestFeat]
//把当前的特征作为tree的根
myTree = {bestFeatLabel:{}}
del(labels[bestFeat])//当前的label已经划分过之后就不会再划分,删除
//得到索引所对应的全部属性值
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: