Naive Bayes
樸素貝葉斯網絡是貝葉斯分類器的一種,貝葉斯分類算法是統計學的一種分類方法,利用概率論和統計知識進行分類。其原理是利用貝葉斯公式根據樣本的先驗概率來計算其後驗概率(即樣本屬於某一類的概率),然後選擇具有最大後驗概率的類作爲該對象所屬的類別。樸素貝葉斯分類以概率論爲基礎,有堅實的數學基礎,以及穩定的分類效率,其優點是算法簡單,在數據較少的情況下仍然準確。理論上樸素貝葉斯分類有最小的誤差率,但實際貝葉斯假設樣本之間的各個特徵相互獨立往往不成立,從而影響分類正確性。
1.貝葉斯理論
在貝葉斯理論中,假設X,Y兩個事件:
貝葉斯理論中,常用公式:
乘法公式:
全概率公式:
貝葉斯公式:
2.樸素貝葉斯法的學習與分類
設輸入空間
具體地:
後驗概率:
其中,
所以最終樸素貝葉斯分類器可以表示爲:
即在所有的後驗概率中找到最大的概率作爲該特徵預測的類別,而且我們注意到最終的分母是隊所有的類別都是一樣的,因此可以簡化爲:
我們以兩個類別來簡要說明貝葉斯的分類準則:假設未知類別樣本特徵爲
樣本爲類別2的概率爲:
其中
- 如果
P(x|c1)P(c1)>P(x|c2)P(c2) ,那麼該測試樣本屬於c1 類 - 如果
P(x|c1)P(c1)<P(x|c2)P(c2) ,那麼該測試樣本屬於c2 類
3.樸素貝葉斯學習算法
損失函數:
通過上述介紹,我們知道樸素貝葉斯方法的分類規則就是後驗概率最大化,這與經驗風險最小化是相匹配的。我們定義樸素貝葉斯分類的損失函數爲:
其中,
其中,
由此可以看出,後驗概率最大化準則符合損失函數最小化的要求。
參數估計:
通過上述介紹,我們知道樸素貝葉斯的學習過程就是估計先驗概率
然後在所有標記爲
其中,X^{(j)}是樣本的第
算法實現:
在本處,我們應用樸素貝葉斯方法來進行垃圾郵件分類。
- 準備數據:首先準備一定量垃圾郵件和正常郵件並給予一定標記
- 數據處理:由於本處文本量少,文本較爲簡單,直接統計文本中各個單詞的數量來作爲文本特徵
- 參數估計:首先統計訓練樣本中正負樣本各佔多少比例,即
- 模型測試:統計給定訓練樣本的特徵,然後通過先驗概率計算出屬於各類的標籤
- 模型應用:可以編輯任意文本進行測試,看未標記文本是否分類正確
以下是程序實現源碼:
# Project: Machine learning-Naive Bayes
# Author: Lyndon
# date: 2015/10/20
from numpy import *
import re,string,os
# create the vocabulary
# input: traing_data text
# output: vocabulary list
def creatVocabulary(dataset):
vocabulary = set([])
for document in dataset:
vocabulary = vocabulary | set(document)
return list(vocabulary)
# describe document using the bag-of-words model
# input: vocabulary list, input document
# output: descriptor of input document
def document2Vec(vocabulary,inputData):
vector = [0]*len(vocabulary)
for word in inputData:
if word in vocabulary:
vector[vocabulary.index(word)]+=1
else:
print "the word: %s is not in the vocabulary!" %word
return vector
# split the document to word list
# input: document
# output: word list
def text2word(textString):
textString.translate(None, string.punctuation)
# split the document
wordsplit = re.split(r'\s+',textString)
# retain the alphabetic characters
#for i in range(len(wordsplit)):
#wordsplit[i] = filter(str.isalpha,wordsplit[i])
# return the lower case word
return [tok.lower() for tok in wordsplit if len(tok) >2]
# process the dataset
# input: NULL
# output: document list, class label list, full text
def proDocument():
documentlist = []
classlist = []
fulltext = []
path1 = "F:/Program/Python/Machine_Learning/Bayes/email/spam"
for root, dirs, files in os.walk(path1):
#print files
numDocument1 = len(files)
for i in range(numDocument1):
wordList = text2word(open(path1+'/%d.txt' %(i+1)).read())
documentlist.append(wordList)
fulltext.extend(wordList)
classlist.append(1)
path2 = "F:/Program/Python/Machine_Learning/Bayes/email/ham"
for root, dirs, files in os.walk(path2):
#print files
numDocument2 = len(files)
for i in range(numDocument2):
wordList = text2word(open(path2+'/%d.txt' %(i+1)).read())
documentlist.append(wordList)
fulltext.extend(wordList)
classlist.append(0)
return documentlist,classlist,fulltext
# training
# input: training_vector, training_label
# output: posterior probability P(Y=1), P(X=x|Y=1),P(X=x|y=0)
def trainNB(trainMatrix,trainlabel):
numTrain = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainlabel)/float(numTrain)
p0Num = ones(numWords); p1Num = ones(numWords)
p0Denom = 2.0; p1Denom =2.0
for i in range(numTrain):
if trainlabel[i]==1:
p1Num += trainMatrix[i]
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
p1Vector = log(p1Num/p1Denom)
p0Vector = log(p0Num/p0Denom)
return p0Vector,p1Vector,pAbusive
# testing
# input: testing_vector, posterior probability P(Y=1), P(X=x|Y=1),P(X=x|y=0)
# output: testing_label
def testNB(testVector,p0Vector,p1Vector,pAbusive):
p1 = sum(testVector*p1Vector)+log(pAbusive)
p0 = sum(testVector*p0Vector)+log(1-pAbusive)
if p1>p0:
return 1
else:
return 0
# main function
if __name__=="__main__":
# dataset processing
documentlist = []
classlist = []
fulltext = []
documentlist,classlist,fulltext=proDocument()
vocabulary = creatVocabulary(documentlist)
# randomly select training_set and testing_set
trainSet=range(len(documentlist));testSet=[]
for i in range(int(len(documentlist)*0.2)):
randIndex = int (random.uniform(0,len(documentlist)-i))
testSet.append(trainSet[randIndex])
del(trainSet[randIndex])
trainMat=[];trainlabel=[]
for docIndex in trainSet:
trainMat.append(document2Vec(vocabulary, documentlist[docIndex]))
trainlabel.append(classlist[docIndex])
p0Vector,p1Vector,pAbusive = trainNB(trainMat,trainlabel)
error = 0
for docIndex in testSet:
doc2Vector = document2Vec(vocabulary, documentlist[docIndex])
result=testNB(doc2Vector,p0Vector,p1Vector,pAbusive)
if result!=classlist[docIndex]:
error +=1
print "classification error:"+str(documentlist[docIndex])+"is "+str(classlist[docIndex])+" but classify to "+str(result)
print "the error rate is:",float(error)/len(testSet)
程序測試結果:
在實際處理過程中,可能會出現某個條件概率
當
PS:
本文爲機器學習(4)總結筆記,主要通過Python編程實現了樸素貝葉斯方法實現垃圾郵件分類系統。理論主要參考李航《統計學習方法》,