統計筆記—淺述樸素貝葉斯

貝葉斯公式簡述(茆書)

 貝葉斯定理是關於隨機事件A和B的條件概率(或邊緣概率)的一則定理。其中P(A|B)是在B發生的情況下A發生的可能性。
數學推導上,貝葉斯公式是由全概率公式與乘法公式推導而來,推導過程如下:

由條件概率可得:P(BiA)=P(ABi)P(A)P\left(B_{i} | A\right)=\frac{P\left(A B_{i}\right)}{P(A)},對分子使用乘法公式,分母使用全概率公式得:

P(ABi)=P(Bi)P(ABi)P\left(A B_{i}\right)=P\left(B_{i}\right) P\left(A | B_{i}\right)

P(A)=i=1nP(Bj)P(ABj)P(A)=\sum_{i=1}^{n} P\left(B_{j}\right) P\left(A | B_{j}\right)

代入原式中就可到得到貝葉斯公式:
P(BA)=P(Bi)P(ABi)i=1nP(Bj)P(ABj)P(B|A)=\frac{P\left(B_{i}\right) P\left(A | B_{i}\right)}{\sum_{i=1}^{n} P\left(B_{j}\right) P\left(A | B_{j}\right)}

樸素貝葉斯(naive Bayes)法(李書)

 樸素貝葉斯法是是基於貝葉斯定理與特徵條件獨立假設的分 類方法。

理論推導

 符號說明:輸出類空間爲:y={c1,c2,,cK}y=\left\{c_{1}, c_{2}, \cdots, c_{K}\right\} 輸入的特徵向量爲x

 在進行理論推導,需要條件分佈概率滿足以下的條件對立性假設:

P(X=xY=ck)=P(X(1)=x(1),,X(n)=x(n)Y=ck)=j=1nP(X(j)=x(j)Y=ck)\begin{aligned} P\left(X=x | Y=c_{k}\right) =P\left(X^{(1)}=x^{(1)}, \cdots, X^{(n)}=x^{(n)} | Y=c_{k}\right) =\prod_{j=1}^{n} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right) \end{aligned}(1)

 在利用樸素貝葉斯法進行分類是,對於輸入的x,我們一般通過學習得到的模型來計算後驗的概率分佈:P(Y=ckX=x)P\left( Y=c_{k}| X=x\right),將得到的概率最大類作爲x的類輸出。後驗概率的計算依據的貝葉斯公式:
P(Y=ckX=x)=P(X=xY=ck)P(Y=ck)kP(X=xY=ck)P(Y=ck)P\left(Y=c_{k} | X=x\right)=\frac{P\left(X=x | Y=c_{k}\right) P\left(Y=c_{k}\right)}{\sum_{k} P\left(X=x | Y=c_{k}\right) P\left(Y=c_{k}\right)}(2)

由式子(1)(2)可得:
P(Y=ckX=x)=P(Y=ck)jP(X(j)=x(j)Y=ck)kP(Y=ck)jP(X(j)=x(j)Y=ck),k=1,2,,KP\left(Y=c_{k} | X=x\right)=\frac{P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}, \quad k=1,2, \cdots, K

於是分類器的最終結果可以表示爲:
y=f(x)=argmaxckP(Y=ck)jP(X(j)=x(j)Y=ck)kP(Y=ck)jP(X(j)=x(j)Y=ck)y=f(x)=\arg \max _{c_{k}} \frac{P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}(3)

不難看出,(3)式的分母結果是相同的,故分類器結果又可等效爲:y=argmaxckP(Y=ck)jP(X(j)=x(j)Y=ck)y=\arg\max_{c_{k}}P\left(Y=c_{k}\right)\prod_{j}P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)

對於期望風險最小化的推導此處省略

樸素貝葉斯的法的參數估計

 在樸素貝葉斯法中,關於估計概率的方法,主要有兩種1、極大似然估計;2、貝葉斯估計。這裏筆者直接給出公式,不做證明。

極大似然估計

先驗 P(Y=Ck)P(Y = C_k) 的極大似然估計是:
P(Y=ck)=i=1NI(yi=ck)N,k=1,2,,KP\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}{N}, \quad k=1,2, \cdots, K

假設第 個特徵 x(j)x^(j) 可能取值的集合爲 αj1aj2...ajSj{α_{j1} a_{j2} . .. a_jS_j },條件概率 P(X(j)=ajlY=ck)P\left(X^{(j)}=a_{j l} | Y=c_k)\right. 的極大似然估計是:
P(X(j)=ajlY=ck)=i=1NI(xi(j)=ajl,yi=ck)i=1NI(yi=ck)P\left(X^{(j)}=a_{j l} | Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x_{i}^{(j)}=a_{j l}, y_{i}=c_{k}\right)}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}
j=1,2,,n;l=1,2,,Sj;k=1,2,,Kj=1,2, \cdots, n ; \quad l=1,2, \cdots, S_{j} ; \quad k=1,2, \cdots, K

貝葉斯估計

 極大似然估計雖然可以得到已知情況下得到概率估計值,但是會出出現概率值爲0的情況,進而影響到之後的分類計算結果,貝葉斯估計可以解決這一問題,其原式引入λ01\lambda大於或等於0(一般取1),得到條件概率的貝葉斯估計爲:
Pλ(X(j)=ajlY=ck)=i=1NI(xi(j)=ajl,yi=ck)+λi=1NI(yi=ck)+SjλP_{\lambda}\left(X^{(j)}=a_{j l} | Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x_{i}^{(j)}=a_{j l}, y_{i}=c_{k}\right)+\lambda}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+S_{j} \lambda}
同理,得到的先驗概率的貝葉斯概率估計爲:

樸素貝葉斯算法的步驟

step1:輸入訓練數據T={(x1,y1),(x2,y2),,(xN,yN)}T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \cdots,\left(x_{N}, y_{N}\right)\right\}基於給定的數據模型得到相對應的概率參數估計(先驗概率及條件分佈概率):

P(Y=ck)=i=1NI(yi=ck)N,k=1,2,,KP\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}{N}, \quad k=1,2, \cdots, K

P(X(j)=ajlY=ck)=i=1NI(xi(j)=ajl,yi=ck)i=1NI(yi=ck)P\left(X^{(j)}=a_{j l} | Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x_{i}^{(j)}=a_{j l}, y_{i}=c_{k}\right)}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}
j=1,2,,n;l=1,2,,Sj;k=1,2,,Kj=1,2, \cdots, n ; \quad l=1,2, \cdots, S_{j} ; \quad k=1,2, \cdots, K

step2:輸入需要進行分類的實例x,計算其對應的概率分佈:

P(Y=ckX=x)=P(Y=ck)jP(X(j)=x(j)Y=ck)kP(Y=ck)jP(X(j)=x(j)Y=ck),k=1,2,,KP\left(Y=c_{k} | X=x\right)=\frac{P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}, \quad k=1,2, \cdots, K

step3:輸出x的類:

y=argmaxckP(Y=ck)jP(X(j)=x(j)Y=ck)y=\arg \max _{c_{k}} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)

算法小結

 內容主要取之李航老師的《統計學習方法》章節4,在這裏,貝葉斯法的推導都是基於設輸入變量都是條件獨立的假設下的,而如果設它們之間存在概率依存關係,模型就變成了貝葉斯網絡,這需要後續繼續的研究與學習。

算例實戰—文本分析

簡言

 不論是書、歷史文檔、社會媒體、電子郵件還是其他以文字爲主的通信方式,都包含大量信息。從文本數據集抽取特徵,用於分類不是件容易事。然而,人們還是總結出了文本挖掘的通用方法。

筆者在此處班門弄斧,使用強大卻出奇簡單的樸素貝葉斯算法來解決幾個實際的問題,樸素貝葉斯算法在計算用於分類的概率時,爲簡化計算,假定各特徵之間是相互獨立的。
 此處主要使用的工具是python 藉助的庫爲自然語言處理庫:NLTK及其當中的數據集 。

識別性別

 利用NLTK庫的性別數據庫與樸素貝葉斯算法進行性別的二分類,主要原理爲:使用用到啓發式方法,即姓名的最後幾個字符可以界定性別特徵。例如,如果某一個名字以“la”結尾,那麼它很有可能是一個女性名字,如“Angela”或者“Layla”。另外,如果一個名字以“im”結尾,那麼它很有可能是一個
男性名字,例如“Tim”或者“Jim”。確定需要用到幾個字符來確定性別後,可以來做這個實驗。接下來介紹如何識別性別。

import random
from nltk.corpus import names
from nltk import NaiveBayesClassifier
from nltk.classify import accuracy as nltk_accuracy

# 提取輸入單詞的特徵
def gender_features(word, num_letters=2):
    return {'feature': word[-num_letters:].lower()}

if __name__=='__main__':
    # 提取特徵名稱
    labeled_names = ([(name, 'male') for name in names.words('male.txt')] +
            [(name, 'female') for name in names.words('female.txt')])

    random.seed(7)
    random.shuffle(labeled_names)
    input_names = ['Leonardo', 'Amy', 'Sam']

    # 搜索參數空間
    for i in range(1, 5):
        print('\nNumber of letters:', i)
        featuresets = [(gender_features(n, i), gender) for (n, gender) in labeled_names]
        train_set, test_set = featuresets[500:], featuresets[:500]
        classifier = NaiveBayesClassifier.train(train_set)

        # 打印分類器準確性
        print('Accuracy ==>', str(100 * nltk_accuracy(classifier, test_set)) + str('%'))

        # 預測新輸入的結果
        for name in input_names:
            print(name, '==>', classifier.classify(gender_features(name, i)))



Number of letters: 1
Accuracy ==> 76.2%
Leonardo ==> male
Amy ==> female
Sam ==> male

Number of letters: 2
Accuracy ==> 78.60000000000001%
Leonardo ==> male
Amy ==> female
Sam ==> male

Number of letters: 3
Accuracy ==> 76.6%
Leonardo ==> male
Amy ==> female
Sam ==> female

Number of letters: 4
Accuracy ==> 70.8%
Leonardo ==> male
Amy ==> female
Sam ==> female

情感分析

 情感分析是指確定一段給定的文本是積極還是消極的過程。有一些場景中,我們還會將“中性”作爲第三個選項。情感分析常用於發現人們對於一個特定主題的看法。情感分析用於分析很多場景中用戶的情緒,如營銷活動、社交媒體、電子商務客戶等

 主要原理:將用NLTK的樸素貝葉斯分類器進行分類。在特徵提取函數中,基本上提取了所有的唯一單詞。然而,NLTK分類器需要的數據是用字典的格式存放的,因此這裏用到了字典格式,便於NLTK分類器對象讀取該數據。將數據分成訓練數據集和測試數據集後,可以訓練該分類器,以便將句子分爲積極和消極。
如果查看最有信息量的那些單詞,可以看到例如單詞“outstanding”表示積極評論,而“insulting”表示消極評論。這是非常有趣的信息,因爲它表明單詞可以用來表示情緒。

import nltk.classify.util
from nltk.classify import NaiveBayesClassifier
from nltk.corpus import movie_reviews
 
def extract_features(word_list):
    return dict([(word, True) for word in word_list])
 
if __name__=='__main__':
    # 加載積極與消極評論
    positive_fileids = movie_reviews.fileids('pos')
    negative_fileids = movie_reviews.fileids('neg')
     
    features_positive = [(extract_features(movie_reviews.words(fileids=[f])), 
            'Positive') for f in positive_fileids]
    features_negative = [(extract_features(movie_reviews.words(fileids=[f])), 
            'Negative') for f in negative_fileids]
     
    # 訓練與測試數據集比例爲(80/20)
    threshold_factor = 0.8
    threshold_positive = int(threshold_factor * len(features_positive))
    threshold_negative = int(threshold_factor * len(features_negative))
     
    features_train = features_positive[:threshold_positive] + features_negative[:threshold_negative]
    features_test = features_positive[threshold_positive:] + features_negative[threshold_negative:]  
    print("\nNumber of training datapoints:", len(features_train))
    print("Number of test datapoints:", len(features_test))
     
    # 訓練樸素貝葉斯分類器
    classifier = NaiveBayesClassifier.train(features_train)
    print("\nAccuracy of the classifier:", nltk.classify.util.accuracy(classifier, features_test))

    print("\nTop 10 most informative words:")
    for item in classifier.most_informative_features()[:10]:
        print(item[0])

    # 輸入簡單的評論
    input_reviews = [
        "but it worked great. Dried my hair in about 15 minutes",
        "Excellent value for travel dryer on a budget",
        "Great hair dryer.",
        "The direction was terrible and the story was all over the place" 
    ]

    print("\nPredictions:")
    for review in input_reviews:
        print("\nReview:", review)
        probdist = classifier.prob_classify(extract_features(review.split()))
        pred_sentiment = probdist.max()
        print("Predicted sentiment:", pred_sentiment) 
        print("Probability:", round(probdist.prob(pred_sentiment), 2))
Number of training datapoints: 1600
Number of test datapoints: 400

Accuracy of the classifier: 0.735

Top 10 most informative words:
outstanding
insulting
vulnerable
ludicrous
uninvolving
avoids
astounding
fascination
symbol
animators

Predictions:

Review: but it worked great. Dried my hair in about 15 minutes
Predicted sentiment: Negative
Probability: 0.63

Review: Excellent value for travel dryer on a budget
Predicted sentiment: Negative
Probability: 0.62

Review: Great hair dryer.
Predicted sentiment: Positive
Probability: 0.54

Review: The direction was terrible and the story was all over the place
Predicted sentiment: Negative
Probability: 0.63

小結

 在學習過程中,筆者總是犯後知後覺的毛病,編程機器學習時才發現自己數學知識不夠,學機器學習理論才發現自己造輪子的能力不夠,好在還有時間給自己從頭再學的機會。希望研究生考試結束後,再回過頭來啃這些書,能有新的收穫,和更深層次的理解。

參考

  • 茆詩松 《概率論與數理統計》
  • 李航 《統計學習方法》
  • Prateek Joshi《Python機器學習經典案例》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章