貝葉斯算法

1、貝葉斯公式

貝葉斯公式基於條件獨立,經過條件機率公式全機率公式推導而來。python

1.條件獨立

條件獨立的公式以下,其含義是當C發生時,A、B的發生互不干擾。
P(A∩B|C)=P(A|C)∩P(B|C)<=>P(A|B,C)=P(A|C)<=>A,B對於C是條件獨立的正則表達式

2.條件機率公式

P(A|B)=P(AB)/P(B)
變形公式:P(AB)=P(A|B)·P(B)=P(B|A)·P(A)算法

3.全機率公式

若是事件B一、B二、B3…Bn 構成一個完備事件組,即它們兩兩互不相容,其和爲全集;而且P(Bi)大於0,則對任一事件A有
P(A)=P(A|B1)P(B1) + P(A|B2)P(B2) + ... + P(A|Bn)P(Bn)。
或者:p(A)=P(AB1)+P(AB2)+...+P(ABn)(其中A與Bn的關係爲交)app

4.貝葉斯公式

貝葉斯定義用來描述兩個條件機率之間的關係,好比 P(A|B) 和 P(B|A)。下面是貝葉斯公式推導過程,其中①②③都是貝葉斯公式的變形。dom

2、樸素貝葉斯分類

1.概念

貝葉斯分類是一類以貝葉斯定理爲基礎的分類算法的總稱,樸素貝葉斯分類是其中之一,這裏的「樸素」指各個特徵之間是相互獨立、互不影響的。主要應用於:求已知一些特徵函數,求其屬於某一類別的機率。
P(類別|特徵1,特徵2,特徵3...)=P(特徵1,特徵2,特徵3...|類別)·P(類別)/P(特徵1,特徵2,特徵3...)
假設各個特徵相互獨立,則:
P(類別|特徵1,特徵2,特徵3...)=P(特徵1,特徵2,特徵3...|類別)·P(類別)/[P(特徵1)·P(特徵2)·P(特徵3)·...]ide

2.實例

咱們想知道考試前一天逛街、刷視頻、玩遊戲、學習對成績的影響。設:成績優秀爲1,成績差爲0;考試前一天逛街了爲1,沒有爲0;考試前一天刷視頻了爲1,沒有爲0;考試前一天玩遊戲了爲1,沒有爲0;考試前一天學習了爲1,沒有爲0。現有以下樣本庫:函數

成績 逛街 刷視頻 玩遊戲
0 1 1 1
0 1 0 1
1 0 0 0
0 0 0 0
1 0 0 1
0 0 1 1
0 1 0 0
1 1 0 1
0 1 0 1
0 1 0 1

求考試前一天逛街了,玩遊戲了,沒有刷視頻、學習,成績優秀的機率是多少?
P(1|1,0,1,0)
=P(1,1,0,1,0)/[P(逛街=1)·P(刷視頻=0)·P(玩遊戲=1)·P(學習=0)]
=0.1/(0.6 * 0.8 * 0.7 * 0.7)
=0.4252學習

咱們再來算一下成績差的機率爲多少
P(0|1,0,1,0)
=P(0,1,0,1,0)/[P(逛街=1)·P(刷視頻=0)·P(玩遊戲=1)·P(學習=0)]
=0.2/(0.6 * 0.8 * 0.7 * 0.7)
=0.8503測試

經過上面的計算,咱們發現兩個機率之和並不等於1。實際上在樸素貝葉斯分類器中,經過比較兩個機率大小,判斷屬於哪一個類別。因爲分母時同樣的,咱們一般省去分母,只比較分子。spa

3、拉普拉斯平滑

拉普拉斯平滑主要處理零機率問題,就是在計算實例的機率時,若是某個量x,在觀察樣本庫(訓練集)中沒有出現過,會致使整個實例的機率結果是0。在文本分類的問題中,當一個詞語沒有在訓練樣本中出現,該詞語調機率爲0,使用連乘計算文本出現機率時也爲0。這是不合理的,不能由於一個事件沒有觀察到就武斷的認爲該事件的機率是0。

爲了解決零機率的問題,法國數學家拉普拉斯最先提出用加1的方法估計沒有出現過的現象的機率,因此加法平滑也叫作拉普拉斯平滑。假定訓練樣本很大時,每一個份量x的計數加1形成的估計機率變化能夠忽略不計,但能夠方便有效的避免零機率問題。

4、項目實戰

1.

(1)

樸素貝葉斯根據先驗機率(特徵的可能性分佈)有三種模型:高斯貝葉斯、伯努利貝葉斯、多項式貝葉斯。這三個類適用的分類場景各不相同,通常來講,若是樣本特徵的分佈大部分是連續值,使用GaussianNB會比較好。若是樣本特徵的分佈大部分是多元離散值,使用MultinomialNB比較合適。而若是樣本特徵是二元離散值或者很稀疏的多元離散值,應該使用BernoulliNB。

sklearn 庫中的 naive_bayes 模塊實現了 5 種樸素貝葉斯算法:高斯貝葉斯、伯努利貝葉斯、多項式貝葉斯、分類貝葉斯、補充貝葉斯。

後綴NB是樸素貝葉斯(Naive Bayes)的縮寫

Accuray表示測試集的準確率,cv=10表示十折交叉驗證

下面代碼舉了三種樸素貝葉斯分類,若是想看高斯樸素貝葉斯,把前三行代碼高斯樸素貝葉斯取消註釋,另兩個註釋,並將qnb=MultinomialNB()改成qnb=GaussianNB()。

#from sklearn.naive_bayes import GaussianNB#高斯分佈下的樸素貝葉斯分類
#from sklearn.naive_bayes import BernoulliNB#駁伯努利分佈
from sklearn.naive_bayes import MultinomialNB#多項分佈
from sklearn.model_selection import cross_val_score
from sklearn import datasets

iris=datasets.load_iris()
print(iris)
qnb=MultinomialNB()
scores=cross_val_score(qnb,iris.data,iris.target,cv=10,scoring='accuracy')
print('Accuracy:%.3f'%scores.mean())

若沒有安裝sklearn包,在終端輸入pip install sklearn便可。

cd C:\Users\WAFF\AppData\Local\Programs\Python\Python37\Scripts
pip install sklearn

(2)k折交叉驗證

數據集包括訓練集和測試集,咱們通常用準確率Auc,即分類正確的樣本個數佔總樣本的比例,來評價分類器的好壞。

k折交叉驗證,指將數據集分K個部分(K個格子):紅色爲測試集test,橙色爲訓練集train,每次劃分都有一個準確率Auci,取其平均值爲最終的準率率。

2.垃圾郵件分類器

垃圾郵件分類器,功能是將郵件樣本集中垃圾郵件分類出來。以英文郵件爲例,主要步驟爲:

(1)查看數據data:郵件內容

(2)分詞:句子->單詞,以空格爲標識

(3)向量化:單詞->數字->二進制

(4)樸素貝葉斯公式:P(類別|單詞1,單詞2,單詞3,...)=P(單詞i|類別)*P(類別)/P(單詞i)

(5)結果

代碼中解釋很是詳細

#樸素貝葉斯分類器訓練函數
#
def trainNB0(trainMatrix,trainCategory):
	#總文件數
	numTrainDocs=len(trainMatrix)
	#總單詞數
	numWords=len(trainMatrix[0])
	#侮辱性文件出現機率
	pAbusive=sum(trainCategory)/float(numTrainDocs)
	#構造單詞出現次數列表
	#p0Num正確的統計
	#p1Num侮辱的統計
	p0Num=np.ones(numWords)
	p1Num=np.ones(numWords)
	#整個數據集單詞出現的總數,根據樣本/實際調查結果調整分母的值
	global p0Denom
	global p1Denom
    p0Denom=2.0
    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])
    #類別1 即侮辱性文檔的[log(F1/C1),log(F2/C2),log(F3/C3)...]避免0的產生,拉普拉斯平滑的一種方法取log?
    p1Vect=np.log(p1Num/p1Denom)
    #類別0 即正常文檔的[log(F0/C0),log(F0/C0),log(F0/C0)...]
    p0Vect=np.log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive
    
    
#切分文本
def textParse(bigString)
    '''
    Desc:
        接收一個大字符串並將其解析爲字符串列表
    Args:
        bigString--大字符串
        jieba 中文切分,本身查
    Returns:
        去掉少於2個字符的字符串,並將全部字符串轉換爲小寫,返回字符串列表
    '''
    import re
    #使用正則表達式來切分句子,其中分隔符是除單詞、數字外的任意字符串
    list0fTokens=re.split(r'\w*',bigString)
    return [tok.lower() for tok in list0fTokens if len(tok)>2]
    
    
def createVocabList(dataSet)
    '''
    獲取全部單詞的集合
    :param dataSet:數據集
    :return:全部單詞的集合(即不含重複元素的列表)
    '''
    vocabSet=set([])#creat empty set
    for document in dataSet:
        #操做符|用於求兩個集合的並集
        vocabSet=vocabSet|set(document)#union of the two sets
    return list(vocabSet)
    
def setofWords2Ved(vocabList,inputSet)
    '''
    遍歷查看該單詞是否出現,出現該單詞則將該單詞置1
    :param vocabList:全部單詞集合列表
    :return:匹配列表[0,1,0,1...],其中1與0表示詞彙表中的單詞是否出如今輸入的數據集中
    '''
    #建立一個和詞彙表等長的向量,並將其元素都設置爲0
    returnVec=[0]*len(vocabList)#[0,0,0...]
    #遍歷文檔中全部單詞,若是出現了詞彙表中的單詞,則輸出的文檔向量中的對應值設爲1
    for word n inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]=1
        else:
            print ("the word :%s is not in my Vocabulary!" %word)
    return returnVec
    
    
#樸素貝葉斯分類函數
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1=sum(vec2Classify*p1Vec)+np.log(pClass1)
    p2=sum(vec2Classify*p0Vec)+np.log(1.0-pClass1)
    if p1>p0:
        return 1
    else :
    return 0
    
def spamTest():
    '''
    Desc:對貝葉斯垃圾郵件分類器進行自動化處理
    Args:none
    Returns:
    '''
    docList=[]
    classList=[]
    fullText=[]
    for i in range(1,26):#前26個文件
        #切分,解析數據,並歸類爲1類別
        wordList=textParse(open(r'文件路徑/%d.txt'% i,encoding='ISO-8859-1'))
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
        #切分,解析數據,並歸類爲0類別
        wordList=textParse(open(r'文件路徑/%d.txt'% i,encoding='ISO-8859-1'))
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
        #建立詞彙表
        vocabList=createVocabList(docList)
        trainingSet=list(range(50))
        testSet=[]
        #隨機取10個郵件用來測試
        for i in range(10):
            #random.uniform(x,y)隨機生成一個範圍爲x-y的實數
            trandIndex=int(random.uniform(0,len(trainingSet)))
            testSet.append(trainingSet[randIndex])
            del(traningSet[randIndex])
        trainMat=[]
        trainClasses=[]
        for docIndex in trainingSet:
        trainMat.append(setofWords2Ved(vocabList,docList(docIndex)))
        trainClasses.append(classList[docIndex])
        p0v,p1v,pSpam=trainNB0(np.array(trainMat),np.array(trainClasses))
        errorCount=0
        for docIndex in testSet:
            wordVector=setofWords2Ved(vocabList,docList(docIndex))
            if classifyNB(np.array(wordVector),p0v,p1v,pSpam)!=classList[docIndex]:
                errorCount+=1
        print('the errorCount is :',errorCount)
        print('the testSet length is :',len(testSet))
        print('the error rate is :',float(errorCount)/len(testSet))
        
import random
import numpy as np
import math
spamTest()

學習視頻

相關文章
相關標籤/搜索