《機(jī)器學(xué)習(xí)(周志華)》學(xué)習(xí)筆記(七)

Q:什么是貝葉斯分類器?

一句話:以貝葉斯方法為核心原理構(gòu)造出來的分類程序統(tǒng)稱為貝葉斯分類器,主要包括樸素貝葉斯分類器,半樸素貝葉斯分類器,以及貝葉斯網(wǎng)絡(luò)。

Q:那么,貝葉斯方法又是什么?

貝葉斯方法是一位英國數(shù)學(xué)家托馬斯·貝葉斯在18世紀(jì)提出來的概率學(xué)方法。此法強(qiáng)大之處不多贅述,貝葉斯學(xué)派占據(jù)了概率江湖中的半壁江山(另外一半江山歸于頻率學(xué)派)。

舉個(gè)例子:

已知
——100名男生中有99個(gè)短發(fā),1個(gè)長發(fā);
——100名女生中有90個(gè)長發(fā),10個(gè)短發(fā);

那么
——從這200名學(xué)生中抽取一個(gè)學(xué)生,已知是男生,則該男生是長發(fā)的概率是多少?答案很簡單,是0.01000。
P(長發(fā)|男生) = \frac{P(長發(fā),男生) }{ P(男生)}
——從中200名學(xué)生中抽取一個(gè)學(xué)生,已知是長發(fā),則該長發(fā)學(xué)生是男生的概率是多少?答案稍難一點(diǎn),是0.01099。
P(男生|長發(fā))= \frac{P(長發(fā)|男生)*P(男生)}{P(長發(fā))}
由此可見,大多數(shù)的概率計(jì)算方法(古典概率模型、幾何概率模型、條件概率公式、全概率公式、聯(lián)合概率公式······)都是已知前提條件發(fā)生的情況下求各種可能結(jié)果發(fā)生的概率。而貝葉斯公式則是用于已知一件事情已經(jīng)發(fā)生,求導(dǎo)致其發(fā)生的各種可能前提條件成立的概率。

已知:A => a 或 b 或 c 求P(a)
用古典概率模型、幾何概率模型、條件概率公式、全概率公式、聯(lián)合概率公式······

已知:A 或 B 或 C => a 求P(A)
用貝葉斯公式

更多貝葉斯方法的知識(shí),可以查閱劉未鵬《數(shù)學(xué)之美番外:貝葉斯方法》

Q:怎樣應(yīng)用貝葉斯方法構(gòu)造分類器?

我們繼續(xù)以西瓜分類問題為例,用下面的色澤、根蒂等8個(gè)特征的數(shù)據(jù),判斷一個(gè)西瓜是好瓜還是壞瓜。

西瓜數(shù)據(jù)集3.0

應(yīng)用貝葉斯方法的基本思想是,分別求出待分類西瓜是好瓜以及壞瓜的概率,哪一個(gè)概率高,就將其歸到那一類。

那么
P(好瓜=是|色澤=青綠,根蒂=蜷縮,······)\\ P(好瓜=否|色澤=青綠,根蒂=蜷縮,······)
這兩個(gè)概率怎么求?

首先我們假設(shè)樣本的所有屬性相互獨(dú)立,比如西瓜的色澤是黑是綠,與根蒂是直是曲無關(guān)。則根據(jù)貝葉斯方法,求一個(gè)西瓜是好瓜還是壞瓜的概率的基本公式是如下

其中c是類別,向量\vec{x}是待測樣本。因?yàn)槲覀儾⒉恍枰蟪?img class="math-inline" src="https://math.jianshu.com/math?formula=P(c%7C%5Cvec%7Bx%7D)" alt="P(c|\vec{x})" mathimg="1">的確切值,只需要知道P(c=好瓜|x)P(c=壞瓜|x)誰更大就行。因?yàn)榉帜窹(x)對(duì)于P(c=好瓜|x)P(c=壞瓜|x)是一樣的,所以可以一并舍去。所以關(guān)鍵要求出P(c)以及P(x|c),也就是

亦即
P(好瓜=是) P(色澤=?|好瓜)P(根蒂=?|好瓜)··· \\ P(好瓜=否)P(色澤=?|壞瓜)P(根蒂=?|壞瓜)···
這兩條式子中基本上每一項(xiàng)都是一個(gè)簡單的條件概率。對(duì)于離散型變量,一般情況下可以直接用數(shù)數(shù)的方法加古典概型算出來。

數(shù)據(jù)集中的密度和含糖率是連續(xù)型變量,他們的條件概率怎么求?可以假設(shè)這些連續(xù)數(shù)據(jù)服從正態(tài)分布,然后算出訓(xùn)練數(shù)據(jù)集中這兩項(xiàng)屬性的均值和方差,代入下面概率密度函數(shù),即可算出。

用訓(xùn)練數(shù)據(jù)集算出各個(gè)特征的條件概率以及各個(gè)類別出現(xiàn)的概率以后,就可以應(yīng)用貝葉斯公式預(yù)測一個(gè)西瓜是好瓜以及壞瓜的概率了。

在上面的例子中,我們

  1. 用到了貝葉斯公式
  2. 假設(shè)各個(gè)屬性互不影響(實(shí)際上不是,比如敲聲可能受密度影響)

所以我們剛剛構(gòu)造出的分類器叫做樸素貝葉斯分類器(Naive Bayesian classifier)

Q:我覺得樸素貝葉斯分類器太Naive,想要高逼格一點(diǎn),如何改進(jìn)?

雖然樸素貝葉斯算法很Naive,但是實(shí)踐顯示其性能很已經(jīng)不錯(cuò),尤其是在文本分類領(lǐng)域有廣泛應(yīng)用,很多垃圾郵件分類算法用的就是樸素貝葉斯。

當(dāng)然,可以不Naive一點(diǎn),用半樸素貝葉斯(semi-naive Bayesian classifier)。

樸素貝葉斯, naive之處在于假設(shè)各個(gè)屬性互不影響。這在實(shí)踐中不易見到,所以人們嘗試放寬點(diǎn)這個(gè)條件,比如改成“假設(shè)各個(gè)屬性最多受一個(gè)屬性影響(最多依賴于一個(gè)屬性)”

如此一改,整個(gè)模型就由


變成了


兩條式子的唯一的不同之處在于各個(gè)條件概率項(xiàng)的條件部分,pai指的是被依賴的屬性。舉個(gè)例子——若敲聲受密度影響,則有

P(敲聲=沉悶|好瓜=是,密度>0.700)
P(敲聲=沉悶|好瓜=否,密度>0.700)
P(敲聲=沉悶|好瓜=是,密度<=0.700)
P(敲聲=沉悶|好瓜=否,密度<=0.700)

······
除此之外,其他與樸素貝葉斯無大出入。

Q:半樸素貝葉斯中還是有點(diǎn)naive,有沒有不naive的貝葉斯算法?

當(dāng)然有,比如貝葉斯網(wǎng)絡(luò)(Bayesian network),又稱信念網(wǎng)絡(luò)(Belief network),也就是當(dāng)我們完全放開了“屬性之間相互影響”的假設(shè)的時(shí)候,所誕生的算法。此時(shí)一個(gè)屬性可以影響多個(gè)其他屬性,也可以受多個(gè)屬性影響,這就比樸素貝葉斯和半樸素貝葉斯復(fù)雜多了。

貝葉斯網(wǎng)絡(luò)之間的屬性的影響關(guān)系,可以用一個(gè)有向無環(huán)圖描述,圖中每一個(gè)節(jié)點(diǎn)存儲(chǔ)著該屬性的條件概率。如



所以一個(gè)貝葉斯網(wǎng)絡(luò)由一個(gè)有向無環(huán)圖和一個(gè)條件概率表組成。

貝葉斯網(wǎng)絡(luò)是相當(dāng)高級(jí)和復(fù)雜的技術(shù),目前我還沒有全面理解,在此留白,等以后有機(jī)會(huì)再來補(bǔ)充。


Talk is cheap, show me the code!

使用樸素貝葉斯算法計(jì)算離散型和連續(xù)性變量時(shí)求條件概率的方法略有不同,但方便起見,我還是將其完全拆開放到兩個(gè)模型里。首先時(shí)離散型變量的樸素貝葉斯模型:

"""
Naive Bayes classifier for categorical variables

:file: supervised.py
:author: Richy Zhu
:email: rickyzhu@foxmail.com
"""
import numpy as np

class MyCategoricalNBC:
    '''categorical naive bayes classifier'''

    def __init__(self):
        self.X = None
        self.y = None

    def fit(self, X, y):
        '''
        Train the nominal naive bayes classifier model

        Parameters
        ----------
        X: ndarray of shape (m, n)
            sample data where row represent sample and column represent feature
        y: ndarray of shape (m,)
            labels of sample data

        Returns
        -------
        self
            trained model
        '''
        self.X = X
        self.y = y
        return self
    
    def _predict(self, x):
        '''
        compute probabilities and make prediction.
        '''
        probas = {}
        clss = list(set(self.y))

        # compute probability for each attributes in x
        for c in clss:
            probas[c] = []
            dat = self.X[self.y==c]
            for attr_id, attr_val in enumerate(x):
                count = 0
                for row in dat:
                    if attr_val == row[attr_id]:
                        count += 1
                # use laplace smoothing
                probas[c].append((count+1)/(len(dat)+len(x)))
            probas[c].append(len(dat)/len(self.X))

        final_probas = {}
        from functools import reduce
        for c, prbs in probas.items():
            # theoretically not final probability because not divided by Pr(x)
           final_probas[reduce(lambda x,y:x * y, prbs)] = c
        return final_probas[max(final_probas)]
    
    def predict(self, X):
        '''
        Make prediction by the trained model.

        Parameters
        ----------
        X: ndarray of shape (m, n)
            data to be predicted, the same shape as trainning data

        Returns
        -------
        C: ndarray of shape (m,)
            Predicted class label per sample.
        '''
        if self.X is None:
             raise Exception("Model haven't been trained!")
        return np.array([self._predict(x) for x in X])

測試代碼如下——因?yàn)閟klearn包沒有離散變量的數(shù)據(jù)集,又不想動(dòng)用新聞數(shù)據(jù)集(其實(shí)是我的代碼處理不了,會(huì)出bug??),所以只能將就著用一下重復(fù)10次的西瓜數(shù)據(jù)集:

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

print('\nDescrete Naive Bayes')
print('---------------------------------------------------------------------')
xigua2 = np.array([
        ['青綠', '蜷縮', '濁響', '清晰', '凹陷', '硬滑', '好瓜'],
        ['烏黑', '蜷縮', '沉悶', '清晰', '凹陷', '硬滑', '好瓜'],
        ['烏黑', '蜷縮', '濁響', '清晰', '凹陷', '硬滑', '好瓜'],
        ['青綠', '蜷縮', '沉悶', '清晰', '凹陷', '硬滑', '好瓜'],
        ['淺白', '蜷縮', '濁響', '清晰', '凹陷', '硬滑', '好瓜'],
        ['青綠', '稍蜷', '濁響', '清晰', '稍凹', '軟粘', '好瓜'],
        ['烏黑', '稍蜷', '濁響', '稍糊', '稍凹', '軟粘', '好瓜'],
        ['烏黑', '稍蜷', '濁響', '清晰', '稍凹', '硬滑', '好瓜'],
        # ----------------------------------------------------
        ['烏黑', '稍蜷', '沉悶', '稍糊', '稍凹', '硬滑', '壞瓜'],
        ['青綠', '硬挺', '清脆', '清晰', '平坦', '軟粘', '壞瓜'],
        ['淺白', '硬挺', '清脆', '模糊', '平坦', '硬滑', '壞瓜'],
        ['淺白', '蜷縮', '濁響', '模糊', '平坦', '軟粘', '壞瓜'],
        ['青綠', '稍蜷', '濁響', '稍糊', '凹陷', '硬滑', '壞瓜'],
        ['淺白', '稍蜷', '沉悶', '稍糊', '凹陷', '硬滑', '壞瓜'],
        ['烏黑', '稍蜷', '濁響', '清晰', '稍凹', '軟粘', '壞瓜'],
        ['淺白', '蜷縮', '濁響', '模糊', '平坦', '硬滑', '壞瓜'],
        ['青綠', '蜷縮', '沉悶', '稍糊', '稍凹', '硬滑', '壞瓜']
    ])
from sklearn.preprocessing import LabelEncoder
for i in range(xigua2.shape[1]):
    le = LabelEncoder()
    xigua2[:,i] = le.fit_transform(xigua2[:,i])
xigua2 = xigua2.astype(np.int).repeat(20, axis=0)
X = xigua2[:, :-1]
y = xigua2[:, -1]
X_train, X_test, y_train, y_test = train_test_split(X, y)

mycnb = MyCategoricalNBC()
mycnb.fit(X_train, y_train)
print('My Accuracy:', accuracy_score(mycnb.predict(X_test), y_test))

from sklearn.naive_bayes import CategoricalNB 
skcnb = CategoricalNB()
skcnb.fit(X_train, y_train)
print('SK Accuracy:', accuracy_score(skcnb.predict(X_test), y_test))

測試結(jié)果如下

$ python supervised_examples.py
Descrete Naive Bayes
---------------------------------------------------------------------
My Accuracy: 0.8235294117647058
SK Accuracy: 0.8235294117647058

下面是處理連續(xù)型變量數(shù)據(jù)集的樸素貝葉斯模型(假設(shè)所有連續(xù)變量都服從高斯分布):

"""
Naive Bayes classifier for continuous variables

:file: supervised.py
:author: Richy Zhu
:email: rickyzhu@foxmail.com
"""
import numpy as np
class MyGaussianNBC:
    '''Gaussian continuous naive bayes classifier'''

    def __init__(self):
        self.X = None
        self.y = None

    def fit(self, X, y):
        '''
        Train the Gaussian continuous naive bayes classifier model

        Parameters
        ----------
        X: ndarray of shape (m, n)
            sample data where row represent sample and column represent feature
        y: ndarray of shape (m,)
            labels of sample data

        Returns
        -------
        self
            trained model
        '''
        self.X = X
        self.y = y
        return self

    def _predict(self, x):
        '''compute probabilities and make prediction.'''
        from scipy.stats import norm
        probas = {}
        clss = list(set(self.y))

        # compute probability for each attributes in x
        for c in clss:
            probas[c] = []
            dat = self.X[self.y==c]
            for i, attr in enumerate(x):
                probas[c].append(norm(np.mean(dat[:,i]), np.std(dat[:,i])).pdf(attr))
            probas[c].append(len(dat)/len(self.X))

        final_probas = {}
        from functools import reduce
        for c, prbs in probas.items():
            # theoretically not final probability because not divided by Pr(x)
           final_probas[reduce(lambda x,y:x * y, prbs)] = c
        return final_probas[max(final_probas)]
    
    def predict(self, X):
        return np.array([self._predict(x) for x in X])

測試代碼如下

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

print('\nContinuous Naive Bayes')
print('---------------------------------------------------------------------')
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y)

mygnb = MyGaussianNBC()
mygnb.fit(X_train, y_train)
print('My Accuracy:', accuracy_score(mygnb.predict(X_test), y_test))

from sklearn.naive_bayes import GaussianNB
skgnb = GaussianNB()
skgnb.fit(X_train, y_train)
print('Sk Accuracy:', accuracy_score(skgnb.predict(X_test), y_test))

測試結(jié)果如下

$ python supervised_examples.py
Continuous Naive Bayes
---------------------------------------------------------------------
My Accuracy: 0.9210526315789473
Sk Accuracy: 0.9210526315789473

更多代碼請參考https://github.com/qige96/programming-practice/tree/master/machine-learning


本作品首發(fā)于簡書博客園平臺(tái),采用知識(shí)共享署名 4.0 國際許可協(xié)議進(jìn)行許可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,400評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,452評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,818評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,997評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,552評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,292評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,510評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,721評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評(píng)論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,235評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,480評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容