模式识别贝叶斯分类器实现垃圾邮件分类代码全

1.1 题目的主要研究内容

(1)工作的主要描述

利用贝叶斯模型实现简单的垃圾邮件分类,将正常邮件和垃圾邮件分别识别出来并分类。

  1. 系统流程图

模式识别贝叶斯分类器实现垃圾邮件分类代码全_第1张图片

1.2 题目研究的工作基础或实验条件

软件环境:Windows10

Python版本:3.7

相关模块:scikit-learn模块;jieba模块;numpy模块;以及⼀些Python⾃带的模块。

1.3 数据集描述

使用的中文邮件数据集和中文停用词表,其中spam文件夹中有7775封垃圾邮件,normal文件夹中有7063封正常邮件,test文件夹中有392封测试邮件,test文件夹中,文件名在1至200的为正常邮件,文件名7801~8000的为垃圾邮件。

1.4 特征提取过程描述

由于词典里的词数量太多,只保留了词频最高的4000个词作为最终创建的词典。词典准备好之后,把每封信的内容转换为词向量,其维度为4000,每一维代表一个高频词在该邮件中出现的频率,最后将这些词向量合并为一个大的特征向量矩阵,其大小为:(7063+7775)×4000,即前7063行为正常邮件的特征向量,其余为垃圾邮件的特征向量。

1.5 分类过程描述

对测试集中的每一封邮件用结巴分词,并用停用表进行简单过滤,然后使用正则表达式过滤掉邮件中的非中文字符,并计算得到P(s|w)(在已知词向量w的条件下求包含该词向量邮件是否为垃圾邮件的概率,s表示分类为垃圾邮件)最高的15个词,在计算过程中,若该词只出现在垃圾邮件的词典中,则令P(w|s')=0.01,反之亦然;若都未出现,则令P(s|w)=0.4(这里做的几个假设基于前人做的一些研究工作得出的)。然后计算得到的每封邮件中重要的15个词的贝叶斯概率,若概率>阈值α,则判为垃圾邮件,否则判为正常邮件。

1.6 主要程序代码

功能函数:

import jieba;

import os;

class spamEmailBayes:

    # 获得中文停用词表

    def getStopWords(self):

        stopList=[]

        for line in open("../data/中文停用词表.txt"):

            stopList.append(line[:len(line)-1])

        return stopList;

    # 分别保存正常邮件与垃圾邮件中出现的词有多少邮件出现该词,得到两个词典

    def get_word_list(self,content,wordsList,stopList):

        #分词结果放入res_list

        res_list = list(jieba.cut(content))

        for i in res_list:

            if i not in stopList and i.strip()!='' and i!=None:

                if i not in wordsList:

                    wordsList.append(i)

                    

    # 若列表中的词已在词典中,则加1,否则添加进去

    def addToDict(self,wordsList,wordsDict):

        for item in wordsList:

            if item in wordsDict.keys():

                wordsDict[item]+=1

            else:

                wordsDict.setdefault(item,1)

                            

    def get_File_List(self,filePath):

        filenames=os.listdir(filePath)

        return filenames

    

    # 通过计算每封邮件中p(s|w)(在已知词向量w的条件下求包含该词向量邮件是否为垃圾邮件的概率)来得到对分类影响最大的15个词

    def getTestWords(self,testDict,spamDict,normDict,normFilelen,spamFilelen):

        wordProbList={}

        for word,num  in testDict.items():

            if word in spamDict.keys() and word in normDict.keys():

                pw_s=spamDict[word]/spamFilelen

                pw_n=normDict[word]/normFilelen

                ps_w=pw_s/(pw_s+pw_n)

                wordProbList.setdefault(word,ps_w)

            if word in spamDict.keys() and word not in normDict.keys():

                # 若该词只出现在垃圾邮件的词典中,则令P(w|s′)=0.01

                pw_s=spamDict[word]/spamFilelen

                pw_n=0.01

                ps_w=pw_s/(pw_s+pw_n)

                wordProbList.setdefault(word,ps_w)

            if word not in spamDict.keys() and word in normDict.keys():

                pw_s=0.01

                pw_n=normDict[word]/normFilelen

                ps_w=pw_s/(pw_s+pw_n)

                wordProbList.setdefault(word,ps_w)

            if word not in spamDict.keys() and word not in normDict.keys():

                # 若都未出现,概率设为0.4

                wordProbList.setdefault(word,0.4)

        sorted(wordProbList.items(),key=lambda d:d[1],reverse=True)[0:15]

        return (wordProbList)

    

    #计算贝叶斯概率

    def calBayes(self,wordList,spamdict,normdict):

        ps_w=1

        ps_n=1

         

        for word,prob in wordList.items() :

            print(word+"/"+str(prob))

            ps_w*=(prob)

            ps_n*=(1-prob)

        p=ps_w/(ps_w+ps_n)

        return p

        print(str(ps_w)+""+str(ps_n))

    #计算预测结果正确率

    def calAccuracy(self,testResult):

        rightCount=0

        errorCount=0

        for name ,catagory in testResult.items():

            if (int(name)<1000 and catagory==0) or(int(name)>1000 and catagory==1):

                rightCount+=1

            else:

                errorCount+=1

        return rightCount/(rightCount+errorCount)

主函数:

from spam.spamEmail import spamEmailBayes

import re

# spam类对象

spam=spamEmailBayes()

# 保存词频的词典

spamDict={}

normDict={}

testDict={}

# 保存每封邮件中出现的词

wordsList=[]

wordsDict={}

# 保存预测结果,key为文件名,值为预测类别

testResult={}

# 分别获得正常邮件、垃圾邮件及测试文件名称列表

normFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\normal")

spamFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\spam")

testFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\test")

# 获取训练集中正常邮件与垃圾邮件的数量

normFilelen=len(normFileList)

spamFilelen=len(spamFileList)

# 获得停用词表,用于对停用词过滤

stopList=spam.getStopWords()

# 获得正常邮件中的词频

for fileName in normFileList:

    wordsList.clear()

    for line in open("../data/normal/"+fileName):

        # 过滤掉非中文字符

        rule=re.compile(r"[^\u4e00-\u9fa5]")

        line=rule.sub("",line)

        # 将每封邮件出现的词保存在wordsList中

        spam.get_word_list(line,wordsList,stopList)

    # 统计每个词在所有邮件中出现的次数

    spam.addToDict(wordsList, wordsDict)

normDict=wordsDict.copy()  

# 获得垃圾邮件中的词频

wordsDict.clear()

for fileName in spamFileList:

    wordsList.clear()

    for line in open("../data/spam/"+fileName):

        rule=re.compile(r"[^\u4e00-\u9fa5]")

        line=rule.sub("",line)

        spam.get_word_list(line,wordsList,stopList)

    spam.addToDict(wordsList, wordsDict)

spamDict=wordsDict.copy()

# 获得测试邮件中的词频

for fileName in testFileList:

    testDict.clear( )

    wordsDict.clear()

    wordsList.clear()

    for line in open("../data/test/"+fileName):

        rule=re.compile(r"[^\u4e00-\u9fa5]")

        line=rule.sub("",line)

        spam.get_word_list(line,wordsList,stopList)

    spam.addToDict(wordsList, wordsDict)

    testDict=wordsDict.copy()

    # 通过计算每个文件中p(s|w)来得到对分类影响最大的15个词

    wordProbList=spam.getTestWords(testDict, spamDict,normDict,normFilelen,spamFilelen)

    # 对每封邮件得到的15个词计算贝叶斯概率

    p=spam.calBayes(wordProbList, spamDict, normDict)

    if(p>0.9):

        testResult.setdefault(fileName,1)

    else:

        testResult.setdefault(fileName,0)

# 计算分类准确率

testAccuracy=spam.calAccuracy(testResult)

for i,ic in testResult.items():

    print(i+"/"+str(ic))

print(testAccuracy)  

1.7 运行结果及分析

运行结果:

对每封邮件得到的15个词的贝叶斯概率:模式识别贝叶斯分类器实现垃圾邮件分类代码全_第2张图片

邮件判别结果:(0代表正常邮件,1代表垃圾邮件)

分类准确率:模式识别贝叶斯分类器实现垃圾邮件分类代码全_第3张图片

结果分析:模式识别贝叶斯分类器实现垃圾邮件分类代码全_第4张图片

在392封邮件(正常邮件与垃圾邮件各一半)的测试集中,测试结果的分类准确率为95.15%,在仅仅统计词频计算概率的情况下,分类结果还是相当不错的。

功能函数:
import jieba;
import os;
class spamEmailBayes:
    # 获得中文停用词表
    def getStopWords(self):
        stopList=[]
        for line in open("../data/中文停用词表.txt"):
            stopList.append(line[:len(line)-1])
        return stopList;
    # 分别保存正常邮件与垃圾邮件中出现的词有多少邮件出现该词,得到两个词典
    def get_word_list(self,content,wordsList,stopList):
        #分词结果放入res_list
        res_list = list(jieba.cut(content))
        for i in res_list:
            if i not in stopList and i.strip()!='' and i!=None:
                if i not in wordsList:
                    wordsList.append(i)
                    
    # 若列表中的词已在词典中,则加1,否则添加进去
    def addToDict(self,wordsList,wordsDict):
        for item in wordsList:
            if item in wordsDict.keys():
                wordsDict[item]+=1
            else:
                wordsDict.setdefault(item,1)
                            
    def get_File_List(self,filePath):
        filenames=os.listdir(filePath)
        return filenames
    
    # 通过计算每封邮件中p(s|w)(在已知词向量w的条件下求包含该词向量邮件是否为垃圾邮件的概率)来得到对分类影响最大的15个词
    def getTestWords(self,testDict,spamDict,normDict,normFilelen,spamFilelen):
        wordProbList={}
        for word,num  in testDict.items():
            if word in spamDict.keys() and word in normDict.keys():
                pw_s=spamDict[word]/spamFilelen
                pw_n=normDict[word]/normFilelen
                ps_w=pw_s/(pw_s+pw_n) 
                wordProbList.setdefault(word,ps_w)
            if word in spamDict.keys() and word not in normDict.keys():
                # 若该词只出现在垃圾邮件的词典中,则令P(w|s′)=0.01
                pw_s=spamDict[word]/spamFilelen
                pw_n=0.01
                ps_w=pw_s/(pw_s+pw_n) 
                wordProbList.setdefault(word,ps_w)
            if word not in spamDict.keys() and word in normDict.keys():
                pw_s=0.01
                pw_n=normDict[word]/normFilelen
                ps_w=pw_s/(pw_s+pw_n) 
                wordProbList.setdefault(word,ps_w)
            if word not in spamDict.keys() and word not in normDict.keys():
                # 若都未出现,概率设为0.4
                wordProbList.setdefault(word,0.4)
        sorted(wordProbList.items(),key=lambda d:d[1],reverse=True)[0:15]
        return (wordProbList)
    
    #计算贝叶斯概率
    def calBayes(self,wordList,spamdict,normdict):
        ps_w=1
        ps_n=1
         
        for word,prob in wordList.items() :
            print(word+"/"+str(prob))
            ps_w*=(prob)
            ps_n*=(1-prob)
        p=ps_w/(ps_w+ps_n)
        return p
        print(str(ps_w)+""+str(ps_n))

    #计算预测结果正确率
    def calAccuracy(self,testResult):
        rightCount=0
        errorCount=0
        for name ,catagory in testResult.items():
            if (int(name)<1000 and catagory==0) or(int(name)>1000 and catagory==1):
                rightCount+=1
            else:
                errorCount+=1
        return rightCount/(rightCount+errorCount)

主函数:
from spam.spamEmail import spamEmailBayes
import re
# spam类对象
spam=spamEmailBayes()
# 保存词频的词典
spamDict={}
normDict={}
testDict={}
# 保存每封邮件中出现的词
wordsList=[]
wordsDict={}
# 保存预测结果,key为文件名,值为预测类别
testResult={}
# 分别获得正常邮件、垃圾邮件及测试文件名称列表
normFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\normal")
spamFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\spam")
testFileList=spam.get_File_List(r"C:\Users\8\Desktop\BayesSpam\data\test")
# 获取训练集中正常邮件与垃圾邮件的数量
normFilelen=len(normFileList)
spamFilelen=len(spamFileList)
# 获得停用词表,用于对停用词过滤
stopList=spam.getStopWords()
# 获得正常邮件中的词频
for fileName in normFileList:
    wordsList.clear()
    for line in open("../data/normal/"+fileName):
        # 过滤掉非中文字符
        rule=re.compile(r"[^\u4e00-\u9fa5]")
        line=rule.sub("",line)
        # 将每封邮件出现的词保存在wordsList中
        spam.get_word_list(line,wordsList,stopList)
    # 统计每个词在所有邮件中出现的次数
    spam.addToDict(wordsList, wordsDict)
normDict=wordsDict.copy()  

# 获得垃圾邮件中的词频
wordsDict.clear()
for fileName in spamFileList:
    wordsList.clear()
    for line in open("../data/spam/"+fileName):
        rule=re.compile(r"[^\u4e00-\u9fa5]")
        line=rule.sub("",line)
        spam.get_word_list(line,wordsList,stopList)
    spam.addToDict(wordsList, wordsDict)
spamDict=wordsDict.copy()

# 获得测试邮件中的词频
for fileName in testFileList:
    testDict.clear( )
    wordsDict.clear()
    wordsList.clear()
    for line in open("../data/test/"+fileName):
        rule=re.compile(r"[^\u4e00-\u9fa5]")
        line=rule.sub("",line)
        spam.get_word_list(line,wordsList,stopList)
    spam.addToDict(wordsList, wordsDict)
    testDict=wordsDict.copy()
    # 通过计算每个文件中p(s|w)来得到对分类影响最大的15个词
    wordProbList=spam.getTestWords(testDict, spamDict,normDict,normFilelen,spamFilelen)
    # 对每封邮件得到的15个词计算贝叶斯概率
    p=spam.calBayes(wordProbList, spamDict, normDict)
    if(p>0.9):
        testResult.setdefault(fileName,1)
    else:
        testResult.setdefault(fileName,0)
# 计算分类准确率
testAccuracy=spam.calAccuracy(testResult)
for i,ic in testResult.items():
    print(i+"/"+str(ic))
print(testAccuracy)  

你可能感兴趣的:(模式识别综合应用代码全,python,开发语言,算法,人工智能,机器学习)