機器學習之樸素貝葉斯

1. 必須理解的基礎理論

  在認識樸素貝葉斯以前,必須查閱資料理解條件機率和貝葉斯法則,這是掌握樸素貝葉斯分類方法的理論基礎算法

(1)條件機率app

  p(x=a|y=b) 表示在y=b成立的條件下x=a的機率less

  p(x=a|y=b) = p(x=a,y=b) / p(x = a)機器學習

(2)貝葉斯法則函數

  樸素貝葉斯最核心的部分是貝葉斯法則,貝葉斯法則的基石是條件機率,貝葉斯法則告訴咱們如何交換條件機率中的條件和結果,即若是已知p(x,y|c)計算p(c|x,y) post

     

2. 什麼是樸素貝葉斯

(1)概述學習

  樸素貝葉斯是爲數很少的基於機率論的分類算法,經過考慮特徵機率來預測分類,多用於文本分類,下面舉個粗略的例子:測試

  郵件的分類爲[垃圾郵件,非垃圾郵件]ui

  如今有封郵件,裏面就三詞[廣告,會議,新聞]spa

  前提:根據訓練數據知道p(廣告|垃圾),p(會議|垃圾),p(新聞|垃圾)和p(廣告|非垃圾),p(會議|非垃圾),p(新聞|非垃圾)

  計算出在垃圾郵件中特徵詞共同出現的機率 p1 = p(廣告)*p(會議)*p(新聞)

  計算出在非垃圾郵件中特徵詞共同出現的機率 p2 = p(廣告)*p(會議)*p(新聞)

  若p1 > p2則推測該郵件爲垃圾郵件,反之,推測爲非垃圾郵件,若是有郵件的分類還有第三類,就繼續算出p3,而後計算max(p1,p2,p3)

  上面就是貝葉斯決策理論的核心思想,即選擇具備最高几率的決策

(2)爲什麼稱爲樸素

  咱們稱之爲「樸素」,是由於整個形式化過程當中只作最原始、最簡單的假設,假設每一個詞都是獨立的特徵,假設全部詞相互條件獨立,一個詞的出現並不依賴於文檔中的其餘詞。

3. 使用樸素貝葉斯對文檔分類

  以在線社區的留言板爲例,爲了避免影響社區的發展,咱們要屏蔽侮辱性的言論,因此要創建一個快速的過濾器,若是某條留言使用了負面或者侮辱性的語言,那麼就將該留言表示爲內容不當。

  需求:根據留言板內容,設計貝葉斯過濾器負責檢測留言內容是否屬於侮辱性言論

(1)樸素貝葉斯的通常過程

  a. 準備數據:訓練文檔

  b. 分析數據:有大量特徵時,繪製特徵做用不大,此時使用直方圖效果好

  c. 訓練數據:計算不一樣的獨立特徵的條件機率

  d. 測試算法:計算錯誤率

  e. 使用算法

(2)準備數據

  準備6條留言板內容,及其確認的類別(侮辱性言論和正常言論),下面代碼中postingList爲留言板列表,classVec 爲每條留言對應的類別

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

(3)建立特徵詞彙數據集,遍歷全部留言,將特徵詞添加到詞聚集中

def create_vocab_list(dataset):
    """
    根據數據集建立詞彙列表
    """
    vocabset = set([])
    for doc in dataset:
        vocabset = vocabset | set(doc)
    return list(vocabset)

(3)根據特徵詞集分別將每條留言轉換爲向量,該向量能夠是詞集也能夠是詞袋

  詞集模式:對於給定文檔,只統計某個詞是否出如今本文檔中,而不統計出現的次數

  詞袋模式:對於給定的文檔,統計某個詞在本文檔中出現的次數,除此以外,每每還須要剔除重要性極低的高頻詞和停用詞

  下面代碼是基於詞袋的:

def trans_doc_to_vector(vocablist, inputset):
    """
    將輸入詞彙經過詞彙錶轉換爲向量
    例:vocablist = ['hello','world','fate0729']
        inputset = ['a','hello','b','c']
        return [0,1,0,0]
    """
    count = len(vocablist)
    return_vector = [0]*count
    for word in inputset:
        if word in vocablist:
            return_vector[vocablist.index(word)] += 1
    return return_vector    

(4)訓練算法

  計算出特徵詞聚集中的每一個特徵值分別在侮辱性言論留言和正常性言論中留言的機率

  以計算每一個特徵值在侮辱性言論類別留言中的機率爲例進行說明

  a. 統計每一個特徵值分別在侮辱性言論留言中出現的總次數num1.....numN

  b. 統計全部特徵值在侮辱性言論留言中出現的總次數sum

  c. 計算每一個特徵值在侮辱性言論類別留言中的機率 num1/sum ... numN/sum

  注意

  a. 因爲在使用貝葉斯算法時會使用到機率相乘的狀況,爲了不機率值爲0的狀況,能夠將全部詞的出現次數初始化爲1,sum初始化爲2

  b. 因爲太多很小的數相乘容易形成程序下溢出或者得不到正確的答案,咱們能夠選擇對成績取天然對數

def bayes_train(train_matrix,train_caltegory):
    """
    訓練集
    train_matrix:轉換後的文檔向量
    train_caltegory:文檔類型
    """
    docs = len(train_matrix)  #文章數量
    wordnum_in_docs = len(train_matrix[0]) #文章的單詞數
    p0num = np.ones(wordnum_in_docs)
    p1num = np.ones(wordnum_in_docs)
    p0Denom = 2
    p1Denom = 2
    for i in range(docs):
        if train_caltegory[i] == 1:
            p1num += train_matrix[i] #單詞在類型1的全部文章中出現的次數
            p1Denom += sum(train_matrix[i]) #類型1的文章中在詞彙表中出現的總次數
        else:
            p0num += train_matrix[i]
            p0Denom += sum(train_matrix[i])
    
    p1vect = np.log(p1num / p1Denom)  #全部單詞在類型1的文章中出現的機率
    p0vect = np.log(p0num / p0Denom)  #全部單詞在類型0的文章中出現的機率
    pAb = sum(train_caltegory) / len(train_caltegory)#類型1在全部類型中的機率
    return p0vect,p1vect,pAb

  先測試下,看看特徵詞聚集和訓練算法返回結果:

if __name__ == '__main__':
    postingList, classVec = loadDataSet()
    vocablist = create_vocab_list(postingList)
    print('vocablist:',vocablist)
    return_vectors = []
    for item in postingList:
        return_vector = trans_doc_to_vector(vocablist,item)
        return_vectors.append(return_vector)
    p0vect,p1vect,pAb = bayes_train(return_vectors, classVec)
    print("pAb:",pAb)
    print('p0vect:',p0vect)
    print('p0vect:',p1vect)

  輸出:

  vocablist爲特徵詞聚集,pAb爲侮辱性留言佔總留言的比例,p0vect爲特徵詞在正常性言論留言中的機率,p1vect爲特徵詞在正常性言論留言中的機率

  以stupid爲例,stupid在p0vect中的機率爲-3.25896,而在p1vect中的機率爲-1.65822808,且爲p1vect中最大值,這意味着stupid最能表明侮辱性留言類別

(5)朴樹貝葉斯分類函數

def classify(pAb,p0vect,p1vect,test_vect):
    """
    分類
    """
    p1 = sum(test_vect*p1vect) + math.log(pAb)
    p0 = sum(test_vect*p0vect) + math.log((1-pAb))
    print("p0:",p0)
    print("p1:",p1)
    if p1 > p0:
        return 1
    else:
        return 0

  該函數比較test_vect向量在類型0類型1中的機率,能夠回頭看看貝葉斯函數原型

(6)測試

  給條留言進行測試

  test_doc = ['love', 'my', 'dalmation']

  test_doc1 = ['stupid', 'garbage']

test_doc = ['love', 'my', 'dalmation']
test_doc_vect = np.array(trans_doc_to_vector(vocablist, test_doc))
label = classify(pAb,p0vect,p1vect,test_doc_vect)
print("留言類型爲:",label)
test_doc1 = ['stupid', 'garbage']
test_doc_vect1 = np.array(trans_doc_to_vector(vocablist, test_doc1))
label1 = classify(pAb,p0vect,p1vect,test_doc_vect1)
print("留言類型爲:",label1)
        

  輸出:

  即第一條留言爲正常性言論,第二條爲侮辱性留言

 4. 總結

(1)對於分類而言,使用機率有時比使用硬規則更爲有效,貝葉斯提供了一種利用已知值來估計未知機率的有效方法

(2)特徵之間的條件獨立性假設,顯然這種假設顯得「粗魯」而不符合實際,這也是名稱中「樸素」的由來。然而事實證實,樸素貝葉斯在有些領域頗有用,好比垃圾郵件過濾;

(3)在具體的算法實施中,要考慮不少實際問題,好比由於「下溢」問題,須要對機率乘積取對數,再好比詞集模型和詞袋模型,還有停用詞和無心義的高頻詞的剔除,以及大量的數據預處理問題,等等

(4)此分類器的準確率很是依賴於訓練集,機器學習算法就和純潔的小孩同樣,取決於其成長(訓練)條件,「吃的是草擠的是奶」,但,「不是全部的牛奶,都叫特侖蘇」

相關文章
相關標籤/搜索