1.3-机器学习分类算法-朴素贝叶斯算法

1.贝叶斯( Bayes)分类法

1.1 贝叶斯分类法原理

贝叶斯分类算法是一种基于概率的常用分类算法,该算法基于贝叶斯定理和特征条件独立假设原则。对该算法两大基础解释如下:

  • 1.特征条件独立假设:即各个条件的出现不会相互影响,例如就不能把这是个男人,这个人有胡子作为两个特征。因为这两个特征本身会相互影响。
  • 2.贝叶斯定理:

该定理的核心思想可以总结为:“A是一个亚洲人,经过统计发现他亚洲人是黄种人的几率最大。读入结果,B是一个黄种人,则他大概率是一个亚洲人。”

该算法学习和预测的过程可以总结为:学习过程即求后验概率的过程,预测过程为根据特征求其先验概率。

以四个特征两种结果的情况举例,例如四个特征分别为(W,X,Y,Z)。两种结果为A和B。假如四个特征每个分别有两种情况,则可能特征分别为:

  • W:W1、W2
  • X:X1、X2
  • Y:Y1、Y2
  • Z:Z1、Z2

那么此时得到的统计数据(输入集)就是在(W1/2,X1/2,Y1/2,Z1/2)时结果为A/B。我们要做的第一步就是训练,也就是要求:

然后,当读入一个数据,例如则计算过程如下:

然后对比,选一个大的认为预测结果为A或者B

1.2 贝叶斯分类法例题

1.2.1 使用朴素贝叶斯进行垃圾邮件分类

这里给出的数据集是两组邮件txt文件,ham文件夹下为正常邮件,spam文件夹下为垃圾邮件,文件名为1.txt-25.txt。

#读取文件并返回列表分词列表
import re
def readFileToList(filename):
    with open(filename) as f:
        bigstring = f.read()
    wordlist =  re.split(r"\W+",bigstring)
    return [word.lower() for word in wordlist if len(word)>2 ] 
#print(readFileToList("attach/1.3/email/ham/1.txt"))
import random
def getTrainDataSet(): #用40个当作训练数据集
    dataSet = []
    wordSet = []
    classifySet = []
    for i in range(1,21):
        hamFile = "attach/1.3/email/ham/"+str(i)+".txt"
        spamFile = "attach/1.3/email/spam/"+str(i)+".txt"
        wordlist = readFileToList(hamFile)
        dataSet.append(wordlist)#保存正常邮件数据集
        wordSet.extend(wordlist)#将单词保存至单词集合中方便后续计算
        classifySet.append(False)#存储数据集定义为非垃圾邮件
        wordlist = readFileToList(spamFile)
        dataSet.append(wordlist)#保存垃圾邮件数据集
        wordSet.extend(wordlist)#将单词保存至单词集合中方便后续计算
        classifySet.append(True)#存储数据集定义为垃圾邮件
    return  dataSet,classifySet,wordSet
    '''
    trainSet = list(range(50))
    testSet =[]
    for i in range(10):
        randomIndex = random.randint(0,len(trainSet))
        #print(randomIndex)
        testSet.append(trainSet[randomIndex])#假如测试集合
        del(trainSet[randomIndex])#假如训练集合
    return  dataSet,classifySet,wordSet,trainSet,testSet
    '''
trainSet,classifySet,wordSet=spamTest()
#print(trainSet,testSet)
#划分好了训练集合和测试集合后现在就是要根据公式求概率
import math
def calcNum(wordNeededCalc,wordlist):#输入一个元素和一个集合,计算该元素在集合中出现的次数
    num = 0.0
    for word in wordlist:
        if word==wordNeededCalc:
            num +=1
    #Prob = num/len(wordlist)
    return num
#print(calcProb('you',wordSet))
def classify(emailwordlist,trainSet,classifySet,wordSet):
    dataTypeList = [] #所有分类集合
    for dataType in classifySet:
        if dataType not in dataTypeList:
            dataTypeList.append(dataType)

    #计算概率P(A)、P(B)..
    dataTypeProbList=[]
    for i in range(len(dataTypeList)):
        num=0.0 #记录每个类型数据数量
        for classify in classifySet:
            if classify==dataTypeList[i]:
                num+=1
        dataTypeProbList.append(num/len(classifySet))


    #计算联合分布概率
    max_prob=0
    res=0
    for i in range(len(dataTypeList)):
        p_up=1
        p_down=1
        for word in emailwordlist:
            num=0.0
            all_word_num=0.0
            if word in wordSet: #先判断这个单词在不在训练数据集的词向量列表里
                for index,value in enumerate(trainSet):
                    if classifySet[index]==dataTypeList[i]:
                        num+=calcNum(word,value)
                        all_word_num+=len(value)
                if (num!=0):
                    p_up*=(num/all_word_num)
                    p_down*=(calcNum(word,wordSet)/len(wordSet))
        if p_up!=1:
            p = p_up/p_down
        else:
            p=0
        if p>max_prob:
            max_prob=p
            res = dataTypeList[i]
        #print(p)
    return res
    #print(dataTypeProbList)

    #for word in emailwordlist:
    #    for index in trainSet:
    #        calcProb(word,)
#res=classify(trainSet[1],trainSet,classifySet,wordSet)
#print(res)
for i in range(21,26):
    testfilename1 =  "attach/1.3/email/ham/"+str(i)+".txt"
    testWordlist1 = readFileToList(testfilename1)
    testfilename2 =  "attach/1.3/email/spam/"+str(i)+".txt"
    testWordlist2 = readFileToList(testfilename2)
    print(classify(testWordlist1,trainSet,classifySet,wordSet),testfilename1)
    print(classify(testWordlist2,trainSet,classifySet,wordSet),testfilename2)
#正确率百分之九十左右,算法整的有点问题,有时间改
False attach/1.3/email/ham/21.txt
True attach/1.3/email/spam/21.txt
False attach/1.3/email/ham/22.txt
True attach/1.3/email/spam/22.txt
False attach/1.3/email/ham/23.txt
True attach/1.3/email/spam/23.txt
False attach/1.3/email/ham/24.txt
True attach/1.3/email/spam/24.txt
False attach/1.3/email/ham/25.txt
False attach/1.3/email/spam/25.txt

参考:

  • 贝叶斯算法分析:https://www.jianshu.com/p/5953923f43f0
  • 贝叶斯算法分析:https://www.cnblogs.com/lliuye/p/9178090.html
  • 非常不错的拉普拉斯平滑讲解
  • 《机器学习实战》