今天介紹機(jī)器學(xué)習(xí)中一種基于概率的常見的分類方法,樸素貝葉斯,之前介紹的KNN, decision tree 等方法是一種 hard decision,因?yàn)檫@些分類器的輸出只有0 或者 1,樸素貝葉斯方法輸出的是某一類的概率,其取值范圍在 0-1 之間,樸素貝葉斯在做文本分類,或者說垃圾郵件識別的時候非常有效。
樸素貝葉斯就是基于我們常用的貝葉斯定理:
假設(shè)我們要處理一個二分類問題: c1,c2,給定一個樣本,比如說是一封郵件,可以用向量 x 來表示,郵件就是一個文本,而文本是由單詞構(gòu)成的,所以 x 其實(shí)包含了這封郵件里出現(xiàn)的單詞的信息,我們要求的就是,給定樣本 x ,我們需要判斷這個樣本是屬于 c1 還是屬于 c2,當(dāng)然,我們可以用概率表示為:
這個就是我們常見的后驗(yàn)概率。根據(jù)貝葉斯定理,我們可以得到:
這就是我們說的樸素貝葉斯,接下來的就是各種統(tǒng)計了。
我們給出一個利用樸素貝葉斯做文本分類的例子:
首先建立一個數(shù)據(jù)庫:
def Load_dataset():
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]
return postingList, classVec
接下來,我們建立一個字典庫,保證每一個單詞在這個字典庫里都有一個位置索引,一般來說,字典庫的大小,就是我們樣本的維度大小:
def Create_vocablist(dataset):
vocabSet = set([])
for document in dataset :
vocabSet = vocabSet | set(document)
return list(vocabSet)
我們可以將樣本轉(zhuǎn)成向量:一種方法是只統(tǒng)計該單詞是否出現(xiàn),另外一種是可以統(tǒng)計該單詞出現(xiàn)的次數(shù)。
def Word2Vec(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 the vocabulary" % word)
return returnVec
def BoW_Vec(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 the vocabulary" % word)
return returnVec
接下來,我們建立分類器:這里需要注意的是,由于概率都是 0-1 之間的數(shù),連續(xù)的相乘,會讓最終結(jié)果趨于0,所以我們可以把概率相乘轉(zhuǎn)到對數(shù)域的相加:
def Train_NB(trainMat, trainClass) :
Num_doc = len(trainMat)
Num_word = len(trainMat[0])
P_1 = sum(trainClass) / float(Num_doc)
P0_num = np.zeros(Num_word) + 1
P1_num = np.zeros(Num_word) + 1
P0_deno = 2.0
P1_deno = 2.0
for i in range(Num_doc):
if trainClass[i] == 1:
P1_num += trainMat[i]
P1_deno +=sum(trainMat[i])
else:
P0_num += trainMat[i]
P0_deno += sum(trainMat[i])
P1_vec = np.log(P1_num / P1_deno)
P0_vec = np.log(P0_num / P0_deno)
return P_1, P1_vec, P0_vec
def Classify_NB(testVec, P0_vec, P1_vec, P1):
p1 = sum(testVec * P1_vec) + math.log(P1)
p0 = sum(testVec * P0_vec) + math.log(1-P1)
if p1 > p0:
return 1
else:
return 0
def Text_parse(longstring):
import re
regEx = re.compile(r'\W*')
Listoftokens = regEx.split(longstring)
return [tok.lower() for tok in Listoftokens if len(tok)>0]
# return Listoftokens
這里給出簡單的測試:
test_string = 'This book is the best book on Python or M.L.\
I have ever laid eyes upon.'
wordList = Text_parse(test_string)
Mydata, classVec = Load_dataset()
'''
Doc_list = []
Full_list = []
for i in range (len(Mydata)):
Doc_list.append(Mydata[i])
Full_list.extend(Mydata[i])
'''
Vocablist = Create_vocablist(Mydata)
Wordvec = Word2Vec(Vocablist, Mydata[0])
trainMat = []
for doc in Mydata:
trainMat.append(Word2Vec(Vocablist, doc))
P_1, P1_vec, P0_vec = Train_NB(trainMat, classVec)
print Mydata
print classVec
print wordList
評論
查看更多