《机器学习实战》个人学习记录笔记(八)———朴素贝叶斯实战篇之垃圾邮件分类

原创 2018年04月16日 18:48:05

第四章 朴素贝叶斯

PS:个人笔记 根据《机器学习实战》这本书,Jack-Cui的博客,以及深度眸的视频进行学习

1 两个改进

拉普拉斯平滑(Laplace Smoothing)又被称为加1平滑,是比较常用的平滑方法,它就是为了解决0概率问题

下溢出:这是由于太多很小的数相乘造成的。为了解决这个问题,对乘积结果取自然对数。通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。

def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)                            
    numWords = len(trainMatrix[0])                           
    pAbusive = sum(trainCategory)/float(numTrainDocs)       
    p0Num = np.ones(numWords); p1Num = np.ones(numWords)    
    p0Denom = 2.0; p1Denom = 2.0                            ⭐#分母初始化为2,拉普拉斯平滑
    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 = np.log(p1Num/p1Denom)                          ⭐#取对数,防止下溢出         
    p0Vect = np.log(p0Num/p0Denom)         
    return p0Vect,p1Vect,pAbusive                          

2 过滤垃圾邮件

import re

"""
Parameters:
    无
Returns:
    无
"""
def textParse(bigString):                                                   #将文本解析为字符串列表
    listOfTokens = re.split(r'\W.*?', bigString)                            #将'\w'作为分隔符,获得单个单词;⭐改为.*? 
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]            #对于单词长度做要求并且规定小写

"""
Parameters:
    dataSet - 整理的样本数据集
Returns:
    vocabSet - 返回不重复的词条列表,也就是词汇表
"""
def createVocabList(dataSet):
    vocabSet = set([])                      #创建一个空的不重复列表,利用set()的不重复功能
    for document in dataSet:               
        vocabSet = vocabSet | set(document) #删除重复的单词,组成词汇表
    return list(vocabSet)

if __name__ == '__main__':
    docList = []; classList = []
    for i in range(1, 26):                                                  #遍历文件,一共有26  
        wordList = textParse(open('spam/%d.txt' % i, 'r',encoding='gb18030',errors='ignore').read())  #⭐打开文件,用之前定义的函数,这里有个编码问题
        docList.append(wordList)
        classList.append(1)                                                 #标记垃圾邮件,1表示垃圾文件
        wordList = textParse(open('ham/%d.txt' % i, 'r',encoding='gb18030',errors='ignore').read())     #这里打开非垃圾邮件,并字符串转换成字符串列表
        docList.append(wordList)
        classList.append(0)                                                 #标记非垃圾邮件,1表示垃圾文件   
    vocabList = createVocabList(docList)                                    #创建词汇表,不重复
    print(vocabList)

文本向量化,我们将数据集分为训练集和测试集,使用交叉验证的方式测试朴素贝叶斯分类器的准确性。

import numpy as np
import random
import re

def createVocabList(dataSet):
    vocabSet = set([])                   
    for document in dataSet:               
        vocabSet = vocabSet | set(document) 
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)                                
    for word in inputSet:                                             
        if word in vocabList:                                         
            returnVec[vocabList.index(word)] = 1
        else: print("the word: %s is not in my Vocabulary!" % word)
    return returnVec                                                  

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

def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)                          
    numWords = len(trainMatrix[0])                         
    pAbusive = sum(trainCategory)/float(numTrainDocs)      
    p0Num = np.ones(numWords); p1Num = np.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 = np.log(p1Num/p1Denom)                        
    p0Vect = np.log(p0Num/p0Denom)         
    return p0Vect,p1Vect,pAbusive                           

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)        #对应元素相乘。logA * B = logA + logB,所以这里加上log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

def textParse(bigString):                                              
    listOfTokens = re.split(r'\W.*?', bigString)                       #这里改为,*?     
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]       


def spamTest():                                                             #样本测试
    docList = []; classList = []; fullText = []
    for i in range(1, 26):                                             
        wordList = textParse(open('spam/%d.txt' % i, 'r',encoding='gb18030',errors='ignore').read())     #读取每个垃圾邮件,并字符串转换成字符串列表⭐编码有问题做了改变
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(1)                                             
        wordList = textParse(open('ham/%d.txt' % i, 'r',encoding='gb18030',errors='ignore').read())      
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(0)                                                 #标记非垃圾邮件,1表示垃圾文件   
    vocabList = createVocabList(docList)                                    #创建词汇表,不重复
    trainingSet = list(range(50)); testSet = []                             #创建存储训练集的索引值的列表和测试集的索引值的列表                       
    for i in range(10):                                                     #从50个邮件中,随机挑选出40个作为训练集,10个做测试集
        randIndex = int(random.uniform(0, len(trainingSet)))                #随机选取索索引值,是均匀随机函数
        testSet.append(trainingSet[randIndex])                              #添加测试集的索引值
        del(trainingSet[randIndex])                                         #在训练集列表中删除添加到测试集的索引值
    trainMat = []; trainClasses = []                                        #创建训练集矩阵和训练集类别标签系向量             
    for docIndex in trainingSet:                                            #遍历训练集
        trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))       #将生成的词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])                            #将类别添加到训练集类别标签系向量中
    p0V, p1V, pSpam = trainNB0(np.array(trainMat), np.array(trainClasses))  #训练朴素贝叶斯模型,要矩阵运算,用np转换
    errorCount = 0                                                          #错误分类计数
    for docIndex in testSet:                                                #遍历测试集
        wordVector = setOfWords2Vec(vocabList, docList[docIndex])           #测试集的词集模型
        if classifyNB(np.array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:    #如果分类错误
            errorCount += 1                                                 #错误计数加1
            print("分类错误的测试集:",docList[docIndex])
    print('错误率:%.2f%%' % (float(errorCount) / len(testSet) * 100))


if __name__ == '__main__':
    spamTest()






C++入门解惑(0)——序

序0.为什么学习C++0.Why Shall I Learn C++?      C++作为一门较为成熟重量级的语言,吸引了许许多多编程学习者。单从市面上编程书籍中C++的书所占的比例即可见一斑。当然...
  • Kusk
  • Kusk
  • 2003-07-14 08:08:00
  • 2314

机器学习实战python版 朴素贝叶斯示例 垃圾邮件分类 从个人广告中获取趋于趋向

首先我们先来看如何使用朴树贝叶斯对电子邮件进行分类 准备数据:切分文本 对于一个文本字符串,使用python的split()就可以切分文本。 >>> mySent = 'this book is...
  • XD_Senior
  • XD_Senior
  • 2015-12-03 20:20:49
  • 1668

机器学习实战-使用朴素贝叶斯分类器来做垃圾邮件分类

coding: from numpy import * import re def loadDataSet(): postingList = [['my', ' dog', 'has', ...
  • OliverkingLi
  • OliverkingLi
  • 2017-06-18 10:50:34
  • 807

《机器学习实战》学习笔记:基于朴素贝叶斯的垃圾邮件过滤

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率。之前的基础实验中简单实现了朴...
  • liyuefeilong
  • liyuefeilong
  • 2015-09-15 09:59:28
  • 6736

[机器学习实战]--朴素贝叶斯过滤垃圾邮件

我们将充分利用python的文本处理能力将文档切分成词向量,然后利用词向量对文档进行分类。还将构造分类器观察其在真实的垃圾邮件数据集中的过滤效果。基于贝叶斯决策理论的分类方法假设现在我们有一个数据集,...
  • sherlockzoom
  • sherlockzoom
  • 2015-08-29 16:52:30
  • 1081

Python3:《机器学习实战》之朴素贝叶斯(3)过滤垃圾邮件

Python3:《机器学习实战》之朴素贝叶斯(3)过滤垃圾邮件 转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://github.com/W...
  • u011475210
  • u011475210
  • 2017-09-10 21:56:36
  • 4144

【机器学习实战二:朴素贝叶斯算法之过滤垃圾邮件】

一、部分说明 ---------------------------------------------------------------- 1、本文代码是《机器学习实战》这本书的例程。点击下载《机...
  • u013634684
  • u013634684
  • 2015-11-05 22:35:14
  • 3296

机器学习Matlab实战之垃圾邮件分类————朴素贝叶斯模型

垃圾邮件分类是监督学习分类中一个最经典的案例,本文先复习了基础的概率论知识、贝叶斯法则以及朴素贝叶斯模型的思想,最后给出了垃圾邮件分类在Matlab中用朴素贝叶斯模型的实现...
  • u014030117
  • u014030117
  • 2015-06-07 11:08:43
  • 4290

《机器学习实战》学习笔记:基于朴素贝叶斯的分类方法

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率。...
  • liyuefeilong
  • liyuefeilong
  • 2015-09-12 00:02:32
  • 4689

机器学习经典算法详解及Python实现---朴素贝叶斯分类及其在文本分类、垃圾邮件检测中的应用

朴素贝叶斯分类是贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验概率计算出其后验概率(即该对象属于某一类的概率),然后选...
  • suipingsp
  • suipingsp
  • 2014-12-12 19:35:45
  • 16899
收藏助手
不良信息举报
您举报文章:《机器学习实战》个人学习记录笔记(八)———朴素贝叶斯实战篇之垃圾邮件分类
举报原因:
原因补充:

(最多只允许输入30个字)