郵件分類和過濾-樸素貝葉斯NB經典案例
關於樸素貝葉斯的理論,已在機器學習之樸素貝葉斯分類器中進行了詳細說明,但是沒有經歷coding親自見證效果,還是無法真正掌握。
本篇旨在理論的基礎上靈活運用樸素貝葉斯進行分類。
再來回顧下樸素貝葉斯分類器的思想、演算法流程,順道把用到的Python函式羅列出來。
演算法思想
比如我們想判斷一個郵件是不是垃圾郵件,那麼我們知道的是這個郵件中的詞的分佈,那麼我們還要知道:垃圾郵件中某些詞的出現是多少,就可以利用貝葉斯定理得到。
樸素貝葉斯最常見的分類應用是對文件進行分類,因此,最常見的特徵條件是文件中,出現詞彙的情況,通常將詞彙出現的特徵條件用詞向量 表示,由多個數值組成,數值的個數和訓練樣本集中的詞彙表個數相同。
演算法流程
1.資料準備:(收集資料+處理資料+提取資料特徵)將資料預處理為數值型或者布林型,如對文字分類,需要將文字解析為詞向量 。
2.訓練資料:根據訓練樣本集計算詞項出現的概率,訓練資料後得到各類下詞彙出現概率的向量 。
3. 測試資料:評估對於測試資料集的預測精度作為預測正確率。
4.合併程式碼:使用所有程式碼呈現一個完整的、獨立的樸素貝葉斯演算法的實現。
使用樸素貝葉斯過濾垃圾郵件
資料夾spam和ham中各有25封txt文件形式的郵件正文,兩個資料夾分別分類為1和0,如開啟ham中2.txt檔案,其內容為:
Yay to you both doing fine!
I'm working on an MBA in Design Strategy at CCA (top art school.) It's a new program focusing on more of a right-brained creative and strategic approach to management. I'm an 1/8 of the way done today!
函式
loadDataSet()
建立資料集,這裡的資料集是已經拆分好的單片語成的句子。
createVocabList(dataSet)
找出這些句子中總共有多少單詞,以確定我們詞向量的大小。
setOfWords2Vec(vocabList, inputSet)
將句子根據其中的單詞轉成向量,這裡用的是伯努利模型,即只考慮這個單詞是否存在。
bagOfWords2VecMN(vocabList, inputSet)
這個是將句子轉成向量的另一種模型,多項式模型,考慮某個詞的出現次數。
trainNB0(trainMatrix,trainCatergory)
計算P(i)和P(w[i]|C[1])和P(w[i]|C[0]),這裡有兩個技巧,一個是開始的分子分母沒有全部初始化為0是為了防止其中一個的概率為0導致整體為0,另一個是後面乘用對數防止因為精度問題結果為0
classifyNB(vec2Classify, p0Vec, p1Vec, pClass1)
根據貝葉斯公式計算這個向量屬於兩個集合中哪個的概率高。
利用以上文件,進行樸素貝葉斯分類演算法訓練和測試:
1 對郵件的文字劃分成詞彙,長度小於2的預設為不是詞彙,過濾掉即可。返回一串小寫的拆分後的郵件資訊。
def textParse(bigString): #input is big string, #output is word list
import re
listOfTokens = re.split(r'\W*', bigString) return [tok.lower() for tok in listOfTokens if len(tok) > 2]
2 文件詞袋模型:使用陣列代替集合資料結構,可以儲存詞彙頻率資訊。
def bagOfWords2VecMN(vocabList, inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
3 輸入為25封正常郵件和25封垃圾郵件。50封郵件中隨機選取10封作為測試樣本,剩餘40封作為訓練樣本。
訓練模型:40封訓練樣本,訓練出先驗概率和條件概率;
測試模型:遍歷10個測試樣本,計算垃圾郵件分類的正確率。
def spamTest():
docList=[]; classList = []; fullText =[]
for i in range(1,26):
wordList = textParse(open('email/spam/%d.txt' % i).read())
# print wordList
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
wordList = textParse(open('email/ham/%d.txt' % i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList = createVocabList(docList)#create vocabulary
trainingSet = range(50); testSet=[] #create test set
for i in range(10):
randIndex = int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
trainMat=[]; trainClasses = []
for docIndex in trainingSet:#train the classifier (get probs) trainNB0
trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
errorCount = 0
for docIndex in testSet: #classify the remaining items
wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
errorCount += 1
print "classification error",docList[docIndex]
print 'the error rate is: ',float(errorCount)/len(testSet)
#return vocabList,fullText
近期熱文
... ...
遲做總比不做好;晚來總比不來強。
更多幹貨內容請關注微信公眾號“AI 深入淺出”
長按二維碼關注