【ML_Algorithm 6 】貝葉斯(Bayes)——算法概念梳理與實際應用

基本概念導引:

貝葉斯法是關於隨機事件A和B的條件概率和邊緣概率的。

其中P(A|B)是在B發生的情況下A發生的可能性。  爲完備事件組,即 
在貝葉斯法則中,每個名詞都有約定俗成的名稱:
P(A)是A的先驗概率或邊緣概率。之所以稱爲"先驗"是因爲它不考慮任何B方面的因素。
P(A|B)是已知B發生後A的條件概率,也由於得自B的取值而被稱作A的後驗概率。
P(B|A)是已知A發生後B的條件概率,也由於得自A的取值而被稱作B的後驗概率。
P(B)是B的先驗概率或邊緣概率,也作標準化常量(normalized constant)。
按這些術語,Bayes法則可表述爲:
後驗概率 = (似然度 * 先驗概率)/標準化常量 也就是說,後驗概率與先驗概率和似然度的乘積成正比。
另外,比例Pr(B|A)/Pr(B)也有時被稱作標準似然度(standardised likelihood),Bayes法則可表述爲:
後驗概率 = 標準似然度 * 先驗概率。

正文引出:

1. 貝葉斯決策論

2. 極大似然估計
 

  • 頻率派  把需要推斷的參數θ看做是固定的未知常數,即概率雖然是未知的,但最起碼是確定的一個值,同時,樣本X 是隨機的,所以頻率派重點研究樣本空間,大部分的概率計算都是針對樣本X 的分佈;

  • 貝葉斯派 的觀點則截然相反,他們認爲參數是隨機變量,而樣本X 是固定的,由於樣本是固定的,所以他們重點研究的是參數的分佈。

此處介紹源自頻率主義學派的極大似然估計(Maximum Likelihood Estimation,簡稱MLE),這是根據數據採樣來估計概率分佈參數的經典方法。         令Dc表示訓練集D中第c類樣本組成的集合,假設這些樣本是獨立同分布的,則參數 θc 對於數據集 Dc 的似然是

對 θc 進行極大似然估計,就是去尋找能最大化似然P(Dc | θc )的參數值 。直觀上看,極大似然估計是試圖在 θc 所有可能的取值中,找到一個能使數據出現的“可能性”最大的值.            式(7.9)中的連乘操作易造成下溢,通常使用對數似然(log-likelihood)

此時參數 θc 的極大似然估計  爲

    需注意的是,這種參數化的方法雖能使類條件概率估計變得相對簡單,但估計結果的準確性嚴重依賴於所假設的概率分佈形式是否符合潛在的真實數據分佈.在現實應用中,欲做出能較好地接近潛在真實分佈的假設,往往需在一定程度上利用關於應用任務本身的經驗知識,否則若僅憑“猜測”來假設概率分佈形式,很可能產生誤導性的結果.

3. 樸素貝葉斯分類器

    估計後驗概率 P(c|x) 的主要困難在於:類條件概率式 P(x|c) 是所有屬性上的聯合概率,難以從有限的訓練樣本直接估計而得。  爲避開這個障礙,樸素貝葉斯分類器(naive Bayes classifier)採用了“屬性條件獨立性假設”(attribute conditional independence assumption):對已知類別,假設所有屬性相互獨立.換言之,假設每個屬性獨立地對分類結果發生影響.    基於屬性條件獨立性假設,則:

其中 d爲屬性數目,xi 爲 x 在第 i 個屬性上的取值。    由於對所有類別來說P(x)相同,因此有

 

“拉普拉斯修正”(Laplacian correction).

爲了避免其他屬性攜帶的信息被訓練集中未出現的屬性值“抹去”,在估計概率值時通常要進行“平滑”(smoothing),常用“拉普拉斯修正”(Laplacian correction)。具體來說,令N表示訓練集D中可能的類別數,從表示第i個屬性可能的取值數,則式(7.16)和(7.17)分別修正爲

拉普拉斯修正避免了因訓練集樣本不充分而導致概率估值爲零的問題,並且在訓練集變大時,修正過程所引入的先驗(prior)的影響也會逐漸變得可忽略,使得估值漸趨向於實際概率值.

現實任務中樸素貝葉斯分類器有多種使用方式。例如,若任務對預測速度要求較高,則對給定訓練集,可將樸素貝葉斯分類器涉及的所有概率估值事先計算好存儲起來,這樣在進行預測時只需“查表”即可進行判別;若任務數據更替頻繁,則可採用“’懶惰學習”(lazy learning)方式,先不進行任何訓練,待收到預測請求時再根據當前數據集進行概率估值;數據不斷增加,則可在現有估值基礎上,僅對新增樣本的屬性值所涉及的概率估值進行計數修正即可實現增量學習.

 

4. 半樸素貝葉斯分類器

爲了降低貝葉斯公式(7.8)中估計後驗概率 P(c|x) 的困難,樸素貝葉斯分類器採用了屬性條件獨立性假設,但在現實任務中這個假設往往很難成立。        於是,人們嘗試對屬性條件獨立性假設進行一定程度的放鬆,由此產生了一類稱爲“半樸素貝葉斯分類器”(semi-naive Bayes classifiers)的學習方法。                                                    半樸素貝葉斯分類器的基本想法是適當考慮一部分屬性間的相互依賴信息,從而既不需進行完全聯合概率計算,又不至於徹底忽略了比較強的屬性依賴關係。    

“獨依賴估計”(One-Dependent Estimator,簡稱ODE)是半樸素貝葉斯分類器最常用的一種策略.顧名思議,所謂“獨依賴”就是假設每個屬性在類別之外最多僅依賴於一個其他屬性,即

其中pai爲屬性 xi 所依賴的屬性,稱爲xi的父屬性。此時,對每個屬性 xi,若其父屬性pai己知,則可採用類似式(7.20)的辦法來估計概率值P(xi | c, pai)。於是,問題的關鍵就轉化爲如何確定每個屬性的父屬性,不同的做法產生不同的獨依賴分類器。

    SPODE (Super-Parent ODE)方法:最直接的做法是假設所有屬性都依賴於同一個屬性,稱爲“超父”(super-parent),然後通過交叉驗證等模型選擇方法來確定超父屬性,由此形成了.例如,在圖7.1(b)中,x1 是超父屬性。

    TAN (Tree Augmented naive Bayes)方法:是在最大帶權生成樹算法的基礎上,通過以下步驟將屬性間依賴關係約簡爲如圖7.1(c)所示的樹形結構:

容易看出,條件互信息 I 功刻畫了屬性xi,和 xj 在已知類別情況下的相關性,因此,通過最大生成樹算法,TAN實際上僅保留了強相關屬性之間的依賴性。

    AODE (Averaged One-Dependent Estimator)方法:是一種基於集成學習機制、更爲強大的獨依賴分類器。與SPODE通過模型選擇確定超父屬性不同,AODE嘗試將每個屬性作爲超父來構建SPODE,然後將那些具有足夠訓練數據支撐的SPODE集成起來作爲最終結果,即

    其中Dxi是在第 i 個屬性上取值爲 xi 的樣本的集合,m‘ 爲閾值常數。 顯然AODE需估計P(c, xi)和P(xj | c,xi)。類似式(7.20),有

其中 Ni 是第 i 個屬性可能的取值數,Dc,xi 是類別爲 c 且在第 i 個屬性上取值爲 xi 的樣本集合,Dc,xi,xj 是類別爲 c 且在第 i 和第 j 個屬性上取值分別爲 xi 和 xj 的樣本集合。

與樸素貝葉斯分類器類似,AODE的訓練過程也是“計數”,即在訓練數據集上對符合條件的樣本進行計數的過程。 

與樸素貝葉斯分類器相似,AODE無需模型選擇,既能通過預計算節省預測時間,也能採取懶惰學習方式在預測時再進行計數,並且易於實現增量學習.  

既然將屬性條件獨立性假設放鬆爲獨依賴假設可能獲得泛化性能的提升,那麼,能否通過考慮屬性間的高階依賴來進一步提升泛化性能呢? 也就是說,將式(7.23)中的屬性 Pai 替換爲包含 k 個屬性的集合 Pai ,從而將 ODE 拓展爲 kDE 。需注意的是,隨着k的增加,準確估計概率P(xi | y, Pai ) 所需的訓練樣本數量將以指數級增加。因此,若訓練數據非常充分,泛化性能有可能提升;但在有限樣本條件下,則又陷入估計高階聯合概率的泥沼.

 

5. 貝葉斯網

5.1 貝葉斯網絡定義

貝葉斯網絡(Bayesian network),又稱信念網絡(Belief Network),或有向無環圖模型(directed acyclic graphical model),是一種概率圖模型,於1985年由Judea Pearl首先提出。它是一種模擬人類推理過程中因果關係的不確定性處理模型,其網絡拓樸結構是一個有向無環圖(DAG)。 

貝葉斯網絡的有向無環圖中的節點表示隨機變量,它們可以是可觀察到的變量,或隱變量、未知參數等。認爲有因果關係(或非條件獨立)的變量或命題則用箭頭來連接。若兩個節點間以一個單箭頭連接在一起,表示其中一個節點是“因(parents)”,另一個是“果(children)”,兩節點就會產生一個條件概率值。

總而言之,連接兩個節點的箭頭代表此兩個隨機變量是具有因果關係,或非條件獨立。

例如,假設節點E直接影響到節點H,即E→H,則用從E指向H的箭頭建立結點E到結點H的有向弧(E,H),權值(即連接強度)用條件概率P(H|E)來表示,如下圖所示:

簡言之,把某個研究系統中涉及的隨機變量,根據是否條件獨立繪製在一個有向圖中,就形成了貝葉斯網絡。其主要用來描述隨機變量之間的條件依賴,用圈表示隨機變量(random variables),用箭頭表示條件依賴(conditional dependencies)。

 

令G = (I,E)表示一個有向無環圖(DAG),其中I代表圖形中所有的節點的集合,而E代表有向連接線段的集合,且令X = (Xi)i ∈ I爲其有向無環圖中的某一節點i所代表的隨機變量,若節點X的聯合概率可以表示成:

則稱X爲相對於一有向無環圖G 的貝葉斯網絡,其中,pa(i)表示節點i之“因”,或稱pa(i)是i的parents(父母)。 

此外,對於任意的隨機變量,其聯合概率可由各自的局部條件概率分佈相乘而得出:

如下圖所示,便是一個簡單的貝葉斯網絡:

因爲a導致b,a和b導致c,所以有

 

5.2 貝葉斯網絡的3種結構形式

給定如下圖所示的一個貝葉斯網絡:

從圖上可以比較直觀的看出:

  • 1. x1,x2,…x7的聯合分佈爲

  • 2. x1和x2獨立(對應head-to-head);

  • 3. x6和x7在x4給定的條件下獨立(對應tail-to-tail)。

根據上圖,第1點可能很容易理解,但第2、3點中所述的條件獨立是啥意思呢?其實第2、3點是貝葉斯網絡中3種結構形式中的其中二種。爲了說清楚這個問題,需要引入D-Separation(D-分離)這個概念:D-Separation是一種用來判斷變量是否條件獨立的圖形化方法。換言之,對於一個DAG(有向無環圖)E,D-Separation方法可以快速的判斷出兩個節點之間是否是條件獨立的。

5.2.1 貝葉斯網絡形式1:head-to-head

所以有:P(a,b,c) = P(a)*P(b)*P(c|a,b)成立,化簡後可得:

即在c未知的條件下,a、b被阻斷(blocked),是獨立的,稱之爲head-to-head條件獨立,對應本節中最開始那張圖中的“x1、x2獨立”。

5.2.2 貝葉斯網絡形式2:tail-to-tail

考慮c未知,跟c已知這兩種情況:

1、在c未知的時候,有:P(a,b,c)=P(c)*P(a|c)*P(b|c),此時,沒法得出P(a,b) = P(a)P(b),即c未知時,a、b不獨立。

2、在c已知的時候,有:P(a,b|c)=P(a,b,c)/P(c),然後將P(a,b,c)=P(c)*P(a|c)*P(b|c)帶入式子中,得到:P(a,b|c)=P(a,b,c)/P(c) = P(c)*P(a|c)*P(b|c) / P(c) = P(a|c)*P(b|c),即c已知時,a、b獨立。

所以,在c給定的條件下,a,b被阻斷(blocked),是獨立的,稱之爲tail-to-tail條件獨立,對應本節中最開始那張圖中的“x6和x7在x4給定的條件下獨立”。

2.2.3 貝葉斯網絡形式3:head-to-tail

還是分c未知跟c已知這兩種情況:

1、c未知時,有:P(a,b,c)=P(a)*P(c|a)*P(b|c),但無法推出P(a,b) = P(a)P(b),即c未知時,a、b不獨立。

2、c已知時,有:P(a,b|c)=P(a,b,c)/P(c),且根據P(a,c) = P(a)*P(c|a) = P(c)*P(a|c),可化簡得到:

所以,在c給定的條件下,a,b被阻斷(blocked),是獨立的,稱之爲head-to-tail條件獨立。

插一句:這個head-to-tail其實就是一個鏈式網絡,如下圖所示:

根據之前對head-to-tail的講解,我們已經知道,在xi給定的條件下,xi+1的分佈和x1,x2…xi-1條件獨立。意味着啥呢?意味着:xi+1的分佈狀態只和xi有關,和其他變量條件獨立。通俗點說,當前狀態只跟上一狀態有關,跟上上或上上之前的狀態無關。這種順次演變的隨機過程,就叫做馬爾科夫鏈(Markov chain)。且有:

接着,將上述結點推廣到結點集,則是:對於任意的結點集A,B,C,考察所有通過A中任意結點到B中任意結點的路徑,若要求A,B條件獨立,則需要所有的路徑都被阻斷(blocked),即滿足下列兩個前提之一:

A和B的“head-to-tail型”和“tail-to-tail型”路徑都通過C;

A和B的“head-to-head型”路徑不通過C以及C的子孫;

 

最後,舉例說明上述D-Separation的3種情況(即貝葉斯網絡的3種結構形式),則是如下圖所示:

640?wx_fmt=png

上圖中左邊部分是head-to-tail,給定 T 時,A 和 X 獨立;右邊部分的右上角是tail-to-tail,給定S時,L和B獨立;右邊部分的右下角是head-to-head,未給定D時,L和B獨立。

 

附一:貝葉斯定理特別版:

 

附二:算法概覽——拼寫檢查

import re, collections
 
def words(text): return re.findall('[a-z]+', text.lower()) 
 
def train(features):
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1
    return model
 
NWORDS = train(words(open('big.txt').read()))
 
alphabet = 'abcdefghijklmnopqrstuvwxyz'
 
def edits1(word):
    n = len(word)
    return set([word[0:i]+word[i+1:] for i in range(n)] +                     # deletion
               [word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] + # transposition
               [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] + # alteration
               [word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet])  # insertion
 
def known_edits2(word):
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
 
def known(words): return set(w for w in words if w in NWORDS)
 
def correct(word):
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
    return max(candidates, key=lambda w: NWORDS[w])

求解:argmaxc P(c|w) -> argmaxc P(w|c) P(c) / P(w)

  • P(c), 文章中出現一個正確拼寫詞 c 的概率, 也就是說, 在英語文章中, c 出現的概率有多大
  • P(w|c), 在用戶想鍵入 c 的情況下敲成 w 的概率. 因爲這個是代表用戶會以多大的概率把 c 敲錯成 w
  • argmaxc, 用來枚舉所有可能的 c 並且選取概率最大的

# 把語料中的單詞全部抽取出來, 轉成小寫, 並且去除單詞中間的特殊符號
def words(text): return re.findall('[a-z]+', text.lower()) 
 
def train(features):
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1
    return model
 
NWORDS = train(words(open('big.txt').read()))

要是遇到我們從來沒有過見過的新詞怎麼辦. 假如說一個詞拼寫完全正確, 但是語料庫中沒有包含這個詞, 從而這個詞也永遠不會出現在訓練集中. 於是, 我們就要返回出現這個詞的概率是0. 這個情況不太妙, 因爲概率爲0這個代表了這個事件絕對不可能發生, 而在我們的概率模型中, 我們期望用一個很小的概率來代表這種情況. lambda: 1

編輯距離:

兩個詞之間的編輯距離定義爲使用了幾次插入(在詞中插入一個單字母), 刪除(刪除一個單字母), 交換(交換相鄰兩個字母), 替換(把一個字母換成另一個)的操作從一個詞變到另一個詞.

#返回所有與單詞 w 編輯距離爲 1 的集合
def edits1(word):
    n = len(word)
    return set([word[0:i]+word[i+1:] for i in range(n)] +                     # deletion
               [word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] + # transposition
               [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] + # alteration
               [word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet])  # insertion

與 something 編輯距離爲2的單詞居然達到了 114,324 個。優化:在這些編輯距離小於2的詞中間, 只把那些正確的詞作爲候選詞,只能返回 3 個單詞: ‘smoothing’, ‘something’ 和 ‘soothing’

#返回所有與單詞 w 編輯距離爲 2 的集合
#在這些編輯距離小於2的詞中間, 只把那些正確的詞作爲候選詞
def edits2(word):
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1))

正常來說把一個元音拼成另一個的概率要大於輔音 (因爲人常常把 hello 打成 hallo 這樣); 把單詞的第一個字母拼錯的概率會相對小, 等等.但是爲了簡單起見, 選擇了一個簡單的方法: 編輯距離爲1的正確單詞比編輯距離爲2的優先級高, 而編輯距離爲0的正確單詞優先級比編輯距離爲1的高.

def known(words): return set(w for w in words if w in NWORDS)

#如果known(set)非空, candidate 就會選取這個集合, 而不繼續計算後面的
def correct(word):
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
    return max(candidates, key=lambda w: NWORDS[w])

 

參考文獻:

  1. 機器學習——周志華
  2. http://dy.163.com/v2/article/detail/CU0MJOCV05118CTM.html
  3. https://blog.csdn.net/t7sfokzord1jaymsfk4/article/details/81350489
  4. 《Python數據分析與機器學習實戰》課程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章