Untitled

来源:互联网 发布:信息碎片化定义知乎 编辑:程序博客网 时间:2024/05/15 01:35

朴素贝叶斯的一般过程

1、收集数据:可以使用任何数据。本文使用RSS源

2、准备数据:需要数值型或布尔型数据

3、分析数据、有大量特征时,绘制特征作用不大,此时使用直方图效果更好

4、训练算法:计算不同的独立特征的条件概率

5、测试算法:计算错误率

6、使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯命类器,不一定非要是文本。

1、准备数据:

我们将把文本看成单词向量或者词条向量,也就是说将句子转换为向量。考虑出现在所有文
档中的所有单词,再决定将哪些词纳人词汇表或者说所要的词汇集合,然后必须要将每一篇文档 转换为词汇表上的向量。接下来我们正式开始。打开文本编辑器创建一个叫beye.py的新文件,
然后将下面的程序清单添加到文件中。

# coding=utf-8from 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]  # 1 is abusive(脏话), 0 not    return postingList, classVec# 创建一个带有所有单词的列表def createVocabList(dataSet):    vocabSet = set([])  # 创建一个空集©    for document in dataSet:        vocabSet = vocabSet | set(document)  # 创建两个集合的并集    return list(vocabSet)def setOfWords2Vec(vocabList, inputSet):    retVocabList = [0] * len(vocabList)  # 创建一个其中所含元素都为0的向量    for word in inputSet:        if word in vocabList:            retVocabList[vocabList.index(word)] = 1        else:            print('word ', word, 'not in dict')    return retVocabList

第一个函数loadDataSet() 创建了一些实验样本。该函数返回的第一个变量是进行词条切分后的文档集合,这些文档来自斑点犬爱好者留言板。这些留言文本被切分成一系列的词条集合,
标点符号从文本中去掉,后面会探讨文本处理的细节。loadDataSet()函数返回的第二个变量 是一个类别标签的集合。这里有两类,侮辱性和非侮辱性。这些文本的类别由人工标注,这些标
注信息用于训练程序以便自动检测侮辱性留言。 下一个函数createVocabList() 会创建一个包含在所有文档中出现的不重复词的列表,为此使用了python 的set数据类型。将词条列表输给set构造函数,set就会返回一个不重复词表。
首先,创建一个空集合© , 然后将每篇文档返回的新词集合添加到该集合中©。操作符丨用于求
两个集合的并集,这也是一个按位或操作符获得词汇表后,便可以使用函数setOfWords2Vec (),该函数的输入参数为词汇表及某个文档 ,输出的是文档向量,向量的每一元素为1或0,分别表示词汇表中的单词在输人文档中是否出现。函数首先创建一个和词汇表等长的向量,并将其元素都设置为0 © 。接着,遍历文档中的所有单词,

如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1

现在看一下这些函数的执行效果

2、分析数据

import bayeslistOPosts,listClasses = bayes.loadDataSet() myVocabList = bayes.createVocabList(listOPosts) print(myVocabList)
['dog', 'buying', 'garbage', 'flea', 'problems', 'not', 'is', 'cute', 'posting', 'has', 'quit', 'how', 'worthless', 'stop', 'mr', 'dalmation', 'maybe', 'licks', 'I', 'ate', 'park', 'my', 'him', 'help', 'love', 'food', 'please', 'steak', 'stupid', 'so', 'take', 'to']

[‘dog’, ‘buying’, ‘garbage’, ‘flea’, ‘problems’, ‘not’, ‘is’, ‘cute’, ‘posting’, ‘has’, ‘quit’, ‘how’, ‘worthless’, ‘stop’, ‘mr’, ‘dalmation’, ‘maybe’, ‘licks’, ‘I’, ‘ate’, ‘park’, ‘my’, ‘him’, ‘help’, ‘love’, ‘food’, ‘please’, ‘steak’, ‘stupid’, ‘so’, ‘take’, ‘to’]
检查上述词表,就会发现这里不会出现重复的单词。目前该词表还没有排序,需要的话,稍后可以对其排序

下面看一下函数setOfWords2Vec()的运行效果:

import bayes print(myVocabList)print(bayes.setOfWords2Vec(myVocabList, listOPosts[0]))print(bayes.setOfWords2Vec(myVocabList, listOPosts[3]))
['dog', 'buying', 'garbage', 'flea', 'problems', 'not', 'is', 'cute', 'posting', 'has', 'quit', 'how', 'worthless', 'stop', 'mr', 'dalmation', 'maybe', 'licks', 'I', 'ate', 'park', 'my', 'him', 'help', 'love', 'food', 'please', 'steak', 'stupid', 'so', 'take', 'to'][1, 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, 0, 0, 0, 0, 0][0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

[‘dog’, ‘buying’, ‘garbage’, ‘flea’, ‘problems’, ‘not’, ‘is’, ‘cute’, ‘posting’, ‘has’, ‘quit’, ‘how’, ‘worthless’, ‘stop’, ‘mr’, ‘dalmation’, ‘maybe’, ‘licks’, ‘I’, ‘ate’, ‘park’, ‘my’, ‘him’, ‘help’, ‘love’, ‘food’, ‘please’, ‘steak’, ‘stupid’, ‘so’, ‘take’, ‘to’]
[1, 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, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
该函数使用词汇表或者想要检查的所有单词作为输入,然后为其中每一个单词构建一个特征。一旦给定一篇文档(斑点犬网站上的一条留言),该文档就会被转换为词向量。接下来检查 一下函数的有效性。myVocabList中索引为0的元素是什么单词?应该是单词dog。该单词在第
一篇文档中出现,现在检查一下看看它是否出现在第四篇文档中。(不在)

3、训练算法:从词向量计算概率

讲解

朴素贝叶斯分类器训练函数

def trainNB0(trainMatrix, trainCatergory):    numTrainDoc = len(trainMatrix)    numWords = len(trainMatrix[0])    pAbusive = sum(trainCatergory) / float(numTrainDoc)    # 防止多个概率的成绩当中的一个为0    p0Num = zeros(numWords) #1 分子    p1Num = zeros(numWords)    p0Denom = 0.0 # 分母     p1Denom = 0.0    for i in range(numTrainDoc):        if trainCatergory[i] == 1:            p1Num += trainMatrix[i]            p1Denom += sum(trainMatrix[i]) # 2        else:            p0Num += trainMatrix[i]            p0Denom += sum(trainMatrix[i]) # 3    p1Vect = p1Num / p1Denom  # 处于精度的考虑,否则很可能到限归零    p0Vect = p0Num / p0Denom    return p0Vect, p1Vect, pAbusive

讲解
接下来试验一下

import bayesimport impimp.reload(bayes)listOPosts,listClasses = bayes.loadDataSet() myVocabList = bayes.createVocabList(listOPosts) # 至此我们构建了一个包含所有词的列表myVocabList 。trainMat=[] for postinDoc in listOPosts:     trainMat.append(bayes.setOfWords2Vec(myVocabList, postinDoc))# 该for循环使用词向量来填充化列表。下面给出属于侮辱性文档的概率以及两个类别的概率向量。p0V,p1V,pAb=bayes.trainNB0 (trainMat, listClasses)print("p0V:",p0V)print("p1V:",p1V)print("pAb:",pAb)
p0V: [ 0.04166667  0.          0.          0.04166667  0.04166667  0.  0.04166667  0.04166667  0.          0.04166667  0.          0.04166667  0.          0.04166667  0.04166667  0.04166667  0.          0.04166667  0.04166667  0.04166667  0.          0.125       0.08333333  0.04166667  0.04166667  0.          0.04166667  0.04166667  0.          0.04166667  0.          0.04166667]p1V: [ 0.10526316  0.05263158  0.05263158  0.          0.          0.05263158  0.          0.          0.05263158  0.          0.05263158  0.  0.10526316  0.05263158  0.          0.          0.05263158  0.          0.  0.          0.05263158  0.          0.05263158  0.          0.  0.05263158  0.          0.          0.15789474  0.          0.05263158  0.05263158]pAb: 0.5

p0V: [ 0.04166667 0. 0. 0.04166667 0.04166667 0.
0.04166667 0.04166667 0. 0.04166667 0. 0.04166667
0. 0.04166667 0.04166667 0.04166667 0. 0.04166667
0.04166667 0.04166667 0. 0.125 0.08333333 0.04166667
0.04166667 0. 0.04166667 0.04166667 0. 0.04166667
0. 0.04166667]
p1V: [ 0.10526316 0.05263158 0.05263158 0. 0. 0.05263158
0. 0. 0.05263158 0. 0.05263158 0.
0.10526316 0.05263158 0. 0. 0.05263158 0. 0.
0. 0.05263158 0. 0.05263158 0. 0.
0.05263158 0. 0. 0.15789474 0. 0.05263158
0.05263158]
pAb: 0.5 这就是任意文档属于侮辱性文档的概率

首先,我们发现文档属于侮辱类的概率pAb为0.5,该值是正确的。接下来,看一看在给定文档类别条件下词汇表中单词的出现概率,看看是否正确。词汇表中的第二个词是buying, 其在类别1 中出现1次 ,而在类别0中从未出现。对应的条件概率分别为0.0与 0.05263158 。该计算是正确的。 我们找找所有概率中的最大值,该值出现在?(1)数组第28个下标位置,大小为0.157 894 74。在 myVocabList中的第18个下标位置上可以查到该单词是stupidstupid。这意味着stupid是最能表征类别1(侮辱性文档类)的单词。 使用该函数进行分类之前,还需解决函数中的一些缺陷

朴素贝叶斯分类函数

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):    p1 = sum(vec2Classify * p1Vec) + log(pClass1)  # element-wise mult    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)    if p1 > p0:        return 1    else:        return 0def 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))

讲解

接下来试验一下

def main():    testingNB()if __name__ == '__main__':    main()
['love', 'my', 'dalmation'] classified as:  0['stupid', 'garbage'] classified as:  1

对文本做一些修改,看看分类器会输出什么结果。这个例子非常简单,但是它展示了朴素贝叶斯分类器的工作原理。接下来,我们会对代码做些修改,使分类器工作得更好。

原创粉丝点击