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.youkuaiyun.com/gane_cheng/article/details/53219332 (这个链接里面也有数据集)
说明:统计的文本函数式counter,对统计英文文本速度还是很快的。