使用朴素贝叶斯过滤垃圾邮件

简介: 使用朴素贝叶斯过滤垃圾邮件

使用朴素贝叶斯过滤垃圾邮件


1.问题描述:

现有50封电子邮件,存放在数据集task1中,试基于朴素贝叶斯分类器原理,用Python编程实现对垃圾邮件和正常邮件的分类。采用交叉验证方式并且输出分类的错误率及分类错误的文档。


2.实验原理:

朴素贝叶斯:


基于概率论的分类方法:朴素贝叶斯,要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值。一种有效计算条件概率的方法称为贝叶斯准则,贝叶斯准则告诉我们如何交换条件概率中的条件与结果,即如果已知$ P(x|c)$,要求 P ( c ∣ x ) ,那么可以使用下面的计算方法:

image.png

于是,可以定义贝叶斯分类准则为:若那么属于类别若$ P(c1|x,y)>P(c2|x,y)$, 那么属于类别 C1


若那么属于类别若 P ( c 1 ∣ x , y ) < P ( c 2 ∣ x , y ) , 那么属于类别 C2


使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。


由词向量计算:


由于这里的特征是词向量,于是重写贝叶斯准则,将之前的x、y 替换为w。粗体w表示这是一个向量,即它由多个数值组成,长度N为词典长度。在词袋模型中,数值个数与词典中的词个数相同,贝叶斯准则公式如下:

P ( c i ∣ w ) = P ( w ∣ c i ) P ( c i ) P ( w )


我们使用上述公式,对每个类别计算该值,然后比较这两个概率值的大小。首先通过类别(垃圾邮件或正常邮件)中样本数除以总的样本数来计算概率$ P(ci)$,接下里计算 P ( w ∣ c i )  ,这里使用朴素贝叶斯假设,若将w展开为一个个独立特征,那么就可以将上述概率写作$ P(w0,w1,w2,…wN|ci)$ ,这里假设所有词都互相独立,该假设也称作条件独立性假设,它意味着可以使用 如下公式计算上述概率:

P ( w ∣ c i ) = P ( w 0 ∣ c i ) P ( w 1 ∣ c i ) P ( w 2 ∣ c i ) . . . P ( w N ∣ c i )


这样就极大的简化了计算过程。


具体步骤:


1.设D是词向量集合,每个词向量用一个N维向量 $w={w0,w1,w2,…,wN} $表示。


2.假定有m个类 c i = { c 1 , c 2 , . . . , c m },给定词向量w,分类法将预测w属于最高后验概率的类,即,朴素贝叶斯分类法预测w属于类ci,当且仅当

P ( c i ∣ w ) > P ( c j ∣ w ) , 1 ≤ j ≤ m , j ≠ i


其中,P(ci|w) 最大的类 ci 称为最大后验概率。


3.做条件独立性假设,于是将公式简化:

image.png


4.训练:利用公式,对每个词向量每个类别分别计算条件概率,得出 P 0 v , P 1 v , P s p a m P0v,P1v,PspamP0v,P1v,Pspam ,分类器训练完成。


5.应用:利用贝叶斯分类准则,对预测词向量分别计算$ P0,P1$ ,选择最大概率对应的分类作为目标预测结果。


3.代码实现:

1.数据处理:


1)需要从文本中获取特征,需要拆分文本,分成词条


2)获取数据字典


3)向量化处理,方便进行特征提取


实现:


分词:

def textParse(bigString):
    import re
    listOfTokens=re.split('\W',bigString)
    #匹配非字母数字下划线
    return [tok.lower() for tok in listOfTokens if len(tok)>2] 
  #取出掉长度过短的单词


获取数据字典:

def creatVocabList(dataset):
    vocabSet=set([])
    for document in dataset:
         vocabSet=vocabSet|set(document)  #两个集合的并集
    return list(vocabSet)


向量化处理:


这里可以使用词集模型或者词袋模型:


1)词集模型:只关注token是否出现,并不关注出现的次数。

def setOfWords2Vec(vocabList, inputSet):
  returnVec = [0]*len(vocabList)
  for word in inputSet:
    if word in vocabList:
      return Vec[vocabList.index(word)] = 1
  return returnVec


2)词袋模型:关注token的出现次数,有较好的处理结果

#词袋模型
def bagOfWords2Vec(vocabList,inputSet): #参数分别为词汇表,输入文档
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]+=1
    return returnVec


2.训练模型:


朴素贝叶斯是基于概率的分类器,其训练过程就是计算各个概率的过程。


流程为:

对每篇训练文档:
===对每个类别:
======如果词条出现在文档中,则增加该词条的计数
======增加所有出现词条的计数值
===对每个类别:
======对每个词条:
=========将该词条的数目除以总词条的数目得到条件概率
===返回每个类别的条件概率


代码:

#朴素贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass): #参数分别为:要分类的向量以及使用trainNB0()计算得到的三个概率
    p1=sum(vec2Classify*p1Vec)+np.log(pClass)
    p0=sum(vec2Classify*p0Vec)+np.log(1-pClass)
    if p1>p0:
        return 1  
    else:
        return 0


3.测试:


在50封邮件中,正常邮件和垃圾邮件各占25,在在其中随机抽取10封电子邮件,预测其所在的类别。

#测试算法:使用朴素贝叶斯交叉验证。同时保存分类模型的词汇表以及三个概率值,避免判断时重复求值
def spamTest():
    docList = []  # 文档(邮件)矩阵
    classList = []  # 类标签列表
    for i in range(1, 26):
        wordlist = textParse(open('spam/{}.txt'.format(str(i))).read())
        docList.append(wordlist)
        classList.append(1)
        wordlist = textParse(open('ham/{}.txt'.format(str(i))).read())
        docList.append(wordlist)
        classList.append(0)
    vocabList = creatVocabList(docList)  # 所有邮件内容的词汇表
    import pickle
    file=open('vocabList.txt',mode='wb')  #存储词汇表
    pickle.dump(vocabList,file)
    file.close()
    # 对需要测试的邮件,根据其词表fileWordList构造向量
    # 随机构建40训练集与10测试集
    trainingSet = list(range(50))
    testSet = []
    for i in range(10):
        randIndex = int(np.random.uniform(0, len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del (trainingSet[randIndex])
    trainMat = []  # 训练集
    trainClasses = []  # 训练集中向量的类标签列表
    for docIndex in trainingSet:
        # 使用词袋模式构造的向量组成训练集
        trainMat.append(bagOfWords2Vec(vocabList, docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0v,p1v,pAb=trainNB0(trainMat,trainClasses)
    file=open('threeRate.txt',mode='wb') #用以存储分类器的三个概率
    pickle.dump([p0v,p1v,pAb],file)
    file.close()
    errorCount=0
    for docIndex in testSet:
        wordVector=bagOfWords2Vec(vocabList,docList[docIndex])
        if classifyNB(wordVector,p0v,p1v,pAb)!=classList[docIndex]:
            errorCount+=1
    return float(errorCount)/len(testSet)


4.测试结果:

由于测试集的生成是随机的,所以分类器误分率每次运行结果不一致。通过运行10次的平均值作为分类器的分类效果:


机器学习导论代码地址:


机器学习导论

目录
相关文章
|
2月前
|
数据采集 机器学习/深度学习 存储
基于多项式朴素贝叶斯的中文垃圾邮件识别
基于多项式朴素贝叶斯的中文垃圾邮件识别
|
21天前
|
算法 Serverless
使用朴素贝叶斯算法过滤垃圾邮件
使用朴素贝叶斯算法过滤垃圾邮件
21 2
|
2月前
|
机器学习/深度学习 自然语言处理 算法
weka文本挖掘分析垃圾邮件分类模型
weka文本挖掘分析垃圾邮件分类模型
|
9月前
|
机器学习/深度学习 数据采集 开发者
基于机器学习的垃圾邮件过滤系统
基于机器学习的垃圾邮件过滤系统
221 0
|
2月前
|
机器学习/深度学习 数据采集 自然语言处理
使用Python实现一个简单的垃圾邮件分类器
使用Python实现一个简单的垃圾邮件分类器
119 0
|
9月前
|
机器学习/深度学习 算法 安全
论题:基于机器学习的垃圾邮件过滤系统
论题:基于机器学习的垃圾邮件过滤系统
271 0
|
数据采集 存储 机器学习/深度学习
秒懂算法 | 基于朴素贝叶斯算法的垃圾信息的识别
本文将带领大家亲手实现一个垃圾信息过滤的算法。 在正式讲解算法之前,最重要的是对整个任务有一个全面的认识,包括算法的输入和输出、可能会用到的技术,以及技术大致的流程。 本任务的目标是去识别一条短信是否为垃圾信息,即输入为一条文本信息,输出为二分类的分类结果。2002年,Paul Graham提出使用“贝叶斯推断”过滤垃圾邮件。1000封垃圾邮件可以过滤掉995封,且没有一个误判。另外,这种过滤器还具有自我学习的功能,会根据新收到的邮件,不断调整。收到的垃圾邮件越多,它的准确率就越高。 朴素贝叶斯算法是一种有监督的机器学习算法,即算法的实现包含了构建训练集、数据预处理、训练、在测试集上验证
434 0
秒懂算法 | 基于朴素贝叶斯算法的垃圾信息的识别
|
机器学习/深度学习 资源调度 算法
使用线性SVM实现对垃圾邮件分类
使用线性SVM实现对垃圾邮件分类
213 0
使用线性SVM实现对垃圾邮件分类
|
数据采集 机器学习/深度学习 人工智能
基于逻辑回归方法完成垃圾邮件过滤任务
基于逻辑回归方法完成垃圾邮件过滤任务
155 0
基于逻辑回归方法完成垃圾邮件过滤任务
|
机器学习/深度学习 数据采集 人工智能
【机器学习项目实战10例】(七):基于逻辑回归方法完成垃圾邮件过滤任务
【机器学习项目实战10例】(七):基于逻辑回归方法完成垃圾邮件过滤任务
285 0
【机器学习项目实战10例】(七):基于逻辑回归方法完成垃圾邮件过滤任务