您的位置:首页 > 其它

《机器学习实战》-朴素贝叶斯笔记

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: