机器学习实战--朴素贝叶斯
来源:互联网 发布:大漠驼铃 php 编辑:程序博客网 时间:2024/05/16 12:20
使用Python进行文本分类
要从文本中获取特征,需要先拆分文本,具体如何做呢?这里的特征是来自文本的词条,一个词条是字符的任意组合。可以把词条想象为单词,也可以使用非单词词条,如URL、IP地址或者任意其他字符串。然后将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现。
此处以社区留言为例,为了过滤侮辱性的言论,我们使用1 和 0 来代表是侮辱类和非侮辱类。
首先会给出将文本转换为数字向量的过程,然后介绍如何基于这些向量来计算条件概率,并在此基础上构建分类器,最后介绍利用Python实现朴素贝叶斯过程中需要考虑的问题。
在进行朴素贝叶斯实战前,建议先理解朴素贝叶斯的原理,我在自己的博客中介绍过 机器学习初涉–贝叶斯分类
1.准备数据,从文本中构建词向量
我们将文本看成词向量或者词条向量,也就是说将橘子转换为向量。考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表或者说所要的词汇集合,然后必须要将每一篇文档转换为词汇表上的向量。接下来我们正式开始。
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] # 1 is 侮辱性文字, 0 not return postingList, classVecdef createVocabList(dataSet): vocabSet = set([]) # create empty set for document in dataSet: vocabSet = vocabSet | set(document) # 并集 return list(vocabSet)def setOfWords2Vec(vocabList, inputSet): """ :param vocabList: 词汇表 :param inputSet: 某个文档 :return: 文档向量,向量的元素是0/1,分别表示词汇表中的单词在输入文档中是否出现。 """ returnVec = [0] * len(vocabList) # 创建一个其中所有元素都是0的向量 for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] = 1 else: print "the word: %s is not in my Vocabulary!" % word return returnVec
已经完成了将一组单词转换为一组数字,那么如何使用这组数字来计算概率。现在已经知道了一个字是否出现在一篇文档中,也知道文档所属的类别。那么一个留言属于侮辱性的还是非侮辱性的这两个概率如何计算?
首先,通过类别i(侮辱性和非侮辱性留言)中文档数除以总的文档数来计算概率P(Ci),接下来计算P(W|Ci),这里需要用到朴素贝叶斯假设,如果将W展开为一个个独立的特征,那么就可以将上述概率写作:P(W0,W1,W2..Wn|Ci)。这里假设所有词都相互独立,也称为条件独立性假设,它意味着可以使用P(W0|Ci)P(W1|Ci)P(W2|Ci)..P(Wn|Ci)来计算上述概率。
函数伪代码:
计算每个类别中的文档数目对每篇训练文档: 对每个类别: 如果词条出现在文档中——>增加该词条的计数值 增加所有词条的计数值 对每个类别: 对每个词条: 将该词条的数目除以总词条数得到条件概率(也就是求P(Wn|Ci)) 返回每个类别的条件概率
说明:这里是将每个词条视为独立的一个特征,因此,需要计算出每一个词条在Ci中出现的概率。
这部分的代码如下:
def trainNB0(trainMatrix, trainCategory): """ :param trainMatrix: 文档矩阵 :param trainCategory: 由每篇文档类别所构成的向量 :return: """ numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory) / float(numTrainDocs) # P(Ci) # 初始化概率.因为计算P(W0|Ci)*P(W1|Ci)...P(W2|Ci)时会出现其中一个概率为0,导致最后的结果也为0, # 因此,将初始化的出现次数设置为1,并将默认的词条总数设置为2 p0Num = ones(numWords) p1Num = ones(numWords) p0Denom = 2.0 p1Denom = 2.0 # 对于每一篇文章 for i in range(numTrainDocs): if trainCategory[i] == 1: p1Num += trainMatrix[i] # 将出现的词条对应计数加1 p1Denom += sum(trainMatrix[i]) # 词条出现的总数加1 else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) # 计算出现概率时,由于大部分因子非常小,会导致程序下溢或者得到不正确的答案,因此,解决办法是通过求对数 p1Vect = log(p1Num / p1Denom) # 计算第一个类别中的P(W/Ci),即在Ci中每个词条的出现概率 p0Vect = log(p0Num / p0Denom) # 另一个类别 return p0Vect, p1Vect, pAbusive
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): """ :param vec2Classify: 待分类文档的词向量数组 :param p0Vec: 第一个类别的各个特征出现的概率 :param p1Vec: 第二个类别的各个特征出现的概率 :param pClass1: P(Ci) :return: """ 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)) # 得到每个特征在每个类别中出现的概率数组,以及P(Ci) 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)
运行的结果如下:
['love', 'my', 'dalmation'] classified as: 0['stupid', 'garbage'] classified as: 1
截止到目前为止,我们将每个词的出现与否视为一个特征,这可以描述为词集模型。如果一个词在文档中出现不止一次,这可能意味着仅仅通过词出现与否表述为特征值是不够的,需要几记录下词的出现次数,这种方法被称为词袋模型。若词袋模型,可将setOfWordsVec()进行如下修改:
def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0] * len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 return returnVec
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》--朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》朴素贝叶斯
- <机器学习实战>--朴素贝叶斯实战(二)
- 机器学习实战之朴素贝叶斯
- 机器学习算法-朴素贝叶斯实战
- 机器学习实战笔记4(朴素贝叶斯)
- 《机器学习实战》之朴素贝叶斯
- 机器学习实战-朴素贝叶斯算法
- 机器学习实战——朴素贝叶斯
- 《机器学习实战》-朴素贝叶斯笔记
- 机器学习之实战朴素贝叶斯算法
- [Sklearn应用5] Feature Selection 特征选择(一) SelectFromModel
- Kotlin-23.内联函数(Inline Functions)
- 微店 Android 插件化实践
- 各种OJ刷题记录6.27-7.6
- Linux/Mac 交叉编译 Android 程序
- 机器学习实战--朴素贝叶斯
- 如何在一个Tomcat下部署两个应用
- eclipse如何设置点击页面找到侧边的目录
- 多线程
- java鬼混笔记:websocket java 多人聊天和一对一聊天
- udp程序设计
- codevs 3117 高精度练习之乘法
- 剑指offer:(30)时间效率 :最小的K个数
- 证明题-算法概论8.3吝啬SAT问题证明