《机器学习实战》代码片段学习3 朴素贝叶斯
来源:互联网 发布:java方法重载意义 编辑:程序博客网 时间:2024/05/20 08:41
知识储备:
贝叶斯决策核心思想:选择具有最高概率的决策。
贝叶斯准则:
利用贝叶斯准则我们可以交换条件概率中的条件与结果。
朴素贝叶斯假设:1.每个特征相互独立。2.每个特征同等重要。
朴素贝叶斯分类器的优缺点:
优点:在数据较少的情况下仍然有效,可以处理多类别问题。
缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据。
例子中朴素贝叶斯分类器的工作流程:
1.获取训练用的文档集合list以及保存了文档分类结果的向量listClasses。
2.从所有文档中建立不重复的词汇列表VocabList。
3.将每一文档转换为文档向量,建立所有文档向量组成的矩阵trainMat
4.利用trainMat与listClasses训练朴素贝叶斯分类器,获取参数p0v,p1v,pAb
5.利用训练好的分类器对未知样本进行分类。
代码学习:
词表到向量的转换函数:
#创建在文档中出现的不重复词的列表def createVocabList(dataSet): vocabSet = set([]) #create empty set for document in dataSet: vocabSet = vocabSet | set(document) #union of the two sets求并集 return list(vocabSet)#创建与词汇表等长的所有元素都为0的向量def setOfWords2Vec(vocabList, inputSet): returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: #使用list.index()取索引 returnVec[vocabList.index(word)] = 1 else: print "the word: %s is not in my Vocabulary!" % word return returnVec
重写以方便编程的贝叶斯准则:
其中w粗体表示向量,本例中向量包含的数值个数与词汇列表长度相同。
朴素贝叶斯分类器训练函数:
#trainMatrix为文档矩阵,其中每一行由上例的setOfWords2Vec()生成,记录文档中对词汇列表中词语的包含情况,0为该文档不包含词汇列表中对应的词语,1为包含#trainCategory为记录每篇文档类别标签的列表,本例中记录每篇文档是否包含侮辱性词汇的情况,0即为对应文档没有侮辱性词汇,1为对应文档包含侮辱性词汇。#值得注意的是,trainMatrix每一行长度与trainCategory相同,都为词汇列表的长度,即为词汇列表中词的个数。def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) #训练文档数 numWords = len(trainMatrix[0]) #词列表的长度,即不重复的词的数量 pAbusive = sum(trainCategory)/float(numTrainDocs) #p(ci) p0Num = ones(numWords); p1Num = ones(numWords) p0Denom = 2.0; p1Denom = 2.0 #对每个文档进行遍历 for i in range(numTrainDocs): #若文档具有侮辱性词汇 if trainCategory[i] == 1: p1Num += trainMatrix[i] #矩阵相加,计算各个词个数 p1Denom += sum(trainMatrix[i]) #计算文档中的总词数 else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = log(p1Num/p1Denom) #每个元素做除法,取对数 p0Vect = log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive
朴素贝叶斯分类器:
#vec2Classify为需要分类的向量def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): p1 = sum(vec2Classify * p1Vec) + log(pClass1) p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) if p1 > p0: return 1 else: return 0将词集模型修改为词袋模型:def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: #累计计算词语的出现次数 returnVec[vocabList.index(word)] += 1 return returnVec
在分词部分,书上为了去掉除数字与单词以外的部分书中结合正则表达式使用了split()方法进行分词,并在后期通过判断分词后的长度是否大于0来去掉空格,通过.lower()方法将单词全部转换为小写。具体代码在以下的测试函数里有。实际分词操作应该结合停用词表比较好,中文分词还得使用专业的分词程序,例如结巴分词。
完整的垃圾邮件测试函数,使用了留存交叉验证的方法进行测试:
def textParse(bigString): import re #正则表达式分词,\W匹配任何非单词字符 listOfTokens = re.split(r'\W*', bigString) #又是这种酷炫的列表操作方法:小写转换、去掉长度小于2的分词结果, return [tok.lower() for tok in listOfTokens if len(tok) > 2] def spamTest(): docList=[]; classList = []; fullText =[] for i in range(1,26): wordList = textParse(open('email/spam/%d.txt' % i).read()) docList.append(wordList) fullText.extend(wordList) classList.append(1) wordList = textParse(open('email/ham/%d.txt' % i).read()) docList.append(wordList) fullText.extend(wordList) classList.append(0) vocabList = createVocabList(docList) #create vocabulary trainingSet = range(50); testSet=[] #随机选取测试集 for i in range(10): #random.uniform()从0到len(trainingSet)中随机取样 randIndex = int(random.uniform(0,len(trainingSet))) testSet.append(trainingSet[randIndex]) del(trainingSet[randIndex]) #从训练集中删除之 trainMat=[]; trainClasses = [] for docIndex in trainingSet: trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex])) trainClasses.append(classList[docIndex]) p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses)) errorCount = 0 #计算错误率 for docIndex in testSet: #classify the remaining items wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]: errorCount += 1 print "classification error",docList[docIndex] print 'the error rate is: ',float(errorCount)/len(testSet) #return vocabList,fullText
书中关于留存交叉验证的说明:“这种随机选择数据的一部分作为训练集,而剩余部分作为测试集的过程称为留存交叉验证(hold-out cross validation)”
小结
朴素贝叶斯分类器的不足之处在于其独立性假设过于理想:“可以通过特征之间的条件独立性假设,降低对数据量的需求。独立性假设是指一个词的出现概率并不依赖于文档中的其他词。当然我们也知道这个假设过于简单。这就是之所以称为朴素贝叶斯的原因。”
编程实现朴素贝叶斯分类器时需要考虑的一些问题:“利用现代编程语言来实现朴素贝叶斯时需要考虑很多实际因素。下溢出就是其中一个问题,它可以通过对概率取对数来解决。词袋模型在解决文档分类问题上比词集模型有所提高。还有其他一些方面的改进,比如说移除停用词,当然也可以花大量时间对切分器进行优化。”
- 《机器学习实战》代码片段学习3 朴素贝叶斯
- 机器学习实战【3】(朴素贝叶斯)
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》--朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》朴素贝叶斯
- 机器学习实战代码详解(四)朴素贝叶斯
- <机器学习实战>--朴素贝叶斯实战(二)
- 机器学习实战之朴素贝叶斯
- 机器学习算法-朴素贝叶斯实战
- 机器学习实战笔记4(朴素贝叶斯)
- 《机器学习实战》之朴素贝叶斯
- 机器学习实战-朴素贝叶斯算法
- Retrofit 2.0 使用教程
- 002 Flask入门
- CodeForces 453 A.Little Pony and Expected Maximum(快速幂)
- 欢迎使用CSDN-markdown编辑器
- NOI
- 《机器学习实战》代码片段学习3 朴素贝叶斯
- 设计模式---策略模式
- guava
- linux 显示文件或文件夹
- HDU 5877 Weak Pair(离散化+dfs+树状数组) 大连区域网络赛
- PPAPI插件开发指南
- c++基础之变量与常量
- 剑指ACM_1,原题+python代码——Feli的生日礼物、取石子游戏、钱币兑换问题
- 【STL】C++11新特性emplace操作