惰性学习法
我们接触比较多的分类方法,例如决策树,关联规则挖掘,支持向量机,贝叶斯分类,后向传播等等,都可以被称为“急切学习法”,他们接受训练集的信息,在对新的元组(测试集中)进行检验之前,就已经构造好了泛化模型(即分类器),然后根据分类器,直接对新元组分类。所以“急切学习法”的名字很形象:赶紧学(训练之后立即得到分类器),学完之后,直接用(对新元组分类)。
现在我要说一种新的分类方法,最近邻(kNN)分类,和这些“急切学习法”不同,kNN分类并不着急学习,他对于接受的训练元组初始时不做任何处理,只是简单存储,直到接收到测试集中新元组的那一刻,再利用训练集中的元组进行泛化,给出分类结果。这种模式也被称为“惰性学习法”。那kNN分类来说,当接收到新元组需要做检验时,程序计算出与这个新元组(测试元组)最近的k个最近的训练元组,根据多数投票的原则,确定测试元组的类别。具体的算法和注意事项我会在下面详细说明。
和“急切学习法”相比,“惰性学习法”有优势,也有缺点:
先说优点:
- 天生支持增量学习。了解上面我说的那几种“急切学习法”的话,你会明白当训练元组增加时,那些方法即使可以做增量拓展,也很复杂且低效。
- 能对超多变形的复杂决策空间建模。而这可能不太容易被“急切学习法”描述。
再说缺点:
- 计算开销大,了解kNN查询的话,你就知道这种计算执行起来很慢。
- 正因为计算开销大,所以需要有效的存储技术和并行硬件的支持。
不过无论如何,“惰性学习法”(尤其是kNN分类)为我们提供了一种和大多分类方法不同的思路,还是有用武之地的,所以我觉得有必要在此总结。
kNN分类
基本步骤
依次读取训练元组: ,其中 由 个属性 组成。即 ,其中 为训练元组 对于属性 的值。
对所有训练元组的所有属性值做归一化处理。以属性值 为例,假设属性 的最大值为 ,最小值为 ,那么令 归一化变为 :
这样使得所有的属性值取值都在 内,避免了属性的值域不同造成的不同权重的影响。查询k最近邻:kNN的思想非常简单,对于测试元组 ,计算与训练集中(别忘了此时已做完归一化)元组的距离,进一步可以得到和 距离最近的 个元组。这里距离的计算一般使用欧几里得距离,当然也可以根据具体情况的不同,使用最恰当的度量方法。有关数据相似性度量的说明我在博客数据相似性的度量方法总结有着相对详细的解释。欧几里得距离的计算方法如下:
分类:原则就是“多数投票”,在查询到的k个最近邻当中,取最多的类别作为分类结果。
细节说明
关于kNN分类,有5点细节需做进一步说明:
如何确定参数 的值:通常的方法是“试”,从 开始,每次对 加1,再根据测试集数据,通过多轮迭代检验效果最佳的 。一般来说,训练元组越多, 的值越大。当然,具体操作时,针对不同数据的经验也很重要,这是书本上学不来的。
如何处理标称属性的情况:属性如果不是数值,而是标称的,甚至可能既有数值,也有标称。面对这种情况,方法是对标称属性“数值化”,拿颜色举例,红蓝黄三色我们可以定义数值为 (得满足归一化的要求)。如果需要考虑不同标称属性之间差距不同的话,可以为属性值赋予权重来调整,例如,黑色与白色的数值差可以设计的比黑色与蓝色之间的数值差大。
如何处理缺失值:训练元组是收集来的数据,大多时候,非我们所愿。比如一个训练元组或测试元组的某一个或多个属性缺失。通常的做法是“往大了放”。即尽可能地考虑令缺失处的差值最大。具体分两种情况:
- 对于属性 ,某个训练元组的 和测试元组的 都缺失了。这时,令他们一个为0,一个为1,即差值最大,达到1。
- 对于属性 ,某个训练元组的 和测试元组的 缺失了其中一个。这时,计算那个未缺失的属性值归一化后的值(记为 )到0和到1的距离谁大。即计算 和 ,假如前者大,令缺失值为0;反之,令缺失值为1。
如何解决不同属性值权重不同的问题:当数据存在噪声或不相关属性时,权重当然应该是有区别的。办法就是加权,具体实现方法很多,不赘述了。
如何提高分类的计算效率:线性遍历的速度在面对大数据时肯定要完。因此现在比较常用的办法是下面几项:
- 建立搜索树,将线性的计算复杂度降低到log。一般来讲,kd-tree比较擅长做这件事
- 并行计算
- 快速剪枝,通过算法实现计算得到阈值,然后可以只计算训练元组和测试元组的一部分属性的距离,根据阈值判断是否把这个训练元组列入候选集。这样可以快速筛出一个 的候选集,再做精确的判断找出top-k即可。这也是信息检索领域非常时髦的方法。当然,一般对于比较复杂的问题,需要你有很强的数学分析能力才能用好这种方法。