PYTHON机器学习实战——朴素贝叶斯
来源:互联网 发布:河北大学工商学院 知乎 编辑:程序博客网 时间:2024/06/06 02:07
有时我们想知道给定一个样本时,它属于每个类别的概率是多少,即P(Ci|X), Ci表示类别,X表示测试样本,
有了概率后我们可以选择最大的概率的类别。
如果P(c1|x) > P(c2|x),那么属于类别c1。
如果P(c1|x) < P(c2|x),那么属于类别c2。
一般直接求P(Ci|X)比较难,但可以用经典贝叶斯公式转化:
p(C/X) = p(X/C)*p(C)/p(X)
而p(X|C)中,X是多个独立特征,即X=X1,X1,X3,... Xn时
p(X|C) = p(X1|C)*p(X2|C)*p(X3|C)*...*p(Xn|C)
所以:
p(C/X) = p(X/C)*p(C)/p(X)=p(X1|C)*p(X2|C)*p(X3|C)*...*p(Xn|C)*p(C)/p(X)
比较 P(c1|x) 与 P(c2|x) 那个较大时,只需要比较分母大小即可。
即比较:p(X1|C1)*p(X2|C1)*p(X3|C1)*...*p(Xn|C1)*p(C1)与
p(X1|C2)*p(X2|C2)*p(X3|C2)*...*p(Xn|C2)*p(C2)的大小即可。
而当 太多很小的数相乘 时 会产生 下溢出问题,或者得到不正确的答案,
在代数中有ln(a*b) = ln(a)+ln(b),于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。
同时,采用自然对数进行处理不会有任何损失。
即 计较 log(p(X1|C1)) +...+ log(p(Xn|C1)) + log(p(C1)) 与
log(p(X1|C2)) +...+ log(p(Xn|C2)) + log(p(C2))的大小 确定 X属于C1类还是C2类\
代码详解:
#-*- coding:utf-8 -*-#!/usr/bin/python'''朴素贝叶斯'''# 测试 侮辱性语句 import bayes as bs bs.testingNB()# 测试 垃圾邮件 import bayes as bs bs.spamTest()# 博客数据分析 测试 import feedparser import bayes as bs# ny = feedparser.parse('http://newyork.craigslist.org/stp/index.ress')# sf = feedparser.parse('http://sfbay.craigslist.org/stp/index.ress')# bs.getTopWords(ny,sf)from numpy import *# import feedparser # rss数据分析器dist_lab = {0: '非侮辱', 1: '侮辱'}dist_mail = {0: '非垃圾邮件', 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] #1 为侮辱性言论 , 0 非侮辱性言论 return postingList,classVec# 创建 词汇表 (生成 字典 单词表) def createVocabList(dataSet): vocabSet = set([]) # 创建空集合(不重复) for document in dataSet: vocabSet = vocabSet | set(document) # 两个集合的并集 set(返回不重复的词表) return list(vocabSet)# 词集模型 词向量 ,出现很多次 也为1# 用字典中的单词 线性表示 输入的词汇 流# 词表转为向量 classVec 类别标签向量 词汇表 vocabList, 输入文档 inputSet def setOfWords2Vec(vocabList, inputSet): returnVec = [0]*len(vocabList) # 类别标签向量 与 词表(单词字典) 等长 for word in inputSet: # 遍历文档中的单词 if word in vocabList: # 如果出现了 词汇表中的单词 returnVec[vocabList.index(word)] = 1 # 相应单词计数为1, 标记为1 出现很多次 也为1,表示使用过词典里的该单词 else: print "the word: %s is not in my Vocabulary!" % word return returnVec# 训练 朴素贝叶斯分类器# trainMatrix 训练文档矩阵(已用字典线性表示) trainCategory 训练文档类别标签向量 1 为侮辱性言论 , 0 非侮辱性言论# p(类别/词向量) = p(词向量/类别)* p(类别) / p(词向量)# p(ci/w) = p(w/ci) * p(ci) / p(w)# 而 p(w/ci) = p(w1/ci)*p(w2/ci)*。。。*p(wn/ci) # 而 p(w1/ci) 为对应 文章中 所有同类别文档 w1单词出现的 概率def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) # 文档个数 numWords = len(trainMatrix[0]) # 文档总字典单词数 pAbusive = sum(trainCategory)/float(numTrainDocs) # 属于侮辱性文档的概率 p(ci=1) # p(word/ci) 各类别(侮辱和非侮辱)中出现 各个单词的总次数 初始化为1 p0Num = ones(numWords); p1Num = ones(numWords) # 避免出现乘以0的情况 p0Denom = 2.0; p1Denom = 2.0 # change to 2.0 for i in range(numTrainDocs): # 每个文档 if trainCategory[i] == 1: # 对应类别 如果是侮辱类 p1Num += trainMatrix[i] # 所有文档中 侮辱类类别 各个单词出现的次数 直接用词向量+ p1Denom += sum(trainMatrix[i]) # 侮辱类文档单词总数 用以计算 侮辱类文档中每个单词出现的概率 else: p0Num += trainMatrix[i] # p(x/c0) 所有文档中 非侮辱类 各个单词出现的次数 p0Denom += sum(trainMatrix[i]) # 非侮辱类文档单词总数 p1Vect = log(p1Num/p1Denom) # change to log() p(w/c1) 取 对数避免下溢出 p0Vect = log(p0Num/p0Denom) # change to log() p(w/c0) return p0Vect,p1Vect,pAbusive # 返回[p(w1/c0),...,p(wn/c0)] [p(w1/c1),...,p(wn/c1)] p(c1)# 测试 朴树贝叶斯分类器def test_trainNB0(): pList,cVec = loadDataSet() # 文档句子 和 对于标签 vocList = createVocabList(pList) # 生成字典 trainMat = [] # 用字典线性表示的 文档 for pDoc in pList: # 字典 待测试文档 trainMat.append(setOfWords2Vec(vocList, pDoc)) # 线性表示后的矩阵(词向量) 与类别标签 p0_not_Vect,p1_yes_Vect,pAbusive=trainNB0(trainMat,cVec )# 得到 参数向量 return p0_not_Vect,p1_yes_Vect,pAbusive# 根据模型计算词向量属于每一类的概率,最大的为分类概率# vec2Classify 要分类的词向量# p(ci/w新)= p(w/ci)* p(ci)/ p(w) 正比 p(w/ci)* p(ci) # 正比log(p(w/ci)* p(ci) ) = log(p(w/ci)) + log(p(ci)) = # sum(log(p(w1/ci))+...+log(p(wn/ci))) + log(p(ci))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 # 属于1类 侮辱类 else: return 0 # 属于0类# 词袋模型 统计单词出现的次数# 字典单词 线性 表示 句子 成 词向量def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 # 统计出现的次数 return returnVec# 测试分类器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)) # 得到 朴树贝叶斯分类器参数 #测试句子包含的单词1 testEntry = ['love', 'my', 'dalmation'] thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) # 测试句子的 词向量 print testEntry,'分类为: ',dist_lab[classifyNB(thisDoc,p0V,p1V,pAb)]# 打印分类结果 #测试句子包含的单词2 testEntry = ['stupid', 'garbage'] thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) print testEntry,'分类为: ',dist_lab[classifyNB(thisDoc,p0V,p1V,pAb)]# 打印分类结果# 垃圾邮件过滤 英文句子 解析成 单词向量def textParse(bigString): # 输入为长长的字符串, # 输出为单词列表向量 import re listOfTokens = re.split(r'\W*', bigString)# 按除去单词、数字外的任意字符分割字符串 return [tok.lower() for tok in listOfTokens if len(tok) > 2] # 排除 单词个数少于2 的小词 变小些 # 垃圾邮件测试 def spamTest(): docList=[]; classList = []; fullText =[]# 文本词向量 标签 所有的词向量 for i in range(1,26):# 总共有25个测试文本 wordList = textParse(open('email/spam/%d.txt' % i).read()) docList.append(wordList) # 垃圾文档向量 fullText.extend(wordList) classList.append(1) # 标签为1 wordList = textParse(open('email/ham/%d.txt' % i).read()) docList.append(wordList) # 非垃圾文档向量 fullText.extend(wordList) classList.append(0) # 标签为0 vocabList = createVocabList(docList) # 创建 单词字典 trainingSet = range(50); testSet=[] # 50个训练样本 从训练样本随机抽取 10个 测试样本,并从训练样本中删除 for i in range(10): 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: # 对每一个测试样本分类 wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) #测试样本 词袋模型生成词向量 if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]: errorCount += 1 print "分类错误",docList[docIndex] print '错误率为: ',float(errorCount)/len(testSet) #return vocabList,fullText# 计算最常出现的词汇 的频率 以及 词汇 前30个def calcMostFreq(vocabList,fullText): import operator freqDict = {} for token in vocabList: freqDict[token]=fullText.count(token) sortedFreq = sorted(freqDict.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedFreq[:30] # def localWords(feed1,feed0): import feedparser # RSS阅读器 下载 wget https://pypi.python.org/packages/source/f/feedparser/feedparser-5.1.3.tar.gz#md5=f2253de78085a1d5738f626fcc1d8f71 sudo python setup.py install docList=[]; classList = []; fullText =[] # 文本词向量 标签 所有的词向量 minLen = min(len(feed1['entries']),len(feed0['entries'])) # 访问所有的条目 好像关键字没有!!! for i in range(minLen): wordList = textParse(feed1['entries'][i]['summary']) # 对RSS源数据 分解 docList.append(wordList) fullText.extend(wordList) classList.append(1) # NY is class 1 类别1 wordList = textParse(feed0['entries'][i]['summary']) docList.append(wordList) fullText.extend(wordList) classList.append(0) # 类别2 vocabList = createVocabList(docList) # 字典 top30Words = calcMostFreq(vocabList,fullText) # 字典单词中 在 所有词汇中出现次数最多的30个词汇 for pairW in top30Words: if pairW[0] in vocabList: vocabList.remove(pairW[0]) # 去除出现次数最高的词汇 # 创建测试数据 trainingSet = range(2*minLen); testSet=[] #create test set for i in range(20): randIndex = int(random.uniform(0,len(trainingSet)))print randIndex, 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: # 对每一个测试样本分类 wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) # 测试样本 词袋模型生成词向量 if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:#识别错误的样本 errorCount += 1 print '错误率: ',float(errorCount)/len(testSet) return vocabList,p0V,p1V# def getTopWords(ny,sf): import operator vocabList,p0V,p1V=localWords(ny,sf) topNY=[]; topSF=[] for i in range(len(p0V)): if p0V[i] > -6.0 : topSF.append((vocabList[i],p0V[i])) if p1V[i] > -6.0 : topNY.append((vocabList[i],p1V[i])) sortedSF = sorted(topSF, key=lambda pair: pair[1], reverse=True) print "SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**" for item in sortedSF: print item[0] sortedNY = sorted(topNY, key=lambda pair: pair[1], reverse=True) print "NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**" for item in sortedNY: print item[0]
- PYTHON机器学习实战——朴素贝叶斯
- 机器学习实战——朴素贝叶斯
- 机器学习实战学习笔记8——朴素贝叶斯
- 机器学习实战——python实现简单的朴素贝叶斯分类器
- 机器学习实战——第四章:朴素贝叶斯
- 《机器学习实战》——朴素贝叶斯算法
- 《机器学习实战》——朴素贝叶斯分类
- 从零开始实战机器学习(3)—朴素贝叶斯算法
- 机器学习实战—朴素贝叶斯及要点注解
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》--朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 机器学习实战--朴素贝叶斯
- 机器学习实战 朴素贝叶斯
- 机器学习实战-朴素贝叶斯
- 《机器学习实战》朴素贝叶斯
- python求解括号匹配的相关问题
- ACM训练日记—8月5日
- Hibernate学习5 事务管理简单例子购买股票
- Cocos2d-x实战项目开发:运动的小球
- javascript 实现父节点下子节点的倒序排列
- PYTHON机器学习实战——朴素贝叶斯
- Dream City ZOJ
- sstream与相比stdio.h的好处
- java mooc第三周对象容器
- Are We There Yet? (zoj1745)
- 用C++写一个日历程序,要求输入年份,显示全年的日历
- poj 1006 中国剩余定理模板
- tinker热修复问题
- 存储过程调试