算法原理
决策树是一种类似于流程图的树结构。其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布。树的最顶层是根结点,典型决策树如下:
这个例子是根据天气决定当天是否游玩。
最上面的节点我们称为根节点,即为OUTLOOK,其中OUTLOOK代表天气,这里有三种情况,sunny,overcast与rain,我们需要判断今天的OUTLOOK怎么样,所以这个根节点代表了属性上的测试(我们判断天气怎么样),在这个根节点下,我们有14个实例,其中9个是没有出去玩,5个是出去玩。
第二层的三个节点代表了属性的输出,天气分别为这三种情况下的输出,其中,sunny这种属性下,有两个人实例选择出去玩,3个实例没有出去玩。
第三层是在第二层的基础上细分,例如sunny的湿度,大于70,选择出去玩的实例为0个,小于等于70,选择出去玩的实例为2个
下面举个例子
根据以上信息,我们需要构建一个决策树,但是,怎么决定节点的层数和顺序呢
所以我们需要一个归纳算法,这里我们使用常用的ID3算法,这里不做介绍,只做说明简介
这里我们提出几个指标,
信息熵(用来衡量信息的多少)
其中,P(x)代表事件x发生的概率,事件x的不确定性越大,熵h(x)越大
信息获取量:
通过A来作为节点分类获取了多少信息,Info(A)表示有A时的信息量,Infor_A(D)表示没有A时的信息量
这是是否购买电脑这一特征的信息熵,一个14个样本,9个购买,5个没有购买,9/14为bug中yes的概率,5/14为bug中no的概率
对于age来说,针对bug这属性下的信息熵为,一共14个样本,young占5个,minage为4个,senior为5个,这时第一层系数5/14,4/14,5/14的意义,而第二层是这对应个数样本中,例如young有5个样本,其中两个是buy_yes,3个是buy_no,这样我们可以计算出有age的信息熵
所以没age的信息熵减去有age的信息熵,得到age的信息获取量
所以我们可以算出所有属性的信息获取量,发现age最大,因此选择age作为根节点。
类似的,我们可以同理获取以下的节点信息获取量,选择出节点的位置
#决策树(ID3)根据信息熵来 # _*_ coding: utf-8 _*_ from sklearn.feature_extraction import DictVectorizer #将dict类型的list数据,转换成numpy array import csv#读取CSV文件 from sklearn import preprocessing #数据预处理 from sklearn import tree#导入决策树算法 from sklearn.externals.six import StringIO # 读入数据 "rU" allData = open(r'D:\Machine_learning\1.csv', "rU") reader=csv.reader(allData)#用reader来代表所有数据 headers=next(reader) #header是指数据的第一行,就是数据的特征 #print(headers) #因为SK包的数据输入是有一定的要求的,他的输入不能是类别。只能是 0,scrapy。所以要先将数据转化成DICT类型 #然后用DictVextorizer的函数进行转换 featurelist=[]#定义一个存放特征的列表 自变量 labelList=[]#定义一个存放标签的列表 因变量 for row in reader:#以行遍历所有数据 labelList.append(row[len(row) - 1])#取每一行最后一个值,即Bug值#取出最后一个值,这个值是每条数据的标签 rowDic = {}#创建一个字典,用于存放特征值 for i in range(1, len(row) - 1): rowDic[headers[i]] = row[i]#把每条数据的 特征:属性 插入字典 featurelist.append(rowDic)#把字典插入列表 #print("featureList:" + str(featureList)) #print("lablelist:" + str(lableList)) #将字符型特征值转化为1/0 vec = DictVectorizer()#实例化 dummyX = vec.fit_transform(featurelist).toarray()#使用实例内的方法对数据进行转换 #print("dummyX:" + str(dummyX))#打印出转换后的数据的表值 #print("get_feature_names():" + str(vec.get_feature_names()))#打印出转换后的数据的表头 #建立决策树 lb = preprocessing.LabelBinarizer()#实例化 dummyY = lb.fit_transform(labelList)#数据的转换 #print("dummyY:" + str(dummyY)) #上面的过程就是把数据都转换成符合格式的数据了 #可以调用sk包中的决策树算法进行分类 clf = tree.DecisionTreeClassifier(criterion="entropy")#使用信息增益的方法 clf = clf.fit(dummyX, dummyY)#构建决策树 #print("clf:" + str(clf)) #输出到DOT文件中 with open("DecisionTree_BuyCompute.dot", "w") as f: f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)#要安装可视化工具graphviz #dot -Tpdf D:\Machine_learning/DecisionTree_BuyCompute.dot -o output.pdf # 转化dot文件至pdf可视化决策树(cmd):dot -Tpdf 路径文件.dot -o =路径文字.pdf #预测数据 oneRowX = dummyX[0, :] print("oneRowX:" + str(oneRowX)) newRowX = oneRowX newRowX[0] = 1 newRowX[2] = 0 print("newRowx:" + str(newRowX)) predictedY = clf.predict(newRowX.reshape(1, -1)) print("predictedY" + str(predictedY))