【转载】朴素贝叶斯

通过这个博客学习:机器学习实战(四)——基于概率论的分类方法:朴素贝叶斯

代码是之前找来学习的一份,讲解比较详细,结合代码更容易对算法形成理解吧。

from numpy import *


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]  # 0不是脏话,1是脏话
    return postingList, classVec


postingList, classVec = loadDataSet()


# 去重复并合并整个文档
def createVocabList(dataSet):
    vocabSet = set([])
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # 集合的并集
    # print("合并后的文档", vocabSet)                        #32
    return list(vocabSet)


vocabList = createVocabList(postingList)


# 单词转换为向量

def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)  # 初始化
    # print(returnVec)      #32个0:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    # print("inputSet:", inputSet)
    for word in inputSet:
        returnVec[vocabList.index(word)] = 1  # 如果输入的inputSet里面的单词在上面的已经合并的文档里,那么则把在里面的响应的单词输出为1
    return returnVec


trainMatrix = []
myVocabList = createVocabList(postingList)


for postinDoc in postingList:
    trainMatrix.append(setOfWords2Vec(myVocabList, postinDoc))  # myVocabList为合并后的32个单词
# print(trainMatrix)
# [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]]
# 这里的意思是把输入数据的每一行(这里总共有6行)转换成向量的形式,即:如果单词是在合并的文档里面的话,就会为转成 1,输出的列表有6个元素,每个元素是一个列表,每个列表里面有32个元素,其中有每行数据元素的单词为1



## trainNB0 这个函数的作用:
# 输入:单词的向量(),这里的意思是把输入数据的每一行(这里总共有6行)转换成向量的形式,即:如果单词是在合并的文档里面的话,就会为转成 1,输出的列表有6个元素,每个元素是一个列表,每个列表里面有32个元素,其中有每行数据元素的单词为1
# 输入:种类(就是(0,1,0,1,0,1))
# 输出:有脏话时特征对应的概率,无脏话时特征对应的概率,脏话的概率(P(B1)),无脏话对应的概率=1-有脏话时对应的概率
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)  # 这里为6,6个样本,计算出样本的个数
    numWords = len(trainMatrix[0])  # 表示单词数目32,计算是单词的数目
    pAbusive = sum(trainCategory) / float(numTrainDocs)  # 计算出脏话的概率,这里为0.5,即P(B1),在这个例子里面只有B0和B1
    # print("脏话的概率:",pAbusive)
    p0Num = ones(numWords)  # 非脏话的计数,这里是初始化,初始化为32个1
    p1NUm = ones(numWords)  # 脏话计数,这里初始化为32个1
    p0Denom = 2.0  # 这里初始化p0Denom为2是为了方便下面的计算
    p1Denom = 2.0  # 这个初始化p1Denom为2是为了方便下面的计算
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            # numTrainDocs表示有6个,i从0至5,trainCategory这里表示传入的也有6个,为1表示为脏话,0表示非脏话,这里是把脏话和非脏话分离开来,这里==1指的是脏话
            # print(trainMatrix[i])
            # [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 0, 0, 0]   trainMatrix[1]
            # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 0, 1, 0, 0]   trainMatrix[3]
            # [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,0, 0, 0,0, 0, 1, 0, 0]  trainMatrix[5]
            # print("这里是trainMatrix[i]")
            p1NUm += trainMatrix[
                i]  # 这里展示出现的脏话,并计数,就是把trainMatrix[1] + trainMatrix[3] + trainMatrix[5]加起来,这样就把六个样本里面的所有脏话都给集合到一起了,同时将其向量化了, 总共32个单词,哪个位置上面出现了脏话,就➕加1
            # print(p1NUm)
            # [2. 1. 1. 1. 1. 1. 1. 1. 2. 2. 2. 1. 1. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.2. 2. 1. 1. 2. 1. 1. 1.]   p1Num
            # [2. 1. 1. 1. 1. 1. 1. 1. 2. 2. 3. 1. 1. 2. 1. 1. 2. 2. 1. 1. 1. 1. 1. 1.2. 2. 1.2. 2. 2. 1. 1.]  p1Num
            # [2. 1. 1. 2. 1. 1. 1. 1. 2. 2. 4. 1. 1. 3. 2. 1. 2. 2. 1. 1. 1. 1. 2. 1.2. 2. 1.2. 2. 3. 1. 1.] p1Num

            p1Denom += sum(trainMatrix[i])  # 这里为脏话出现的次数计数,(初始值,自己设定)+8=10.0---》15---》21
            # print("p1Denom:",p1Denom)          #2(初始值,自己设定)+8=10.0---》15---》21

        else:
            p0Num += trainMatrix[i]  # 这里计数为非脏话
            p0Denom += sum(trainMatrix[i])  # 这里统计非脏话出现的次数
    p1 = p1NUm / p1Denom  # 这里为有脏话时特征对应的概率,即P(A1|B0),P(A2|B0)...P(A32|B0)
    p1Vect = log(p1NUm / p1Denom)  # 加Log是为了方便计算
    # print("p1NUm:",p1NUm)
    # print("p1Denom",p1Denom)
    # print("P1:",p1)
    # print("P1Vect:", p1Vect)
    p0 = p0Num / p0Denom  # 这里计算非脏话时特征对应的的概率,即P(A1|B1),P(A2|B1)...P(A32|B1)
    p0Vect = log(p0Num / p0Denom)  # 加log是为了后面计算方便
    return p0Vect, p1Vect, pAbusive


# [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 0, 0, 0]   trainMatrix[1]
#
# [2. 1. 1. 1. 1. 1. 1. 1. 2. 2. 2. 1. 1. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.2. 2. 1. 1. 2. 1. 1. 1.]   p1Num
#
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 0, 1, 0, 0]   trainMatrix[3]
#
# [2. 1. 1. 1. 1. 1. 1. 1. 2. 2. 3. 1. 1. 2. 1. 1. 2. 2. 1. 1. 1. 1. 1. 1.2. 2. 1.2. 2. 2. 1. 1.]  p1Num
#
# [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,0, 0, 0,0, 0, 1, 0, 0]  trainMatrix[5]
#
# [2. 1. 1. 2. 1. 1. 1. 1. 2. 2. 4. 1. 1. 3. 2. 1. 2. 2. 1. 1. 1. 1. 2. 1.2. 2. 1.2. 2. 3. 1. 1.] p1Num


def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):  # 这里的vec2Classify是测试集
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)
    # p(Bi|A) = P(Bi)P(A1|Bi)P(A2|Bi)P(A3|Bi)/(P(A1)P(A2)P(A3));
    # 这里把分子上面的乘法转换成加法了,这里的P(Bi)就是trainNB0里面的pAbusive,
    # pAbusive对应的就是这里的pClass1,vec2Classify指的是测试集,p1Vec乘以测试集就会得到
    # P(A1|B1)*P(A2|B1)。。。P(A32|B1),
    # 由于分母是一样的,故只需要比较P(B1|A)和P(B0|A)的分子即可
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)  # 这里是计算的P(B1|A)
    if p1 > p0:  # 这里是比较P(B0|A)和P(B1|A)的大小,哪个大就取哪个
        return 1
    else:
        return 0


##有关array的相关解释ß
# trainmat = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]]
# arr = array(trainmat)
# print(trainmat)
# #[[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]]
#
# print(arr)
# [[0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 0 0]
#  [0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0]
#  [0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 1]
#  [0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
#  [1 0 1 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 1 0]
#  [0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]]

def testingNB():
    listOPosts, listClasses = loadDataSet()  # 加载数据,listOPosts为原来文本,总共6个列表
    myVocabList = createVocabList(listOPosts)  # 合并文档,输出32个单词(把重复的单词去除掉)
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,
                                       postinDoc))  ##这里的意思是把输入数据的每一行(这里总共有6行)转换成向量的形式,即:如果单词是在合并的文档里面的话,就会为转成 1,输出的列表有6个元素,每个元素是一个列表,每个列表里面有32个元素,其中有存在每行数据元素的单词,则这个位置为1
    # print(trainMat)
    p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))  #

    testEntry = ['love', 'my', 'dalmation']
    thisDoc = array(
        setOfWords2Vec(myVocabList, testEntry))  # [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]
    print(testEntry, '类别为: ', classifyNB(thisDoc, p0V, p1V, pAb))  #
    testEntry = ['stupid', 'garbage']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, '类别为: ', classifyNB(thisDoc, p0V, p1V, pAb))


testingNB()

# print(loadDataSet())
# print(createVocabList(dataSet))
# setOfWords2Vec(vocabList,['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'])
# trainNB0(trainMatrix,classVec)

运行截图:

原文地址:https://www.cnblogs.com/dong973711/p/13831384.html