Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

B.2 训练朴素贝叶斯分类器

怎样学习概率 P(c)P(c)P(fic)P(f_i\mid c)?先考虑最大似然估计,也就是直接使用数据中的频率。对于类别先验 P(c)P(c),我们计算训练集中有多少比例的文档属于类别 cc。令 NcN_c 为训练数据中类别为 cc 的文档数,NdocN_{doc} 为文档总数,则:

P^(c)=NcNdoc(B.11)\hat P(c)=\frac{N_c}{N_{doc}}\tag{B.11}

为学习 P(fic)P(f_i\mid c),我们假设一个特征就是某个词存在于文档词袋中,因此需要估计 P(wic)P(w_i\mid c):词 wiw_i 在主题为 cc 的所有文档全部词语中所占的比例。先把类别为 cc 的所有文档连接成一篇很大的“类别 cc”文本,再用 wiw_i 在这个连接文档中的频率作最大似然估计:

P^(wic)=count(wi,c)wVcount(w,c)(B.12)\hat P(w_i\mid c)=\frac{\operatorname{count}(w_i,c)}{\sum_{w\in V}\operatorname{count}(w,c)}\tag{B.12}

这里的词表 VV 是所有类别中全部词类型的并集,而不只是类别 cc 中的词。

然而,最大似然训练有一个问题。假设我们要估计正面类别下 fantastic 的似然,却没有任何同时包含 fantastic 且被标为正面的训练文档;也许它碰巧以讽刺语气出现在负面类别中。此时,这个特征的概率为零:

P^(“fantastic”positive)=count(“fantastic”,positive)wVcount(w,positive)=0(B.13)\hat P(\text{“fantastic”}\mid\text{positive})=\frac{\operatorname{count}(\text{“fantastic”},\text{positive})}{\sum_{w\in V}\operatorname{count}(w,\text{positive})}=0\tag{B.13}

但是,朴素贝叶斯会把所有特征似然朴素地相乘,因此任一类别的似然项中只要出现零概率,该类别的概率就会变成零,不管其他证据如何。

最简单的解决方案是第 3 章介绍的加一(Laplace)平滑。语言模型中通常会用更复杂的平滑算法取代 Laplace 平滑,但它在朴素贝叶斯文本分类中很常用:

P^(wic)=count(wi,c)+1wV(count(w,c)+1)=count(wi,c)+1(wVcount(w,c))+V(B.14)\hat P(w_i\mid c)=\frac{\operatorname{count}(w_i,c)+1}{\sum_{w\in V}(\operatorname{count}(w,c)+1)}=\frac{\operatorname{count}(w_i,c)+1}{\left(\sum_{w\in V}\operatorname{count}(w,c)\right)+|V|}\tag{B.14}

再次注意,词表 VV 必须是所有类别中全部词类型的并集,而不能只包含某个类别 cc 中的词。(请试着说服自己为什么必须如此;参见本附录末尾的练习。)

如果测试数据中的词根本不在词表里,即它没有在任何类别的任何训练文档中出现,该怎么办?对这种未知词的处理办法是忽略它们:从测试文档中删除,不为其计入任何概率。

最后,有些系统还会完全忽略另一类词:thea 之类非常高频的停用词。可以按训练集频率对词表排序,把前 10~100 个词项定义为停用词;也可以采用网上已有的停用词表。然后,从训练文档和测试文档中删除停用词的每次出现,就像它们从未出现过一样。不过,在多数文本分类应用中,停用词表并不能提升性能,因此更常见的做法是使用整个词表而不使用停用词表。

图 B.2 给出最终算法。

函数 TRAIN NAIVE BAYES(D, C) 返回 V、log P(c)、log P(w|c)
  对每个类别 c ∈ C:                         # 计算 P(c)
    N_doc ← D 中的文档数
    N_c ← D 中类别为 c 的文档数
    logprior[c] ← log(N_c/N_doc)
    V ← D 的词表
    bigdoc[c] ← 连接 D 中类别为 c 的所有文档 d
    对 V 中每个词 w:                         # 计算 P(w|c)
      count(w,c) ← w 在 bigdoc[c] 中出现的次数
      loglikelihood[w,c] ← log((count(w,c)+1)/Σ_{w'∈V}(count(w',c)+1))
  返回 logprior、loglikelihood、V

函数 TEST NAIVE BAYES(testdoc, logprior, loglikelihood, C, V) 返回最佳类别 c
  对每个类别 c ∈ C:
    sum[c] ← logprior[c]
    对 testdoc 中每个位置 i:
      word ← testdoc[i]
      若 word ∈ V:
        sum[c] ← sum[c] + loglikelihood[word,c]
  返回 argmax_c sum[c]

图 B.2 使用加一平滑的朴素贝叶斯算法。若要使用加 α\alpha 平滑,把训练时似然计数中的 +1 改为 +α+\alpha