貝葉斯分類器是在第6章介紹的。在那一章中,我們已經學會了如何建立一個文檔分類系統(tǒng),將其用于垃圾郵件過濾,或是根據關鍵字的模糊搜索來對一組文檔進行劃分。
盡管所有的例子都是關于文檔處理的,但是第6章的貝葉斯分類器實際上也可以適用于任何其他形式的數據集,只要我們能將其轉換成一組特征列表。
所謂特征,就是指一個給定項中存在或缺少的某種東西。
在文檔的例子中,特征就是文檔中的單詞,但它們也可以是某個不明對象的特有屬性、一種疾病的癥狀,或是其他任何形式的東西,只要我們能夠稱其是"存在的"或"缺少的"即可。
訓練 Training
和所有監(jiān)督算法一樣,貝葉斯分類器是利用樣本進行訓練的。
每個樣本包含了一個特征列表和對應的分類。
假定我們要對一個分類器進行訓練,使其能夠正確判斷出:一篇包含單詞"python"的文檔究竟是關于編程語言的,還是關于蛇的。表12-1給出了一個樣本訓練集。
表12-1:針對一組文檔的特征和分類
特征 | 分類
-- |
Python是以鳥和哺乳動物為食的大蟒 | 蛇
Python最初是作為一門腳本語言被開發(fā)出來的 | 語言
在印度尼西亞發(fā)現了一條14.935米(49英尺)長的Python | 蛇
Python具有動態(tài)類型系統(tǒng) | 語言
擁有鮮艷表皮的Python | 蛇
開源項目 | 語言
分類器記錄了它迄今為止見過的所有特征,以及這些特征與某個特定分類相關聯的數字概率。
分類器逐一接受樣本的訓練。當經過某個樣本的訓練之后,分類器會更新該樣本中特征與分類的概率,同時還會產生一個新的概率,即:在一篇屬于某個分類的文檔中,含有指定單詞的概率。
例如,經過如表12-1所示的一組文檔的訓練之后,也許我們最終會得到如表12-2所示的一組概率。
表12-2:單詞屬于某個給定分類的概率
特征 | 語言 | 蛇
-- |
dynamic | 0.6 | 0.1
constrictor | 0.0 | 0.6
long | 0.1 | 0.2
source | 0.3 | 0.1
and | 0.95 | 0.95
從上表中我們可以看到,經過訓練之后,特征與各種分類的關聯性更加明確了。
單詞"constrictor"屬于蛇的分類概率更大,而單詞"dynamic"屬于編程語言的分類概率更大。
另一方面,有些特征的所屬分類則并沒有那么明確,比如:單詞"and"出現在兩個分類中的概率是差不多的(單詞"and"幾乎會出現在每一篇文檔中,不管它屬于哪一個分類)。
分類器在經過訓練之后,只會保留一個附有相應概率的特征列表,與某些其他的分類方法不同,此處的原始數據在訓練結束之后,就沒有必要再加以保存了。
分類 Classifying
當一個貝葉斯分類器經過訓練之后,我們就可以利用它來對新的項目進行自動分類了。
假定我們有一篇新的文檔,包含了特征"long"、"dynamic"和"source"。表12-2列出了每個特征的概率,但這些概率只是針對于各個單詞而言的。如果所有單詞同屬于一個分類的概率值更大,那么答案顯然是很清楚的。
然而在本例中,"dynamic"屬于語言分類的概率更大,而"long"屬于蛇分類的概率更大。因此,為了真正對一篇文檔進行有效地分類,我們需要一種方法能將所有特征的概率組合到一起,形成一個整體上的概率。
解決這一問題的一種方法是利用我們在第6章中介紹過的樸素貝葉斯分類器。它是通過下面的公式將概率組合起來的:
Pr(Category | Document) = Pr(Document | Category) * Pr(Category) / Pr(Document)
此處:
Pr (Document | Category) = Pr(Word1 | Category) * Pr(Word2 | Category) *…
- Pr(Word | Category)的取值來自于上表,比如:Pr (dynamic | Language) = 0.6。
- Pr(Category)的取值則等于某個分類出現的總體幾率。因為"language"有一半的機會都會出現,所以Pr(Language)的值為0.5。
無論是哪個分類,只要其Pr(Category | Document)的值相對較高,它就是我們預期的分類。
代碼使用說明 Using Your Code
為了利用第6章中構造的貝葉斯分類器對數據集進行分類,我們所要做的唯一一件事情就是定義一個特征提取函數,該函數的作用是將我們用以訓練或分類的數據轉化成一個特征列表。
在第6章中我們處理的是文檔,所以該函數將字符串拆分成了一個個單詞,但是也可以采用任何其他形式的函數,只要它接受的是一個對象,并且返回一個列表:
>>> docclass.getwords('python is a dynamic language')
{'python': 1, 'dynamic': 1, 'language': 1}
上述函數可用于創(chuàng)建一個新的分類器,針對字符串進行訓練:
>>> cl=docclass.naivebayes(docclass.getwords)
>>> cl.setdb('test.db')
>>> cl.train('pythons are constrictors','snake')
>>> cl.train('python has dynamic types','language')
>>> cl.train('python was developed as a scripting language','language')
然后進行分類:
>>> cl.classify('dynamic programming')
u'language'
>>> cl.classify('boa constrictors')
u'snake'
對于允許使用的分類數量,此處并沒有任何的限制,但是為了使分類器有一個良好的表現,我們須要為每個分類提供大量的樣本。
優(yōu)點和缺點 Strengths and Weaknesses
-
樸素貝葉斯分類器與其他方法相比最大的優(yōu)勢或許就在于,它在接受大數據量訓練和查詢時所具備的高速度。即使選用超大規(guī)模的訓練集,針對每個項目通常也只會有相對較少的特征數,并且對項目的訓練和分類也僅僅是針對特征概率的數學運算而已。
尤其當訓練量逐漸遞增時則更是如此--在不借助任何舊有訓練數據的前提下,每一組新的訓練數據都有可能會引起概率值的變化。
(你會注意到,貝葉斯分類器的算法實現代碼允許我們每次只使用一個訓練項,而其他方法,比如決策樹和支持向量機,則須要我們一次性將整個數據集都傳給它們。)對于一個如垃圾郵件過濾這樣的應用程序而言,支持增量式訓練的能力是非常重要的,因為過濾程序時常要對新到的郵件進行訓練,然后必須即刻進行相應的調整;更何況,過濾程序也未必有權訪問已經收到的所有郵件信息。
樸素貝葉斯分類器的另一大優(yōu)勢是,對分類器實際學習狀況的解釋還是相對簡單的。由于每個特征的概率值都被保存了起來,因此我們可以在任何時候查看數據庫,找到最適合的特征來區(qū)分垃圾郵件與非垃圾郵件,或是編程語言與蛇。保存在數據庫中的這些信息都很有價值,它們有可能會被用于其他的應用程序,或者作為構筑這些應用程序的一個良好基礎。
-
樸素貝葉斯分類器的最大缺陷就是,它無法處理基于特征組合所產生的變化結果。假設有如下這樣一個場景,我們正在嘗試從非垃圾郵件中鑒別出垃圾郵件來:假如我們構建的是一個Web應用程序,因而單詞"online"時常會出現在你的工作郵件中。而你的好友則在一家藥店工作,并且喜歡給你發(fā)一些他碰巧在工作中遇到的奇聞趣事。同時,和大多數不善于嚴密保護自己郵件地址的人一樣,偶爾你也會收到一封包含單詞"online pharmacy"的垃圾郵件。
也許你已經看出了此處的難點--我們往往會告訴分類器"online"和"pharmacy"是出現在非垃圾郵件中的,因此這些單詞相對于非垃圾郵件的概率會更高一些。當我們告訴分類器有一封包含單詞"online pharmacy"的郵件屬于垃圾郵件時,則這些單詞的概率又會進行相應的調整,這就導致了一個經常性的矛盾。由于特征的概率都是單獨給出的,因此分類器對于各種組合的情況一無所知。在文檔分類中,這通常不是什么大問題,因為一封包含單詞"online pharmacy"的郵件中可能還會有其他特征可以說明它是垃圾郵件,但是在面對其他問題時,理解特征的組合可能是至關重要的。