机器学习之利用朴素贝叶斯算法实现垃圾邮件分类

一、什么是朴素贝叶斯算法?

朴素贝叶斯算法是一种基于贝叶斯定理与特征条件独立假设的分类方法。

朴素:特征条件独立;

贝叶斯:基于贝叶斯定理。属于监督学习的生成模型,实现简单,并有坚实的数学理论作为支撑。

 

二、朴素贝叶斯的算法原理

1.贝叶斯定理:

  • 条件概率:就是事件 A在另外一个事件B已经发生条件下的发生概率。条件概率表示为P(A∣B) 读作“在B发生的条件下A 发生的概率”。
  • 联合概率:表示两个事件共同发生(数学概念上的交集)的概率。A与B的联合概率表示为联合概率。  P(AB) = P(A∣B)P(B) = P(B∣A)P(A),若AB相互独立,P(AB) = P(A)P(B)
  • 全概率公式:P(X) = ∑k P(X∣Y = Yk )P(Yk ),其中∑k P(Yk ) = 1

贝叶斯定理:贝叶斯理论是以18世纪的一位神学家托马斯.贝叶斯(Thomas Bayes)命名。通常,事件A在事件B(发生)的条件下的概 率,与事件B在事件A(发生)的条件下的概率是不一样的。然而,这两者是有确定的关系的,贝叶斯定理就是这种关系的陈述。

 

朴素贝叶斯:朴素贝叶斯方法是基于贝叶斯定理和特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设 学习输入/输出的联合概率分布;然后基于此模型,对给定的输入 ,利用贝叶斯定理求出后验概率最大的输出 :

朴素贝叶斯算法原理:其实朴素贝叶斯方法是一种生成模型,对于给定的输入x xx,通过学习到的模型计算后验概率分布P ( Y = c k ∣ X = x ) P(Y=c_k | X=x)P(Y=ck​∣X=x),将后验概率最大的类作为x xx的类输出。其中后验概率计算根据贝叶斯定理进行: 

机器学习之利用朴素贝叶斯算法实现垃圾邮件分类_第1张图片

最后的朴素贝叶斯分类模型为:

三、使用贝叶斯进行文档分类

1.把句子转换为一维词向量

# 创建标签
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

 2.创建不重复的词的词汇表

# 词汇表(不重复)
def createVocabList(dataSet):
    vocabSet = set([])                       # 创建一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # 创建两个集合的并集
    return list(vocabSet)                    # 返回不重复的词条列表

3.输出提供的文档的词向量 

# 输出文档词向量
def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)             # 创建一个其中所含元素都为0的向量
    for word in inputSet:                        # 遍历文档中的所有单词
        if word in vocabList:                    # 如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1
            returnVec[vocabList.index(word)] = 1
        else:
            print("单词 %s 不在词汇表中!" % word)
    return returnVec

 四、贝叶斯实现垃圾邮件分类

根据上述代码,统筹之后得到垃圾邮件实现代码:

# 垃圾邮件分类器
def classifyEmail():
    docList = []                 # 文档列表
    classList = []               # 文档标签
    fullText = []                # 全部文档内容集合
    for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个
        wordList = textParse(open('email/spam/%d.txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合
        classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件
        wordList = textParse(open('email/ham/%d.txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 非垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合
        classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,
 
    vocabList = createVocabList(docList)                             # 创建不重复的词汇表
    trainingSet = list(range(50))                                    # 为训练集添加索引
    trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量
    trainClasses = []                                                # 训练集类别标签
    for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中
    p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数
 
    testList = textParse(open('email/test/1.txt').read())            # 读取邮件,将大字符串并将其解析为字符串列表
    testVector = bagOfWords2VecMN(vocabList, testList)               # 获得测试集的词集模型
    if classifyNB(array(testVector), p0V, p1V, pSpam):
        result = "垃圾邮件"
    else:
        result = "正常邮件"
    print("输入邮件内容为: ")
    print(' '.join(testList))
    print('该邮件被分类为: ', result)

 

 

你可能感兴趣的:(算法,分类)