1. Bayes 定理
- P(A,B)=P(A|B)P(B);
- P(A,B)=P(B|A)P(A);
- P(A|B)=P(B|A)P(A)/P(B); 貝葉斯定理變形
2. 概率圖模型
2.1 定義
2.2 隨機變量的條件獨立
如果有P(A,B|C)=P(A|C)P(B|C), 則稱在給定事件C的條件下,兩個事件A和B獨立,這裏假設P(C)>0;
如:設A=2x+z; B=y+z; C=z;
在C確定的條件下 A,B是獨立的。如假設z=0(常數),則A和B沒有任何關聯。
等價形式P(A|B,C)=P(A|C)
推導: P(A,B|C)=P(A|C)P(B|C); ...1 P(A,B|C)=P(A|B,C)P(B|C); ...2
聯合1,2式可以=> P(A|C)=P(A|B,C)
2.3概率圖模型的有向圖表示
利用有向圖來表示變量之間的概率依賴關係,典型應用就是貝葉斯網絡.
上圖Naive Bayes 可以表示爲: p(y,x1,x2,x3)=p(y).p(x1|y)p(x2|y)p(x3|y)
3. Naive Bayes Model
3.1 Bayes 決策理論思想
樸素貝葉斯是貝葉斯決策理論的一部分, 所以講述樸素貝葉斯之前有必要快速瞭解一下貝葉斯決策理論。
假設我們有一個數據集,如下圖所示:
我們用P(c1|x,y) 表示數據點(x,y)屬於類別c1的概率(圖中紅色圓點的概率),用P(c2|x,y)表示數據點(x,y)屬於類別c2的概率(圖中綠色的三角形概率)。那麼對於一個新的數據點(x,y),我們就可以用一下規則來判斷它的類別。
- If p(c1|x, y) > p(c2|x, y), then the class is c1.
- If p(c2|x, y) > p(c1|x, y), then the class is c2.
也就是說,我們會選擇高概率對應的類別。這就是貝葉斯決策理論的核心思想, 即選擇具有最高概率的決策。
3.2 Naive Bayes 公式推導
假設某個體有n項特徵(Feature),分別爲F1、F2、...、Fn。現有m個類別(Category),分別爲C1、C2、...、Cm。
貝葉斯分類器就是計算出概率最大的那 個 分類,也就是求下面這個算式的最大值:P(C|F1,F2,...,Fn);
可以理解爲求 在屬性F1,F2,....Fn條件下,屬於各個類別Ci的概率,然後求出最大的那個P(Ci|F1,F2,...Fn) ,這樣就得到F1,F2,...Fn 屬於哪一類(Ci)了。
使用貝葉斯原理可以寫成
因爲對於每一個類別的Ci的概率都存在P(F1,F2,......Fn)所以只需要關注P(C)P(F1,F2.....Fn|C)
寫成聯合概率的形式P(C,F1,F2...Fn)=P(C)P(F1,F2.....Fn|C)
重複使用貝葉斯原理=>
現在“樸素”的“條件獨立”(2中有推導)假設開始發揮作用:假設每個特徵對於其他特徵,是條件獨立的。這就意味着
對於,所以聯合分佈模型可以表達爲
4. 例子
4.1 性別分類
下面是一組人類身體特徵的統計資料。
性別 | 身高(英尺) | 體重(磅) | 腳掌(英寸) |
男 | 6 | 180 | 12 |
男 | 5.92 | 190 | 11 |
男 | 5.58 | 170 | 12 |
男 | 5.92 | 165 | 10 |
女 | 5 | 100 | 6 |
女 | 5.5 | 150 | 8 |
女 | 5.42 | 130 | 7 |
女 | 5.75 | 150 | 9 |
已知某人身高6英尺、體重130磅,腳掌8英寸,請問該人是男是女?
即,P(C|F1,F2,F3)的最大概率。
根據上面的Naive Bayes Model P(C|F1,F2,F3)=P(身高|性別) x P(體重|性別) x P(腳掌|性別) x P(性別)
這裏的困難在於,由於身高、體重、腳掌都是連續變量,不能採用離散變量的方法計算概率。而且由於樣本太少,所以也無法分成區間計算。怎麼辦?
這時,可以假設男性和女性的身高、體重、腳掌都是正態分佈,通過樣本計算出均值和方差,也就是得到正態分佈的密度函數。有了密度函數,就可以把值代入, 算出某一點的密度函數的值。
比如,男性的身高是均值5.855、方差0.035的正態分佈。所以,男性的身高爲6英尺的概率的相對值等於1.5789(大於1並沒有關係,因爲這裏是密度函數的 值,只用來反映各個值的相對可能性)。
如上,我們就可以推出
有了P(height|male),P(weight|male),...我們就可以得到
P(height=6|male) x P(weight=130|male) x P(footsize=8|male) x P(male)
= 6.1984 x e-9
P(height=6|female) x P(weight=130|female) x P(footsize=8|female) x P(female)
= 5.3778 x e-4
可以看到,女性的概率比男性要高出將近10000倍,所以判斷該人爲女性。
4.2 使用Naive Bayes Model 實現髒話評論
- 分析:
- 訓練過程:
已分類[0, 1, 0, 1, 0, 1]
訓練評論構成的唯一字典:['maybe', 'him', 'help', 'problems', 'so', 'I', 'dog', 'is', 'cute', 'love', 'buying', 'flea', 'how', 'food', 'licks', 'posting', 'has', 'take', 'stupid', 'steak', 'park', 'please', 'to', 'worthless', 'garbage', 'my', 'dalmation', 'mr', 'quit', 'not', 'ate', 'stop']
訓練評論向量化(0表未出現,1表示出現):[[0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,0, 1, 0, 0, 0]]
- 分類過程:
__author__ = 'essex.user'
from numpy import *
from math import *
from pylab import *
#load example data
def loadDataSet():
postingList=[['my', 'dog', 'has', 'flea','problems', 'help', 'please'],
['maybe', 'not', 'take', 'him','to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute','I', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how','to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
classVec = [0,1,0,1,0,1] #1 is abusive, 0 not
return postingList,classVec
# create a list of all the unique words in all of our documents
def createVocabList(dataSet):
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet|set(document)
return list(vocabSet)
#文檔的向量(inputSet)是否在詞彙表(vacabList)中,則將輸出向量的下標變爲1
#將文字轉化爲關於0,1的向量
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1
else:
print("the word: %s is not in my Vocabulary!" % word)
return returnVec
#樸素貝葉斯分類器訓練函數1
def trainNB0(trainMatrix,trainCategory):
#print("trainMatrix:%s\ntrainCategory:%s"%(trainMatrix,trainCategory))
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
#print("numTrainDocs=%d\tnumWords=%d"%(numTrainDocs,numWords))
pAbusive = sum(trainCategory)/float(numTrainDocs) #3/6
p0Num = zeros(numWords); p1Num = zeros(numWords) #長度爲32的0向量
#print("pAbusive=%d\np0Num:%s\np1Num:%s"%(pAbusive,p0Num,p1Num))
p0Denom = 0.0; p1Denom = 0.0 #所有文檔中,屬於類別0和1的詞彙個數
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
#print("p1Num:",p1Num)
p1Denom += sum(trainMatrix[i])
#print("p1Denom",p1Denom)
else:
p0Num += trainMatrix[i]
#print("p0Num:",p0Num)
p0Denom += sum(trainMatrix[i])
p1Vect = p1Num/p1Denom #change to log()
p0Vect = p0Num/p0Denom #change to log()
#print("p1Vect:",p1Vect)
return p0Vect,p1Vect,pAbusive
#樸素貝葉斯分類器訓練函數--改進版
def trainNB(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix) #文檔數
numWords = len(trainMatrix[0]) #詞彙表的詞彙數
pAbusive = sum(trainCategory)/float(numTrainDocs) #帶侮辱性質類別的文檔數
p0Num = ones(numWords) #是侮辱性質類別的向量
p1Num = ones(numWords) #長度爲32的0向量
p0Denom = 2.0; p1Denom = 2.0 #所有文檔中,屬於類別0和1的詞彙個數
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i] #類別1的詞頻
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i] #類別0的詞頻
p0Denom += sum(trainMatrix[i])
p1Vect = log(p1Num/p1Denom)
p0Vect = log(p0Num/p0Denom)
return p0Vect,p1Vect,pAbusive
#樸素貝葉斯分類函數
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
p1 = sum(vec2Classify * p1Vec) + log(pClass1)
p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
if p1>p0:
return 1
else:
return 0
#分類器測試
def testingNB():
listOPosts,listClasses = loadDataSet()
myVocabList = createVocabList(listOPosts)
trainMat=[]
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V,p1V,pAb = trainNB(array(trainMat),array(listClasses))
testEntry = ['love', 'my', 'dalmation']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
testEntry = ['stupid', 'garbage']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
testingNB()
運行結果:
['love', 'my', 'dalmation'] classified as: 0
['stupid', 'garbage'] classified as: 1