前面已经谈到我们收集的数据:
一共收集了有P个人脸图片(正样本),N个非人脸图片(负样本),记总数为M=P+N。
已经知道如何提取特征——Haar特征:
假设我们使用的图像大小为W*H,全部的haar特征总数为F个(F很大,数以万计)。
现在对每个样本图片提取全部特征,第i个样本图片得到F个特征值组成特征向量Xi[F],那么所有样本的Xi按行存入矩阵X[M][F],矩阵X为一个M行F列二维矩阵,X[i][j]为第i个样本的第j个haar特征的值。注意后面我们提到样本,指的就是图片提取的特征向量Xi,不是指原始图片数据。
为了标识每个样本属于人脸还是非人脸,定义Y[M]为类别标记,正样本Y[i]=+1,负样本Y[i]=-1。
此外用W[M]记录样本权值,表示每个样本的重要性。一开始我们让正样本的权值和为0.5,负样本和也为0.5,每个正样本的权值为0.5/P,负样本0.5/N.所有样本的权值之和为1。权值的用途用到时再说,暂时不管它。
更具体一些,假设我们有9个样本数据,前5个是人脸,后4个是其他图片,对这9个样本提取第f个haar特征值,记录到下表中,其中Idx为样本的序号,Y为样本的类别+1表示正样本,-1为负样本,val为haar特征数值。
看得不直观,我们来画个图,红*表示正样本,绿圆圈表示负样本。
有了数据如何进行区分呢?
最简单最直接的想法就是这个分界线,也就是我们常说的阈值threshold,简记为t,正样本的值都在分界线的左边(或者右边),而负样本都落在另外一边。这样正负样本就被分开了,问题也就解决了。因为我们找到的规律就是,所有人脸图片的第f个haar特征值都小于t,而其他事物的haar特征值都大于t值。当给我一个新的图片时,只要计算第f个特征值就可以做出判断。
想法很完美,但是再看看上面的数据,我们找不到这样的t,太糟糕了有么有。理想很丰满,现实很骨感。真的勇士要敢于直面惨淡的现实。不能完全分开也不要灰心,那就让分界线两边的样本都尽量偏向某一类的样本。
这个时候我们需要一个衡量选取的阈值t好坏的标准,也就是反映划分后的误差情况。例如当我们取阈值1.5时,图中的蓝色线表示。这时候左边只有一个正样样本,我们可以把左边的定义为正样本类的区间,这样落在左边的都是正样本,误差为0。再来看右边,有4个正样本和4个负样本,不管把右边作为正样本区间还是负样本区间,误差都有4个。我们可以把错分的个数定义为上面说的评价划分好坏的标准,术语叫做误差函数Error function,它是t的函数,记为E(t)。也就是取阈值为1.5时,总分类误差为E(1.5) = 0+4,因为我们度量的是总体误差,需要把两边的误差求和。
学习的过程就是通过尝试不同的t的取值,找到能过使误差函数最小参数t。例如通过计算我们找到当t取5.5时,误差达到最小为E(5.5) = 1 + 1 = 2。把左边作为正样本区间,只包含一个负样本,误差为1,同样右边作为负样本区间,误差也为1,总误差为2。
得到这一结果有什么作用呢,或者说对区分人脸和非人脸有什么帮助呢?
我们先来看蓝线的左边区间,统计一下,正样本有4个,负样本只有1个,也就是说落在这个区间里面,它属于正样本的概率为p(y=+1)=4/(4+1)=0.8,属于负样本的概率仅为0.2。同样的可以计算右边区间正负样本的概率分别为0.75和0.25。
当没有这个结果时我们只能随机猜测,分类正确的概率为0.5,有了上面结论我们可以把分类概率提高到0.8或0.75,这就是学习的效果。
上面我们只讨论了某个特征f的特征值进行划分的情况,实际上我们有F个特征,如果只用一个其他的岂不是都浪费了。之所有提取F个特征,就是为了从海里的特征里面选择最好的特征来进行划分。
我们对F中的每个特征都进行这样的尝试,找到使误差最小的。得重写一下误差函数E(f,t),它是特征f和阈值t的函数,编程让机器遍历所有的f和t的组合找到误差最小的一个,记为split=<fmin,tmin>。得到split后,我们来定义一个函数p(X),让它输出等于给定的样本X属于正样本的概率,设split划分左边正样本概率为pl,右边为pr。则h(X)如下:
有了p(X)函数,我们可以轻松的构造一个分类方法,例如p(X) > 0.5为正样本,p(X) <=0.5为负样本。实际上我们还可以定义一个函数h(X),让它输出[-1,+1]直接的值,因为我们的样本标签值中正样本为+1,负样本为-1。我们把p(X)值接近1的样本,让其h(X)接近+1,p(X)值接近0的使其h(X)接近-1。
h(X) = 2p(X) – 1
我们把函数h取了一个高大上的名字——弱分类器,英文名 Weak classifier。
分类树
我们使用theta划分后会把所有样本一份为二,集左边的样本集合为S0右边为S1,总体误差为S0,S1误差之和。
到这里我们只进行了一次划分,实际上,我们可以把得到的S0,S1进一步划分成更小的区间。还拿上面的数据集做例子。取阈值t=5.5,右边的数据集为S1,它包含4个样本,序号为{1,5,6,8}。
用同样的方法遍历所有的特征和阈值<f,t>的组合,找到能过最小化误差的分割,例如我们找到某个特征f1对应的特征值如上表,显然可以取阈值t=6,因为正样本都大于6,负样本都小于6。这样S1总体的误差为0,比细分之前的1要更小。
我们把一个<f,t>的组合叫做一个分割节点,split node。一个分割节点总是把数据集一分二,然后可以在左右两边的数据上继续分割,创建新的分割节点。直到我们把数据完全划分,也就是总误差为0,或者设置一些结束条件,比如集合上的样本总数不能太小或者限制最大划分的次数也就是节点数。通过多次增加新的节点最终形成了一棵二叉树。
注意一点,在每次尝试增加一个新的节点时,需要尝试增加在现有的每一个叶子节点上leaf k,因为我们的目标是最小化误差,因此总是优先选择能够最快减小误差E的节点。
我们把这样的一棵树叫做CART(Classification And Regression Tree,分类与回归树)。图中的蓝色圆圈表示一个分割节点,也就是上面说的split node,绿色圆圈表示的是一个叶子节点leaf node,它对应于一个划分的区间。任何一个样本从上到下都会最终落到某个叶子节点上。记录每个叶子上的样本集合,然后计算出正负样本的分布比例。红色的直方图表示,这里只有正负两类,直方图只需要两个bin就够了(实际上只需要正样本的比值p就行,因为两外一个值等于1-p)
前面我们提到实际上是只有一个分割节点的情况,是一种特例。如果我们通过学习得到这样一棵CART树,又该如何对一个新的样本X作出预测呢?
首先我们把样本交给第一个分割节点,也就是根节点,它计算响应的特征值并判断,发现样本的特征值比阈值大,然后交给它的右子节点,…,直到最后样本落在了某个叶子节点k中。跟原先的情况一样,在学习节点我们已经记录了落在k中正样本的比例,也就是对应的区间中属于正样本的概率pk。现在既然X落入了这个区间,当然给出的预测p(X)=pk。
同样的,此时的弱分类器仍然是 h(X) = 2p(X) –1。
弱分类器学习过程我们说完了,最后来总结一下分割的数学意义。
上面我们谈到一共有F个haar特征,也就是说整个特征空间为Ω=RF,任何一个样本的特征向量X都是该空间的一个点。我们再来看一个分割节点split node0=<f0,t0>做了什么事情,它定义了一个超平面Plane:X[f0]=t0,该平面把整个特征空间一分为二,分成左右两个子空间记为Ω0l, Ω0r,
当我们在左边加一个分割节点splite node1=<f1,t1>时,它在Ω0l子空间上定义了超平面X[f1]=t1,将Ω0l一分为二。
最后每个叶子实际上就是特征空间中的一个超立方体,所有叶子的超立方体的并集就是整个特征空间。