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

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

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

先說一下主要思路,我們日常從一個人的名字中,基本上能大致判斷這個名字的主人是男是女。比如李大志,這個名字一聽就很男性。爲什麼呢?因爲大字和志字男性名字用得比較多。雖然機器一眼看不出來,但它可以通過統計信息來判斷。如果有足夠多的數據,我們就可以統計出大字和志字用作男性名字的比例,計算概率信息。然後就可以用這些概率,運用上述的貝葉斯公式來進行計算,判定性別。

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

裏面核心代碼文件爲:

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

如果你對python感興趣,我這有個學習Python基地,裏面有很多學習資料,感興趣的+Q羣:688244617

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=女)兩部分誰比較大即可做出判斷。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章