1. 程式人生 > >人工智慧演算法—樸素貝葉斯分類

人工智慧演算法—樸素貝葉斯分類

文/騰訊soso林世飛

    以下是個人學習貝葉斯分類器—文字分類的學習筆記,和大家一起學習交流。

準備工作

    監督學習型分類器特點 ,能夠從一個不確定度狀態開始,通過提供 正確和錯誤的樣本 ,不斷來確定哪些特徵(特徵由特徵提取函式,從樣本中提取 )對於分類更重要,可以有很多個分類器,來應對不同的分類或者過濾需求。所以訓練本身非常重要。

    先來複習下一個數學符號,條件概率:pr(A|B) 給定B條件下(也就是B發生情況下),A出現的概率。 

    Bayes公式和文字分類的基本原理

    Pr(A | B) = Pr(B | A) x Pr(A)/Pr(B)

    其實是由 下面這個式子移項得到的

    Pr(A | B)×Pr(B) = Pr(B | A) × Pr(A) –個人瞭解含義是A B同時出現的交集是一樣的

    在文字分類中變成:

    Pr(Category | Document) = Pr(Document | Category) x Pr(Category) /Pr(Document)

    我們需要計算當某個Document(這個往往使用特徵來表示)出現時候,他可能的分類的概率,取概率最大的一個。

    貝葉斯假設每項的各個概率是彼此獨立的。即,一個單詞在屬於某個指定分類的文件中出現的概率,與其他單詞出現於該分類的概率是不相關的。

    事實上這個假設是不成立的,因為你也許會發現,與有關Python

程式設計的文件相比,包含單詞“casino”的文件更有可能包含單詞“money”。這意味著,我們無法將採用樸素貝葉斯分類器所求得的結果實際用作一篇文件屬於某個分類的概率,因為這種獨立性的假設會使其得到錯誤的結果。不過,我們還是可以對各個分類的計算結果進行比較,然後再看哪個分類的概率最大。在現實中,若不考慮假設的潛在缺陷,樸素貝葉斯分類器將被證明是一種非常有效的文件分類方法。

下面來計算貝葉斯公式的每一項:

    Pr(Document | Category)的計算方法:為了使用樸素貝葉斯分類器,首先我們須要確定整篇文件屬於給定分類的概率。正如此前討論過的,我們須要假設概率的彼此獨立性,即:可以通過將所有的概率相乘,計算出總的概率值。例如,假設我們已經注意到有20%

的“bad”類文件中出現了單詞“Python”——Pr(Python | Bad) = 0.2——同時有80%的文件出現了單詞“casino”(Pr(Casino | Bad) = 0.8)。那麼,預期兩個單詞出現於同一篇“bad”類文件中的獨立概率為——Pr(Python & Casino | Bad)——0.8×0.2 = 0.16。從中我們會發現,計算整篇文件的概率,只須將所有出現與某篇文件中的各單詞的概率相乘即可。

     Pr(Category)是隨機選擇一篇文件屬於該分類的概率,因此就是屬於該分類的文件數除以文件的總數。計算方法根據樣本中統計的某一個分類的數量/ 所有分類出現的概率。

    Pr(Document) :某個文件出現的概率,我們可以認為任何一篇文件出現概率是相等的,也就是說這個值都是一樣的,因為我們最終是算概率的最大值,所以從所以計算中消去這項值,其對結果所產生的影響也完全是一樣的,因此我們完全可以忽略這一項。實際的公式計算變成:Pr(Category | Document) = Pr(Document | Category) x Pr(Category)

實際工程中可能遇到的問題:

    如何進行提取特徵

    剛剛提到 我們一般要用 一個 documentfeature 來代表這個 文件。所以需要一個函式Feature =fdocument),最簡單就是用非字母非數字類字元作為分隔符對單詞進行拆分。複雜一點可能需要解析這個document,比如如果是html 需要解析成DOM 樹 , 再取一個關鍵樹節點,比如title url

    為了便於理解,我們把公式重新寫成:Document 由特徵函式提取為feature

Pr(Category | Document) = Pr(Document | Category) x Pr(Category) /Pr(Document)

Pr(Category | feature) = Pr(feature | Category) x Pr(Category) /Pr(feature)

    訓練初始化和概率加權

    在訓練用的樣本資料中,單詞“money”只在一篇文件中出現過,並且由於這是一則涉及賭博的廣告,因此文件被劃歸為了“bad”類。由於單詞“money”在一篇“bad”類的文件中出現過,而任何“good”類的文件中都沒有該單詞,所以此時利用fprob計算所得的單詞“money”在“good”分類中出現的概率為0。這樣做有一些偏激,因為“money”可能完全是一箇中性詞,只是恰好先出現在了一篇 “bad”類的文件中而已。伴隨著單詞越來越多地出現在同屬於一個分類的文件中,其對應的概率值也逐漸接近於0,恐怕這樣才會更合理一些。

    為了解決上述問題,在我們手頭掌握的有關當前特徵的資訊極為有限時,我們還須要根據一個假設的概率來作出判斷。一個推薦的初始值是0.5。我們還須要確定為假設的概率賦以多大的權重——權重為1代表假設概率的權重與一個單詞相當。經過加權的概率值返回的是一個由getprobability與假設概率組成的加權平均。

    在單詞“money”的例子中,針對“money”的加權概率對於所有分類而言均是從0.5開始的。待到在classifier訓練期間接受了一篇 “bad”分類的文件,並且發現“money”適合於“bad”分類時,其針對“bad”分類的概率就會變為0.75。這是因為:此處最簡單的方法,是計算被考查內容在每個不同分類中的概率,然後選擇概率最大的分類

    分類閾值

    在許多應用中,我們無法將各個分類同等看待,而且在一些應用中,對於分類器而言,承認不知道答案,要好過判斷答案就是概率值稍大一些的分類。

    在垃圾資訊過濾的例子中,避免將普通郵件錯當成垃圾郵件要比截獲每一封垃圾郵件更為重要。收件箱中偶爾收到幾封垃圾郵件還是可以容忍的,但是一封重要的郵件則有可能會因為自動過濾到廢件箱而被完全忽視。假如我們必須在廢件箱中找回自己的重要郵件,那就真的沒必要再使用垃圾資訊過濾器了。

    為了解決這一問題,我們可以為每個分類定義一個最小閾值。對於一封將要被劃歸到某個分類的新郵件而言,其概率與針對所有其他分類的概率相比,必須大於某個指定的數值才行。這一指定的數值就是閾值。以垃圾郵件過濾為例,假如過濾到“bad”分類的閾值為3,則針對“bad”分類的概率就必須至少3倍於針對 “good”分類的概率才行。假如針對“good”分類的閾值為1,則對於任何郵件,只要概率確實大於針對“bad”分類的概率,它就是屬於“good” 分類的。任何更有可能屬於“bad”分類,但概率並沒有超過3倍以上的郵件,都將被劃歸到“未知”分類中。

綜述

    貝葉斯分類器都是監督型學習方法(supervised learning methods)的例子,這是一種利用正確結果接受訓練並逐步作出更準確預測的方法。

    貝葉斯分類器之所以經常被用於文件分類的原因是,與其他方法相比它所要求的計算資源更少。一封電子郵件可能包含數百甚至數千個單詞,與訓練相應規模大小的神經網路相比,簡單地更新一下計數值所需佔用的記憶體資源和處理器時鐘週期會更少。而且正如你所看到的,這些工作完全可以在一個數據庫中完成。神經網路是否會成為一種可行的替代方案,取決於訓練和查詢所要求的速度,以及實際執行的環境。神經網路的複雜性導致了其在理解上的困難。在本章中,我們可以清楚地看到單詞的概率,以及它們對最終分值的實際貢獻有多大,而對於網路中兩個神經元之間的連線強度而言,則並不存在同樣簡單的解釋。

另一方面,分類器相比,神經網路和支援向量機有一個很大的優勢:它們可以捕捉到輸入特徵之間更為複雜的關係。在貝葉斯分類器中,每個特徵都有一個針對各分類的概率值,將這些概率組合起來之後就得到了一個整體上概率值。在神經網路中,某個特徵的概率可能會依據其他特徵的存在或缺失而改變。也許你正在試圖阻止有關線上賭博的垃圾資訊,但是又對跑馬很感興趣,在這種情況下,只有當電子郵件中的其他地方沒有出現單詞“horse”時,單詞 “casino”才被認為是“bad”的。樸素貝葉斯分類器無法捕獲這樣的相互依賴性,而神經網路卻是可以的。

例項 :

訓練函式

def sampletrain(cl):

cl.train('Nobody owns the water.','good')

cl.train('the quick rabbit jumps fences','good')

cl.train('buy pharmaceuticals now','bad')

cl.train('make quick money at the online casino','bad')

cl.train('the quick brown fox jumps','good')

>>> reload(docclass)

<module 'docclass' from 'docclass.py'>

>>> cl=docclass.classifier(docclass.getwords)

>>> docclass.sampletrain(cl)

>>> cl.fprob('quick','good')

0.66666666666666663

出現quick文件的屬於good這個分類的概率0.66666666666666663

注:以上例子來自 《Programming Collective Intelligence》附原始碼。