首先要明确的一点是朴素贝叶斯属于生成式模型,指导思想是贝叶斯公式。
文本分类
假设现在有一些评论数据,需要识别出这篇文本属于正向评论还是负面评论,也就是对文本进行分类。用数学语言描述就是:
假设已经有分好类的 N 篇文档:(d1,c1)、(d2,c2)、(d3,c3)……(dn,cn),di 表示第 i 篇文档,ci 表示第 i 个类别。目标是:寻找一个分类器,这个分类器能够:当丢给它一篇新文档 d,它就输出 d(最有可能)属于哪个类别 c。
词袋模型
文本分类需要寻找文本的特征。而词袋模型就是表示文本特征的一种方式。词袋模型只考虑一篇文档中单词出现的频率 (次数),用每个单词出现的频率作为文档的特征。
朴素贝叶斯分类器
朴素贝叶斯分类器是一个概率分类器。假设现有的类别 C={c1,c2,……cm}。给定一篇文档 d,文档 d 最有可能属于哪个类呢?这个问题用数学公式表示如下:
c^ 就是:在所有的类别 C={c1,c2,……cm} 中,使得:条件概率 P (c|d) 取最大值的类别。使用贝叶斯公式,将上式转换成如下形式:
对类别 C 中的每个类型,计算 (p (d|c)* p (c))/p (d) 的值,然后选取最大值对应的那个类型 ci ,该 ci 就是最优解 c^,因此,可以忽略掉分母 p (d),可以变成如下形式:
这个公式由两部分组成,前面那部分 P (d|c) 称为似然函数,后面那部分 P (c) 称为先验概率。
前面提到使用词袋模型来表示 文档 d,文档 d 的每个特征表示为:d={f1,f2,f3……fn},那么这里的特征 fi 其实就是单词 wi 出现的频率(次数),因此可以转化成如下形式:
对文档 d 做个假设:假设各个特征之间是相互独立的。那么 p (f1,f2……fn|c)=p (f1|c) p(f2|c) …… * p (fn|c),转化成如下形式:
由于每个概率值很小(比如 0.0001)若干个很小的概率值直接相乘,得到的结果会越来越小。为了避免计算过程出现下溢 (underflower),引入对数函数 Log,在 log space 中进行计算。然后使用词袋模型的每个单词 wi 出现频率作为特征,得到如下公式:
训练朴素贝叶斯分类器
训练朴素贝叶斯的过程其实就是计算先验概率和似然函数的过程。
①先验概率 P (c) 的计算
P (c) 的意思是:在所有的文档中,类别为 c 的文档出现的概率有多大?假设训练数据中一共有 Ndoc 篇文档,只要数一下类别 c 的文档有多少个就能计算 p (c) 了,类别 c 的文档共有 Nc 篇,先验概率的计算公式如下:
先验概率其实就是准备干一件事情时,目前已经掌握了哪些信息了。
②似然函数 P (wi|c) 的计算
由于是用词袋模型表示一篇文档 d,对于文档 d 中的每个单词 wi,找到训练数据集中所有类别为 c 的文档,数一数 单词 wi 在这些文档(类别为 c)中出现的次数:count (wi,c),
然后,再数一数训练数据集中类别为 c 的文档一共有多少个单词,计算二者之间的比值,就是似然函数的值。似然函数计算公式如下:
其中 V,就是词库。(有些单词在词库中,但是不属于类别 C,那么 count (w,c)=0)
unknow words 的情形
假设只考虑文本二分类:将文档分成 positve 类别,或者 negative 类别,C={positive, negative}。
在训练数据集中,类别为 positive 的所有文档 都没有 包含 单词 wi = fantastic(fantastic 可能出现在类别为 negative 的文档中)那么 count (wi=fantastic,ci=positive)=0 。那么:
而注意到前面公式五中的累乘,整篇文档的似然函数值为 0,也就是说:如果文档 d 中有个单词 fantastic 在类别为 c 的训练数据集文档中从未出现过,那文档 d 被分类到类别 c 的概率为 0,尽管文档 d 中还有一些其他单词(特征),而这些单词所代表的特征认为文档 d 应该被分类到类别 c 中。
解决方案就是 add-one smoothing。似然函数公式变成如下形式:
朴素贝叶斯分类示例
假设训练数据集有五篇文档,其中 Negative 类别的文档有三篇,用符号 ‘-‘ 标识;Positive 类别的文档有二篇,用符号 ‘+’ 标识,它们的内容如下:
1 | - just plain boring |
测试数据集T 有一篇文档dt,内容如下:
1 | predictable with no fun |
朴素贝叶斯分类器会把“predictable with no fun”归为哪个类呢?根据训练朴素贝叶斯分类器的过程,需要计算先验概率和似然函数。
由于训练数据集中一共有 5 篇文档,其中类别 ‘+’ 的文档有 2 篇,类别为 ‘-‘ 的文档有 3 篇,因此先验概率:P (c)=P (‘-‘)=Nc/Ndoc=3/5=0.6
类别为’+’ 的文档有 2 篇,故 P (c)=P (‘+’)=Nc/Ndoc=2/5=0.4
对测试数据集文档 dt 中的每个单词,似然函数采用 “add-one smoothing” 处理,计算相应的似然概率:
首先单词 predictable 在训练数据集中 类别为’-‘的文档中只出现了 1 次,类别为’-‘的文档一共有 14 个单词,训练数据集中两种类型的文档加起来一共有 23 个单词,但是有三个单词 (and、
very、the) 重复出现了两次,故词库 V 的大小为 20。因此单词 predictable 对应的似然概率如下:
p(predictable|’-‘)=(1+1)/(14+20)=2/34
同理:p (predictable|’+’)=(0+1)/(9+20)=1/29 (predictable 没有在类别为’+’的训练数据集中出现过)
类似地:p (no|’-‘)=(1+1)/(14+20) p (no|’+’)=(0+1)/(9+20)
p(fun|’-‘)=(0+1)/(14+20) p(fun|’+’)=(1+1)/(9+20)
因此,测试集中的文档 d 归类为 ‘-‘ 的概率为:0.6 (221)/343 = 6.110-5
测试集中的文档 d 归类为 ‘+’ 的概率为:0.4(112)/293 =3.210-5
比较上面两个概率的大小,就可以知道将 “predictable with no fun” 归为 ‘-‘ 类别。
代码实现
1 | import numpy as np |
输出结果:
1 | 类别0的单词个数:14,类别1的单词个数:9,总词表长度:20 |