Python學習-機器學習實戰-ch04 Bayes__Python

來源:互聯網
上載者:User

畢業論文寫不下去,就逃避來學這個

萬事開頭難,要勇敢邁出第一步

加油。

========================================================================================

貝葉斯的原理不贅述啦,網上還是有很多資料的


建立一個資料集,書中是以文檔分類的例子來講

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

上面這個函數就建立了一個小資料集,包含六篇文檔,每篇文檔有各自的分類(此例僅有0和1兩類)

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 bayeslistPost,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)    #使用中Regex提取    return [token.lower() for token in listOfTokens if len(token) >2]
</pre>此處,我犯了個錯,就是Regex那一塊,打的小寫w,所以結果錯誤。怎麼犯這麼愚蠢的錯誤<p></p><p><span style="background-color:rgb(240,240,240)"></span></p><pre code_snippet_id="1627130" snippet_file_name="blog_20160329_12_57207" name="code" class="python">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))
</pre>修改了一個地方:按照原文的話抱一個錯就是在trainingSet的地方<p></p><p><span style="background-color:rgb(240,240,240)">del(trainingSet[randIndex])TypeError: 'range' object doesn't support item deletion</span></p><p><span style="background-color:rgb(240,240,240)">於是,我在初始化的時候,把它改成了List型</span></p><p><span style="background-color:rgb(240,240,240)"><img src="https://img-blog.csdn.net/20160329104816823?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></span></p><p><span style="background-color:rgb(240,240,240)"></span></p><p><span style="background-color:rgb(240,240,240)"></span><pre name="code" class="python">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 feedparserny=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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.