【機器學習實戰】03-樸素貝葉斯算法實例

【博客的主要內容主要是自己的學習筆記,并結合個人的理解,供各位在學習過程中參考,若有疑問,歡迎提出;若有侵權,請告知博主刪除,原創文章轉載還請注明出處。】

[機器學習實戰:文本過濾器]

實例一:在線社區留言板過濾器

1 需求描述:

為維護在線社區留言板的正常次序,需屏蔽侮辱性的言論,需構建一個快速過濾器,如果某條留言使用了負面或侮辱性的言語,那么就將該留言標識為內容不當。

2 算法分析:【自問的過程】

1、擁有數據樣本情況?

有若干條數據樣本,其中每條“言論”均標識所屬類別(即侮辱性言語或非侮辱性言語)

2、程序如何判斷言語為侮辱性和非侮辱性?

  1. 樸素貝葉斯

將使用樸素貝葉斯公式:

Paste_Image.png

c 表示分類類別即:侮辱性言語和非侮辱性言語

對每個類別分母都一樣,即需計算$P(w|c_i)$ 和 $P(c_i)$,在樸素貝葉斯中假設事件是相互獨立的,故:
$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...P(w_n|c_i)$

  1. 需要計算什么?
    $P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$
    以上用文字描述:計算每個類別下各個單詞出現的概率。由此,需要統計內容:
    a)每條言論下各個單詞出現的次數;
    b)每個類別的單詞總數;

  2. 數據分析:現有數據什么樣?需要對數據如何處理?

  • a、對每條言語轉換成向量數組;

  • b、制定“詞典集合”,將每條言語做并集,去除重復單詞;并將“詞典集合”轉換為向量數組;

  1. 特殊情況分析:
  • a、由于$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$ 是做乘法運算,若其中一個單詞概率為0,則該言語概率為0。

    • [解決方法]將所有詞出現數初始化為1,分母初始化為2。
  • b、太多很小數相乘,結果將趨近為0.

    • [解決方法]對乘積取自然對數。在代數中有ln(a*b) = ln(a) + ln(b)。

3 算法實現

#1、將文本轉換為數字向量
##a、建立不重復的詞匯表
def createVocabList(dataSet):
    vocabSet = set([])
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)
    

#test
myVocabLists = createVocabList(postingLists)   
    
##b、將每條言語轉換為數字向量:建立與詞匯表同等大小的言語向量,若言語中的詞匯在詞匯表中出現則標記為1,否則為0.
#vocabList:單詞字典集合
#inputSet:單條文本
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

#test
wordsVec=[]
for postingList in postingLists:
    wordsVec.append(setOfWords2Vec(myVocabLists,postingList))

#trainMainx - 輸入文檔矩陣
#trainCategory - 由每篇文檔類別標簽所構成的向量
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    
    #初始化概率
    p0Num = ones(numWords)
    p1Num = 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 = log(p1Num / p1Denom)
    p0Vect = log(p0Num / p0Denom)  
    
    return p0Vect,p1Vect,pAbusive
    
##test
p0Vect,p1Vect,pAbusive=trainNB0(wordsVec,classLists)

2 實例二:電子郵件垃圾過濾

如何從文本文檔中構建自己的詞列表
隨機選擇數據的一部分作為訓練集,剩余部分作為測試集的過程稱為“留存交叉驗證”(hold-out cross validation)

思路:
1)構建詞列表:對文本文檔進行按詞切分
2)交叉驗證:對現有數據劃分為訓練集和測試集
3)樸素貝葉斯算法計算獨立事件概率

  1. 計算算法準確率
    5)多次重復實驗,提高正確率

textParse()接受一個大字符串并將其解析為字符串列表;
spamTest()對垃圾郵件分類器進行自動處理。主要:
1)解析文本文件編制成詞列表;
2)構建測試集合訓練集

######電子郵件垃圾過濾######
def textParse(bigString):
    import re
    listOfTokens = re.split(r'\W*',bigString)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

def spamTest():
    docList=[]; classList=[]; fullText=[]
    #創建詞匯表
    for i in range(1,26):
        wordList = textParse(open('email/spam/%d.txt'%i).read())
        docList.append(workList)
        fullText.extend(workList) 
        
        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(bagOfWord2VecMN(vocabList,docList[docIndex]))
        trainClasses.append(classList[docIndex])
        
        p0V,p1V,pSpam=trainNB(array(trainMat),array(trainClasses))      
        
    #統計錯誤率
    errorCount = 0 
    for docIndex in testSet:
        wordVector = bagOfWord2VecMN(vocabList,docList[docIndex])
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount +=1
            print "classification error:",docList[docIndex]
            print "the error rate is:", float(errorCount)/len(testSet)

3 實例三:使用樸素貝葉斯分類器從個人廣告中獲取區域傾向

對兩個城市所發布的征婚廣告信息,來比較這兩個城市的人們在廣告用詞上是否不同。
如果結論是不同,那么他們各自常用的詞是那些?
從人們的用詞中,能否對不同城市的人所關心的內容有所了解?

該實例目的:通過觀察單詞和條件概率值來發現與特定城市相關的內容

calcMostFreq() 遍歷詞匯表中每個詞并統計它在文本中出現的次數,然后根據出現次數從高到低對詞典進行排序,最后返回排序最高的100個單詞。

localWords() 主要:1)解析文本詞列表;2)構建測試集合訓練集
getTopWords() 訓練并測試樸素貝葉斯分類器,返回使用的概率值。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 第4章 基于概率論的分類方法:樸素貝葉斯 樸素貝葉斯 概述 貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理...
    Joyyx閱讀 3,035評論 1 15
  • 忘光了概率統計的知識還想學樸素貝葉斯算法?這一篇就是為你準備的。雖然如此,作為初學者,別指望 5 分鐘就能完全理解...
    kamidox閱讀 2,762評論 4 7
  • 【博客的主要內容主要是自己的學習筆記,并結合個人的理解,供各位在學習過程中參考,若有疑問,歡迎提出;若有侵權,請告...
    Paullu閱讀 2,303評論 0 11
  • 注:題中所指的『機器學習』不包括『深度學習』。本篇文章以理論推導為主,不涉及代碼實現。 前些日子定下了未來三年左右...
    我偏笑_NSNirvana閱讀 40,144評論 12 145
  • 音樂課:保持家庭和諧 為了掌握演奏種樂器的技巧,孩子需對他們努力的贊賞,而不是對他們錯誤的批評。 家長應理...
    尤占芳閱讀 206評論 0 0