樸素貝葉斯公式
也可以簡寫為:
轉載請注明出處:Michael孟良
其中:
P(A)叫做A事件的先驗概率,即一般情況下特漩,認為A發(fā)生的概率黄娘。
P(B|A)叫做似然度,是A假設條件成立的情況下發(fā)生B的概率天通。
P(A|B)叫做后驗概率泊窘,在B發(fā)生的情況下發(fā)生A的概率,也就是要求的概率像寒。P(B)叫做標準化常量烘豹,即在一般情況下,認為B發(fā)生的概率诺祸。
理解樸素貝葉斯
假設現(xiàn)在有一堆郵件携悯,正常郵件的比例是80%,垃圾郵件的比例是20%序臂,這堆郵件中蚌卤,5%的郵件中出現(xiàn)Viagra單詞,如果有一封郵件奥秆,這封郵件中包含Viagra單詞,求這封郵件是垃圾郵件的概率咸灿。
顯然不能使用5%*20%=1%得到這封郵件是垃圾郵件的概率构订,因為垃圾郵件中有可能出現(xiàn)Viagra也有可能不會出現(xiàn)Viagra單詞。那么根據(jù)貝葉斯公式可得包含Viagra單詞的郵件是垃圾郵件的概率為:
P(spam)是已知20%避矢,P(Viagra)也是已知 5%悼瘾,那么如果求出P(Viagra|spam)的概率,結果就可以知道审胸。我們可以根據(jù)郵件的數(shù)據(jù)集統(tǒng)計得到單詞頻率表:
其中P(spam|Viagra)表示在垃圾郵件中出現(xiàn)Viagra單詞的概率亥宿,通過統(tǒng)計得出為4/20∩芭妫可以得出如果一封郵件中有Viagra單詞烫扼,這封郵件是垃圾郵件的概率為:
通過同樣的計算可以得到,含有Viagra單詞但不是垃圾郵件的概率為0.2碍庵。那么可以認為這封郵件是垃圾郵件的概率比較大映企。這里的Viagra可以理解為郵件中的一個特征悟狱。那么當一封郵件有額外更多的特征時,貝葉斯如何擴展堰氓?
假設所有歷史郵件中只出現(xiàn)了4個單詞挤渐,也就是4個特征,根據(jù)歷史郵件統(tǒng)計的單詞頻率表如下:
假設現(xiàn)在給定一封郵件中有Viagra和Unsubscribe(取消訂閱)兩個單詞双絮,求這封郵件是垃圾郵件的概率浴麻、不是垃圾郵件的概率?
利用貝葉斯公式囤攀,我們可以得到:
是垃圾郵件的概率:
最后約等于98.07%
不是垃圾郵件的概率:
最后約等于17.4%
拉普拉斯估計
根據(jù)以上例子白胀,假設有一封郵件這4個單詞都出現(xiàn)了,求這封郵件是垃圾郵件的概率:
由于P(W3)的概率為0/20抚岗,會導致整個結果是垃圾郵件的概率為0或杠,那么就否定了其他單詞出現(xiàn)的權重。
拉普拉斯估計本質上是給頻率表中的每個單詞的計數(shù)加上一個較小的數(shù)宣蔚,這樣就保證每一類中每個特征發(fā)生的概率非零向抢。通常,拉普拉斯估計中加上的數(shù)值為1胚委,這樣就保證了每一個特征至少在數(shù)據(jù)中出現(xiàn)一次挟鸠。
以上例子如果四個單詞都出現(xiàn)情況下計算是否是垃圾郵件,出現(xiàn)P(W3)的概率為0/20亩冬,可以增加4封垃圾郵件艘希,使4封郵件中每個郵件中只有一個單詞出現(xiàn),這樣就避免了垃圾郵件中有的單詞出現(xiàn)概率為0的情況硅急。同樣在不是垃圾郵件中也增加4封覆享,避免在正常郵件中出現(xiàn)有的單詞出現(xiàn)概率為0的情況。
Python 貝葉斯案例
# coding:utf-8
import os
import sys
import codecs
# #####################################################
# Multinomial Naive Bayes Classifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
print('*************************\nNaive Bayes\n*************************')
if __name__ == '__main__':
# read the file
corpus = []
labels = []
corpus_test = []
labels_test = []
f = codecs.open("./sms_spam.txt", "rb")
count = 0
while True:
# readline() read every line营袜,including "\n"
line = f.readline().decode("utf-8")
# read the first line and ignore it
if count == 0:
count = count + 1
continue
if line:
count = count + 1
line = line.split(",")
label = line[0]
sentence = line[1]
corpus.append(sentence)
if "ham" == label:
labels.append(0)
elif "spam" == label:
labels.append(1)
if count > 5550:
corpus_test.append(sentence)
if "ham" == label:
labels_test.append(0)
elif "spam" == label:
labels_test.append(1)
else:
break
# 文本特征提热龆佟:
# 將文本數(shù)據(jù)轉化成特征向量的過程
# 比較常用的文本特征表示法為詞袋法
#
# 詞袋法:
# 不考慮詞語出現(xiàn)的順序,每個出現(xiàn)過的詞匯單獨作為一列特征
# 這些不重復的特征詞匯集合為詞表
# 每一個文本都可以在很長的詞表上統(tǒng)計出一個很多列的特征向量
# CountVectorizer是將文本向量轉換成稀疏表示數(shù)值向量(字符頻率向量) vectorizer 將文檔詞塊化,只考慮詞匯在文本中出現(xiàn)的頻率
# 詞袋
vectorizer = CountVectorizer()
# 每行的詞向量荚板,fea_train是一個矩陣
fea_train = vectorizer.fit_transform(corpus)
print("vectorizer.get_feature_names is ", vectorizer.get_feature_names())
print("fea_train is ", fea_train.toarray())
# vocabulary=vectorizer.vocabulary_ 只計算上面vectorizer中單詞的tf(term frequency 詞頻)
vectorizer2 = CountVectorizer(vocabulary=vectorizer.vocabulary_)
fea_test = vectorizer2.fit_transform(corpus_test)
print("vectorizer2.get_feature_names()",vectorizer2.get_feature_names())
print("fea_test.toarray()",fea_test.toarray())
# create the Multinomial Naive Bayesian Classifier
# alpha = 1 拉普拉斯估計給每個單詞個數(shù)加1
clf = MultinomialNB(alpha=1)
clf.fit(fea_train, labels)
pred = clf.predict(fea_test);
for p in pred:
if p == 0:
print("正常郵件")
else:
print("垃圾郵件")
sms_spam.txt:
type,text
ham,you are having a good week. Just checking in 00 00 00 0089 0089
ham,K..give back my thanks.
ham,Am also doing in cbe only. But have to pay.
spam,"complimentary 4 STAR Ibiza Holiday or £10,000 cash needs your URGENT collection. 09066364349 NOW from Landline not to lose out! Box434SK38WP150PPM18+"
...
邏輯思路:
sms_spam.txt有5560條數(shù)據(jù)凤壁, 取5550條數(shù)據(jù)作為訓練,后十條作為測試數(shù)據(jù)跪另。每一行的第一個詞是這份郵件的類型拧抖,就是之前已經(jīng)人為判斷過,ham表示它為正常郵件免绿, spam為垃圾郵件唧席。
這里labels就是收集人為判斷的結果
# 詞袋
vectorizer = CountVectorizer()
# 每行的詞向量,fea_train是一個矩陣
fea_train = vectorizer.fit_transform(corpus)
vectorizer 拿到所有郵件的所有單詞,fea_train 是所有郵件每個詞在每份郵件出現(xiàn)的次數(shù)袱吆,相當一個矩陣厌衙。
# create the Multinomial Naive Bayesian Classifier
# alpha = 1 拉普拉斯估計給每個單詞個數(shù)加1
clf = MultinomialNB(alpha=1)
clf.fit(fea_train, labels)
這里 alpha = 1 ,就是前面講到的拉普拉斯估計绞绒,給每個單詞個數(shù)加1婶希,防止它出現(xiàn)0的情況。
fea_train是訓練出來的矩陣蓬衡,labels是人為判斷的結果喻杈,把他們fit到clf里面。
pred = clf.predict(fea_test);
for p in pred:
if p == 0:
print("正常郵件")
else:
print("垃圾郵件")
fea_test是后面十條的數(shù)據(jù)狰晚,把它放到我們之前訓練好的貝葉斯模型clf筒饰,然后預測出這十條數(shù)據(jù)。
打印出來的結果
代碼:https://github.com/MichaelYipInGitHub/PythonTest/tree/master/com/test/bayes