朴素贝叶斯笔记(1)

朴素贝叶斯(Naive Bayes)是一种简单的分类算法,它的经典应用案例为人所熟知:文本分类(如垃圾邮件过滤)。
优点:在数据较少的情况下仍然有效,可以处理多类别问题
缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据(即离散型数据,变量的结果只在有限目标集中取值)

贝叶斯决策理论核心思想:选择高概率对应的类别。
例:p1(x,y)表示(x,y)属于类别1的概率, p2(x,y)表示(x,y)属于类别2的概率。如果p1>p2,则类别为1。如果p2>p1,则类别为2

假设y为类别,x为测试数据,那么贝叶斯分类器就是一个求p(y|x)的过程。

image.png

P(y)就是在不知道数据是类别为y的概率,这个数值可以通过计算训练集中属于特定类别的样本比例来得到。
假设F1,F2为训练集数据的特征,C为一种类别,P(x)就是每个特征的概率P(F1,F2)。这可以通过计算训练集中含有特定特征值的样本比例来得到。
比较微妙的部分是计算P(x|y),即P(F1,F2|C)。这个值的意义为:如果知道样本的类别为C,那么有多大的可能性可以看到特征值F1,F2。

在概率论中我们还知道:
P(F1,F2|C)=P(F1|C)P(F2|C,F1)
在这里我们假设F1,F2相互独立,那么就可以把P(F2|C,F1)简化成P(F2|C)

最终我们得到的公式为:

最终推导出、公式.png

对于每个类别的结果,其分母的P(F1,F2)都是一样的值,因此可以简单忽略,这并不会改变最终胜出的类别。也就是说我们只要求到p(C)和p(F1|C) p(F2|C)就可以得到p(C|F1,F2)

接下来我们使用朴素贝叶斯进行文档分类。

准备数据:

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):
    vocabList=set([])#set方法用于创建集合
    for document in dataSet:
        vocabList=vocabList|set(document)
        # |用于求两个集合的并集,最终得到不重复词表。
    return list(vocabList)

将文档向量化

#vocabList为词汇表 inputSet为输入文本
def setOfWords2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]+=1
    return returnVec

训练函数:

#trainMatrix为向量化后的文档矩阵
#trainCategory为每篇文档类别标签构成的列表,即第一个函数中的classVec
def trainNB0(trainMatrix,trainCategory): #训练函数
    numTrainDocs=len(trainMatrix) #文档矩阵所含文档数量,即训练集数据数量
    numWords=len(trainMatrix[0]) #数据的特征值数量
    pAbusive=sum(trainCategory)/float(numTrainDocs) 
    #计算任意文档属于侮辱性文档(class=1)的概率。即p(1)。p(0)=1-p(1),也就是公式中的p(y)
    p0Num=np.ones(numWords)
    p1Num=np.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=sp.log(p1Num/p1Denom) #对每个元素做除法
    #p0Vect,p1Vect为给定文档类别条件下词汇表中单词的出现概率
    p0Vect=sp.log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive

朴素贝叶斯分类函数:

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):#测试函数
    p1=sum(vec2Classify*p1Vec)+sp.log(pClass1)
    p0=sum(vec2Classify*p0Vec)+sp.log(1.0-pClass1)
    if p1>p0:
        return 1
    else:
        return 0

测试函数:

def testingNB():
    listOPosts,listClasses=loadDataSet()#加载训练数据和标签
    myVocabList=createVocabList(listOPosts)#创建词汇表
    trainMat=[]#初始化训练向量矩阵
    for postinDoc in listOPosts:#将训练数据转化为向量
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
    p0V,p1V,pAb=trainNB0(trainMat,listClasses)
    testEntry=['love','my','dalmation']
    thisDoc=setOfWords2Vec(myVocabList,testEntry)
    print testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb)
    testEntry=['stupid','garbage']
    thisDoc=np.array(setOfWords2Vec(myVocabList,testEntry))
    print testEntry,'classified as:',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]
    #将单词小写化,并过滤掉小于两个字符的单词。

垃圾邮件分类函数:

import random
def spamTest():
    docList=[]; classList=[];fullText=[]
    for i in range(1,26):
        wordList=textParse(open('C:\Users\Lenovo\Desktop\Data\machinelearninginaction\Ch04\email\spam\%d.txt' %i).read())
        docList.append(wordList)
        fullText.extend(wordList)#在fullText末尾扩展添加wordList
        classList.append(1)
        wordList=textParse(open('C:\Users\Lenovo\Desktop\Data\machinelearninginaction\Ch04\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)))
        #uniform函数生成0到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=trainNB0(np.array(trainMat),np.array(trainClasses))
    errorCount=0
    for docIndex in testSet:
        wordVector=setOfWords2Vec(vocabList,docList[docIndex])
        if classifyNB(np.array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
            errorCount+=1
    print 'the error rate is: ',float(errorCount)/len(testSet)

spamTest()     

随机选择数据的一部分作为训练集,
而剩余部分作为测试集的过程称为留存交叉验证
函数spamTest()会输出在10封随机选择的电子邮件上的分类错误率。既然这些电子邮件是随机选择的,所以每次的输出结果可能有些差别。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容