问题描述:
隐形眼镜数据集是非常著名的数据集,它包含很多换着眼部状态的观察条件以及医生推荐的隐形眼镜类型。隐形眼镜类型包括硬材质(hard)、软材质(soft)以及不适合佩戴隐形眼镜(no lenses)。数据来源与UCI数据库(dTree目录下存在着info.txt文件记录着24份历史记录)。数据的Labels依次是age、prescript、astigmatic、tearRate、class,也就是第一列是年龄,第二列是症状,第三列是是否散光,第四列是眼泪数量,第五列是最终的分类标签。数据如下图所示:
配镜大师的目的是,在给定年龄, 症状,是否散光,眼泪数量的情况下,预测是否需要配眼镜。
解决方案:
使用上节的机器学习实战之分类篇 一 决策树,同时结合sklearn库,快速实现。sklearn官方User Guide地址:
sklearn.tree.DecisionTreeClassifier。部分函数及应用如下图:
代码实现:
from sklearn.preprocessing import LabelEncoder
from sklearn.externals.six import StringIO
from sklearn import tree
import pandas as pd
import numpy as np
import pydotplus
if __name__ == '__main__':
with open('info.txt', 'r') as fr:
lenses = [inst.strip().split('\t') for inst in fr.readlines()]
lense_target = []
for each in lenses:
lense_target.append(each[-1])
#print(lense_target) #to get the target label
lenseLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
lenseList = []
lenseDict = {}
for label in lenseLabels:
for each in lenses:
lenseList.append(each[lenseLabels.index(label)])
lenseDict[label] = lenseList
lenseList = []
#print(lenseDict) #to create lenseDict
#print('###################################')
lenseDF = pd.DataFrame(lenseDict)
#print(lenseDF) #to create pandas dataframe
encoder = LabelEncoder()
for col in lenseDF.columns:
lenseDF[col] = encoder.fit_transform(lenseDF[col])
#print(lenseDF) #to convert 0 ~ num_class-1 integer
model = tree.DecisionTreeClassifier(max_depth = 4)
model = model.fit(lenseDF.values.tolist(), lense_target)
dotData = StringIO()
tree.export_graphviz(model, out_file = dotData, feature_names = lenseDF.keys(),
class_names = model.classes_, filled = True, rounded = True,
special_characters = True)
graph = pydotplus.graph_from_dot_data(dotData.getvalue())
graph.write_pdf('lenses.pdf')
#age : pre, presbyopic, young
#prescript : myope, hyper
#astigmatic : no, yes
#treaRate : normal, reduced
#2 1 1 0 hard
#0 0 0 1 no lense
#0 0 0 0 soft
'''
young hyper yes normal hard
pre myope no reduced no lenses
pre myope no normal soft
'''
print(model.predict([[2, 1, 1, 0]]))
print(model.predict([[0, 0, 0, 1]]))
print(model.predict([[0, 0, 0, 0]]))
可视化决策树需要安装pydotplus & graphviz 库,具体安装步骤参见: Ubuntu18.04 Anaconda 安装pydotplus和graphviz可视化工具
可视化效果:
最终预测结果:
本章使用的算法称为ID3,它是一个好的算法但并不完美。 ID3算法无法直接处理数值型数据,尽管我们可以通过量化的方法将数值型数据转化为标称型数值,但是如果存在太多的特征划分, ID3算法仍然会面临其他问题。
决策树优点:
1、易于理解和解释,决策树可以可视化;
2、几乎不需要数据预处理。其他方法经常需要数据标准化,创建虚拟变量和删除缺失值,决策树还不支持缺失值;
3、使用树的花费(例如预测数据)是训练数据点(data points)数量的对数;
4、可以同时处理数值变量和分类变量。其他方法大都适用于分析一种变量的集合;
5、可以处理多值输出变量问题;
6、使用白盒模型。如果一个情况被观察到,使用逻辑判断容易表示这种规则。相反,如果是黑盒模型(例如人工神经网络),结果会非常难解释;
7、即使对真实模型来说,假设无效的情况下,也可以较好的适用;
决策树缺点:
1、决策树学习可能创建一个过于复杂的树,并不能很好的预测数据。也就是过拟合。修剪机制(现在不支持),设置一个叶子节点需要的最小样本数量,或者数的最大深度,可以避免过拟合。
2、决策树可能是不稳定的,因为即使非常小的变异,可能会产生一颗完全不同的树。这个问题通过decision trees with an ensemble来缓解。
3、概念难以学习,因为决策树没有很好的解释他们,例如,XOR, parity or multiplexer problems。
4、如果某些分类占优势,决策树将会创建一棵有偏差的树。因此,建议在训练之前,先抽样使样本均衡。