面试中,大家不仅要懂得目前比较流行的深度学习算法,对于传统的分类和聚类算法也要了解一些。在实际应用中也不是所有的深度学习算法就是万能的,训练时间久、可解释性差都可能会阻碍在工业界的使用,很多情况下还是需要用到传统的分类和聚类算法。
十二年前就接触到LR和Bayes,然后是K-mean、KNN、决策树、随机森林、SVM、adaboost、xgboost等各种各样的分类和聚类算法,不过当时只是做项目或者竞赛直接应用了,没有把自己的理解写下来,也是忘了的差不多,发现还是需要写下来整理一下,方便后面回顾。
监督学习和无监督学习
监督学习(Supervised Learning)和无监督学习(Unsupervised Learning)是数据挖掘和机器学习必须要了解的两个概念,这两个概念不了解,那真的是无轮之车走不远。除了监督学习和无监督学习,又延伸出了半监督学习(Semi-supervised Learning)。
监督学习是给定了标注好的训练数据,根据标注好的数据进行模式识别的过程,一般分类分析会用到监督学习比较多。要求必须事先知道各个类别的信息,并且断言所有待分类的项都有一个类别,但是这种假设在很多时候不一定成立,特别是当数据量比较大的时候,需要通过预处理才能满足分类算法的要求,代价会比较大,就要考虑无监督学习或者半监督学习。常见的分类算法有决策树分类、朴素贝叶斯分类、基于支持向量的分类器、神经网络分类、KNN(K近邻)分类、模糊分类。这里需要注意一点,分类是一种监督学习,但是并不是监督学习就是要做分类,也有些监督学习不是做分类的,比如相似性学习、特征学习等也是监督学习,但是不是进行分类。
而无监督学习则是训练数据是未标注,不需要对于数据事先打上标签。我们所说的聚类算法属于无监督学习,聚类的时候,我们并不关心具体的类是什么,只是把相似的东西聚在一起。所以聚类分析,一般我们只要知道怎么计算要聚类个人的相似就可以开始工作了。常见的聚类方法有:K-MEANS(K均值)聚类,属于划分法的K-MEDOIDS和CLARANS算法,属于层次法的BIRCH算法、CURE算法、CHAMELEON算法等,基于密度的DSCAN算法、OPTICS算法、DENCLUE算法等,基于网格的STING算法、CLIQUE算法、WAVE-CLUSTER算法等,基于模型的方法等。
而半监督学习是介于监督学习和无监督学习之间,采用大量未标注的数据,并同时使用标注数据进行模式识别。半监督学习使用尽量少的人员投入且能够获得比较高的准备性,因此半监督学习也越来越受人重视。
下面着重介绍几种算法。
1. 什么是决策树
决策树就是依托于策略抉择而建立起来的一棵树,代表着对象属性与对象值之间的一种映射关系,树的每个叶子节点代表一个对象,树的分叉节点代表某个属性值。决策树仅有单一的输出。从数据到决策树的学习称为决策树学习,又直接被称为决策树,其实就是基于分类和训练的预测树。
举个简单的例子,看下Tom M.Mitchell的机器学习力比较经典的例子,根据天气情况明天是否去打球,可以把其中的数字认为是想去和不想去打球的心理指数。
不考虑天气的情况下,想去打球的占9点,不想去的占5点;如果明天晴天(太阳比较大),想打的占2点,不想打占3点;如果明天晴天的情况下,湿度小于等于70则去打球,但是心理指数只有2点;如果明天晴天而且湿度大于70,那么肯定不想去打球了,不想去打球的心理指数占3点。同样的,如果明天阴天,就去打球,心理指数占4点。如果明天下雨,则想打和不想打的心理指数占3和2点;然后会考虑是否有风,如果有风,则不去打球,心理指数为2;如果没有风,则去打球,心理指数为3。
我们发现决策树的每一层的想打综合等于上一层的想打的指数;不想打的总和也同样等于上层的不想打的指数。上面决策树的表达式可以写为:
Outlook = (Sunny ^ ( Humidity<=70 )) V ( Overcast )V ( Rain ^ Wind=FALSE )
对于上面的例子,我们选择了几个准则进行一步步的判断,然后得到最终的接口,但是为什么选择天气、湿度、风这三个规则呢?为什么要先考虑天气,然后考虑湿度呢?
举个简单的例子,你收集到了一批照片,想快速的通过照片上的特征判断是男孩还是女孩。有人说根据头发长短判断就可以了,女孩头发长,男孩头发短;也有人说,根据穿衣打扮,女孩穿裙子,男孩穿长裤;当然也有人看的比较细致,可以根据是否打耳洞判断,女孩有耳洞,男孩没有耳洞。我们发现可以简单用头发长短划分生成一个比较简单的决策树,划分的依据就是头发长短。当然也可以根据其他规则生成一个决策树,但是我们发现这些规则都没有办法一下子决定是男孩还是女孩,这个时候就要考虑对于决策树的生成规则,我们不能保证生成的决策树就是万能的且100%准确的,只能说越接近100%的分类准确率越好。那怎么选择指标,优选使用哪个?就需要一个评价标准来衡量分类效果。
量化分类效果的方式比较多,常用的有信息增益(在ID3中应用)、信息增益率(在C4.5中应用)、基尼系数(在CART中应用)等。
对于信息增益及信息增益率的计算离不开熵的概念,可以参考熵的计算方法:简单理解熵的概念
下面简单介绍一下ID3、C4.5、CART
2. 决策树 - ID3算法
ID3是决策树的一种经典算法,ID3的思想来自于:奥卡姆剃刀,可以先了解一下奥卡姆剃刀。
奥卡姆剃刀(Occam's Razor, Ockham's Razor),又称为“奥坎的剃刀”,意思是简约之法则,是由14世纪的逻辑学家、圣方济各会修士奥卡姆的威廉提出的一个解决问题的法则:切勿浪费较多东西,去做‘用较少的东西,同样可以做好的事情’。换一种说法,如果关于同一个问题有许多种理论,每一种都能作出准去的预言,那么应该挑选其中使用假定最少的。尽管越复杂的方法通常能够作出的越好的预言,但是在不考虑预言能力(即结果大致相同)的情况下,假设越少越好。
ID3算法(Iterative Dichotomiser 3, 迭代二叉树3代)是又Ross Quinlan发明的一种用于决策树的算法,这个算法便是建立在奥卡姆剃刀的基础上:决策树越小越好。当然这个算法也不是总能够生成最小的树形结构,而是一种启发式算法。从信息论的角度讲,期望信息越小,信息的增益越大,从而纯度越高,熵就会越低。ID3算法的核心就是信息增益度量属性的选择,选择分裂后信息增益最大的属性进行分裂,采用自顶向下的贪婪搜索遍历可能的决策树空间。
ID3算法的伪代码如下:
主要思想如下:
1. 自顶向下的贪婪搜索遍历可能的决策树空间构造决策树(这是ID3和C4.5)算法的基础
2. 从“哪一个属性将在树的根节点被测试”开始
3. 使用统计测试来确定每个实例属性单独分类训练样例的能力,分类能力最好的属性作为树的根节点测试(评判属性分类能力好坏通过信息增益或则信息增益率)
4. 为根节点属性的每个可能的值产生一个分支,并把训练样例按照对应的属性值排列到适当的分支之下
5. 把每个分支再次作为根分支,重复上述步骤,用每个分支下关联的的训练样例选取在该节点被测试的最近属性
经过上面的步骤,就完成了对于决策树贪婪搜索,算法从不回溯重新考虑之前已经做过的选择。
我们看到上面的过程就是选择一个最好的属性作为测试节点,那么哪个属性才是最好的呢?这里引入信息增益,而信息增益的度量标准就是:熵。
简单理解熵
通常我们为了量化分类效果的好坏,会引入信息增益(ID3)、信息增益率(C4.5)、基尼系数(CART)等。一般采用熵(Entropy)来度量信息增益。
ID3算法的核心思想就是以信息增益度量属性的选择,选择分裂后能够获得最大信息增益的属性进行分裂。信息增益(Information Gain)是用来衡量给定的属性区分训练样例的能力。先了解一下信息增益相关联的一个名词“熵”(entropy),熵是信息论中广泛使用的一个名词,刻画任意数据集的纯度。假设一个二分类的问题,正反样例集为S,那么这个数据集S相对于这个二分类的熵为:
其中代表正样例的先验概率(统计概率,占比),
代表负样例的先验概率,在熵的计算中任务0log_{2}0= 0。
举个例子对于人脸特征区分男女的例子,样本集S一共15个样本,其中包括7个男生、8个女生,我们把样本集S记为:
,那么熵为:
根据上面公式可以很容易得到如下结论:
1. 如果S所有的成员都属于一类,那么Entrop(S)=0
2. 如果S所有成员的正负例个数相等,那么Entrop(S)=1
3. 如果S的正反例数量不等,那么0 < Entropy(S) < 1
可以根据上面公式的正例和entropy的关系简单画出示意图。
泛化一下,如果目标属性包含n个不同的值,那么S相对于n个状态的分类熵定义为:
,其中
为第i个状态的比率(统计概率)
信息增益Gain(S,A)
已知熵是衡量训练样例集合纯度的标准,那么我们就可以定义出属性分类训练数据的效力的度量标准:信息增益(Information Gain)。一个属性的信息增益就是由于使用这个属性分割样例而导致的期望熵降低,或者说是按照某个属性划分时造成的熵减少的期望。属性A相对于集合S的信息增益Gain(S,A)定义为:
是属性
的值域
是样本集合
是
中在属性
上值等于
的样本集合
通过上面的公式可知Gain(S,A)是由给定属性A的值而得到的关于目标函数值的信息,当对于S的任意一个成员的目标值编码时,Gain(S,A)的值是知道属性A的值后可以节省的二进制位数。
结合熵里面描述例子看看怎么来计算这个信息增益,假设S包含15个样本,其中7个男生,8个女生,记为;其中男生中有2个高鼻子和女生中有4个高鼻子,其他均为扁鼻子。按照属性鼻子特征分类15个样本得到的信息增益计算如下:
同理,通过其他特征脸型也会计算出来不同的信息增益,比如Gain(S,B)=0.0252,依次类推。我们发现Gain(S,A)>Gain(S,B),那么在这一轮选择中,我们会选择信息增益最大的那个作为分类,比如选择的是A,那么我们就根据A的{High, Flat}两个特征把样本分成两组,把这个特征从特征列表中去除,依次往下迭代。最终会形成一棵树,即基于ID3的决策树。
3. C4.5算法
C4.5算法其实是ID3算法的改进,是另一种比较经典的分类决策树算法。理论和ID3差不多,基本构造方法依然是每次选择一个好的特征以及分裂点作为当前节点的分类条件。那么C4.5到底比ID3改进了哪些方面呢?
1. 用信息增益率来选择属性。ID3是采用的子树的信息增益选择的属性,也就是熵的变化值,而C4.5用的是信息增益率;区别在于一个是信息增益,一个是信息增益率
2. 在树构造过程中进行剪枝。在构造决策树的时候,那些挂着比较少元素的节点,不考虑最好,不然容易导致overfitting
3. 对非离散数据也能处理
4. 能够对不完整数据进行处理
那么为什么用增益率呢?我们一般知道“率”是指一个相对值,比如概率、增长率、斜率等等都是基于某个值基础上的一个比率。比如说北京高考总分是750分,江苏高考总分是480分(只是以分数为例,具体高考总分可以参考官方文档),北京学生A考了600分,而江苏学生B考虑450分,如果按考取分数计算,北京的考生肯定要比江苏的考生考的好,但是江苏的考生肯定觉得不公平。如果按照考试的总分比北京学生考的成绩效果应该是P1= 600/750=0.8,而那位江苏的同学成绩效果应该是P2=450/580=0.9375,很明显江苏的那个同学考的好一点。同理,C4.5克服了ID3采用信息增益选择属性时偏向选择取值多的属性的不足。
信息增益率
下面看下信息增益率的计算,信息增益率是基于前面的信息增益量Gain(S,A)和分裂信息度量SplitInformation(S,A)共同定义:
Gain(S,A)可以通过前面介绍的公式获得,那么SplitInformation(S,A)的计算公式如下:
其中到
是根据属性A的c个值域(属性A的值值域空间大小为c)分隔的样本子集,这里分裂信息是S关于属性A的各个值的熵。
分裂信息会阻碍把样本集分的更细的属性被选择。举个例子,有一个含有n个样本的集合被属性A彻底分隔,刚好每个样本是一组,这时分裂信息的值为;如果属性B把样本集刚好分成两类,那么分裂信息值为1;如果属性C把样本集仅分成一类,那么分裂信息值就是0,此属性对于分类并没有作用,是不可取的。也就是说这里要求选择至少分为2类的属性,如果属性A和属性B产生同样的信息增益,根据增益比率度量,则B属性会分的更好点。
通过上面例子我们发现,当选择属性的时候越接近于S,分裂信息越小,而GainRatio越大,当属性A对于S的所有样例都取几乎同样的值得话,那么可能会到导致GainRatio未定义或者GainRatio非常大。为了避免选择这种属性,可以采用一些启发式规则,比如可以先计算每个属性的增益,仅对那些增益高于平均值得属性应用增益比率测试。
当然除了信息增益和信息增益率来度量分类效果外,也可以采用基于距离的度量,即定义一个数据划分的距离尺度。
4. CART算法
CART算法全称是Classification And Regression Tree,翻译为分类与回归树。CART算法采用二分递归分割技术将当前样本集分为两个子样本集,使得生成的每个非叶子节点都有两个分支。非叶子节点的特征取值为TRUE和FALSE,左分支取值为TRUE,右分支取值为FALSE,因此CART算法生成的决策树是结构简洁的二叉树。
CART可以处理联系变量和离散型变量,利用训练数据递归的划分特征空间进行建树,用验证数据进行剪枝。
- 待预测的分类是离散性数据,则CART生成分类决策树
- 待预测的分类是连续性数据,则CART生成回归决策树
4.1 CART分类决策树算法
CART分类树预测分类离散型数据,采用的Gini指数(选Gini指数最小的特征s)作为分裂的标准,同时也是包含后剪枝操作。ID3算法和C4.5算法虽然在对训练样本集的学习中可以尽可能多地挖掘信息,但其生成的决策树分支较大。为了简化决策树的规模,提高生成决策树的效率,就出现了根据GINI系数来选择测试属性的决策树算法CART。
基尼指数(Gini指数):又称为基尼不存度,表示在样本集合中一个随机选中的样本被分错的概率。
注意Gini指数越小表示集合被选中的样本被分错的概率越小,也就是说集合的纯度越高;反之,集合越不纯。
基尼指数(基尼不存度)= 样本被选中的概率 * 样本被分错的概率
假设有K个分类,样本点属于第k个类的概率为,则概率分布的基尼指数定义为:
根据基尼指数的定义,假设样本集合为D,有K个分类,表示数据集D中属于第k类的样本子集,则样本集合D的基尼指数为:
如果数据集D根据特征A在某一取值a上进行分割,得到了集合和
两部分,那么在特征A下,集合D的基尼系数如下:
,其中:
基尼系数Gini(D)表示集合D的不确定,基尼系数Gini(D, A)表示特征A=a分割后集合的不确定性。基尼系数越大,样本集合的不确定越大。
对于属性A,分别计算所有属性值将数据集划分为两部分之后的Gain_Gini,选取其中的最小值,作为属性A得到的最优二分方案。然后对训练集D,再计算所有属性的最优二分方案,选取其中最小值,作为样本及D的最优方案。
举个例子:
名称 | 体温 | 胎生 | 水生 | 类标记 |
---|---|---|---|---|
人 | 恒温 | 是 | 否 | 哺乳类 |
巨蟒 | 冷血 | 否 | 否 | 爬行类 |
鲑鱼 | 冷血 | 否 | 是 | 鱼类 |
鲸 | 恒温 | 是 | 是 | 哺乳类 |
蛙 | 冷血 | 否 | 有时 | 鱼类 |
巨蜥 | 冷血 | 否 | 否 | 爬行类 |
蝙蝠 | 恒温 | 是 | 否 | 哺乳类 |
猫 | 恒温 | 是 | 否 | 哺乳类 |
豹纹鲨 | 冷血 | 是 | 是 | 鱼类 |
海龟 | 冷血 | 否 | 有时 | 爬行类 |
豪猪 | 恒温 | 是 | 否 | 哺乳类 |
鳗 | 冷血 | 否 | 是 | 鱼类 |
蝾螈 | 冷血 | 否 | 有时 | 两栖类 |
针对上面的离散型数据,按照体温特征为恒温和非恒温划分。其中恒温物种中包含5个哺乳类,2个鸟类;非恒温的物种中包含3个爬行类、3个鱼类、2个两栖类,则和
的基尼系数为:
我们可以进一步计算得出在体温特征下数据集的Gini系数:
我们计算所有的特征,选择Gini最小的特征。
4.2 CART回归树算法
CART回归树预测回归连续型数据,假设X与Y分别是输入和输出变量,并且Y是连续变量,在训练集的所在的输入空间中,递归的将每个区域划分为两个子区域上额输出值,构建二叉决策树。样本空间记为:
选择最优切分特征j与切分点s,遍历特征j,对规定的切分变量j扫描切分点s,选择使得下面的式子取得最小值的(j, s)对,其中是被划分的输入空间,
是空间
对应的固定输出值。
选定(j,s)对,划分区域并决定相应的输出值
继续对两个子区域迭代上述步骤,将输入空间划分为M个区域,生成决策树。
当输入空间划分确定时,可以用平方误差来表示回归树对于训练数据的预测方法,用平方误差最小的准则求解每个单元上的最优输出值。
下面举个例子:
我们有连续性变量,根据给定的数据点如下:
![]() | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
![]() | 5.56 | 5.70 | 5.91 | 6.40 | 6.80 | 7.05 | 8.90 | 8.70 | 9.00 | 9.05 |
考虑1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5切分点,对各个切分点依次取出,
,
,
以及m(s),例如当切分点
时,得到
,
,其中
,
,
如下:
依次变换(j,s)对,可以得到s及m(s)的计算结果,如下表所示:
s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 | 6.5 | 7.5 | 8.5 | 9.5 |
m(s) | 15.72 | 12.07 | 8.36 | 5.78 | 3.91 | 1.93 | 8.01 | 11.73 | 15.74 |
当x=6.5时,此时,
,
,
。回归树
为
之后利用拟合训练数据的残差,如下表所示:
![]() | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
![]() | -0.68 | -0.54 | -0.33 | 0.16 | 0.56 | 0.81 | -0.01 | -0.21 | 0.09 | 0.14 |
用拟合训练数据得到平方误差
第二步求与求
的方法相同,只是拟合的数据是上面表格的残差数据,可以得到:
用拟合训练数据的平方误差
依次继续求出,如下:
用拟合训练数据的平方损失误差如下所示,假设此时已经满足误差要求,那么
便是所求的回归树。
下面简单看下基于Sklearn的实现。
以sklearn的iris数据集作为训练集,iris属性特征包括花萼长度、花萼宽度、花瓣长度、花瓣宽度、类别共三类,分别为Setosa、Versicolour、Virginca。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from sklearn.datasets import load_iris
from sklearn import tree
import graphviz
#load data
iris=load_iris()
X=iris.data
y=iris.target
clf=tree.DecisionTreeClassifier()
clf=clf.fit(X,y)
#export the decision tree
#export_graphviz support a variety of aesthetic options
dot_data=tree.export_graphviz(clf,out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True,rounded=True,
special_characters=True)
graph=graphviz.Source(dot_data)
graph.view()
5. 问题参考
1. 决策树一般被应用于取值离散的场景,连续的特征一般要处理成离散的然后英语与决策树
2. 实际的应用中决策树很容易出现overfitting的情况,一般会做boosting
3. 分类器的性能不好,很可能是选择的特征鉴别性不足,好的特征才能有好的分类效果,和分类器只是弱相关。那么如何提到特征的鉴别性呢?第一、可以在设计特征向量时尽量引入domain knowledge;第二、对于提取出来的特征做选择、变换和再学习。当然这些不属于机器学习算法要管的部分,而是数据预处理的部分。
参考:
从决策树学习谈到贝叶斯分类算法、EM、HMM_v_JULY_v的博客-CSDN博客
https://github.com/yingzk/MyML/blob/master/A-Decision%20Tree/ppt/hbchap9.pdf
参考地址:LiveToolkit