65.9K
CodeProject 正在变化。 阅读更多。
Home

朴素贝叶斯定理

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (17投票s)

2009年3月2日

CPOL

4分钟阅读

viewsIcon

108240

downloadIcon

8641

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

Screenshot.JPG

引言

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

probability.JPG

接下来的部分将描述一些将要使用的基本概率公式

条件概率:一个事件的概率可能取决于另一个事件的发生或不发生。这种依赖性用条件概率来表示

P(A|B)

“在已知B已经发生的情况下A发生的概率”或“在B中选择A的概率”

注意,B先给出,然后我们找出B中A的比例

ABProp.JPG

根据上面的公式:如果条件概率等于边缘概率,则事件A与事件B是独立的。

P(B|A) = P(B)
P(A|B) = P(A) 

从公式中,贝叶斯定理说明了先验概率:在我们获得任何数据或任何新证据之前,我们假设的无条件概率。简单来说,这是在观察到数据之前我们知识的状态。

同样也陈述了后验概率:在我们根据新数据进行修正之后,关于我们假设(我们知识的状态)的条件概率。

似然性是我们假设成立的情况下,基于观测数据的条件概率。

贝叶斯定理

bayesTheorem.JPG

托马斯·贝叶斯(约1702年 - 1761年4月17日)是一位英国数学家和长老会牧师,他以提出以他名字命名的特定情况的定理而闻名:贝叶斯定理,该定理在他去世后发表。

以下是数学形式化以及一个垃圾邮件过滤器的例子,但请记住基本思想。

贝叶斯分类器使用贝叶斯定理,该定理指出

bayesianClassifier.JPG

将每个属性和类标签视为一个随机变量,给定一个具有属性(A1、A2、…、An)的记录,目标是预测类C。具体来说,我们想找到使P(C| A1,A2,…An)最大的C值。

所采用的方法是使用贝叶斯定理计算所有C值的后验概率P(C| A1,A2,…An)。

finalBT.JPG

因此,您选择使P(C| A1,A2,…An)最大的C值。这等同于选择使P(A1,A2,…An | C) P(C)最大的C值。

为了简化朴素贝叶斯分类器的任务,我们假设属性具有独立的分布。

朴素贝叶斯定理具有以下优缺点:

优点

  1. 处理定量和离散数据
  2. 对孤立的噪声点具有鲁棒性
  3. 通过忽略实例来处理缺失值
  4. 在概率估计计算过程中
  5. 快速且节省空间
  6. 对不相关的特征不敏感
  7. 二次决策边界

缺点

  • 如果条件概率为零
  • 假设特征独立

朴素贝叶斯预测要求每个条件概率非零。否则,预测概率将为零。

zeroProb.JPG

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

lapla.JPG

这些的解释超出了本教程的范围。

程序

为了区分垃圾邮件和非垃圾邮件,我将使用以下技术和假设

  1. 我将按语言(垃圾邮件或非垃圾邮件),然后按单词,然后按计数进行排序
  2. 如果一个词不存在,考虑使用拉普拉斯平滑来近似P(word|class)
  3. 我将使用以下表格进行分析

antispam-table.txt 文件包含内容过滤用于确定消息是否为垃圾邮件的每个单词。在每个单词旁边,有三个数字。第一个数字是反垃圾邮件引擎分配的标识符。第二个数字是该单词在非垃圾邮件中出现的次数。第三个数字是该单词在垃圾邮件中出现的次数。

table_content.JPG

http://support.ipswitch.com/kb/IM-20030513-DM01.htm

用于统计过滤的反垃圾邮件表和用于短语过滤的新短语列表。

我已经从CSV文件创建了一个数据库。请参阅教程。我还附上了Excel计算作为参考。代码如下:

  1. 删除或替换任何已知或未知的特殊字符,以便只使用单词进行概率计算。最好坚持使用小写或将所有内容转换为小写。(我没有这样做。)
    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("&", "");
  2. 分离每个单词并从数据库中查找相应的值。该值显示了该单词在垃圾邮件或非垃圾邮件中找到的次数。如果找不到该单词,则使用拉普拉斯平滑或将其设为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()));
    }
  3. 通过将每个单词与总概率相乘来获得最终概率
    //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;
  4. 在表格中显示结果
    //Show results in table
    Label6.Text = NonSpamPercent.ToString();
    Label7.Text = SpamPercent.ToString();

    将结果进行比较,并根据最高概率确定是垃圾邮件还是非垃圾邮件。

    if (SpamPercent > NonSpamPercent)
    Label8.Text = "Spam Mail";
    else Label8.Text = "NonSpam Mail";
  5. 最后,如果您已确定一封电子邮件为垃圾邮件,请更新数据库中每个单词的值。与非垃圾邮件相同。如果数据库中不存在该值,则为其插入以供将来训练。训练越多,分类效果越好。
    //insert words or add new word and count for future training
    //TO DO: .....

历史

  • 2009年2月27日:教程草稿(无源代码)
  • 2009年3月1日:程序下载和输出截图
© . All rights reserved.