【写在前面】
最近因为工作原因,需要做文本过滤任务,即从海量文本中过滤掉杂质文本——也可以理解为感兴趣的文本。这是一个特殊的文本分类任务。特殊在于,只有两个类别;而且杂质文本的数量远小于正常文本的数量。
先不理会它的特殊性。我们就按照文本分类任务来做。首先想到的,自然是号称最简单、最高效的naive bayes模型。不过实践起来,发现遇到的问题挺多。模型不复杂,但在应用的时候,还需要考虑一些问题。
【问题定义】
这是一个分类问题,即将一些样本分到若干个类别c当中。通常,类别用整数表示,对于两个类别,可以用+1和-1来表示,也可以用0和1来表示。而样本的表示方法,通常用向量来表示,如:X = {x(0), x(1), x(2).....}。大写的X表是一个向量,这个向量代表了样本集合中的一个样本。小写的x表示向量X中的一个分量,表征样本的某种属性,例如:大小、光泽、啥啥的。而x(i)的取值,则表示这种属性的具体取值,可以是连续值,用实数表示,也可以是离散值,用整数表示。
总的来说,输入是一个R维的空间,输出是一个整数类型的值。其实分类器,可以看作R维空间的超平面,将R为空间分成若干个部分,每个部分就是一个类别,用一个整数值来表示。
【朴素贝叶斯】
那么朴素贝叶斯模型是怎么解决这个问题的呢?我们去掉“朴素”两个字,先看贝叶斯模型。
贝叶斯公式,在机器学习里面还被称为是“黄金公式”,很多模型的最初推导,都是从贝叶斯公式得来的。针对上面的问题,对于新的样本X,直观地说,我们要找到 p(c|X) 概率值最大的c,来作为样本X的类别。这个怎么算呢?就用到贝叶斯公式,如下:
p(c|X) = p(c, X) / p(X) = p(X|c) * p(c) / p(X)
因为p(X)只和输入样本相关,对所有类别来讲都是相同的,在求最优化问题的时候可以不予以考虑。即:
argmax p(c|X) = argmax p(X|c) * p(c)
上面公式将条件概率分解了,成为先验概率和条件概率的乘积。先验概率p(c)很好估计,因为c的可能取值不会太多。条件概率p(X|c)就麻烦了,因为X是个向量,R维的。R维空间的点多了去了。假设每个维度可以取值的个数是m,则X所有可能个数是m^R。用最大似然方法根本没法估计——样本还没参数多。btw:最大似然的基本假设是大数定律,即当样本趋向于无穷大的时候,估计的概率才和真是的概率相同。这时候,“朴素”两个字就起作用了。所谓的朴素贝叶斯模型,是在上面模型的基础上做了这样一个独立性假设:输入空间的每一个维度的取值是相互独立的,他与类别之间的条件概率可以分解为各个维度与类别的条件概率的乘积,如下:
p(X|c) = p(x(0), x(1), x(2)...|c) = p(x(0)|c) *p(x(1)|c) *p(x(2)|c) ......p(x(R)|c)
这样一来,就将联合概率分解为每个维度的子概率的乘积。而对于每个维度的条件概率p(x(i)|c)是比较好估计的,参数空间是m*|C|,其中m是维度取值的个数,|C|是类别个数。如果算上R个维度,参数空间也不过是R*m*|C|,远比m^R这样的指数复杂度小。对于每个维度的条件概率p(x(i)|c)可以用最大似然方法估计概率值。好,这就是“朴素贝叶斯”模型。
朴素贝叶斯模型为了算法效率而做了独立性假设,这个假设对于绝大多数的问题都是不成立的。有些研究也尝试着放宽这个假设,即在一定程度上将各个维度之间的联系加入到模型当中,不过实验效果表明,这种扩展模型的性能往往还不如原始的朴素贝叶斯模型。
【训练与预测】
其实这一节的内容在上文都有cover到。这节,我们思考一下,如果我们来写一个朴素贝叶斯分类器的话——原理如上——我们要怎样写?
本科的时候老师就教我们,在设计程序之前,要先设计好数据结构。那么,对于朴素贝叶斯模型,需要什么样的参数?参数之间的关系是什么?需要如下几种参数:
- 所有类别的类别标签,标志都有哪些类别
- 所有输入样本R维空间标签,标志着维度,也对应着我们在现实中考虑用哪些因素来对样本进行分类
- 在R维空间中,每一维的取值参数空间。对于不同维度,有可能取值空间相同,例如对于文本分类任务,每一个维度是词表中的词,取值空间为{0,1}空间,即表示新样本是否包含这个词;而不同纬度也有可能取值空间不同,例如对于天气预报任务,需要考虑因素譬如说为气压和节气,气压为一个实数值,而节气为离散值。
- 以上三点回答了“模型都有哪些因素需要表示”这个问题,接下来需要回答的是“模型的这些因素都有哪些联系”这样的问题。
- 类别的先验概率p(c(k)),其中c(k)是第k个类别
- 类别与输入空间每一维度的每一个可能取值的条件概率——有点拗口哈:假设X的第i维是x(i),他有m个可能的取值,分别表示为 x(i, 0), x(i, 1)......x(i, m-1),那么朴素贝叶斯模型需要知道 p ( x(i,j) | c(k) )的值。
p ( x(i,0) | c(k) ) = 1.0 -p ( x(i,1) | c(k) )