《机器学习实战》-朴素贝叶斯笔记
2015-06-06 11:08
411 查看
本章内容
本章内容使用概率分布进行分类
学习朴素贝叶斯分类器
解析RSS源数据
使用朴素贝叶斯分类器从个人广告中获取区域倾向
使用概率分布进行分类
分类:if p1(x,y)>p2(x,y),属于类别1
if p1(x,y)>p2(x,y),属于类别2
如何计算概率值呢?
p(ci|x,y)=p(x,y|ci)p(ci)p(x,y)p(ci|x,y)=\frac{p(x,y|ci)p(ci)}{p(x,y)}
即在(x,y)的条件下属于类别ci的概率值
学习朴素贝叶斯分类器
朴素贝叶斯的一般过程:1、收集数据
2、准备数据
3、分析数据
4、训练算法
5、测试算法:计算错误率
6、使用算法
例子1:使用Python进行文本分类
背景:构建一个快速过滤器,判断在线社区留言板是否使用了负面或者侮辱性的语言
Step 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 is abusive, 0 not return postingList,classVec //创建一个包含在所有文档中出现的不重复词的列表 def createVocabList(dataSet): vocabSet=set([]) //set 集合,无序不重复元素集,基本功能包括关系测试和消除重复元素,支持&,|,-,交集并集差集 //set()可以去掉重复的元素 for document in dataSet: vocabSet=vocabSet | set(document)//创建两个集合的并集 return list(vocabSet) def setOfWords2Vec(vocabList,inputSet)://输入词汇表和某个文档,生成词汇向量 returnVec=[0]*len(vocabList)//创建一个所含元素都为零的向量 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
文档词袋模型:
之前计算特征向量,将每个词的出现与否作为一个特征,这里可以被描述为词集模型。如果一个词在文档中多次出现,这传达的信息就大于该词是否在文档里出现,这种方法称为词袋模型。
//词袋模型 def bagOfWordsVecMN(vocabList,inputSet): returnVec=[0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)]+=1 return returnVec
Step 2: 训练算法,从词向量计算概率
朴素贝叶斯假设所有词都互相独立:
p(w0,w1,w2...wN)|Ci)=p(w0|Ci)p(w1|Ci)...p(wN|Ci)p(w0,w1,w2...wN)|Ci)=p(w0|Ci)p(w1|Ci)...p(wN|Ci)
伪代码:
计算每个类别中的文档数据:
对每篇训练文档:
对每个类别:
如果词条出现文档中–>增加该词条技术
增加所有词条计数值
对每个类别:
对每个词条:
将该词条的数目除以总词条数目得到条件概率
返回每个类别的条件概率
def trainNBD(trainMatrix,trainCategory)://输入文档矩阵和类别标签向量 numTrainDocs=len(trainMatrix) numWords=len(trainMatrix[0])//每个文档包含的词汇量 pAbusive=sum(trainCategory)/float(numTrainDocs)//p(Ci=1) p0Num=ones(numWords) p1Num=ones(numWords) p0Denom=2.0 p1Denom=2.0 for i in range(numTrainDocs): if trainCategory[i]==1: p1Num+=trainMatrix[i]//特征i出现的累计次数 p1Denom+=sum(trainMatrix[i])//类别1出现的总次数 else: p0Num+=trainMatrix[i] p0Denom+=sum(trainMatrix[i]) p1Vec=log(p1Num/p1Denom) //计算 P(wi|c1)为了防止许多很小的数相乘最终四舍五入后为零,成为程序下溢,解决方法取log p0Vec=log(p0Num/p0Denom)// P(wi|c0) return p0Vec,p1Vec,pAbusive
Step 3: 测试算法: 朴素贝叶斯分类函数
//对每个文档的特征向量计算每个类别的概率值,输出概率最大的那个类别 def classifyNB(vec2Classify,p0Vec,p1Vec,pClass): p1=sum(vec2Classify*p1Vec)+log(pClass) p0=sum(vec2Classify*p0Vec)+log(1.0-pClass) if p1>p0: return 1 else: return 0
例子2 使用朴素贝叶斯过滤垃圾邮件
Step 5: 测试算法:交叉验证
//使用朴素贝叶斯进行交叉验证 //切分文本 //使用正则表达式来切分句子,分隔符是除单词、数字外的任意字符串 def textParse(bigString): import re regEx=re.compile('\\W*') listOfTokens=regEx.split(bigString) return [tok.lower() for tok in listOfTokens if len(tok)>0] 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) trainingSet=range(50) testSet=[] 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(setOfWords2Vec(vocabList,docList[docIndex]))//针对训练数据算出特征矩阵 trainClasses.append(classList[docIndex]) p0V,p1V,pSpam=trainNBD(array(trainMat),array(trainClasses)) errorCount=0 for docIndex in testSet: wordVector=setOfWords2Vec(vocabList,docList[docIndex]) if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]: errorCount+=1 print 'the error rate is: ',float(errorCount)/len(testSet)
解析RSS源数据
例子三 个人广告中获取区域倾向流程
1、收集数据:从RSS源收集内容,这里需要对RSS源构建一个接口
2、准备数据:将文本文件解析成词条向量
3、分析数据:检查词条确保解析的正确性
4、训练算法:使用之前建立的trainNBD()函数
5、使用算法:构建一个完整的程序,封装所有内容。给定两个RSS源,该程序会显示最常用的公共词
目的:通过将不同城市的广告训练成一个分类器,然后观察单词和条件概率来发现与特定城市相关的内容
通过网址下载 feedparser包:https://github.com/kurtmckee/feedparser,python setup.py install 进行安装
ny=feedparser.parse('http://newyork.craigslist.org/stp/index.rss') ny['entries']
构建一个类似spamTest的函数来对测试过程自动化
找到fullText中词出现频率最高的30个词
移除高频词,语言中大都是冗余和结构辅助性内容,另一个常用的方法是从某个预定词表中移除结构上的辅助词,成为停用词表
http://www.ranks.nl/resources/stopwords.html上有一个很好的多语言停用词列表
使用朴素贝叶斯来分析不同地区的态度
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): docList=[];classList=[];fullText=[] minLen=min(len(feed1['entries']),len(feed0['entries'])) for i in range(minLen): wordList=textParse(feed1['entries'][i]['summary']) docList.append(wordList) fullText.extend(wordList) classList.append(1) wordList=textParse(feed0['entries'][i]['summary']) docList.append(wordList) fullText.extend(wordList) classList.append(0) vocabList=createVocabList(docList) //构建字典 //去掉出现频率最高的那些词 //选择训练样本和测试样本 top30words=calcMostFreq(vocabList,fullText) for pairW in top30words: if pairW[0] in vocabList:vocabList.remove(pairW[0]) trainingSet=range(2*minLen);testSet=[]#trainingSet只记录index,最后计算Mat的时候,用dicList[Index] for i in range(20):#在训练样本中随机挑选20个做测试样本 randIndex=int(random.uniform(0,len(trainingSet))); testSet.append(trainingSet[randIndex]) del(trainingSet[randIndex]) trainMat=[];trainClasses=[] //根据训练样本计算字典中字词的正负样本概率 for docIndex in trainingSet: trainMat.append(bagOfWordsVecMN(vocabList,docList[docIndex])) trainClasses.append(classList[docIndex]) p0V,p1V,pSpam=trainNBD(array(trainMat),array(trainClasses)) errorCount=0 //测试样本结果判断正误 for docIndex in testSet: wordVector=bagOfWordsVecMN(vocabList,docList[docIndex]) if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]: errorCount+=1 print 'the error rate is: ',float(errorCount)/len(testSet) return vocabList,p0V,p1V ny=feedparser.parse('http://newyork.craigslist.org/stp/index.rss') sf=feedparser.parse('http://sfbay.craigslist.org/stp/index.rss') vocabList,psF,pNY=localWords(ny,sf) print vocabList
使用朴素贝叶斯分类器从个人广告中获取区域倾向
这里的错误率要远高于垃圾邮件中的错误率,这里关注的是单词概率而不是实际分类,可以通过函数caclMostFreq()改变要移除的单词数目,观察错误率的变化情况分析数据:显示地域相关的用词
最具表征性的词汇显示函数
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**" 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**" for item in sortedNY: print item[0] ny=feedparser.parse('http://newyork.craigslist.org/stp/index.rss') sf=feedparser.parse('http://sfbay.craigslist.org/stp/index.rss') getTopWords(ny,sf)
相关文章推荐
- LightOJ1011---Marriage Ceremonies (状压dp)
- surface pro 3系统运行中关闭fn功能键
- 程序员修炼之路
- ZigBee之无线射频程序解析
- 图片压缩问题
- Qt4.8.6与VS2008的集成开发环境的安装配置
- php函数—preg_quote()转义正则表达式字符
- 6.函数的参数
- 容器适配器之queue
- CSS Margin(外边距)
- 音频采样概念
- mysqldump命令 数据库的还原备份操作。
- 最近项目中的一些常用工具类写一下
- Android25图灵聊天项目------源码下载
- MyBatis学习总结(三)——优化MyBatis配置文件中的配置
- 暴力破解wifi密码
- java实现代理domino web邮件下载
- BZOJ 1620: [Usaco2008 Nov]Time Management 时间管理( 二分答案 )
- 实验--文件操作
- Android学习