朴素贝叶斯实现垃圾邮件识别

import numpy as np
from collections import Counter

'''词频进行统计,统计出每个单词出现的个数
输入的是一个一个很长的文章或者句子,应该有断点吧 ,还是在jieba中处理,就在说了
return:1,key-value 2,就是0,1,2这种标记.貌似第一种比较容易实现
'''
'''用counter一次计数文件,这样对原始文件只操作一次。
统计每个单词出现的次数
   输入:文件地址
   输出:{word1:num1,word2:num2...}
   hamcnt:正常邮件
   spamcnt:垃圾邮件
   totanNum:邮件总数
   hamNum: 正常邮件数目
   spamNum: 垃圾邮件数目
'''
def seperate(filename):
    hamcnt = Counter() #正常邮件统计字典
    spamcnt = Counter()#垃圾邮件统计字典
    file = open(filename,encoding='gb18030',errors = 'ignore')#处理不能打开的异常
    totalNum=0  #邮件的总数
    hamNum=0   #正常邮件数
    spamNum=0  #垃圾邮件数
    i=0
    for line in file:
        i=i+1
        new = line.split(' ')   #将单个文本,按照单词分开
        totalNum = totalNum +1
        if 'ham' in new[0]:   #如果是正常邮件,进入hamcnt统计
            hamNum =hamNum+1
            for word in new[1:]:
                hamcnt[word] +=1
        if 'spam' in new[0]:      #如果是垃圾邮件,进入spamcnt统计
            spamNum =spamNum +1
            for word in new[1:]:
                spamcnt[word] +=1
    print('*********样本的总的行数是%s**********'%i)
    return hamcnt,spamcnt,totalNum,hamNum,spamNum
'''preData是一个句子,或者一封邮件。
return:true,false 是否是垃圾邮件
过程:1,先进行分表,分为两类---调用seperate()
     2,进行词频统计,为下面计算概率做准备
     3,计算两种情况的概率:p1(spam)p(word1|spam)p(word2|spam)p(word3|spam)...
         *****修正公式p(word|spam) = (1+wordExistNUm)/(wordsExistNum+wordsNum)
     4,比较概率,确定输出结果
'''
def train(filename,preData):
    hamcnt,spamcnt,totalNum,hamNum,spamNum = seperate(filename)
    #计算词的总数
    wordNumerOfham = 0
    for key in hamcnt:
        wordNumerOfham += hamcnt[key]
    wordNumerOfspam = 0
    for key in spamcnt:
        wordNumerOfspam +=spamcnt[key]
   #对要预测的文本进行拆解
    newPreData = preData.split(' ')
    #计算概率p(spam|total),p(ham|total)
    p1_spam = hamNum/totalNum
    p1_ham = spamNum/totalNum
    hamProbablity =1
    spamProbability =1
    for word in newPreData:
        try:  
            hamProbablity = hamProbablity*(hamcnt[word]+1)/(wordNumerOfham+len(hamcnt))
        except:  #文本中没有该单词
            hamProbablity = hamProbablity*1/(wordNumerOfham+len(hamcnt))
    res1 = hamProbablity*p1_ham
    
    for word in newPreData:
        try:
            spamProbability = spamProbability*(spamcnt[word]+1)/(wordNumerOfspam+len(spamcnt))
        except:
            spamProbability = spamProbability*(1)/(wordNumerOfspam+len(spamcnt))
    res2 = spamProbability*p1_spam
    
    if res1 == res2:
        print('res1',res1,'res2',res2)
    if res1>res2:
        print('不是垃圾邮件!','正常文件:',res1,'垃圾邮件',res2)
        return 0
    else:
        print('是垃圾邮件','正常文件:',res1,'垃圾邮件',res2)
        return 1

'''外部调用过程:
1,读取数据
2,训练,得到结果
'''
filename = 'D:\\学习\\计算机培训\\机器学习部分\\贝叶斯分类器\\smsspamcollection\\SMSSpamCollection.txt'

preData = 'You have won ?1,000 cash or a ?2,000 prize! To claim, call09050000327'
res = train(filename,preData)

朴素贝叶斯的实现理论:http://blog.csdn.net/gane_cheng/article/details/53219332 (这个链接里面也有数据集)

英文的网址:https://nlp.stanford.edu/IR-book/html/htmledition/naive-bayes-text-classification-1.html#eqn:documentprior

说明:统计的文本函数式counter,对统计英文文本速度还是很快的。


猜你喜欢

转载自blog.csdn.net/tortelee/article/details/79219659