#①Aggregation Model 回顾上一篇文章讲到的聚合模型,三个臭皮匠顶一个诸葛亮。于是出现了blending,bagging,boost,stacking。blending有uniform和non-uniform,stacking是属于条件类的,而boost里面的Adaboost是边学习边做linear,bagging也是属于边学习边做uniform的。Decision Tree就是属于边做学习然后按照条件分的一种。如下图,aggregation model就是是补全了:

#②Decision Tree Hypothesis 决策树是一种很传统的算法,出现的很早,例如下面,按照下班时间,是否约会,提交截止时间进行判断,和人的处理方式很像:

上面的菱形就像是很简单的分割平面,而箭头就是判断过程,其实就是学习过程,最后的Y和N就是分出来的结果。可以对应到下面的式子: 最后那些小小的Y,N就是g(x),和之前的SVM他们都不太一样,这里的g(x)通常就是一个常数了,也叫base hypothesis;箭头就是q(x)判断条件,红色就是找到了最好split method的地方。 从另一个方面来看决策树: 和上面理解是一样的。

Strengths and Weaknesses 优点: 模型直观,便于理解,应用很广泛 简单,容易实现。 训练和预测的时候,时间短预测准确率高 缺点 缺少足够的理论支持,后面给出的VC dimension没有什么太完备的道理。 对于找到合适的树要花额外的时间。 决策树代表性的演算法比较少

#③Decision Tree Algorithm 根据上面的公式,基本算法:

按照决策树执行流程,可以分成四个部分: 首先学习设定划分不同分支的标准和条件是什么;接着将整体数据集D根据分支个数C和条件,划为不同分支下的子集Dc;然后对每个分支下的Dc进行训练,得到相应的机器学习模型Gc;最后将所有分支下的Gc合并到一起,组成大矩G(x)。但值得注意的是,这种递归的形式需要终止条件,否则程序将一直进行下去。当满足递归的终止条件之后,将会返回基本的hypothesis gt(x)。 所以,包含了四个基本算法选择: 分支个数 分支条件 终止条件 基本算法

####常用决策树算法模型——CART CART算法对决策树算法追加了一些限制: ①c = 2,分支的个数要等于2,和二叉树有点想。 ②本着g(x)simplify的原则,g(x)规定他就是一个常数,也就是类别。 ③按照Ein最小化的原则每一次选择condition。

其实决策树的分类有点像Adaboost的stump分类。但是Adaboost的stump仅仅是按照准确率来了,而decision tree的标准是purity,纯净度。意思就是熵了。purifying的核心思想就是每次切割都尽可能让左子树和右子树中同类样本占得比例最大或者yn都很接近(regression),即错误率最小。比如说classifiacation问题中,如果左子树全是正样本,右子树全是负样本,那么它的纯净度就很大,说明该分支效果很好。 所以主要问题就变成了如何寻找纯净度最好的问题了。

#④purifying 纯净度其实就是熵了。熵是代表混乱程度的。几个比较常见的算法:ID3,ID4.5,gini系数。 ####ID3 以信息论为基础,以信息熵和信息增益为衡量标准,从而实现对数据的归纳分类。

信息增益,就是指split前后熵的变化,选择最好的一个,也就是说由于使用这个属性分割样例而导致的期望熵降低。信息增益就是原有信息熵与属性划分后信息熵(需要对划分后的信息熵取期望值)的差值。 但是他的缺点也很明显: 1.没有剪枝过程,为了去除过渡数据匹配的问题,可通过裁剪合并相邻的无法产生大量信息增益的叶子节点。因为选择的已经是最好的了,如果合并了肯定不够之前的好。 2.信息增益的方法偏向选择具有大量值的属性,也就是说某个属性特征索取的不同值越多,那么越有可能作为分裂属性,这样是不合理的。比如前面的ID编号,1/N再来个log很小的。 3.只可以处理离散分布的数据特征。这个很明显了,如果是连续型数据,很难分的。 基于以上缺点又改进了一下。

####ID4.5 改进就是ID4.5了,这个就不是信息增益了,是信息增益率。

信息增益率是信息增益与信息熵的比例 这样的改进其实就是使得离散化可以连续化而已,二分就好了。 优点: 1.面对数据遗漏和输入字段很多的问题时非常稳健。 2.通常不需要很长的训练次数进行估计。工作原理是基于产生最大信息增益的字段逐级分割样本。 3.比一些其他类型的模型易于理解,模型推出的规则有非常直观的解释。 4.允许进行多次多于两个子组的分割。目标字段必须为分类字段。

####CART Cart算法里面用的是gini系数,但是还是有必要说一下decision tree做拟合的时候Ein要怎么optimal。 #####regression 对于regression问题,首先想到的肯定是均方差了:

y杆就是yn的平均。 #####classification 对于分类: y表示类别最多的。 以上都是借鉴前面algorithm的思想推导的,现在回到纯度。想要purity最小,那么就是y要多了,最好全部都是了,所以classification error: 上面的只是考虑了分支最大的,我们需要把所有的都考虑进去,于是: gini系数就出来了: 可以看到gini系数和熵差不了多少,一定程度上可以代表熵。

对于CART的Teminal condition,自然就是两个条件:1.首先是yn只有一个种类,分不了了。2.其次就是Xn都是一样的不能再分。

#⑤Decision Tree Heuristics in CART 基本流程:

可以看到CART算法在处理binary classification和regression问题时非常简单实用,而且,处理muti-class classification问题也十分容易。 但是要注意一个问题,既然有错误就分,那么到最后肯定是一个二分完全树,Ein一定是0,这样是有过拟合的。对于overfit,要引入的就是过拟合: 既然是过拟合了,这棵树不要这么大就行了,于是进行修剪,pruning,剪枝操作。比如,总共是10片叶子,我们取掉1片,剩下9片,9种情况,我们比较这9种情况哪种好。

这里其实就是刚刚说的decision tree理论不是特别的完善,事实上NumberOfLeaves ≈ Ω其实我们在实践中得到的。因为叶子越多复杂度越大。所以就直接把叶子数量当做是复杂度Ω了。

在决策树中预测中,还会遇到一种问题,就是当某些特征缺失的时候,没有办法进行切割和分支选择。一种常用的方法就是surrogate branch,即寻找与该特征相似的替代feature。如何确定是相似的feature呢?做法是在决策树训练的时候,找出与该特征相似的feature,如果替代的feature与原feature切割的方式和结果是类似的,那么就表明二者是相似的,就把该替代的feature也存储下来。当预测时遇到原feature缺失的情况,就用替代feature进行分支判断和选择。

#⑥Decision Tree in action

貌似和Adaboost很像啊!

最后在总结一下:

#⑦代码实现Decision Tree 包括创建树,预测,可视化树,这篇东西内容不多,代码讲解多。 首先引入一个计算gini系数:

def cal_gini(data):'''calculate the gini indexinput:data(list)output:gini(float)'''total_sample = len(data)if total_sample == 0:return 0label_count = label_uniqueness(data)gini = 0for label in label_count:gini = gini + pow(label_count[label] , 2)gini = 1 - float(gini) / pow(total_sample , 2)return ginipass
复制代码

传进的是一个list,计算这个list里面label数量,然后统计gini系数返回。 还有一个分别计算类别数量的函数,刚刚的gini系数用到的:

def label_uniqueness(data):'''Counting the number of defferent labels in the datasetinput:datasetoutput:Number of labels'''label_uniq = {}for x in data:label = x[len(x) - 1]if label not in label_uniq:label_uniq[label] = 0label_uniq[label] += 1return label_uniqpass
复制代码

这个就是tool文件里面的。 创建节点node:

class node:'''Tree node'''def __init__(self , fea = -1, value = None, results = None, right = None, left = None):'''initialization function:param fea:column index value:param value:split value:param results:The class belongs to:param right:right side:param left:left side'''self.fea = feaself.value = valueself.results = resultsself.right = rightself.left = leftpass
复制代码

fea就是当前分割的维度,value就是分割的值,result就是label,right右子树,left左子树。 接下来就是主要创建树的类了:

class decision_tree(object):def build_tree(self,data):'''Create decision treeinput:dataoutput:root'''if len(data) == 0:return node()currentGini = tool.cal_gini(data)bestGain = 0.0bestCriterria = None # store the optimal cutting pointbestSets = None # store two datasets which have been splitedfeature_num = len(data[0]) - 1 # Number of featuresfor fea in range(0 , feature_num):feature_values = {}for sample in data:feature_values[sample[fea]] = 1 # store the value in the demension fea possiblyfor value in feature_values.keys():(set_first, set_second) = self.split_tree(data, fea, value)nowGini = float(len(set_first) * tool.cal_gini(set_first) + len(set_second) * tool.cal_gini(set_second)) / len(data)gain = currentGini - nowGiniif gain > bestGain and len(set_first) > 0 and len(set_second) > 0:bestGain = gainbestCriterria = (fea , value)bestSets = (set_first , set_second)passif bestGain > 0:right = self.build_tree(bestSets[0])left = self.build_tree(bestSets[1])return node(fea = bestCriterria[0], value = bestCriterria[1], right = right, left = left)else:return node(results=tool.label_uniqueness(data))def split_tree(self , data , fea , value):'''split the dataset according demension and valueinput:dataoutput:two data'''set_first = []set_second = []for x in data:if x[fea] >= value:set_first.append(x)else:set_second.append(x)return (set_first, set_second)passdef predict(self, sample, tree):'''predictioninput:sample, the tree which we have been builtoutput:label'''if tree.results != None:return tree.resultselse:val_sample = sample[tree.fea]branch = Noneif val_sample >= tree.value:branch = tree.rightelse:branch = tree.leftreturn self.predict(sample, branch)def predcit_samples(self, samples, tree):predictions = []for sample in samples:predictions.append(self.predict(sample, tree))return predictionspass复制代码

其实很简单,就是按照feature和value分类。忘了这个是前向还是后向了,我是看那个二叉树跟着搞的,大一的时候学过,过了半年差不多忘光了。 看看预测效果吧! 使用的数据还是iris数据集,可视化还得降维,麻烦,于是就是可视化树了,发现更麻烦:

if __name__ == '__main__':print('load_data......')dataSet = load_data()data = dataSet.datatarget = dataSet.targetdataframe = pd.DataFrame(data = data, dtype = np.float32)dataframe.insert(4, 'label', target)dataMat = np.mat(dataframe)'''test and train'''X_train, X_test, y_train, y_test = train_test_split(dataMat[:, 0:-1], dataMat[:, -1], test_size=0.3, random_state=0)data_train = np.hstack((X_train, y_train))data_train = data_train.tolist()X_test = X_test.tolist()tree = decisionTree.decision_tree()tree_root = tree.build_tree(data_train)predictions = tree.predcit_samples(X_test, tree_root)pres = []for i in predictions:pres.append(list(i.keys()))y_test = y_test.tolist()accuracy = 0for i in range(len(y_test)):if y_test[i] == pres[i]:accuracy += 1print('Accuracy : ', accuracy / len(y_test))
复制代码

准确率还是蛮高的。 首先要求树的叶子数: 一样是递归。

def getNumLeafs(myTree):if myTree == None:return 0elif myTree.right == None and myTree.left == None:return 1else:return getNumLeafs(myTree.right) + getNumLeafs(myTree.left)
复制代码

然后是求深度:

def getDepth(myTree):if myTree == None:return 0right = getDepth(myTree.right)left = getDepth(myTree.left)return max(right+1, left+1)
复制代码

之后就是画节点了,求深度和叶子数只是想着可以按照深度把树画的分开点。 还有一个装parent节点坐标的:

class TreeNode(object):def __init__(self, x, y, parentX = None, parentY = None):self.x = xself.y = yself.parentX = parentXself.parentY = parentYpass
复制代码

最后就是主要的画图了:


def drawNode(x, y ,parent,color, marker, myTree, position):if myTree.results == None or len(list(myTree.results.keys())) > 1:plt.scatter(x, y, c=color, marker=marker, s=200)if myTree.right == None and myTree.left == None:results = list(myTree.results.keys())plt.annotate(s = 'label == ' + str(results[0]), xy=(x - 15, y))if results[0] == 0.0:plt.annotate(s='label == 0.0', xy=(x , y))plt.scatter(x, y, c='orange', marker='H', s=100)if results[0] == 1.0:plt.scatter(x, y, c='pink', marker='8', s=100)if results[0] == 2.0:plt.scatter(x, y, c='r', marker='+', s=100)if myTree.value != None and myTree.fea != None:po = 5if position == 'right':plt.annotate(s = 'dimension' + str(myTree.fea) + '>' + str(round(myTree.value, 2)), xy = (x-25 - po, y))else:plt.annotate(s='dimension' + str(myTree.fea) + '>' + str(round(myTree.value, 2)), xy=(x - 25 + po, y))if parent != None:plt.plot([x, parent.x], [y, parent.y], color = 'gray', alpha = 0.5)
def draw(myTree, parent = None, x = 100, y = 100, color = 'r', marker = '^', position = None):NumberLeaf = getNumLeafs(myTree)Depth = getDepth(myTree)delta = (NumberLeaf+Depth)drawNode(x, y, parent, color, marker, myTree,position)if myTree.right != None:draw(myTree.right, parent=TreeNode(x, y) ,x=x+5*delta, y=y-5-delta,color='b', marker='x', position='right')if myTree.left != None:draw(myTree.left,parent=TreeNode(x, y) ,x=x-5*delta, y=y-2-delta, color='g', marker='o', position='left')pass复制代码

加上这句 plt.annotate(s='label == 0.0', xy=(x , y))是因为那个注释死活画不出来,应该是挡住了。主要还是draw函数,drawNode只是画而已,判断都是为了加注释的,来看看效果图:

如果当时学数据结构用的是python多好!

所有代码在GitHub上: github.com/GreenArrow2…

转载于:https://juejin.im/post/5c3211556fb9a049c84f9c33

Decision Tree相关推荐

  1. OpenCV3.3中决策树(Decision Tree)接口简介及使用

    OpenCV 3.3中给出了决策树Decision Tres算法的实现,即cv::ml::DTrees类,此类的声明在include/opencv2/ml.hpp文件中,实现在modules/ml/s ...

  2. Python实现决策树(Decision Tree)分类

    关于决策树的简介可以参考: http://blog.csdn.net/fengbingchun/article/details/78880934 在  https://machinelearningm ...

  3. 决策树分类Decision tree classifier

    2019独角兽企业重金招聘Python工程师标准>>> import org.apache.spark.sql.SparkSession import org.apache.spar ...

  4. Machine Learning | (7) Scikit-learn的分类器算法-决策树(Decision Tree)

    Machine Learning | 机器学习简介 Machine Learning | (1) Scikit-learn与特征工程 Machine Learning | (2) sklearn数据集 ...

  5. 决策树(Decision Tree)、决策树的构建、决策树流程、树的生长、熵、信息增益比、基尼系数

    决策树(Decision Tree).决策树的构建.决策树流程.树的生长.熵.信息增益比.基尼系数 目录

  6. 深度学习:知识回收(Lecture3+4 PLA+Decision Tree)

    Lecture 3 PLA and Lecture 4 Decision Tree 序 Lecture 3 PLA Lecture 4 Decision Tree 特征划分 ID3 信息增益 C4.5 ...

  7. 【机器学习实战】第3章 决策树(Decision Tree)

    第3章 决策树 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/ ...

  8. decisiontreeregressor_机器学习算法-Decision Tree

    决策树算法-Decision Tree,有监督的学习算法,模仿的是人类做决策的过程. 定义: 从根节点开始一步一步走到叶子节点(决策),所有数据最终都会落到叶子节点,即可以做分类,也可以做回归.它适用 ...

  9. 【深度学习】模式识别技术探索之决策树(Decision tree)

    [深度学习]模式识别技术探索之决策树(Decision tree) 文章目录 1 什么是模式和模式识别? 2 常见的模式识别系统 3 应用领域 4 举例:随机森林(Random Forest)4.1 ...

最新文章

  1. K8S - Kubernetes简介
  2. UnicodeEncodeError: 'locale' codec can't encode character '\u5e74' in position 2: encoding error
  3. 根据输入时间段备份压缩日志文件
  4. 图片相似度识别_deepface:人脸识别\特征分析
  5. AJAX异步--ajax请求
  6. 大数相关计算(c语言版)
  7. PowerShell设置命令别名Alias
  8. python学了有什么用-python学来有什么用
  9. [转载] Python函数中把列表(list)当参数
  10. eclipse中新建JSP文件时的编码设置
  11. iOS测试包安装途径实践
  12. Young不等式的一个新证明
  13. python编程midi键盘按键错乱_键盘按键错乱有以下几种相应的解决办法
  14. [入门篇]Linux操作系统fork子进程的创建以及进程的状态 超超超详解!!!我不允许有人错过!!!
  15. 如何修改win7上的mac地址
  16. 镜头离焦对于ToF深度的影响分析
  17. web服务器端预约系统,Web场馆预约管理系统
  18. 机械键盘按键不灵敏怎么办、机械键盘按键坏了怎么办、维修机械键盘
  19. 判断点是否在圆上(java)
  20. MSP430单片机串口控制5路PWM频率变化程序

热门文章

  1. python 亮度一致_Python玩转各种多媒体,视频、音频到图片
  2. Java迭代器(转)(iterator详解以及和for循环的区别)
  3. java 之 多线程
  4. 'python program'.count('p')的值是_如何用Python分析泰坦尼克号生还率?
  5. 周末都花费在智能车实验室,结果......
  6. 2021年春季学期-信号与系统-第十二次作业参考答案-第一小题
  7. Boston房价PaddlePaddle测试程序
  8. 信号转换| 如何使用模拟电路完成对方波信号倍频PWM转换?
  9. pandas 索引_10分钟带你学会Pandas多层级索引
  10. oracle600错误,oracle在导入数据时报600错误的解决方法