1.先将文本语料构建为one-hot类型的词向量
2.基于语料词向量组成的矩阵计算词向量中所有词在不同类别状态下出现的概率,以及不同类别的概率
3.面对新词汇的时候根据贝叶斯公式求出其属于每一个类别的概率并选择最大的输出

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''=================================================
@Project -> File   :bayes -> bayes
@IDE    :PyCharm
@Author :zgq
@Date   :2021/1/9 20:33
@Desc   :
=================================================='''
from numpy import *


#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]
    return postingList,classVec

#2、创建一个包含在所有句子中的不重复出现的词列表
def createVocabList(dataSet):
    vocabSet=set([])    #创建一个set变量,她可以去掉重复的词
    for document in dataSet:
        vocabSet=vocabSet | set(document)   #将词条列表输给set构造函数,set就回返回一个不重复的list
    return list(vocabSet)

#3、将输入的一句话转换为词向量(one hot类型)
def setOfWords2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList)    #先将这个返回的词向量初始化一个长度为onehot的向量
    for word in inputSet:
        #对于传入这句话的每个单词来判断是否有 有放1没有放o
        if word in vocabList:
            returnVec[vocabList.index(word)]=1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    return returnVec

#测试上面的
listOPosts,listClasses=loadDataSet()
print("输出原始样本和标签")
print(listOPosts)
print(listClasses)
myVocabList=createVocabList(listOPosts)
print("创建我们的词汇表,one-hot类型")
print(myVocabList)
#将上面N句文本转换为词向量填充到trainMat中
trainMat=[]
for postinDoc in listOPosts:
    trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
print("输出一下替换为词向量的trainMat")
print(trainMat)


#训练算法:从词向量计算概率
def trainNB0(trainMatrix,trainCategory):        #trainMatrix是一个矩阵是一个二维的,每一行是一个样本(由词向量组成的矩阵)
    #此处是上边要传递的不是原先的都是单词的矩阵,而是one hot类型的矩阵
    numTrainDocs=len(trainMatrix)   #len(矩阵)返回行数
    numWords=len(trainMatrix[0])    #trainMatrix返回矩阵一行的长度,即每条样本的属性数(词数)
    pAbusive=sum(trainCategory)/float(numTrainDocs)     #文档属于侮辱性类的概率,第一项为侮辱性类词向量次数、第二行为总样本数
    p0Num=ones(numWords)   #做了一个全为0的向量(0,0,0,0),长度为样本数
    p1Num=ones(numWords)
    p0Denom=2.0         #
    p1Denom=2.0
    for i in range(numTrainDocs):       #遍历文本矩阵每一行,即遍历每一条样本
        if trainCategory[i]==1:
            p1Num=p1Num+trainMatrix[i]  #如果该行种类为1的话,将这行词向量盖上到这个(0,0,0,0,0,0,0) 上去
            #如果这句话是侮辱性的句子,将这句话的里边的所有词都放入P1num中,最后执行完毕后会是一个(3,1,0,11,15……),对应于我的词汇表中每个词出现的次数
            p1Denom=p1Denom+sum(trainMatrix[i]) #加和该句话的总词数
        else:
            p0Num=p0Num+trainMatrix[i]
            p0Denom=p0Denom+sum(trainMatrix[i])

        #在上面的过程中,步骤为对句子构成的词向量构成的矩阵,对每一句话,如果这句话是侮辱性类别的,在我们词表中记录她出现了,出现一次次数加一
        #最后得到的是  p1Num 所有的词在句子为侮辱性的情况下出现的次数。
        #而对于P1Denom,对与每句属于类被1的句子,都将这句话的词数加进去,最后得到了,这个总的 矩阵中,语料中,是侮辱性的词语总数
        #因为 p1Num为一个向量,记录了每个词在所有的侮辱性句子中出现的总次数,将其除以侮辱性句子总词数,获得在c概率下p(w|1)
    p1Vect=log(p1Num/p1Denom)    #词向量除以浮点数,结果为我们的词汇表中每一个词在侮辱性句子下出现的概率
    p0Vect=log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive

#测试一下算法
p0V,p1V,pAB=trainNB0(trainMat,listClasses)
print("输出属于脏话文本占总共样本的数量 : ")
print(pAB)
print("输出在脏话文本的情况下,各词汇出现的概率:")
print(p1V)


#根据实际情况修改分类器(做一个数据平滑,因为要计算p(wi|c)即p(w1|1)*p(w2|1)……p(wn|1)时,若出现一项为0则全为0
#使用加1法,将所有词出现次数初始化为1,将分母初始化为2
#在最后相乘时,由于很多数很小相乘后精度损失最后为0,所以将相乘转换为对数相加


#开始构建贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1=sum(vec2Classify*p1Vec)+log(pClass1)
    p0=sum(vec2Classify*p0Vec)+log(1-pClass1)
    if p1>p0:
        return 1
    else:
        return 0
#封装所有代码进行效果测试
def testingNB():
    listOPosts,listClasses=loadDataSet()
    myVocabList=createVocabList(listOPosts)
    trainMat=[]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
    p0V,p1V,pAB=trainNB0(array(trainMat),array(listClasses))
    testEntry=['love','my','dalmation']
    thisDoc=array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAB))
    testEntry=['stupid','garbage']
    thisDoc=array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAB))


testingNB()

运行测试结果:

输出原始样本和标签
[['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']]
[0, 1, 0, 1, 0, 1]
创建我们的词汇表,one-hot类型
['not', 'licks', 'my', 'I', 'dog', 'love', 'help', 'posting', 'problems', 'to', 'how', 'flea', 'park', 'cute', 'steak', 'mr', 'him', 'please', 'stop', 'has', 'so', 'stupid', 'dalmation', 'garbage', 'worthless', 'maybe', 'quit', 'take', 'buying', 'ate', 'food', 'is']
输出一下替换为词向量的trainMat
[[0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]]
输出属于脏话文本占总共样本的数量 : 
0.5
输出在脏话文本的情况下,各词汇出现的概率:
[-2.35137526 -3.04452244 -3.04452244 -3.04452244 -1.94591015 -3.04452244
 -3.04452244 -2.35137526 -3.04452244 -2.35137526 -3.04452244 -3.04452244
 -2.35137526 -3.04452244 -3.04452244 -3.04452244 -2.35137526 -3.04452244
 -2.35137526 -3.04452244 -3.04452244 -1.65822808 -3.04452244 -2.35137526
 -1.94591015 -2.35137526 -2.35137526 -2.35137526 -2.35137526 -3.04452244
 -2.35137526 -3.04452244]
['love', 'my', 'dalmation'] classified as: 0
['stupid', 'garbage'] classified as: 1

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐