朴素贝叶斯定理
使用朴素贝叶斯定理的垃圾邮件过滤器

引言
概率被定义为不确定性状态或事件的信息的量化度量。它有一个索引,范围从0到1。它也可以通过事件数量占总实验次数的比例来近似。如果一个状态的概率为0(零),我们确定该状态不会发生。但是如果概率为1,事件肯定会发生。概率为0.5意味着我们对将要发生的状态存在最大的疑问。

接下来的部分将描述一些将要使用的基本概率公式
条件概率:一个事件的概率可能取决于另一个事件的发生或不发生。这种依赖性用条件概率来表示
P(A|B)
“在已知B已经发生的情况下A发生的概率”或“在B中选择A的概率”
注意,B先给出,然后我们找出B中A的比例

根据上面的公式:如果条件概率等于边缘概率,则事件A与事件B是独立的。
P(B|A) = P(B)
P(A|B) = P(A)
从公式中,贝叶斯定理说明了先验概率:在我们获得任何数据或任何新证据之前,我们假设的无条件概率。简单来说,这是在观察到数据之前我们知识的状态。
同样也陈述了后验概率:在我们根据新数据进行修正之后,关于我们假设(我们知识的状态)的条件概率。
似然性是我们假设成立的情况下,基于观测数据的条件概率。
贝叶斯定理

托马斯·贝叶斯(约1702年 - 1761年4月17日)是一位英国数学家和长老会牧师,他以提出以他名字命名的特定情况的定理而闻名:贝叶斯定理,该定理在他去世后发表。
以下是数学形式化以及一个垃圾邮件过滤器的例子,但请记住基本思想。
贝叶斯分类器使用贝叶斯定理,该定理指出

将每个属性和类标签视为一个随机变量,给定一个具有属性(A1、A2、…、An)的记录,目标是预测类C。具体来说,我们想找到使P(C| A1,A2,…An)最大的C值。
所采用的方法是使用贝叶斯定理计算所有C值的后验概率P(C| A1,A2,…An)。

因此,您选择使P(C| A1,A2,…An)最大的C值。这等同于选择使P(A1,A2,…An | C) P(C)最大的C值。
为了简化朴素贝叶斯分类器的任务,我们假设属性具有独立的分布。
朴素贝叶斯定理具有以下优缺点:
优点
- 处理定量和离散数据
- 对孤立的噪声点具有鲁棒性
- 通过忽略实例来处理缺失值
- 在概率估计计算过程中
- 快速且节省空间
- 对不相关的特征不敏感
- 二次决策边界
缺点
- 如果条件概率为零
- 假设特征独立
朴素贝叶斯预测要求每个条件概率非零。否则,预测概率将为零。

为了克服这个问题,我们使用以下之一的概率估计

这些的解释超出了本教程的范围。
程序
为了区分垃圾邮件和非垃圾邮件,我将使用以下技术和假设
- 我将按语言(垃圾邮件或非垃圾邮件),然后按单词,然后按计数进行排序
- 如果一个词不存在,考虑使用拉普拉斯平滑来近似P(word|class)
- 我将使用以下表格进行分析
antispam-table.txt 文件包含内容过滤用于确定消息是否为垃圾邮件的每个单词。在每个单词旁边,有三个数字。第一个数字是反垃圾邮件引擎分配的标识符。第二个数字是该单词在非垃圾邮件中出现的次数。第三个数字是该单词在垃圾邮件中出现的次数。
http://support.ipswitch.com/kb/IM-20030513-DM01.htm
我已经从CSV文件创建了一个数据库。请参阅教程。我还附上了Excel计算作为参考。代码如下:
- 删除或替换任何已知或未知的特殊字符,以便只使用单词进行概率计算。最好坚持使用小写或将所有内容转换为小写。(我没有这样做。)
String inputContent = TextBox1.Text; inputContent = inputContent.Replace("\t", ""); inputContent = inputContent.Replace("\n", ""); inputContent = inputContent.Replace(",", ""); inputContent = inputContent.Replace(".", ""); inputContent = inputContent.Replace(";", ""); inputContent = inputContent.Replace(":", ""); inputContent = inputContent.Replace("?", ""); inputContent = inputContent.Replace("!", ""); inputContent = inputContent.Replace("&", "");
- 分离每个单词并从数据库中查找相应的值。该值显示了该单词在垃圾邮件或非垃圾邮件中找到的次数。如果找不到该单词,则使用拉普拉斯平滑或将其设为1(原因如上所述)。
char seperator = ' '; String[] words = inputContent.Split(seperator); int CountWords = words.Length; //keep P(score) and multiply double SpamPercent = 1.0; double NonSpamPercent = 1.0; //look for percentage of word in nonspam for (int i = 0; i < CountWords; i++) { String thisword = words[i]; String DBaseValue = (BayesTheorem.FindNonSpamWord(thisword)); if (DBaseValue == "") { //Perform Laplace or just equal to 1 DBaseValue = "1"; } NonSpamPercent = NonSpamPercent * (Convert.ToDouble(DBaseValue) / Convert.ToInt32(BayesTheorem.TotalNonSpam())); } //look for percentage of word in spam for (int i = 0; i < CountWords; i++) { String thisword = words[i]; String DBaseValue = (BayesTheorem.FindSpamWord(thisword)); if (DBaseValue == "") { //Perform Laplacin or just equal to 1 DBaseValue = "1"; } SpamPercent = SpamPercent * (Convert.ToDouble(DBaseValue) / Convert.ToInt32(BayesTheorem.TotalSpam())); }
- 通过将每个单词与总概率相乘来获得最终概率
//get P(mailType).P(Word | MailType) for Spam SpamPercent = SpamPercent * Convert.ToDouble(Label4.Text) * 100; //get P(mailType).P(Word | MailType) for NonSpam NonSpamPercent = NonSpamPercent * Convert.ToDouble(Label3.Text) * 100;
- 在表格中显示结果
//Show results in table Label6.Text = NonSpamPercent.ToString(); Label7.Text = SpamPercent.ToString();
将结果进行比较,并根据最高概率确定是垃圾邮件还是非垃圾邮件。
if (SpamPercent > NonSpamPercent) Label8.Text = "Spam Mail"; else Label8.Text = "NonSpam Mail";
- 最后,如果您已确定一封电子邮件为垃圾邮件,请更新数据库中每个单词的值。与非垃圾邮件相同。如果数据库中不存在该值,则为其插入以供将来训练。训练越多,分类效果越好。
//insert words or add new word and count for future training //TO DO: .....
历史
- 2009年2月27日:教程草稿(无源代码)
- 2009年3月1日:程序下载和输出截图