毕业论文写不下去,就逃避来学这个
万事开头难,要勇敢迈出第一步
加油!
========================================================================================
贝叶斯的原理不赘述啦,网上还是有很多资料的
创建一个数据集,书中是以文档分类的例子来讲
def loadDataSet():
postingList=[['my','dog','has','flea','problem','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]
return postingList,classVec
def createVocabList(dataset):
vocabSet=set([])
for document in dataset:
vocabSet=vocabSet|set(document)
#循环对数据集内的每个文件提取word,set用于去重
#求并集
return list(vocabSet)
该函数将文档集转换为一个词汇库(vocabulary),里面包含在文档集内的所有word
贝叶斯的文档分类都是基于词汇库将文档转换成(特征)向量的,值就0和1表示存在或不存在
def setOfWords2Vec(vocabList,inputSet):
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
#该函数首先创建一个与词汇表等长的向量
#输出表示判断文档中的单词在词汇表中是否出现
#从而将文档转换为词向量
def trainNB0(trainMatrix,trainCategory):
numTrainDocs=len(trainMatrix)
#获取训练集的文档个数
numWords=len(trainMatrix[0])
#由第一行的个数获得vocabulary的长度
pAbusive=sum(trainCategory)/float(numTrainDocs)
#表示类别的概率,此例中仅限类别为0和1的状况
p0Num=zeros(numWords)
p1Num=zeros(numWords)
#pXNum是一个与Vocabulary等长的向量,用于统计对应word出现的次数
p0Denom=0.0
p1Denom=0.0
#pXDenom表示第X类内单词的总数
for i in range(numTrainDocs):
if trainCategory[i]==1:
p1Num+=trainMatrix[i]
p1Denom+=sum(trainMatrix[i])
else:
p0Num+=trainMatrix[i]
p0Denom+=sum(trainMatrix[i])
p1Vec=p1Num/p1Denom
p0Vec=p0Num/p0Denom
#vocabulary中的某个词在某类别里头出现的频率
return p0Vec,p1Vec,pAbusive
#首先搞清楚参数的意思
#结合前几个函数:postingList表示文档的集合,每一行表示一篇文档,行数即文档数
#classVec向量内值的个数与文档数相同,表示各文档的分类
#createVocabList函数把这些文档整合起来求得不含重复word的vocabulary
#setOfWords2Vec函数把一篇文档的word对应到vocabulary中,变成一个向量
#本函数的第一个参数表示每篇转化到vocabulary对应的向量,为n*m,n是文档数,m是vocabulary的长度
#trainCategory是一个向量,是每篇文档对应的类别
测试用的代码:
from numpy import *
import bayes
listPost,listClass=bayes.loadDataSet()
myVoc=bayes.createVocabList(listPost)
trainMat=[]
for postinDoc in listPost:
trainMat.append(bayes.setOfWords2Vec(myVoc,postinDoc))
p0V,p1V,pAb=bayes.trainNB0(trainMat,listClass)
print(myVoc)
print(p0V)
print(p1V)
print(pAb)
vocabulary里的word在个类别中出现的概率(先验概率)
每个类别出现的概率(先验概率)
此例中pAb结果为0.5,表示0和1两类是等概率出现的
根据现实情况修改:
1.初始化问题
贝叶斯进行文档分类时,需要多个概率的乘积以获得文档属于某个类别的概率
即:分别在每个类内对文档内的每个WORD的概率相乘,以获得整个文档对应该类别的概率
但是如果某个概率值为0,则整个概率值也为0。所以书中将所有单词出现数初始化为1,分母初始化为2
p0Num=ones(numWords)
p1Num=ones(numWords)
#pXNum的个数被初始化为1
p0Denom=2.0
p1Denom=2.0
2.下溢出
由于有很多个很小的数相乘,容易造成下溢出,最后会四舍五入得0.
解决的方法是:对乘积取对数
ln(a*b)=ln(a)+ln(b)
具体代码中为:
p1Vec=log(p1Num/p1Denom)
p0Vec=log(p0Num/p0Denom)
最后是整合上面的步骤,用于进行分类
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 testingNB():
listPost,listClass=loadDataSet()
myVoc=createVocabList(listPost)
trainMat=[]
for postinDoc in listPost:
trainMat.append(setOfWords2Vec(myVoc,postinDoc))
p0V,p1V,pAb=trainNB0(trainMat,listClass)
testEntry=['love','my','dalmation']
thisDoc=array(setOfWords2Vec(myVoc,testEntry))
print(testEntry,' classified as ',classifyNB(thisDoc,p0V,p1V,pAb))
testEntry=['stupid','garbage']
thisDoc=array(setOfWords2Vec(myVoc,testEntry))
print(testEntry,' classified as ',classifyNB(thisDoc,p0V,p1V,pAb))
检测结果:
使用朴素贝叶斯过滤垃圾邮件
def textParse(bigString):
import re
listOfTokens=re.split(r'\W*',bigString)
#使用中正则表达式提取
return [token.lower() for token in listOfTokens if len(token) >2]
此处,我犯了个错,就是正则表达式那一块,打的小写的w,所以结果错误。怎么犯这么愚蠢的错误def spamTest(): docList=[];classList=[];fullText=[] for i in range(1,26): wordList=textParse(open('email\spam\%d.txt' %i).read()) docList.append(wordList) fullText.append(wordList) classList.append(1) #正例 wordList=textParse(open('email\ham\%d.txt' %i).read()) docList.append(wordList) fullText.append(wordList) classList.append(0) #反例 vocabulary=createVocabList(docList) trainingSet=list(range(50)) testSet=[] for i in range(10): randIndex=int(random.uniform(0,len(trainingSet))) #random模块用于生成随机数 #random.uniform(a,b)用于生成制定范围内的随机浮点数 testSet.append(trainingSet[randIndex]) del trainingSet[randIndex] #随机选择10个文档作为测试集,其余作为训练集 trainMat=[];trainClasses=[] for docIndex in trainingSet: trainMat.append(setOfWords2Vec(vocabulary,docList[docIndex])) trainClasses.append(classList[docIndex]) #将选中的训练集逐个整合在一起 p0V,p1V,pSpam=trainNB0(trainMat,trainClasses) errorCount=0 for docIndex in testSet: wordVector=setOfWords2Vec(vocabulary,docList[docIndex]) if(classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]): errorCount+=1 #如果分类结果与原类别不一致,错误数加1 print('the error rate is:',float(errorCount)/len(testSet))
修改了一个地方:按照原文的话抱一个错就是在trainingSet的地方del(trainingSet[randIndex])TypeError: 'range' object doesn't support item deletion
于是,我在初始化的时候,把它改成了List型
def calcMostFreq(vocabulary,fulltext): import operator freqDict={} for token in vocabulary: freqDict[token]=fulltext.count(token) sortedFreq=sorted(freqDict.items(),key=operator.itemgetter(1),reverse=True) return sortedFreq[:30] #出现频率前30的词
def localWords(feed1,feed0):
import feedparser
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)
#两个RSS源作为正反例
vocabulary=createVocabList(docList)
#创建词汇库
top30Words=calcMostFreq(vocabulary,fullText)
#获得出现频率最高的30个
for pairW in top30Words:
if pairW[0] in vocabulary:vocabulary.remove(pairW[0])
#去除前30的单词
trainingSet=list(range(2*minlen));testSet=[]
for i in range(20):
randIndex=int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
#随机选择训练和测试集;测试集为20个
trainMat=[];trainClass=[]
for docIndex in trainingSet:
trainMat.append(bagOfWords2VecMN(vocabulary,docList[docIndex]))
trainClass.append(classList[docIndex])
#将训练集内的文档转换成频数特征
p0V,p1V,pSpam=trainNB0(array(trainMat),array(trainClass))
errorCount=0
for docIndex in testSet:
wordVector=bagOfWords2VecMN(vocabulary,docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
errorCount+=1
print('the error rate is: ',float(errorCount)/len(testSet))
return vocabulary,p0V,p1V
其中还是修改了
trainingSet=list(range(2*minlen))
不知道其他学习的同学们有没有遇到这个问题,这么处理对不对?
测试用的代码:
import feedparser
ny=feedparser.parse('http://newyork.craigslist.org/stp/index.rss')
sf=feedparser.parse('http://sfbay.craigslist.org/stp/index.rss')
vocabulary,pSF,pNY=bayes.localWords(ny,sf)
最具表征性词汇显示:
def getTopWord(ny,sf):
import operator
vocabulary,p0V,p1V=localWords(ny,sf)
topNY=[];topSF=[]
for i in range(len(p0V)):
if p0V[i]>-6.0:topSF.append((vocabulary[i],p0V[i]))
if p1V[i]>-6.0:topNY.append((vocabulary[i],p1V[i]))
#按照排序选择
sortedSF=sorted(topSF,key=lambda pair:pair[1],reverse=True)
#pair:pair[1]表示按每个元素的第二个参数排序
print("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")
for item in sortedNY:
print(item[0])
=========================================================================================
下载安装feedsparse
下载地址:点击打开链接
安装方法:首先将路径转换到该文件夹下
然后输入指令python setup.py install