介紹樸素貝葉斯分類器的文章已經很多了。本文的目的是通過基本概念和微小執行個體的複述,鞏固對于樸素貝葉斯分類器的了解。
樸素貝葉斯分類器基于貝葉斯定義,特别适用于輸入資料維數較高的情況。雖然樸素貝葉斯分類器很簡單,但是它确經常比一些複雜的方法表現還好。
為了簡單闡述貝葉斯分類的基本原理,我們使用上圖所示的例子來說明。作為先驗,我們知道一個球要麼是紅球要麼是綠球。我們的任務是當有新的輸入(new
cases)時,我們給出新輸入的物體的類别(紅或者綠)。這是貝葉斯分類器的典型應用-label,即給出物體标記。
從圖中我們
還看到,綠球的數量明顯比紅球大,那麼我們有理由認為:一個新輸入(new
case)更有可能是綠球。假如綠球的數量是紅球的二倍,那麼對于一個新輸入,它是綠球的機率是它是紅球的機率的二倍。
是以,我們知道:
假設一共有60個球,其中40個是綠球,20個是紅球,那麼類别的先驗機率為:
有了先驗機率之後,我們就可以準備對新來的物體(new
object),圖中白色圈所示,進行分類。如果要取得比較準确的分類結果,那麼我們猜測它是綠球比較保險,也就是新物體與綠球的likelihood比與紅球的likelihood更大。那麼我們接下來衡量這種相似性-likelihood(似然)。
通過上面的公式,我們可以看出x是綠球的似然比x是紅球的似然小,因為在x周圍鄰域内,有3個紅球但是隻有1個綠球。是以:
是以,盡管對于先驗機率來說,x是綠球的可能性比其是紅球的可能性大,但是似然(likelihood)表現的結果卻相反。在貝葉斯分析中,最後的類别是有上述兩個機率
(先驗和似然),這就是貝葉斯準則:
注:在實際使用時,機率要經過歸一化(normalized)。
對于一組變量x={x1,x2,x3,,,,,,xd},我們希望構造輸出c={c1,c2,c3,,,,,cd}的一個具體取值cj(比如cj是一個分類的情況)的先驗機率。利用貝葉斯定理可知:
此處p(cj|x1,x2,,,,,xd)就是cj的顯眼高鋁,或者說是x屬于cj這類的機率。樸素貝葉斯假設互相獨立變量的條件機率也互相獨立。是以:
并且,先驗可以寫成如下的形式:
通過貝葉斯定義,我們可以在類别向量cj的條件下估計x的類别标簽。
樸素貝葉斯模型可以通過多種形式模組化:正态分布,log正态分布,gamma分布和泊松分布(poisson)
注:此處的泊松分布被認為連續分布,當變量是離散值的時候另作處理。
假設我們已經有如下資料:
這些資料可以歸納如下:
那麼,對于一組新資料:
我們來計算兩類的似然:
"yes"
= 2/9 * 3/9 * 3/9 * 3/9 * 9/14 = 0.0053
"no" = 3/5 * 1/5 * 4/5 * 3/5 * 5/14 = 0.0206
歸一化:
p("yes") = 0.0053 / (0.0053 + 0.0206)
= 0.205
p("no") = 0.0206 / (0.0053 +
0.0206) = 0.795
那麼,結論是我們今天 not play。
[python]
<span style="font-size: 12px;" abp="387">from __future__ import division
def calc_prob_cls(train, cls_val, cls_name=‘class‘):
‘‘‘‘‘
calculate the prob. of class: cls
‘‘‘
cnt = 0
for e in train:
if e[cls_name] == cls_val:
cnt += 1
return cnt / len(train)
def calc_prob(train, cls_val, attr_name, attr_val, cls_name=‘class‘):
calculate the prob(attr|cls)
cnt_cls, cnt_attr = 0, 0
cnt_cls += 1
if e[attr_name] == attr_val:
cnt_attr += 1
return cnt_attr / cnt_cls
def calc_nb(train, test, cls_y, cls_n):
calculate the naive bayes
prob_y = calc_prob_cls(train, cls_y)
prob_n = calc_prob_cls(train, cls_n)
for key, val in test.items():
print ‘%10s: %s‘ % (key, val)
prob_y *= calc_prob(train, cls_y, key, val)
prob_n *= calc_prob(train, cls_n, key, val)
return {cls_y: prob_y, cls_n: prob_n}
if __name__ == ‘__main__‘:
#train data
train = [
{"outlook":"sunny", "temp":"hot", "humidity":"high", "wind":"weak", "class":"no" },
{"outlook":"sunny", "temp":"hot", "humidity":"high", "wind":"strong", "class":"no" },
{"outlook":"overcast", "temp":"hot", "humidity":"high", "wind":"weak", "class":"yes" },
{"outlook":"rain", "temp":"mild", "humidity":"high", "wind":"weak", "class":"yes" },
{"outlook":"rain", "temp":"cool", "humidity":"normal", "wind":"weak", "class":"yes" },
{"outlook":"rain", "temp":"cool", "humidity":"normal", "wind":"strong", "class":"no" },
{"outlook":"overcast", "temp":"cool", "humidity":"normal", "wind":"strong", "class":"yes" },
{"outlook":"sunny", "temp":"mild", "humidity":"high", "wind":"weak", "class":"no" },
{"outlook":"sunny", "temp":"cool", "humidity":"normal", "wind":"weak", "class":"yes" },
{"outlook":"rain", "temp":"mild", "humidity":"normal", "wind":"weak", "class":"yes" },
{"outlook":"sunny", "temp":"mild", "humidity":"normal", "wind":"strong", "class":"yes" },
{"outlook":"overcast", "temp":"mild", "humidity":"high", "wind":"strong", "class":"yes" },
{"outlook":"overcast", "temp":"hot", "humidity":"normal", "wind":"weak", "class":"yes" },
{"outlook":"rain", "temp":"mild", "humidity":"high", "wind":"strong", "class":"no" },
]
#test data
test = {"outlook":"sunny","temp":"cool","humidity":"high","wind":"strong"}
#calculate
print calc_nb(train, test, ‘yes‘, ‘no‘)</span>
輸出為:
outlook: sunny
wind: strong
temp: cool
humidity: high
{‘yes‘: 0.0052910052910052907, ‘no‘: 0.020571428571428574}