機器學習算法--貝葉斯公式及分類應用、附源代碼

機器學習--貝葉斯分類

作者:wangxinxi
貝葉斯分類已經是老生常談了,應用也很廣泛,但是我發現資料有些是偏於理論, 有些是偏於堆積代碼, 遂有寫此blog的想法,希望能幫助到一部分人。本文難免有錯誤之處,希望能指出來

1、男女的問題


試想一下,你前往影院看電影,突然發現前面看電影的一個人的門票掉在了地上,,此刻應該是我們發揚中華民族傳統美德的是時候了!但是你偏偏只看到了背景,通過看到的背景推斷,那麼你應該提醒說“Hello,美女,你的電影票掉了"”, 還是應該說:“Hi,帥哥,你的電影票掉了”。很顯然,考慮到我們對男人和女人髮型的認知,或許會潛意識的認爲這位是位女士,那麼結果真的是這樣的?讓我們量化一下數據後,再做分析。
第一種情況:電影院100個人中,50個男人,50個女人。50個女人中,25人長髮,25人短髮。而50個男人中,48人短髮,2人長髮。存在25個長髮女人和2個長髮男人,由此推斷,門票持有者爲女士的可能性很大。
第二中況情況:稍微變一下,電影院100個人中,98個男人,2個女人。2個女人中,1人長髮,1人短髮。而98個男人中,94人短髮,4人長髮。此時這個人是美女還是帥哥的可能性大一些?很容易計算一共有1個長髮女人和4個長髮男人,所以此人是男人的可能性更大。
那麼問題來了,第一種情況:女人的長髮的概率是25/50、男人長髮的概率是2/48,第二種情況:女人的長髮的概率1/2、男人長髮的概率4/98。男人和女人中,長髮的概率並沒有發生太大的改變, 但是結果卻很不一樣。透過現象要分析本質原因,影響推斷結果不僅僅是男女中長髮概率相關,還和男女的所佔的比例相關。這麼說有什麼理論依據?貝葉斯也許可以很好的幫我們解答這個問題。

2、貝葉斯

貝葉斯(Thomas Bayes,1701—1761)英國牧師、“業餘”數學家(其實我也想當業餘的)。生活在18世紀的貝葉斯生前是位受人尊敬英格蘭長老會牧師。爲了證明上帝的存在,他發明了概率統計學原理,遺憾的是,他的這一美好願望至死也未能實現。貝葉斯在數學方面主要研究概率論。他首先將歸納推理法用於概率論基礎理論,並創立了貝葉斯統計理論,對於統計決策函數、統計推斷、統計的估算等做出了貢獻。1763年發表了這方面的論著,對於現代概率論和數理統計都有很重要的作用,其所採用的許多術語被沿用至今。貝葉斯思想和方法對概率統計的發展產生了深遠的影響。今天,貝葉斯思想和方法在許多領域都獲得了廣泛的應用。


3、貝葉斯公式
貝葉斯定理也稱貝葉斯推理,公式表達:
事件A,事件B,則事件A發生在事件B的條件之上的概率:


貝葉斯公式的名詞的定義:

其推導過程如下:
如果P(A) > 0、P(B) > 0

解釋一下推導過程,首先由條件概率公式可知:

或者

然後由乘法公式,把分母乘到左邊可得:

從而可得貝葉斯公式:

或許寫成:

多說一句,也有人把貝葉斯寫成:


是因爲,由全概率公式:
設 B1,B2,....Bn 是樣本空間Ω的一個劃分,B1,B2....Bn兩兩互斥,
P(A)=P(AΩ)

證明全概率公式:

然後把條件概率P(AB)=P(A|B)·P(B)帶入,即可得全概率公式

把全概率公式帶入 貝葉斯公式:


寫成這樣是因爲有時候直接求P(A)比較困難,可以迂迴的通過全概率公式求出來P(A)。

在全概率公式中,如果將A看成是“結果”,Bi看成是導致結果發生的諸多“原因”之一,那麼全概率公式就是一個“原因推結果”的過程。但貝葉斯公式卻恰恰相反。貝葉斯公式中,我們是知道結果A已經發生了,所要做的是反過來研究造成結果發生的原因,是Bi原因造成的可能性有多大,即“結果推原因”。貝葉斯公式體現的是因果的關係,可以通過一些已經知道的信息推測出未知的信息。

4、後知後覺--通過貝葉斯公式來分析男女
我們通過貝葉斯公式來分析上述的背景是長頭髮的是男還是女的問題。
設:A1爲女人的概率,A2爲男人的概率;B1爲長頭髮的概況,B2爲短頭髮的概率
第一種情況推斷:
長頭髮的是女的概率P(A1|B1) = P(B1|A1)·P(A1)/P(B1)=(25/50)·(50/100)/((25+2)/100) = 50/54
長頭髮的是男的概率P(A2|B1) = P(B1|A2)·P(A2)/P(B1)=(2/50)·(50/100)/((25+2)/100) = 4/54
很顯然長頭髮的是美女的概率比較大。
第二種情況的推斷:
長頭髮的是女的概率P(A1|B1) = P(B1|A1)·P(A1)/P(B1)=(1/2)·(2/100)/((1+4)/100) = 1/5
長頭髮的是男的概率P(A2|B1) = P(B1|A2)·P(A2)/P(B1)=(4/98)·(98/100)/((1+4)/100) = 4/5
很顯然長頭髮的是帥哥的概率比較大。

5、貝葉斯應用--垃圾郵件過濾
現在貝葉斯已經廣泛應用了,海難搜救、生物醫藥、疾病診斷、郵件過濾、文本分類、偵破案件、工業生產等很多方面。幾個標準事件,1、聯邦黨人文集作者公案;2、天蠍號核潛艇搜救等,具體可以參見:大數據背後的神祕公式(上):貝葉斯公式

下面我們用來介紹一個經典的案例:垃圾郵件過濾。

我們機會每天都會收到類似以下的垃圾郵件:
“XX公司優惠,商品打折,全場八折,返利多少錢”
“金融公司,XX理財產品,XX保險”
“招聘兼職,工資日結”
諸如此類的垃圾郵件,鋪天蓋地、沒完沒了的發。我們能不能通過一個算法自動的識別出這些垃圾郵件呢?貝葉斯公式就很好用, 下面我們來一步步的講如果利用貝葉斯公式解決垃圾郵件。
1、進行中文分詞
例如把“晚上在公司聚餐”,進行中文分詞會變成:“晚上/ 在/ 公司/ 聚餐”四個單詞。常用的中文分詞庫有jieba等分詞工具。
2、分詞後去掉停用詞
漢語去掉一些“是、在”等之類停用詞之後,並不能明顯影響句子表達的信息,反而能提高計算速度和準確率。比如“晚上在公司聚餐 ”把“在”去掉之後對句子的影響就有限。常用的停用詞也有字典
3、構建詞向量
把所有的詞語聚起來並去重,形成一個全部的詞的集合。然後,根據單詞是否出現在每個裏面,構建每個郵件的詞向量。
4、計算分類概率
根據貝葉斯公式


設B1爲垃圾郵件,B2爲正常郵件; A爲待分類的郵件, 按照貝葉斯算法我們需要求出郵件A爲垃圾郵件的概率P(B1|A) 和爲正常郵件的概率P(B2|A),二分類裏面最大的概率作爲推測的分類。

然而,事情往往沒有這麼容易, 郵件A可能在我們的已知分類庫沒有出現過,所以很難求出P(A|B1)和P(A|B2)。事情進行到這裏彷彿陷入了僵局。。。。讓我們在梳理一下思緒,我們剛剛把郵件通過分詞都向量化了,郵件A可以表示爲一個[w0,w1,w2,w3....wn]的特徵, 就是說事件A是由若干個特徵表示,如果特徵彼此獨立而都有相等的重要性,那麼P(A|B1)= P(w0|B1)·P(w1|B1)·P(w2|B1)·....P(wn|B1),而P(w0|B1)、P(w1|B1)、P(w2|B1)·....P(wn|B1)的每一項都可以通過已知的條件計算出來。這就是傳說的樸素貝葉斯分類器(Naive Bayes classifiers),naive的英文意思是“幼稚的; 天真的; 單純的”。我們把漢語中每個單詞出現想象成“獨立的和同等重要的”,這件事情確實夠“天真的”,但是當我們天真一回後,通過結果你會發現這種“天真”反而很有用。

再來回顧公式

我們會發現分母都有P(A), 所以我只需要比較P(A|B)·P(B),求出最大的P(A|B)·P(B)就可以認爲是我們預測出來的分類。
環境:Python3
庫:numpy
分詞後,下面是簡單實現的代碼:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @time : 2018/3/13 22:01
# @author : wangxinxi
# @file : bayes.py
# @aoftware: PyCharm

from numpy import *
from functools import reduce

#廣告、垃圾標識
adClass = 1

def loadDataSet() :
'''加載數據集合及其對應的分類'''
wordsList = [['週六', '公司', '一起', '聚餐','時間'],
['優惠', '返利', '打折', '優惠', '金融', '理財'],
['喜歡', '機器學習', '一起', '研究', '歡迎', '貝葉斯', '算法', '公式'],
['公司', '發票', '稅點', '優惠', '增值稅', '打折'],
['北京', '今天', '霧霾', '不宜', '外出', '時間', '在家', '討論', '學習'],
['招聘', '兼職', '日薪', '保險', '返利']]
# 1 是, 0 否
classVec = [0, 1, 0, 1, 0, 1]
return wordsList, classVec


def doc2VecList(docList) :
'''合併去重,生成包含所有單詞的集合'''
return list(reduce(lambda x, y : set(x) | set(y), docList))


def words2Vec(vecList, inputWords) :
'''把單子轉化爲詞向量'''
resultVec = [0] * len(vecList)
for word in inputWords :
if word in vecList :
# 在單詞出現的位置上的計數加1
resultVec[vecList.index(word)] += 1
else :
print('沒有發現此單詞')
return array(resultVec)


def trainNB(trainMatrix, trainClass) :
'''計算,生成每個詞對於類別上的概率'''
numTrainClass = len(trainClass)
numWords = len(trainMatrix[0])
# 全部都初始化爲1, 防止出現概率爲0的情況出現
p0Num = ones(numWords)
p1Num = ones(numWords)
# 相應的單詞初始化爲2
p0Words = 2.0
p1Words = 2.0
# 統計每個分類的詞的總數
for i in range(numTrainClass) :
if trainClass[i] == 1 :
#數組在對應的位置上相加
p1Num += trainMatrix[i]
p1Words += sum(trainMatrix[i])
else :
p0Num += trainMatrix[i]
p0Words += sum(trainMatrix[i])
# 計算每種類型裏面, 每個單詞出現的概率
p0Vec = log(p0Num / p0Words)
p1Vec = log(p1Num / p1Words)
# 計算1出現的概率
pClass1 = sum(trainClass) / float(numTrainClass)
return p0Vec, p1Vec, pClass1


def classifyNB(testVec, p0Vec, p1Vec, pClass1) :
'''樸素貝葉斯分類, max(p0, p1)作爲推斷的分類'''
# y=x 是單調遞增的, y=ln(x)也是單調遞增的。 , 如果x1 > x2, 那麼ln(x1) > ln(x2)
# 因爲概率的值太小了,所以我們可以取ln, 根據對數特性ln(ab) = lna + lnb, 可以簡化計算
# sum是numpy的函數
p1 = sum(testVec * p1Vec) + log(pClass1)
p0 = sum(testVec * p0Vec) + log(1 - pClass1)
if p0 > p1 :
return 0
return 1

def printClass(words, testClass):
if testClass == adClass:
print(words, '推測爲:廣告郵件')
else:
print(words, '推測爲:正常郵件')

def tNB() :
'''測試,進行預測'''
docList, classVec = loadDataSet()
# 生成包含所有單詞的list
allWordsVec = doc2VecList(docList)
# 構建詞向量矩陣
trainMat = list(map(lambda x : words2Vec(allWordsVec, x), docList))
# 訓練計算每個詞在分類上的概率, p0V:每個單詞在非分類出現的概率, p1V:每個單詞在是分類出現的概率
p0V, p1V, pClass1 = trainNB(trainMat, classVec)
testWords = ['公司', '聚餐', '討論', '貝葉斯']
# 當前需要預測的詞向量
testVec = words2Vec(allWordsVec, testWords)
# 預測分類
testClass = classifyNB(testVec, p0V, p1V, pClass1)
printClass(testWords, testClass)
# 預測
testWords = ['公司', '保險', '金融']
testVec = words2Vec(allWordsVec, testWords)
testClass = classifyNB(testVec, p0V, p1V, pClass1)
printClass(testWords, testClass)


if __name__ == '__main__' :
tNB()


代碼執行結果:
['公司', '聚餐', '討論', '貝葉斯'] 推測爲:正常郵件
['公司', '保險', '金融'] 推測爲:廣告郵件

代碼已經上傳至github上:https://github.com/qiuyukuhe/ml

樸素貝葉斯算法侷限性:如果特徵變量的有些特徵關聯性較強(比如“首都”“北京”這兩個詞就很大的可能同時出現),或者特徵之間的重要性不一樣(比如,TF-IDF(詞頻和逆詞頻)的問題), 在解決比較複雜的問題的時候效果就不是那麼好。

郵件過濾攻防:現在很多垃圾郵件通過發送圖片、鏈接等途徑來避過貝葉斯分類算法。

您可以隨意轉載、修改此文章

參考:
《機器學習實戰》


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章