经过前面几节课的学习,我们了解了机器学习的基本概念、Regression、以及error的来源。而今天要处理的task是Classification。
Why do we need to classify
为什么我们需要解决分类问题?分类有什么意义?与我何干?
两个好处
- 界定、分析、处理问题
- 提高效益
举两个例子:
快速记忆:
「分类」本身就是一种「结构」,而人脑通过「结构」来理解和存储信息。我们知道,短时记忆的容量只有4个单位。那么,为什么有人能够同时记住更多的信息?能够思考更复杂、信息量更大的问题?
你能否在20秒内记忆下图中各种颜色的各种形状的物体分别有几个?
倘若不行,试着对其先进行「分类」,再进行「编码」:比如纵向分为橙色、绿色、蓝色,横向分为圆形、正方形、三角形,并记录个数。如果你选择从左到右,之上而下编码,那么结果就是140,013,320。
一开始可能会有些困难,熟悉之后你会发现,通过「分类」,你记忆的效率更高了。
人脸识别:当你拥有一个人脸的数据库时,你就能把每一个人作为一个类别,进行分类。可用于高铁站身份认证、手机支付、网上实名认证等,省下不少人力物力。
What is Classification
特征(用于分析适合处理什么样的task)
Regression:输入一个object x,输出一个scalar。
Classification:输入一个object x,输出一个class,表示object x属于哪一个class。
以宝可梦为例,已知宝可梦有18种类型,我们现在要做的是设计一个宝可梦种类的分类器;我们要找到一个function,这个function的input是某一个宝可梦,它的output是这只宝可梦属于18个类别中哪一类型。
How to do Classification
数字化
为了将宝可梦作为function的input,我们对宝可梦进行数字化,比如我们只考虑宝可梦的Total(数值总和)、HP(生命值)、Attack(攻击)、Defense(防御)、SP Atk(特攻)、SP Def(特防)、Speed(速度),那么我们输入的就是一个包含7个元素的vector。
以皮卡丘为例,我们可以用以上7种特性数值构成的vector来描述它。
用回归来做分类是否合适?
以二分类问题为例
Training:输入为class1的输出为1,输入为class2的输出为-1
Testing:输出趋近于1判定为class1;输出趋近于-1判定为class2 。
假设我们真的找到了一个model,就像下边左图一样,绿色的线表示,也就是class1和class2的分界线。这种情况下,输出值接近-1的宝可梦都集中在绿线的左上方;值接近1的宝可梦都集中在绿线右下方,这样的表现是不错的。
但是上述现象只在样本点比较集中地分布在输出为-1和1的时候才成立。
如果像下图右边所示,我们已经知道绿线为最好的那个model的分界线,它的左上角的值小于0;右下角的值大于0,越往右下方值越大。所以,如果要考虑右下角这些点的话,用绿线对应的model,它们做Regression的时候输出会是远大于1的,但是做Regression的时候,实际上已经给所有的点都打上了-1和1的标签(因为你想做的是分两个类),你会希望这些蓝色点在model中的输出越接近1(接近所谓的“真值”)越好,所以这些输出值远大于1的点,它对于绿线对于的model来说是error,是不好的。因此,这组样本点通过Regression训练出来的model会是紫色这条分界线对应的model。这对于Regression来说是合理的,因为相对于绿线,它减小了由右下角这些点所带来的error。但这对于Classification来说结果是不好的。
Regression的output是连续性质的数值,而Classification的输出是离散性质的点。我们很难找到一个Regression的function使得大部分样本点的输出都集中在某几个离散的点附近。
因此,Regression定义model好坏的方式,对Classification是不适用的。
注:下图为三维图像在二维平面上的投影,颜色代表y的大小。
另外,值得注意的是,如果是多元分类问题,还把class1的target当作1,class2的target当作2,class3的target当作3是不合适的。
因为当你这样做的时候,Regression就会认为class1和class2的关系是比较近的,而class1和class3的的关系是比较远的,但是实际上这种关系可能根本不存在。
理想方案
model
比较合适的方案是,我们定义一个函数g(x)。如果g(x) > 0,那么输出为class1,如果g(x) < 0,那么输出为class2。
这个方法保证了model的输出都是离散的表示class的数值。
Loss function
我们在这里把Loss function定义为,即这个model在所有的training data上predict错误的次数,也就说分类错误的次数越少,这个function表现的越好。
Find the best function
由于Loss function无法微分,因此是无法用Gradient Descent去做的。我们可以选择用感知机或者支持向量机去做,但在这里先用另一个方法来做。
Solution:Generative model(生成模型)
概率论基本概念
贝叶斯公式:
现在我们将问题简化一下,仅考虑二分类问题,那么此时的贝叶斯公式可以改为.
假设我们现在拿到了一个已知种类的宝可梦x,想要知道这个宝可梦x属于class1还是class2 。
这就是一个贝叶斯的问题,「已知宝可梦x,求它属于class1的概率」就等于(class1自身发生的概率乘以class1里含有x的概率)除以(class1自身发生的概率乘以class1里含有x的概率加上class2自身发生的概率乘以class2里含有x的概率)。
贝叶斯公式 = 单条路径概率/所有路径概率
因此,我们想要知道宝可梦x属于class1或是class2的概率,只需要知道4个值:
P(C1)、P(C2)、P(x|C1)、P(x|C2)
通过training data我们可以得到这4个值,进而求出P(x)。
这就是所谓的Generative Model(生成模型)。为什么叫它生成模型呢?因为有这个model的话,就可以拿它来生成x。如果你计算出了每一个x出现的概率,就可以用这个distribution来生成x,sample x出来。
Prior probability(先验概率)
P(C1)和P(C2)这两个值被称为Prior probability(先验概率)。
我们在ID < 400的宝可梦中取水系和普通系的作为训练集,剩下的作为测试集。
ps:为了更严谨,可以引入Validation。
现在用于训练的有79只水系宝可梦和61只普通系宝可梦。
因此:P(C1) = 79 / (79 + 61) = 0.56; P(C2) = 61 / (79 + 61) = 0.44
高斯分布
假设每个宝可梦都由一个包含7个数值的向量表示。但现在我们仅考虑「防御」和「特防」,且假设所有我们采样的代表宝可梦的点都服从高斯分布。
那么我们能否预测水系宝可梦是下图这只海龟的概率是多少呢?
要知道,这只海龟不在我们采样的点里( 因为我们取的是ID < 400的宝可梦,而这只海龟的ID > 400 ),这是否代表P(海龟|Water) = 0 ?
答案是否定的。我们可以想象说这已有的79只水系宝可梦其实是所有水系宝可梦中的冰山一角,假设水系宝可梦的「特防」和「防御」是从一个高斯分布中采样出来的,上图只是采样了79个点,但是从整个高斯分布里采样出这个海龟的概率并不是零。
那么根据已有的79个点,找到它的高斯分布呢?
高斯分布
对于高斯函数:,μ表示均值,Σ表示协方差。
输入一个x,输出是采样点为x的概率。高斯函数的形状由均值μ和协方差Σ共同决定。
在μ不同,Σ相同时,分布中心点位置不一样,但分散程度一致;在μ相同,Σ不同时,分布中心点位置一样,但分散程度不同。
Maximum Likehood(最大似然估计)
为了找到采样点的高斯分布,我们只需要去估测出这个高斯分布的均值μ和协方差Σ即可。
估测μ和Σ的方法就是最大似然估计法,极大似然估计法的思想是,找出最特殊的μ和Σ,从它们共同决定的高斯函数中再次采样出79个点,使“得到的分布情况与当前已知79个点的分布情况相同”这件事的可能性最大。
实际上可以存在不同的高斯分布,它们都包含这79个点。但是我们想要找的是发生概率最大的那一个。
为此我们需要的就是找到μ*和Σ*,使得似然函数达到最大值。
如果样本点服从高斯分布,我们有结论:
即使L(μ,Σ)最大的那组参数,实际上就是所有样本点的均值和协方差。
注:这里假设各个样本点xi之间相互独立。
通过上面的方法,我们分别得到水系宝可梦和普通系宝可梦样本点最好的高斯分布的均值和协方差为:
此时,我们终于可以进行分类工作啦。
已知:
P(C1) = 79 / (79+61) = 0.56
P(C2) = 61 / (79+61) = 0.44
P(x|C1) =
P(x|C2) =
可以计算得
如果P(C1|x) > 0.5,则我们认为它属于class1(水系)。
小结一下
我们先是假设采样点的两项feature都服从高斯分布,随后找到了满足最大似然估计的高斯函数(也就找到了从class1和class2中取出x的概率),这样我们就可以计算任意P(C1|xi) 、P(C2|xi) ,判断取的宝可梦是水系还是普通系。甚至我们还可以求P(xi)。
来看结果
- 当我们考虑2个feature(防御、特防)时,在测试集上的准确率仅有47%。
- 当我们考虑7个feature时,在测试集上的准确率达到了54%。
我们仅考虑2个feature时效果不好,想着模型在更高维度上会不会有更好的表现,于是尝试考虑7个feature,但结果仍旧不如人意。
调整模型
其实之前使用的model是不常见的,你是不会经常看到每一个高斯函数都有自己的平均值μ和协方差Σ的,比较常见的是,不同的class可以共用一个协方差矩阵Σ。
其实Σ是和输入的feature size的平方成正比的,所以当feature的数量很大的时候,Σ大小的增长是可以非常快的。在这种情况下,给不同的高斯函数以不同的Σ,会造成model的参数太多,而参数太多会导致该model的variance过大,出现overfitting的现象。因此,不同的class选用同一个Σ,可以有效降低overfitting造成的error。
找到μ1,μ2,Σ,使得似然函数得到最大值:
其中Σ是Σ1和Σ2的加权,权重分别为class1样本点数占总样本点数的比例、class2样本点数占总样本点数的比例,具体证明见Bishop的书。
共用Σ后,我们发现class1和class2的分界线由原来的曲线变成了线性的直线,且准确率有所提升。
可选的分布
为什么选用高斯?
你也许会有一个疑惑,为什么我们选用高斯模型,而不选择别的分布函数。其实这里只是拿高斯举个例子而已,你完全可以选择自己喜欢的概率分布函数。
如果你选择的是简单的分布函数,相对来说你的bias就比较大,variance就比较小;你选择复杂的函数,相对来说你的bias就比较小,variance就比较大。
你可以都试试,最后选择合适的分布函数作为model就可以了。
伯努利分布
对于输入仅考虑2个特征的问题,你可以假设样本点服从伯努利分布。
比如宝可梦有某个feature是二元的,它只有两种结果:是或不是。这个时候就不太可能是高斯分布了,而很有可能是伯努利分布。
朴素贝叶斯分类法
假设x = [x1 x2 … xk]中每一个维度的xk的分布都是相互独立的,它们之间的协方差都是0,那么我们可以把
class1中x产生的几率分解为class1中x1、x2、… xk产生的几率的乘积。
注:这里的x1到xk指的是feature。
那么在这里每一个维度的分布函数都是一维的高斯分布,等于是说,原来那么多维度的高斯分布函数,它的协方差矩阵变成了对角的,在不是对角线的地方,值都是0,这样就可以更加减少需要的参数量,就可以得到一个更简单的model。
我们把上述这种方法叫做「朴素贝叶斯分类法」,如果真的明确了所有的feature之间是相互独立的,是不相关的,使用朴素贝叶斯分类法的表现会是不错的。但如果假设不成立,那么它的bias就会很大(朴素贝叶斯分类法本质就是减少参数)。
当然对于前面宝可梦的分类,这种model就不适合。因为各种feature之间并不独立。
总之,找model的原则是,尽量减少不必要的参数,但是不要缺省必要参数。
将后验概率转化成sigmoid函数
我们可以将复杂的后验概率函数化简成一个简单的sigmoid函数。
如果class1和class2对应的高斯分布函数共用一个协方差Σ,那么经过计算,sigmoid函数中的参数z又可以写成的形式。
即,这也就解释了为什么当class1和class2共用Σ的时候,它们之间的分界线会是线性的。td
在Generative model中,我们要做的事情就是,找到,然后计算出w和b。把它们代入这个式子就可以计算出概率了。
但是,当你看到这个式子的时候,也许你会想,既然我的最终目标是要找到一个向量w和标量b,那么我必须要经过这么多的复杂计算吗?我能否直接找到w和b呢?
这,是下一章的内容。
Conclusion
- 回归的方法不适合分类
- 我们做回归时,输出的是连续的值,这个值可以是任何值。而我们做分类时,输出是离散的值。
- 这次我们将Loss function定义为,我们希望它足够小。
- 为了找到最好的function,我们采用了Generative model,并假设了采样点服从高斯分布,通过计算最大似然估计找到了最好的高斯概率分布函数,为分类提供了条件。
- 为了提高准确率,选择不同类共用一个协方差Σ。
- 我们发现后验概率可以用sigmoid函数线性表达。