1.3.1 开发准备

在这个开发案例中,我们将演示TDD的开发模式。开发前需要做3项准备:邮件数据准备、开发工具准备和朴素贝叶斯定理基础知识学习。

1.数据准备

原始邮件语料来自公开数据源[1],内容全部为英文,其中垃圾邮件为500封,正常邮件为1400封。为了专注于测试驱动开发贝叶斯邮件分类器,笔者已先将数据进行清洗,每个文件包含一行邮件正文,示例如下:

lowest rates available for term life insurance take a moment and fill out our online form to see the low rate you qualify for save up to 70 from regular rates smokers accepted http www newnamedns com termlife representing quality nationwide carriers act now to easily remove your address from the list go to http www newnamedns com stopthemailplease please allow 48 72 hours for removal

我们只需读取文件、统计单词,然后实现朴素贝叶斯分类器即可。

2.测试工具

Python语言内置有断言,可将其作为测试的工具,例如:


assert 1==2,' 断言失败'

这里我们选用unittest包,因为它比其他常见的测试包更为强大。表1-3列出了unittest包中的常用断言,详情可参考https://docs.python.org/3/library/unittest.html

表1-3 unittest中的常用断言

使用示例如下:


import unittest
t_test = unittest.TestCase()
t_test.assertEqual(1,2,' 断言失败')

在新建测试类时继承unittest.TestCase即可使用这些断言。TestCase中有两个特殊函数setUp()和tearDown(),分别在测试函数的前后执行,方便测试程序前置准备和后置清理工作。

3.朴素贝叶斯定理

下面以大家熟知的天气预报为例简要说明朴素贝叶斯定理。

(1)条件概率

设事件A为5级大风,事件B为晴天。出现5级大风时是晴天的条件概率表示为式(1-3)。

假设获取到的100天的数据里A出现了5天,则P(A)=0.05,在5天里有一天是晴天,则P(A∩B)=0.01,所以P(B|A)=0.01/0.05=0.2。这种正向求解的方式又称正向概率。

(2)朴素贝叶斯

计算条件概率的另一种方式是使用贝叶斯定理,已知P(B|A),求P(A|B),即求反向概率:已知是晴天,求出现5级大风的概率。贝叶斯公式表示为式(1-4)。

假设在100天里,晴天出现了50天,那么P(B)=0.5,代入式(1-4)可求得P(A|B)=0.02。如果再加入更多的事件,例如气温(用A2表示),则问题的求解将变得更复杂,上述事件概率分别表示为P(B|A,A2)和P(A,A2|B)。为此我们先看多变量非独立联合条件概率分布的链式法则,见式(1-5)。

以上是通用表达式,但在现实中计算复杂,例如求解P(B|A,A2),按贝叶斯公式得到式(1-6)。

上式不够简洁,可以先按贝叶斯和链式法则展开P(B,A,A2)再观察,如式(1-7)所示。

式(1-7)中,假设A和A2独立,可简化为式(1-8)。

以上即为朴素贝叶斯的计算方式。

此时式(1-6)将简化为式(1-9)。

对于所有的B来说,P(A,A2)都是固定的,所以此处将B扩展为晴天B1和雨天B2。当要判断晴天或雨天这样的二分类问题时,只要比较P(B1|A,A2)和P(B2|A,A2)的大小即可,而这等价于判断P(B1)P(A|B1)P(A2|B1)和P(B2)P(A|B2)P(A2|B2)的大小。

在下面的朴素贝叶斯邮件分类器中,B1和B2分别表示垃圾邮件和正常邮件,A则代表各个单词。此时式(1-9)的含义为:当某封邮件中出现了某些单词的情况下,该邮件为垃圾邮件的概率。其求解方法是分别在训练样本中的垃圾邮件和正常邮件中统计各单词的词频,而P(B)则表示垃圾邮件和正常邮件的先验概率。我们简单地以样本中的邮件情况作为先验,比如垃圾邮件P(B1)=500/(1400+500)=0.2632,正常邮件P(B2)=1400/(1400+500)=0.7368。

(3)贝叶斯决策

我们按照贝叶斯决策理论做如下二分类决策。

·垃圾邮件:P(垃圾|X)>P(正常|X)

·正常邮件:P(垃圾|X)≤P(正常|X)

等号意为:正常邮件被判断为垃圾邮件的危害比垃圾邮件被判断为正常邮件大。

[1] https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham_2.tar.bz2;https://spamassassin.apache.org/old/publiccorpus/20030228_spam.tar.bz2