朴素贝叶斯算法实现垃圾邮件分类

目录

1.朴素贝叶斯算法介绍

 1.朴素贝叶斯介绍

2.朴素贝叶斯公式的理解

3.朴素贝叶斯算法优总结

4.朴素贝叶斯实现垃圾邮件分类

4.1垃圾邮件分类问题背景

4.2朴素贝叶斯算法实现垃圾邮件分类的步骤

4.3具体实现

1.数据集准备

2.将词表转换成向量

 3.词集模型

4.词袋模型

5.朴素贝叶斯函数

6.朴素贝叶斯分类函数

7.提取单词

8.垃圾邮件测试函数

运行结果

5.总结


1.朴素贝叶斯算法介绍

 1.朴素贝叶斯介绍

朴素贝叶斯法(Naive Bayes model)是基于贝叶斯定理与特征条件独立假设的分类方法 。朴素贝叶斯算法(Naive Bayesian algorithm) 是应用最为广泛的分类算法之一。

       最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBM)。和决策树模型相比,朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。同时,NBC模型所需估计的参数很少,对缺失数据不太敏感,算法也比较简单。理论上,NBC模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为NBC模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,这给NBC模型的正确分类带来了一定影响。朴素贝叶斯方法是在贝叶斯算法的基础上进行了相应的简化,即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。虽然这个简化方式在一定程度上降低了贝叶斯分类算法的分类效果,但是在实际的应用场景中,极大地简化了贝叶斯方法的复杂性。
 

2.朴素贝叶斯公式的理解

朴素贝叶斯公式

设有样本数据集D{d1,d2,d3,..,dn},对应样本数据的特征属性集X={x1,x2,x3,...,xn},类变量为Y={y1,y2,y3,...,yn},即D可以分为yn个类别。其中x1,x2,x3,...,xn相互独立且随机,则Y的先验概率P1=P(Y),Y的后验概率P2=P(Y|X),由朴素贝叶斯算法可得,后验概率可以由先验概率P1=P(Y)、证据P(X)、类条件概率P(X|Y)计算出:

概率基础复习

  • 联合概率:包含多个条件,且所有条件同时成立的概率
    • 记作:P(A,B)
  • 条件概率:就是事件A在另外一个事件B已经发生条件下的发生概率
    • 记作:P(A|B)
  • 相互独立:如果P(A, B) = P(A)P(B),则称事件A与事件B相互独立

3.朴素贝叶斯算法优总结


(1)优点

朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率
对缺失数据不太敏感,算法也比较简单,常用于文本分类
分类准确度高,速度快


(2)缺点

由于使用了样本属性独立性的假设,所以如果特征属性有关联时其效果不好
需要计算先验概率,而先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳;
 

4.朴素贝叶斯实现垃圾邮件分类

4.1垃圾邮件分类问题背景

垃圾邮件曾经是一个令广大网友非常头痛的问题,长期困扰着邮件运营商和用户。据官方统计,用户收到的电子邮件中80%以上是垃圾邮件。影响我们的正常网络生活而且还占取有限的可用资源;占用大量网络带宽,浪费存储空间,影响网络传输和运算速度;妖言惑众,骗人钱财,传播色情、反动等内容的垃圾邮件,已对现实社会造成严重危害。

       传统的垃圾邮件过滤方法,主要有"关键词法"和"校验码法"等。关键词法的过滤依据是特定的词语,(如垃圾邮件的关键词:“发票”,“贷款”,“利率”,“中奖”,“办证”,“抽奖”,“号码”,“钱”,“款”,“幸运”……等等。)但这种方法效果很不理想,而且容易规避。一是正常邮件中也可能有这些关键词,非常容易误判。二是将关键词进行变形,如“代!开-发/票”,“中奖”如果被拆成“中 ~~~ 奖”可能会识别不了。后来,直到提出了使用“贝叶斯”的方法才使得垃圾邮件的分类达到一个较好的效果,而且随着邮件数目越来越多,贝叶斯分类的效果会更加好。如果将关键词的各种变形都找出来过滤,那是无穷无尽的,而且更容易误判正常邮件。

       校验码法则是计算邮件文本的校验码,再与已知的垃圾邮件进行对比。它们的识别效果都不理想,而且很容易规避。直到2002年,Paul Graham提出使用“贝叶斯方法”过滤垃圾邮件,经过几年的工程化应用,才算解决了这个问题。而这种方法的效果,好的不可思议。此外,这种过滤方法还具有自我学习能力,会根据新收到的邮件,不断调整。收到的垃圾邮件越多,它的准确率就越高。采用的分类方法是通过多个词来判断是否为垃圾邮件,但这个概率难以估计,通过贝叶斯公式,可以转化为求垃圾邮件中这些词出现的概率。
 

4.2朴素贝叶斯算法实现垃圾邮件分类的步骤

(1)提供样本数据(邮件样本):收集相关文本文件,在此我在网上搜集了一些 Enron Email Dataset 数据集

(2)数据读入:第一步将准备的数据文件读入

(3)准备数据(预处理):清除标点符符号、将字符串标记为单词、计算某个单词出现的次数等

(4)数据处理:建立一个集合存储所有出现的单词、统计spam和ham邮件的个数、计算先验概率(即在所有的样本邮件中垃圾邮件和正常邮件的占比)、构建一个字典存储单封邮件中的单词以及其个数

(5)测试:遍历所有的测试集、计算P(内容|垃圾邮件)和P(内容|正常邮件),所有的单词都要进行拉普拉斯平滑、把计算到的P(内容|垃圾邮件)和P(内容|正常邮件)加起来、把先验加上去(P(垃圾邮件)和P(正常邮件))、最后进行预测,如果spam_score > ham_score则标志为1,即垃圾邮件
 

4.3具体实现

1.数据集准备

2.将词表转换成向量

def loadDataSet():
    postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                   ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                   ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                   ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                   ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                   ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classVec = [0, 1, 0, 1, 0, 1]  # 1代表侮辱性文字,0代表正常言论
    return postingList, classVec
 
 
# 创建词汇表
def createVocabList(dataSet):
    vocabSet = set([])  # 创建一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # |表示求并操作
    return list(vocabSet)  # 返回一个不重复的列表
 
 
# 输出文档向量
def setOfwords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)  # 创建一个等长向量并设置为0
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1  # 若出现了单词表中的单词,则将对应值设置为1
        else:
            print("单词:%s 不存在!" % word)
    return returnVec
 
 
# 测试函数效果
 
# 创建实验样本
listPosts, listClasses = loadDataSet()
print('数据集\n', listPosts)
# 创建词汇表
myVocabList = createVocabList(listPosts)
print('词汇表:\n', myVocabList)
# 输出文档向量
print(setOfwords2Vec(myVocabList, listPosts[5]))

 3.词集模型

为输入的邮件构造单词集合

#词集模型
def setOfWord2Vec(vocabList,inputSet):
    returnVec=zeros(len(vocabList))
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]=1
        else:
            print("这个单词不在所有的单词向量里面") 
    return  returnVec

4.词袋模型

#词袋模型
def bagOfword2VecMN(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]+=1
    return  returnVec

5.朴素贝叶斯函数

#朴素贝叶斯训练函数
def trainB0(trainMatrix,trainCategory):
    numTrainDocs=len(trainMatrix)
    numwords=len(trainMatrix[0])
    #对于category为0,1 才可以使用sum
    pAbusive=sum(trainCategory)/float(numTrainDocs)
    p0Num=ones(numwords)
    p1Num=ones(numwords)
 
    p0Denom=2.0
    p1Denom=2.0
    for i in range(numTrainDocs):
        if trainCategory[i]==1:
            p1Num+=trainMatrix[i]
            p1Denom+=sum(trainMatrix[i])
        else:
            p0Num+=trainMatrix[i]
            p0Denom+=sum(trainMatrix[i])
 
    p1Vect=log(p1Num/p1Denom)
    p0Vect=log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive

6.朴素贝叶斯分类函数

#朴素贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1=sum(vec2Classify*p1Vec)+log(pClass1)
    p0=sum(vec2Classify*p0Vec)+log(1-pClass1)
    if p1>p0:
        return 1
    else:
        return 0

7.提取单词

#将输入的文本字符串分割成单词list
def textParse(bigString):
    listOfTokens=re.split(r'\W*',bigString)
    return [tok.lower() for tok in listOfTokens if len(tok)>2]

8.垃圾邮件测试函数

def spamTest():
    docList=[]
    classList=[]
    fullText=[]
 
    filenameList1=listdir("email/train")
    for name in filenameList1:
        wordList=textParse(open("email/train/"+name).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
 
    filenameList2=listdir("email/test")
    for name in filenameList2:
        wordList = textParse(open("email/test/"+name).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
 
    vocabList=createVocabList(docList)
    trainingSet=list(range(len(docList)))
 
    testSet=[]
    for i in range(int(0.2*len(docList))):
        randIndex=int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])
    trainMat=[]
    trainClasses=[]
    for docIndex in trainingSet:
        trainMat.append(setOfWord2Vec(vocabList,docList[docIndex]))
        trainClasses.append(classList[docIndex])
 
    p0V,p1V,pSpam=trainB0(array(trainMat),array(trainClasses))
    errorCount=0
 
    for  docIndex in testSet:
        wordVector=setOfWord2Vec(vocabList,docList[docIndex])
        if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
            errorCount+=1
    print (r"垃圾邮件准确率:",float(errorCount/float(len(testSet))))

运行结果

5.总结

对于该模型来说想要提高准确率,下次使用的应该是具有独立性比较高的数据集,只有在完全独立的时候才能满足公式算出来的概率。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值