因为自己凭印象写的,大致流程跟书上一样,细节不太一样,看了看书上的一些细节问题的确做的更好
本章学习的是用构建决策树来预测隐形眼睛类型,决策树算法优点是计算复杂度不高(用ID3算法到尽头,公式少且简单),结果易看懂(因为是字典形式,或者用图片的形式表现决策树),中间值缺失不敏感(因为可以凭借其他的信息判断所属类型),可以处理不相关特征数据(每个数据都是独立,谁大谁小互不影响)
还有用到了ID3算法,这个是重点。我就直接把书上原话搬过来。ID3算法推荐看一下,写的挺好的 https://blog.youkuaiyun.com/m0_37786726/article/details/79699972
熵定义为信息的期望值,在明晰这个概念之前,我们必须知道信息的定义。如果待分类的事
务可能划分在多个分类之中,则符号x i 的信息定义为
其中p(x i )是选择该分类的概率。
为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面的公式得到:
计算信息增益:Entropy就是上面的H
pi表示该分类方式所产生的第i组数据量和原数据量的比
Info_Gain越大,表示分裂后的熵越小,子节点变得越纯,分类的效果越好
pickle模块在python3安装的时候就有了
from math import log
from numpy import array, delete
from pickle import dump, load
def GetData(String):
fl = open(String, 'r')
lines = fl.readlines()
DataSet = []
for line in lines:
line = line.split('\n')[0] #去掉字符串最后一个换行符,取换行符前面的字符串
linelist = line.split('\t')
DataSet.append(linelist)
return DataSet
def GetshannongEnt(dataSet):
shannongEnt = 0.0
l = len(dataSet) #计算有多少组数据
K = {} #以字典的形式计算不同类型的个数
for dataline in dataSet:
if dataline[-1] not in K:
K[dataline[-1]] = 1
else:
K[dataline[-1]] += 1
for key in K.keys():
shannongEnt -= K[key]/l*log(K[key]/2,2)
return shannongEnt
def GetNewDataSet(DataSet, axis):
NewDataSet = []
Data = {} #利用字典将DataSet中axis位置按照不同值分类
for datalist in DataSet:
if datalist[axis] not in Data:
Data[datalist[axis]] = [datalist]
else:
Data[datalist[axis]].append(datalist)
for key in Data.keys(): #将字典中的不同类插入到NewDataSet中
NewDataSet.append(Data[key])
return NewDataSet #返回值应该是一个二维list,第一层list代表axis位置有几种类型的值,第二层list代表DataSet每一行中axis位置为这个值的行的集合
def ID3(DataSet):
DataTree = {}
FatherEntropy = GetshannongEnt(DataSet)
Information_Add = 0.0
best_i = 0
for i in range(len(DataSet[0])-1):
NewDataSet = GetNewDataSet(DataSet, i)
SonEntropy = 0.0
for NewDatalist in NewDataSet:
SonEntropy += len(NewDatalist)/len(DataSet)*GetshannongEnt(NewDatalist) #计算子节点们的熵
if Information_Add < FatherEntropy - SonEntropy:
Information_Add = FatherEntropy - SonEntropy #计算信息增益
best_i = i #选出当前DataSet最好的分类位置
if len(DataSet[0]) == 2: #也就是只剩下最好的分类位置和最后的判定结果
for Datalist in DataSet:
if Datalist[best_i] not in DataTree:
DataTree[Datalist[best_i]] = Datalist[-1]
return DataTree
else:
for Datalist in DataSet:
if Datalist[best_i] not in DataTree:
key = Datalist.pop(best_i) #将第i个位置的元素删除,返回删除的元素
DataTree[key] = [Datalist]
else:
key = Datalist.pop(best_i)
DataTree[key].append(Datalist)
#现在的DataTree是张这个模样:{key1:[...],key2:[...],....},接下来变成字典嵌套,也就算把[...]变成字典
for key in DataTree.keys():
DataTree[key] = ID3(DataTree[key])
return DataTree
def classify(DataTree, testData):
for data in testData:
DataTree = DataTree[data]
return DataTree
def storeTree(DataTree, filename = 'PythonTest/机器学习/第二章的决策树.txt'):
fl = open(filename, 'wb') #python3:必须是wb因为是二进制文件,否则报错 python2:就可以直接是w
dump(DataTree,fl)
fl.close()
def readTree(filename):
fl = open(filename)
return load(fl)
#下面的是测试一下结果
storeTree(ID3(GetData('PythonTest/机器学习/machinelearninginaction-master/Ch03/lenses.txt')))
print(classify(ID3(GetData('PythonTest/机器学习/machinelearninginaction-master/Ch03/lenses.txt')),['pre', 'myope', 'no', 'normal']))