機器學習筆記(一)樸素貝葉斯的Python程式碼實現
阿新 • • 發佈:2019-01-07
上研究生的時候,一心想讀生物資訊學的方向,由此也選修了生物數學,計算生物學等相關課程。給我印象最深的是給我們計算生物學的主講老師,他北大數學系畢業,後來做起了生物和數學的交叉學科研究。課上講的一些演算法比如貝葉斯,馬爾科夫,EM等把我給深深折磨了一遍。由於那時候不會程式設計,對於這些演算法的理解只有停留在理論層面。課程結束了,學習也就結束了。最後畢業了,自己沒能把生物堅持下去,轉而成為了一隻程式猿……
偶然間,翻開了自己買的一本機器學習實戰的書(Machine learning in Action),看到裡面有裡面也有程式碼實現,甚是喜歡,同時也勾起我那段演算法學習時光。於是我決定將書中的程式碼都敲一遍,修煉修煉內功。第一篇就從聽出繭子的貝葉斯演算法開始吧。
貝葉斯演算法的一個核心就是貝葉斯準則:
p(c|x)=p(x|c)*p(c)/p(x)
如果想知道在x條件下c發生的概率,上面的公式提供給了我們一個逆向求解的過程,就是如果我們知道了在c條件下發生x的概率(核心),再加上p(c)和p(x),就可以得到我們想要的結果。這也是上面公式的魅力所在。
在書中,作者給的第一個例子是用貝葉斯方法區分某個網路用語是否文明的。程式碼如下:
# coding=utf-8
from numpy import *
def loadDataSet():
postingList=[['my','dog','has','flea','problem','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代表侮辱性文字
return postingList,classVec
#建立當地資料庫,生成一個大池子
def createVocabList(dataSet):
vocabSet=set([])
for document in dataSet:
#取dataset的交集,去除重複的單詞
vocabSet=vocabSet|set(document)
return list(vocabSet)
#將字串轉換成向量物件
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
def trainNBO(trainMatrix,trainCategory):
numTrainDocs=len(trainMatrix)
numWords=len(trainMatrix[0])
pAbusive=sum(trainCategory)/float(numTrainDocs)
p0Num=ones(numWords)#將矩陣的初始值都設為1,防止一個值為0,相乘以後都為0的情況.ones()為numpy的函式
p1Num=ones(numWords)
p0Denom=0.0
p1Denom=0.0
for i in range(numTrainDocs):
if trainCategory[i]==1:
print("p1Num%s"%p1Num)
p1Num+=trainMatrix[i]
print("trainMatrix%s"%trainMatrix[i])
p1Denom+=sum(trainMatrix[i])
print("p1Num%s"%p1Num)
else:
print("p0Num%s"%p0Num)
p0Num+=trainMatrix[i]
print("trainMatrix%s"%trainMatrix[i])
p0Denom+=sum(trainMatrix[i])
print("p0Num%s"%p0Num)
print("p1Num%s"%p1Num);
print("p0Num%s"%p0Num)
#分別計算在侮辱性語言前提下每個單詞出現的概率以及在非侮辱性前提下這個單詞出現的概率(p(x|c1)和p(x|c0))
p1Vect=log(p1Num/p1Denom) #設定用log()是為了許多很小的數相乘使得結果過小而超過語言的識別範圍
p0Vect=log(p0Num/p0Denom) #change to log()
return p0Vect,p1Vect,pAbusive
def classifyNB(vec2classify,p0Vect,p1Vect,pClass1):
p1=sum(vec2classify*p1Vect)+log(pClass1)#相當於log(p(c1)*p(x1/c1)*p(x2/c1))
p0=sum(vec2classify*p0Vect)+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=trainNBO(trainMat,listClasses)
testEntry=['love','my','dalmation']
thisDoc=array(setOfWords2Vec(myVocablist,testEntry))
print ("testEntry,classified as%s"%classifyNB(thisDoc,p0V,p1V,pAb))
testEntry=['stupid','garbage','hello']
thisDoc=array(setOfWords2Vec(myVocablist,testEntry))
print("testEntry,classified as %s"%classifyNB(thisDoc,p0V,p1V,pAb))
if __name__ == '__main__':
testingNB()