文章目錄
貝葉斯公式簡述(茆書)
貝葉斯定理是關於隨機事件A和B的條件概率(或邊緣概率)的一則定理。其中P(A|B)是在B發生的情況下A發生的可能性。
數學推導上,貝葉斯公式是由全概率公式與乘法公式推導而來,推導過程如下:
由條件概率可得:,對分子使用乘法公式,分母使用全概率公式得:
代入原式中就可到得到貝葉斯公式:
樸素貝葉斯(naive Bayes)法(李書)
樸素貝葉斯法是是基於貝葉斯定理與特徵條件獨立假設的分 類方法。
理論推導
符號說明:輸出類空間爲: 輸入的特徵向量爲x
在進行理論推導,需要條件分佈概率滿足以下的條件對立性假設:
(1)
在利用樸素貝葉斯法進行分類是,對於輸入的x,我們一般通過學習得到的模型來計算後驗的概率分佈:,將得到的概率最大類作爲x的類輸出。後驗概率的計算依據的貝葉斯公式:
(2)
由式子(1)(2)可得:
於是分類器的最終結果可以表示爲:
(3)
不難看出,(3)式的分母結果是相同的,故分類器結果又可等效爲:
對於期望風險最小化的推導此處省略
樸素貝葉斯的法的參數估計
在樸素貝葉斯法中,關於估計概率的方法,主要有兩種1、極大似然估計;2、貝葉斯估計。這裏筆者直接給出公式,不做證明。
極大似然估計
先驗 的極大似然估計是:
假設第 個特徵 可能取值的集合爲 ,條件概率 的極大似然估計是:
貝葉斯估計
極大似然估計雖然可以得到已知情況下得到概率估計值,但是會出出現概率值爲0的情況,進而影響到之後的分類計算結果,貝葉斯估計可以解決這一問題,其原式引入,得到條件概率的貝葉斯估計爲:
同理,得到的先驗概率的貝葉斯概率估計爲:
樸素貝葉斯算法的步驟
step1:輸入訓練數據基於給定的數據模型得到相對應的概率參數估計(先驗概率及條件分佈概率):
step2:輸入需要進行分類的實例x,計算其對應的概率分佈:
step3:輸出x的類:
算法小結
內容主要取之李航老師的《統計學習方法》章節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機器學習經典案例》