入了机器学习的大坑之后,最近跟着《机器学习实战》学到决策树
我用的jupyter
代码敲到creatTree卡住了。
返回检查前面的代码,函数一个一个的查,最后得出结论,没问题啊!!!可是问题还是没有解决
报错原因如上,我实在是按书上的敲的,奈何就是进行不下去,之后在网上找了一大堆这一章的代码copy还是不行,这特么是怎么了 ??
之后我想我把代码贴到pycharm中,找错误应该好找些,然后我把代码贴到pycharm中运行,居然成功运行了
我在想这难道是编译器的问题,
睡了一觉起来感觉还是不对,都是python3,怎么可能?
找网上的关于list out of range的相关文章
参考https://blog.csdn.net/cckchina/article/details/79776572
而这个兄弟的报错问题则是这个
参考https://bbs.csdn.net/topics/392427506
然而对于我这个菜鸟,这些大神的思路我还是跟不上,上面的没有返回值,明明有return啊,怎么没有返回值?下面的说添加数据,我更不知所云了,但好像知道问题出在哪里了:
bestFeatLabel=labels[bestFeat]我的这句里面肯定是空的
果然还是有问题,但是pycharm为什么能运行啊???兼容性这么强?
黄天不负有心人啊!终于还是让我找到了答案
当我看到这个的时候,我想我知道问题在哪了
前面有一行代码这特么直接把原数据删了,我后面递归去哪里找数据去,果然是大坑啊!!!
解决办法:先复制一遍,然后再删掉
问题得到解决
之后在网上页看到了同样的说法
参考https://blog.csdn.net/coolerzz/article/details/79075539
一个晚上加一个上午终于把这个问题解决了!虽然很累,但是解决的那一刻还是很快乐的,哈哈哈哈哈哈
附上原码:
from math import log
def calcShannonEnt(dataSet):
numEntries=len(dataSet) #数据实例总数,即训练数的数目
labelCounts={} #创建一个数据字典 以下表明它的键值是最后一列的数值
for featVec in dataSet:
currentLabel=featVec[-1]
#如果当前键值不存在 扩展字典并将当前键值加入字典,每个键值记录当前类别出现的次数
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1
#currentLabel作为键,labelCounts[currentLabel]表示键对应的值,对于下面的简单数据集,labelcounts最终的结果是{'yes':2,'no':3}
#适用所有类标签的发生频率计算类别出现的概率,利用这个概率计算香农熵
shannonEnt=0.0
for key in labelCounts:
prob=float(labelCounts[key])/numEntries
shannonEnt-=prob*log(prob,2)
return shannonEnt
def creatDataSet():
dataSet=[[1,1,'yes'],
[1,1,'yes'],
[1,0,'no'],
[0,1,'no'],
[0,1,'no']]
labels=['no surfacing','flippers']
return dataSet, labels
dataSet,labels=creatDataSet()
def splitDataSet(dataSet,axis,value):
retDataSet=[]
for featVec in dataSet:
if featVec[axis]==value:
reducedFeatVec=featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
def chooseBestFeatureToSplit(dataSet):
numFeatures=len(dataSet[0])-1
#计算原始数据集信息熵,以便与划分后的数据集进行比较
baseEntropy=calcShannonEnt(dataSet)
#假设信息熵差值初值为0,最好的划分特征为最后一列
bestInfoGain=0.0;bestFeature=-1
for i in range(numFeatures):#循环特征
featList=[example[i] for example in dataSet]
#set()用于删除重复元素
uniqueVals=set(featList)
#uniqueVals得到了每一种(i)特征中的取值如(0,1)或者(yes,no)
newEntropy=0.0
#新的分类方式的信息熵
for value in uniqueVals:#遍历第i个特征的取值
#按照一种特征进行数据集划分,并计算当下的信息熵
subDataSet=splitDataSet(dataSet,i,value)
prob=len(subDataSet)/float(len(dataSet))
newEntropy+=prob*calcShannonEnt(subDataSet)
infoGain=baseEntropy-newEntropy
if (infoGain>bestInfoGain):
bestInfoGain=infoGain
bestFeature=i
return bestFeature
def majorityCnt(classList):#输入为分类名称的列表
classCount={}
for vote in classList:
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):
#取出dataset中的所有类标签,对于原数据集就是['yes', 'yes', 'no', 'no', 'no'],实际上是对于每个分支而言。
classList=[example[-1] for example in dataSet]
#如果该分支下全是相同的类别,即都是yes或者都是no,就返回这种分类(类别)
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:{}}
subLabels = labels[:]#大坑!!!!!!
del(subLabels[bestFeat])#不复制就删会改变原来的数据
featValues=[example[bestFeat] for example in dataSet]
uniqueVals=set(featValues)
for value in uniqueVals:#遍历当前选择特征的所有属性值
#复制类标签,并将其存储在新列表变量sublabels中
subLabels=labels[:]
#递归调用
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
return myTree
然而今天进行到后面画图又碰一鼻子灰
昨天调试的时候没有注意到结果,改了的代码,然而结果是错的:
{'no surfacing': {0: 'no', 1: {'no surfacing': {0: 'no', 1: 'yes'}}}}
而正确结果是:
{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
感觉昨天是高兴过了头,结果都疏忽掉了,然后今天发现之后继续回去分析昨天的代码,
subLabels = labels[:]#大坑!!!!!
del(subLabels[bestFeat])#不复制就删会改变原来的数据
突然就发现这个东西有问题了,这样做了之后这个labels根本就不更新了,每次都是一样的值,从而导致错误的结果!
然后我去想原本的代码:
del(labels[bestFeat])
还是和原来的想法,昨天是报超限问题,这个labels是有问题的,但是前面的代码都没有问题,还是想到的是bestFeat的问题,于是我把bestFeat打印出来看看到底超到哪里去了,结果打印出来bestFeat的值都是0,这是对的啊!!怎么会超限呢??
还是不甘心,我把代码重新组织了一下,又跑了一次,what the fuck!!!!!!!!!!居然跑出来了,没有报错
顿时感觉,自己被这个jupyter notebook耍的团团转!!!!顿时心态爆炸!有木有。。
但是还好,问题解决了!兜兜转转又回到原点!!