貝葉斯分類算法實例 --根據姓名推測男女

一.從貝葉斯公式開始

貝葉斯分類實際上是利用用貝葉斯公式,算出每種狀況下發生的機率,再取機率較大的一個分類做爲結果。咱們先來看看貝葉斯公式:html

P(A|B) = P(B|A) P(A) / P(B)python

其中P(A|B)是指在事件B發生的狀況下事件A發生的機率。git

在貝葉斯定理中,每一個名詞都有約定俗成的名稱:github

  • P(A|B)是已知B發生後A的條件機率,也因爲得自B的取值而被稱做A的後驗機率。
  • P(A)是A的先驗機率(或邊緣機率)。之因此稱爲"先驗"是由於它不考慮任何B方面的因素。
  • P(B|A)是已知A發生後B的條件機率,也因爲得自A的取值而被稱做B的後驗機率。
  • P(B)是B的先驗機率或邊緣機率。

這裏能夠用一個例子來講明這個公式。算法

看一個簡單的小例子來展現貝葉斯定理函數

病人的例子: 某個醫院早上收了八個門診病人,以下表。編碼

症狀 職業 疾病
打噴嚏 護士   感冒
打噴嚏 農夫   過敏
頭痛  建築工人 腦震盪
頭痛  建築工人 感冒
打噴嚏  建築工人 過敏
打噴嚏 教師   感冒
頭痛  教師   腦震盪
打噴嚏 教師   過敏

如今又來了第九個病人,是一個打噴嚏的建築工人。請問他患上感冒的機率有多大?spa

根據貝葉斯定理:code

P(A|B) = P(B|A) P(A) / P(B)server

可得知足「打噴嚏」和「建築工人」兩個條件下,感冒的機率以下:

P(感冒|打噴嚏x建築工人)
= P(打噴嚏x建築工人|感冒) x P(感冒) / P(打噴嚏x建築工人)

假定"打噴嚏"和"建築工人"這兩個特徵是獨立的(即這兩個條件沒有相關性,好比不存在說他是建築工人他打噴嚏的機率比較大或者比較小這種關係),所以,上面的等式就變成了。

P(感冒|打噴嚏x建築工人) 
 = P(打噴嚏|感冒) x P(建築工人|感冒) x P(感冒) /  P(打噴嚏) x P(建築工人)

經過統計可得:

P(感冒|打噴嚏x建築工人) 
 = (2/3) x (1/3) x (3/8) / (5/8) x (3/8) 
 = (16/45)

經過貝葉斯公式算出了知足條件下感冒的機率,那麼如今貝葉斯分類器如何實現呢?

接上面的例子,從上面咱們得出了 P(感冒|打噴嚏x建築工人) 的值,那麼咱們能夠再算出 P(不感冒|打噴嚏x建築工人) 的值,計算結果以下:

P(不感冒|打噴嚏x建築工人) 

 = P(打噴嚏|不感冒) x P(建築工人|不感冒) x P(不感冒)  /  P(打噴嚏) x P(建築工人)
 = (3/5) x (2/5) x (5/8) / (5/8) x (3/8) 
 = (16/25)

OK,如今咱們知道來若是新來一個打噴嚏的建築工人,他患感冒的概率是P(感冒|打噴嚏x建築工人)= (16/45)。不患感冒的概率是P(不感冒|打噴嚏x建築工人)= (16/25)。

經過對機率的比較,咱們就能夠將打噴嚏的建築工人分類到「不感冒」人羣中(不感冒的機率比較大)。 這就是樸素貝葉斯分類器的最簡單的應用了。固然你也看到了,貝葉斯分類器須要咱們應用到統計所得的結果,這須要數據量比較大,大到能知足大數定理(大數定理這裏就很少解釋啦,自行百度便可),以及樣本數據足夠客觀。

接下來咱們看一個實際的例子,是我在 github 上看到的一個項目例子,根據姓名來對性別進行分類。看上去以爲很難以想象吧,其實也是用了上述說的貝葉斯分類的方法。

二.貝葉斯分類器根據姓名判別男女 -python

項目github地址:https://github.com/observerss/ngender

先說一下主要思路,咱們平常從一我的的名字中,基本上能大體判斷這個名字的主人是男是女。好比李大志,這個名字一聽就很男性。爲何呢?由於字和字男性名字用得比較多。雖然機器一眼看不出來,但它能夠經過統計信息來判斷。若是有足夠多的數據,咱們就能夠統計出字和字用做男性名字的比例,計算機率信息。而後就能夠用這些機率,運用上述的貝葉斯公式來進行計算,斷定性別。

代碼其實不難,各個字的統計數據已經計算好,在項目中給出。咱們只須要讀取文件數據,存儲到 python 的字典中,計算出機率,而後預測的時候進行計算便可。咱們先看核心代碼,稍後會有例子說明。

裏面核心代碼文件爲:

這裏主要講一下核心代碼的內容:https://github.com/observerss/ngender/blob/master/ngender/ngender.py

class Guesser(object):

	//初始化函數,調用下面的_load_model()函數
    def __init__(self):
        self._load_model()

	//初始化一些參數
    def _load_model(self):
        self.male_total = 0
        self.female_total = 0
        self.freq = {}

		//這裏加載charfreq.csv文件,這個文件存放的是一些漢字是男女的統計信息
        with open(os.path.join(os.path.dirname(__file__),
                               'charfreq.csv'),
                  'rb') as f:
            # skip first line
            next(f)
			//將文件中的信息存儲,累加,以便稍後計算機率
            for line in f:
                line = line.decode('utf-8')
                char, male, female = line.split(',')
                char = py2compat(char)
				//計算男性總數
                self.male_total += int(male)
				//計算女性總數
                self.female_total += int(female)
				//一個漢字對應的那女數量
                self.freq[char] = (int(female), int(male))

        self.total = self.male_total + self.female_total

		//一個漢字是男女機率
        for char in self.freq:
            female, male = self.freq[char]
            self.freq[char] = (1. * female / self.female_total,
                               1. * male / self.male_total)

    def guess(self, name):
        name = py2compat(name)
         //去掉姓氏
        firstname = name[1:]
		//過濾掉不在這個unicode編碼範圍內的字符
        for char in firstname:
            assert u'\u4e00' <= char <= u'\u9fa0', u'姓名必須爲中文'

 		//貝葉斯分類器,分別計算出男的機率和女的機率
        pf = self.prob_for_gender(firstname, 0)
        pm = self.prob_for_gender(firstname, 1)

		//若名字爲男的機率較大,則分類爲男,反之則爲女
        if pm  pf:
            return ('male', 1. * pm / (pm + pf))
        elif pm < pf:
            return ('female', 1. * pf / (pm + pf))
        else:
            return ('unknown', 0)

	//貝葉斯公式的應用
    def prob_for_gender(self, firstname, gender=0):
        p = 1. * self.female_total / self.total \
            if gender == 0 \
            else 1. * self.male_total / self.total

        for char in firstname:
            p *= self.freq.get(char, (0, 0))[gender]

        return p


guesser = Guesser()

上述代碼仍是比較簡單的,首先在初始化的時候會調用 _load_model() 函數,這個函數完成的是一些機率計算工做,好比先將每一個字對應是男是女的機率計算好存儲在字典中。

而後在計算的時候,先過濾掉姓氏。而後分別計算出這個名字是男是女的機率,好比計算 P(男|李大志)和P(女|李大志),,對比哪一個機率大一些,而後進行男女分類。

這裏放上一個例子:判斷

P(gender=男|name=本山) 
= P(name=本山|gender=男) * P(gender=男) / P(name=本山)
= P(name has 本|gender=男) * P(name has 山|gender=男) * P(gender=男) / P(name=本山)
  • 公式原理爲貝葉斯公式,下面對公式中中各個項進行解答,首先明確咱們已經統計獲得P(gender=男),P(gender=女)的機率。

怎麼算 P(name has 本|gender=男)?

  • 「本」在男性名字中出現的次數 / 男性字出現的總次數

怎麼算 P(gender=男)?

  • 男性名出現的次數 / 總次數

怎麼算 P(name=本山)?

這個機率對男女來講都是同樣的,因此不必算出來,即咱們只須要比較P(name=本山|gender=男) * P(gender=男)和P(name=本山|gender=女) * P(gender=女)兩部分誰比較大便可作出判斷。

以上就是貝葉斯分類器介紹的所有內容啦。

參考文章: http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html


推薦閱讀:

python Kmeans算法解析 從分治算法到 MapReduce

相關文章
相關標籤/搜索