Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1964829
  • 博文数量: 606
  • 博客积分: 9991
  • 博客等级: 中将
  • 技术积分: 5725
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-17 19:07
文章分类

全部博文(606)

文章存档

2011年(10)

2010年(67)

2009年(155)

2008年(386)

分类: Java

2009-05-21 15:48:44

贝叶斯公式是在1763年提出来的:

假定B1,B2,……是某个过程的若干可能的前提,则P(Bi)是人们事先对各前提条件出现可能性大小的估计,称之为验前概率.如果这个过程得到了一个结果A,那么贝叶斯公式提供了我们根据A的出现而对前提条件做出新评价的方法.P(Bi∣A)既是对前提Bi的出现概率的重新认识,称 P(Bi∣A)为验后概率.经过多年的发展与完善,贝叶斯公式以及由此发展起来的一整套理论与方法,已经成为概率统计中的一个冠以“贝叶斯”名字的学派,在自然科学及国民经济的许多领域中有着广泛应用.

一. 贝叶斯过滤算法的基本步骤

1) 收集大量的垃圾邮件和非垃圾邮件,建立垃圾邮件集和非垃圾邮件集。
2) 提取邮件主题和邮件体中的独立字串例如 ABC32,¥234等作为TOKEN串并统计提取出的TOKEN串出现的次数即字频。按照上述的方法分别处理垃圾邮件集和非垃圾邮件集中的所有邮件。
3) 每一个邮件集对应一个哈希表,hashtable_good对应非垃圾邮件集而hashtable_bad对应垃圾邮件集。表中存储TOKEN串到字频的映射关系。
4) 计算每个哈希表中TOKEN串出现的概率P=(某TOKEN串的字频)/(对应哈希表的长度),替换存储哈希表的映射关系,概率P替换字频,TOKEN串到概率P的映射关系。
5) 综合考虑hashtable_good和hashtable_bad,推断出当新来的邮件中出现某个TOKEN串时,该新邮件为垃圾邮件的概率。数学表达式为:
A事件----邮件为垃圾邮件;
t1,t2 …….tn代表TOKEN串
则P(A|ti)表示在邮件中出现TOKEN串ti时,该邮件为垃圾邮件的概率。

P1(ti)=(ti在hashtable_good中的值)
P2(ti)=(ti在hashtable_ bad中的值)
则 P(A|ti)= P1(ti)/[(P1(ti)+ P2(ti)];
/*
假设有三个哈希表hashtable_good、hashtable_ bad和hashtable_ unkown

P1(ti)=(ti在hashtable_good中的值)
P2(ti)=(ti在hashtable_ bad中的值)
P3(ti)=(ti在hashtable_unkown中的值)
则 P(A|ti)= P1(ti)/[(P1(ti)+ P2(ti)+ P3(ti)];
 
四、五..个哈希表类似
*/
6) 建立新的哈希表 hashtable_probability存储TOKEN串ti到P(A|ti)的映射
7) 至此,垃圾邮件集和非垃圾邮件集的学习过程结束。根据建立的哈希表 hashtable_probability可以估计一封新到的邮件为垃圾邮件的可能性。
当新到一封邮件时,按照步骤2)生成TOKEN串。查询hashtable_probability得到该TOKEN 串的键值。
假设由该邮件共得到N个TOKEN串,t1,t2…….tn, hashtable_probability中对应的值为P1,P2,。。。。。。PN,
P(A|t1 ,t2, t3……tn)表示在邮件中同时出现多个TOKEN串t1,t2…….tn时,该邮件为垃圾邮件的概率。
由复合概率公式可得
P(A|t1 ,t2, t3……tn)=(P1*P2*。。。。PN)/[P1*P2*。。。。。PN+(1-P1)*(1-P2)*。。。(1-PN)]
当P(A|t1 ,t2, t3……tn)超过预定阈值时,就可以判断邮件为垃圾邮件。

二. 贝叶斯过滤算法举例

例如:一封含有“法学家”字样的垃圾邮件 A
和 一封含有“法律”字样的非垃圾邮件B
根据邮件A生成hashtable_ bad,该哈希表中的记录为
法:1次
学:1次
家:1次
计算得在本表中:
法出现的概率为0。3
学出现的概率为0。3
家出现的概率为0。3
根据邮件B生成hashtable_good,该哈希表中的记录为:
法:1
律:1
计算得在本表中:
法出现的概率为0。5
律出现的概率为0。5
综合考虑两个哈希表,共有四个TOKEN串: 法 学 家 律
当邮件中出现“法”时,该邮件为垃圾邮件的概率为:
P=0。3/(0。3+0。5)=0。375
出现“学”时:
P=0。3/(0。3+0)=1
出现“家“时:
P=0。3/(0。3+0)=1
出现“律”时
P=0/(0+0。5)=0;
由此可得第三个哈希表:hashtable_probability 其数据为:
法:0。375
学:1
家:1
律:0

当新到一封含有“功律”的邮件时,我们可得到两个TOKEN串,功 律
查询哈希表hashtable_probability可得
P(垃圾邮件| 功)=1
P (垃圾邮件|律)=0
此时该邮件为垃圾邮件的可能性为:
P=(0*1)/[0*1+(1-0)*(1-1)]=0
由此可推出该邮件为非垃圾邮件
 
Java 代码:

/* Description:贝叶斯算法判断垃圾邮件
 * * author:Tony
 * * date: 2007/10/23
 */


import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.cn.*;

import java.util.*;
import java.io.*;

public class Bayes
{
     private Hashtable badHash;
     private Hashtable goodHash;
     private Hashtable probabilityHash;
     //初始化

     public void init()throws Exception
     {
         badHash = new Hashtable();
         goodHash = new Hashtable();
         buildEmailHash("D:\\JavaWorkSpace\\Bayes\\src\\data\\badEmail",badHash);
         buildEmailHash("D:\\JavaWorkSpace\\Bayes\\src\\data\\goodEmail",goodHash);
         buildNewHashTable();
        
     }
     //创建垃圾邮件哈希表

     public void buildEmailHash(String path, Hashtable table) throws Exception
     {
         String badInput = readFile(path);
     ChineseTokenizer tokenizer = new ChineseTokenizer(
              new StringReader(badInput));
     Token token;
     Hashtable tempHash = new Hashtable();
     double rate = 0.0;
     int total = 0;
         while ((token = tokenizer.next()) != null)
         {
             total++;
             String temp = token.termText();
             if(table.containsKey(temp))
             {
                 int counter = (Integer)tempHash.get(temp);
                 counter++;
                 tempHash.remove(temp);
                 tempHash.put(temp, counter);
             }
             else
             {
                 tempHash.put(temp, 1);
             }
         }
         //将垃圾邮件中字符及其概率放入badhash中

         for(Iterator it = tempHash.keySet().iterator(); it.hasNext();)
         {
             String key = (String)it.next();
             rate = (Integer)tempHash.get(key)/total;
             table.put(key, rate);
         }
     }
     /*创建新的probability Hash表,其中的概率表示
     在邮件中出现 TOKEN 串 ti 时,该邮件为垃圾邮件的概率
     */

     public void buildNewHashTable()
     {
        for(Iterator it = badHash.keySet().iterator(); it.hasNext();)
         {
             String key = (String)it.next();
             // P ( A|ti ) =P2 ( ti ) /[ ( P1 ( ti ) +P2 ( ti ) ]

             double badRate = (Double)badHash.get(key);
             double allRate = badRate;
             if(goodHash.containsKey(key))
             {
                 allRate += (Double)goodHash.get(key);
             }
             probabilityHash.put(key, (badRate/allRate));
         }
     }

     //读文件

     public String readFile(String path)throws Exception
     {
         BufferedReader br = new BufferedReader(
                 new FileReader(path));
         String str = "";
         while(true)
         {
             if(br.readLine() == null) break;
             str += br.readLine();
         }
         br.close();
         return str;
     }
     //判断是否为垃圾邮件 返回true表示非垃圾邮件 返回false表示是垃圾邮件

     public boolean judgeEmail(String email, double weight) throws Exception
     {
         //P(A|t1 ,t2, t3……tn)=(P1*P2*……PN)/[P1*P2*……PN+(1-P1)*(1-P2)*……(1-PN)]

         ChineseTokenizer tokenizer = new ChineseTokenizer(
                 new StringReader(email));
     Token token;
     boolean flag = true;
     double rate = 1.0;
     double tempRate = 1.0;
     double finalRate = 0.0;
         while ((token = tokenizer.next()) != null)
         {
             String key = token.termText();
             if(!probabilityHash.containsKey(key))
             {
                 break;
             }
             else
             {
                 double temp = (Double)probabilityHash.get(key);
                 tempRate *= 1 - temp;
                 rate *= temp;
             }
         }
         finalRate = rate/(rate + tempRate);
         if(finalRate > weight) flag = false;
         return flag;
     }
     public static void main(String args[]) throws Exception
     {
         Bayes bayes = new Bayes();
         bayes.init();
         String email ="";
         double weight = 0.5;
         if(bayes.judgeEmail(email, weight))
         {
             System.out.println("It is OK!");
         }
         else
         {
             System.out.println("It is wrong!");
         }
     }

}

阅读(1141) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~