溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

發(fā)布時間:2021-04-07 09:53:42 來源:億速云 閱讀:193 作者:小新 欄目:開發(fā)技術

小編給大家分享一下python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、模型方法

       本工程采用的模型方法為樸素貝葉斯分類算法,它的核心算法思想基于概率論。我們稱之為“樸素”,是因為整個形式化過程只做最原始、最簡單的假設。樸素貝葉斯是貝葉斯決策理論的一部分,所以講述樸素貝葉斯之前有必要快速了解一下貝葉斯決策理論。假設現(xiàn)在我們有一個數(shù)據(jù)集,它由兩類數(shù)據(jù)組成,數(shù)據(jù)分布如下圖所示。

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

        我們現(xiàn)在用p1(x,y)表示數(shù)據(jù)點(x,y)屬于類別1(圖中用圓點表示的類別)的概率,用p2(x,y)表示數(shù)據(jù)點(x,y)屬于類別2(圖中用三角形表示的類別)的概率,那么對于一個新數(shù)據(jù)點(x,y),可以用下面的規(guī)則來判斷它的類別:

如果 p1(x,y) > p2(x,y),那么類別為1。

如果 p2(x,y) > p1(x,y),那么類別為2。

       也就是說,我們會選擇高概率對應的類別。這就是貝葉斯決策理論的核心思想,即選擇具有最高概率的決策。

在本工程中我們可以使用條件概率來進行分類。其條件概率公式如下:

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

       其中粗體w表示這是一個向量,它是有多個值組成。對于類別i表示分類的個數(shù),在本工程中i=0時,c0表示非垃圾郵件。i=1時,c1表示垃圾郵件。w展開為一個個獨立特征,那么就可以將上述概率寫作p(w0,w1,w2..wN|ci)。這里假設所有詞都互相獨立,該假設也稱作條件獨立性假設,它意味著可以使用p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)來計算上述概率,這就極大地簡化了計算的過程,這也是被稱為樸素貝葉斯的原因。在本工程中wj代表第i個單詞特征,而p(wj|ci)則代表了在垃圾郵件(或非垃圾郵件)中,第j個單詞出現(xiàn)的概率;而p(w|ci)則表示在垃圾郵件(或非垃圾郵件)中的全體向量特征(單詞向量特征)出現(xiàn)的概率;而p(ci| w)則表示在全體向量特征(單詞向量特征)下是垃圾郵件(或非垃圾郵件)的概率。本工程項目主要是計算p(ci|w);p(ci)則表示是垃圾郵件(或非垃圾郵件)的概率。

二、系統(tǒng)設計

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

數(shù)據(jù)的收集及保存

郵件的收集來源于網(wǎng)上,保存在email文件夾中。其中email分兩個子文件,一個為ham文件夾(保存非垃圾郵件),另一個為spam文件夾(保存垃圾郵件)。ham與spam中各保存25各郵件,保存格式為x.txt(x為1到25)。

訓練集和測試集的選取

由于收集的郵件個數(shù)有限,故選取80%的郵件作為訓練集,其方式為隨機選取。剩余20%郵件作為測試集。

特征向量構建

特征向量的構建分為兩種,一個為對訓練集的特征向量構建。一個為測試集的特征向量構建。對于訓練集特征向量只需要分為兩類,因為郵件只分為垃圾郵件和非垃圾郵件。特征向量分為對訓練集中所有垃圾郵件中構成的特征向量(記做w)和訓練集中所有非垃圾郵件構成特征向量(記做w')。對于w的計算實際就是統(tǒng)計所有訓練集中垃圾郵件中的每個單詞的出現(xiàn)情況,出現(xiàn)則次數(shù)加1。其計數(shù)初值為1,按照正常情況應為0,因為用的樸素貝葉斯算法,假設所有詞都互相獨立 ,就有p(w|ci) = p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)。所以當?shù)趇個單詞wi在其特征向量中沒有出現(xiàn),則有p(wi|ci) =0,這就導致了p(w|ci)導致結果的不正確性。所以我們索性將所有單詞默認出現(xiàn)1遍,所以從1開始計數(shù)。對于w'的計算和w的計算方法相同,這里就不在贅述。

對于測試集的特征向量構建就是對每個郵件中單詞出現(xiàn)的次數(shù)進行統(tǒng)計,其單詞表可以來源于50個郵件中的所有單詞。對于每一個郵件中單詞如果出現(xiàn)就加1,其計數(shù)初值為0。每個測試集的郵件都需構建特征向量。其特征向量在python中可用列表表示。

構建貝葉斯分類器

對于分類器的訓練其目的訓練三個參數(shù)為p1Vect(w中每個單詞出現(xiàn)的概率構成的特征向量)、p0Vect(w'中每個單詞出現(xiàn)的概率構成的特征向量)和pAbusive(訓練集中垃圾郵件的概率)。對于p1Vect、p0Vect計算可能會造成下溢出,這 是 由 于 太 多 很 小 的 數(shù) 相 乘 造 成 的 。 當 計 算 乘 積p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)時,由于大部分因子都非常小,所以程序會下溢出或者得到不正確的答案。一種解決辦法是對乘積取自然對數(shù)。在代數(shù)中有l(wèi)n(a*b) = ln(a)+ln(b),于是通過求對數(shù)可以避免下溢出或者浮點數(shù)舍入導致的錯誤。同時,采用自然對數(shù)進行處理不會有任何損失。圖1給出函數(shù)f(x)與ln(f(x))的曲線。檢查這兩條曲線,就會發(fā)現(xiàn)它們在相同區(qū)域內同時增加或者減少,并且在相同點上取到極值。它們的取值雖然不同,但不影響最終結果。

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

所以p1Vect = log(w/p1Denom),p0Vect = log(w'/p0Denom),其中p1Denom、p0Denom分別為垃圾郵件中單詞的總數(shù)和非垃圾郵件中單詞的總數(shù)。而pAbusive 就等于訓練集中垃圾郵件總數(shù)與訓練集中郵件總數(shù)之比。

測試集驗證與評估

對于判斷是否為垃圾郵件,只需對每個郵件判斷p(c0|w)(不是垃圾郵件的概率)與p(c1|w)(是垃圾郵件的概率)。

q如果p(c0|w) > p(c1|w),那么該郵件為非垃圾郵件。

q如果 p(c0|w) < p(c1|w),那么該郵件為垃圾郵件。

       然而p(ci|w)(i=0或1)的計算則依賴于p(w|ci)與p(ci)的計算,p(w)無需計算。所以最終結果依賴于pi = p(w|ci)·p(ci)。由于p(w|ci)很小,可能向下溢出。所以我們取以10為底的對數(shù)得log(pi) = log(p(w|ci))+log(p(ci)),所以可得以下結論:

q如果log(p0) > log(p1),那么該郵件為非垃圾郵件。

q如果log(p0) < log(p1),那么該郵件為垃圾郵件。

其中p(w|ci)為在垃圾郵件(或非垃圾郵件)中的全體向量特征(單詞向量特征)出現(xiàn)的概率,p(ci)為訓練集中垃圾郵件(或非垃圾郵件)的概率。

三、系統(tǒng)演示與實驗結果分析對比

       由訓練集(40個)和測試集(個)的樣本數(shù)目比較小,所以測試的分類結果正確性為90%-100%之間,如下圖所示:

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法

        本工程只是對郵件進行二分類,貝葉斯算法也可以處理多分類問題,如新聞的分類,如分成軍事、體育、科技等等。當然本工程只是對英文的垃圾郵件分類,但也可以對中文的垃圾郵件分類(可用python中的jieba的庫模塊進行對中文分詞)。

四、代碼實現(xiàn)

#coding=UTF-8
import random
from numpy import *
 
#解析英文文本,并返回列表
def textParse(bigString):
 #將單詞以空格劃分
 listOfTokens = bigString.split()
 #去除單詞長度小于2的無用單詞
 return [tok.lower() for tok in listOfTokens if len(tok)>2]
 
#去列表中重復元素,并以列表形式返回
def createVocaList(dataSet):
 vocabSet = set({})
 #去重復元素,取并集
 for document in dataSet:
 vocabSet = vocabSet | set(document)
 return list(vocabSet)
 
#統(tǒng)計每一文檔(或郵件)在單詞表中出現(xiàn)的次數(shù),并以列表形式返回
def setOfWordsToVec(vocabList,inputSet): 
 #創(chuàng)建0向量,其長度為單詞量的總數(shù)
 returnVec = [0]*len(vocabList)
 #統(tǒng)計相應的詞匯出現(xiàn)的數(shù)量
 for word in inputSet:
 if word in vocabList:
  returnVec[vocabList.index(word)] += 1
 return returnVec
 
#樸素貝葉斯分類器訓練函數(shù)
def trainNB0(trainMatrix,trainCategory): 
 #獲取訓練文檔數(shù)
 numTrainDocs = len(trainMatrix)
 #獲取每一行詞匯的數(shù)量
 numWords = len(trainMatrix[0])
 #侮辱性概率(計算p(Ci)),計算垃圾郵件的比率
 pAbusive = sum(trainCategory)/float(numTrainDocs)
 #統(tǒng)計非垃圾郵件中各單詞在詞數(shù)列表中出現(xiàn)的總數(shù)(向量形式)
 p0Num = ones(numWords)
 #統(tǒng)計垃圾郵件中各單詞在詞數(shù)列表中出現(xiàn)的總數(shù)(向量形式)
 p1Num = ones(numWords)
 #統(tǒng)計非垃圾郵件總單詞的總數(shù)(數(shù)值形式)
 p0Denom = 2.0
 #統(tǒng)計垃圾郵件總單詞的總數(shù)(數(shù)值形式)
 p1Denom = 2.0
 for i in range(numTrainDocs):
 #如果是垃圾郵件
 if trainCategory[i] == 1:
  p1Num += trainMatrix[i]
  p1Denom +=sum(trainMatrix[i])
 #如果是非垃圾郵件
 else:
  p0Num += trainMatrix[i]
  p0Denom +=sum(trainMatrix[i])
 #計算每個單詞在垃圾郵件出現(xiàn)的概率(向量形式)
 p1Vect = log(p1Num/p1Denom)
 #計算每個單詞在非垃圾郵件出現(xiàn)的概率(向量形式)
 p0Vect = log(p0Num/p0Denom)  
 return p0Vect,p1Vect,pAbusive
#樸素貝葉斯分類函數(shù)
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
#test
def spamtest():
 #導入并解析文本文件
 docList =[];classList=[];fullText = []
 for i in range(1,26):
 #讀取第i篇垃圾文件,并以列表形式返回
 wordList = textParse(open('email/spam/{0}.txt'.format(i)).read())
 #轉化成二維列表
 docList.append(wordList)
 #一維列表進行追加
 fullText.extend(wordList)
 #標記文檔為垃圾文檔
 classList.append(1)
 #讀取第i篇非垃圾文件,并以列表形式返回
 wordList = textParse(open('email/ham/{0}.txt'.format(i)).read())
 #轉化成二維列表
 docList.append(wordList)
 #一維列表進行追加
 fullText.extend(wordList)
 #標記文檔為非垃圾文檔
 classList.append(0)
 #去除重復的單詞元素
 vocabList = createVocaList(docList)
 #訓練集,選40篇doc
 trainingSet = [x for x in range(50)]
 #測試集,選10篇doc
 testSet = []
 #選出10篇doc作測試集
 for i in range(10):
 randIndex = int(random.uniform(0,len(trainingSet)))
 testSet.append(trainingSet[randIndex])
 del trainingSet[randIndex]
 trainMat = [];trainClasses=[]
 #選出40篇doc作訓練集
 for docIndex in trainingSet:
 trainMat.append(setOfWordsToVec(vocabList, docList[docIndex]))
 trainClasses.append(classList[docIndex])
 p0V,p1V,pSpam = trainNB0(array(trainMat), array(trainClasses))
 #對測試集分類
 errorCount = 0
 for docIndex in testSet:
 wordVector = setOfWordsToVec(vocabList,docList[docIndex])
 if classifyNB(array(wordVector), p0V, p1V, pSpam)!=classList[docIndex]:
  errorCount+=1
 print("錯誤率為:{0}".format(float(errorCount)/len(testSet)))
spamtest()

以上是“python怎么實現(xiàn)基于樸素貝葉斯的垃圾分類算法”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI