日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《机器学习实战》笔记(04):基于概率论的分类方法 - 朴素贝叶斯分类

發布時間:2023/12/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《机器学习实战》笔记(04):基于概率论的分类方法 - 朴素贝叶斯分类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基于概率論的分類方法:樸素貝葉斯分類

Naive Bayesian classification

這大節內容源于帶你理解樸素貝葉斯分類算法,并非源于《機器學習實戰》。個人認為《機器學習實戰》闡述貝葉斯分類算法較簡略難懂,故查閱其他文章來理解這貝氏算法。

貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理為基礎,故統稱為貝葉斯分類。而樸素樸素貝葉斯分類是貝葉斯分類中最簡單,也是常見的一種分類方法。

分類問題綜述

對于分類問題,其實誰都不會陌生,日常生活中我們每天都進行著分類過程。例如,當你看到一個人,你的腦子下意識判斷他是學生還是社會上的人;你可能經常會走在路上對身旁的朋友說“這個人一看就很有錢、”之類的話,其實這就是一種分類操作。

既然是貝葉斯分類算法,那么分類的數學描述又是什么呢?

從數學角度來說,分類問題可做如下定義:

已知集合C=y1,y2,…,yn和I=x1,x2,…x3,確定映射規則y = f(),使得任意xi∈I有且僅有一個yi∈C ,使得yi∈f(xi) 成立。

其中C叫做類別集合,其中每一個元素是一個類別,而I叫做項集合(特征集合),其中每一個元素是一個待分類項,f叫做分類器。分類算法的任務就是構造分類器f

分類算法的內容是要求給定特征,讓我們得出類別,這也是所有分類問題的關鍵。那么如何由指定特征,得到我們最終的類別,也是我們下面要講的,每一個不同的分類算法,對應著不同的核心思想。

樸素貝葉斯分類

那么既然是樸素貝葉斯分類算法,它的核心算法又是什么呢?

是下面這個貝葉斯公式:

換個表達形式就會明朗很多,如下:

我們最終求的p(類別|特征)即可!就相當于完成了我們的任務

例題分析

下面我先給出例子問題。

給定數據如下:

現在給我們的問題是,

如果一對男女朋友,男生想女生求婚,男生的四個特點分別是不帥,性格不好,身高矮,不上進,請你判斷一下女生是嫁還是不嫁?

這是一個典型的分類問題,轉為數學問題就是比較p(嫁|(不帥、性格不好、身高矮、不上進))與p(不嫁|(不帥、性格不好、身高矮、不上進))的概率,誰的概率大,我就能給出嫁或者不嫁的答案

這里我們聯系到樸素貝葉斯公式:

我們需要求p(嫁|(不帥、性格不好、身高矮、不上進),這是我們不知道的,

但是通過樸素貝葉斯公式可以轉化為好求的三個量,p(不帥、性格不好、身高矮、不上進|嫁)、p(不帥、性格不好、身高矮、不上進)、p(嫁)(至于為什么能求,后面會講,那么就太好了,將待求的量轉化為其它可求的值,這就相當于解決了我們的問題!)

樸素貝葉斯算法的樸素一詞解釋

那么這三個量是如何求得?

是根據已知訓練數據統計得來,下面詳細給出該例子的求解過程。

回憶一下我們要求的公式如下:

那么我只要求得p(不帥、性格不好、身高矮、不上進|嫁)、p(不帥、性格不好、身高矮、不上進)、p(嫁)即可,好的,下面我分別求出這幾個概率,最后一比,就得到最終結果。

p(不帥、性格不好、身高矮、不上進|嫁) = p(不帥|嫁)*p(性格不好|嫁)*p(身高矮|嫁)*p(不上進|嫁),那么我就要分別統計后面幾個概率,也就得到了左邊的概率!

等等,為什么這個成立呢?學過概率論的同學可能有感覺了,這個等式成立的條件需要特征之間相互獨立吧!

對的!這也就是為什么樸素貝葉斯分類有樸素一詞的來源,樸素貝葉斯算法是假設各個特征之間相互獨立,那么這個等式就成立了

為什么需要假設特征之間相互獨立呢?

1、我們這么想,假如沒有這個假設,那么我們對右邊這些概率的估計其實是不可做的,這么說,我們這個例子有4個特征,其中帥包括{帥,不帥},性格包括{不好,好,爆好},身高包括{高,矮,中},上進包括{不上進,上進},那么四個特征的聯合概率分布總共是4維空間,總個數為2 * 3 * 3 * 2 = 36個。

36個,計算機掃描統計還可以,但是現實生活中,往往有非常多的特征,每一個特征的取值也是非常之多,那么通過統計來估計后面概率的值,變得幾乎不可做,這也是為什么需要假設特征之間獨立的原因。

2、假如我們沒有假設特征之間相互獨立,那么我們統計的時候,就需要在整個特征空間中去找,比如統計p(不帥、性格不好、身高矮、不上進|嫁),

我們就需要在嫁的條件下,去找四種特征全滿足分別是不帥,性格不好,身高矮,不上進的人的個數,這樣的話,由于數據的稀疏性,很容易統計到0的情況。 這樣是不合適的。

根據上面倆個原因,樸素貝葉斯法對條件概率分布做了條件獨立性的假設,由于這是一個較強的假設,樸素貝葉斯也由此得名!這一假設使得樸素貝葉斯法變得簡單,但有時會犧牲一定的分類準確率。

好的,上面我解釋了為什么可以拆成分開連乘形式。那么下面我們就開始求解!

開始求解

將上面公式整理一下如下:

下面我將一個一個的進行統計計算(在數據量很大的時候,根據中心極限定理,頻率是等于概率的,這里只是一個例子,所以我就進行統計即可)。

p(嫁)=?

首先我們整理訓練數據中,嫁的樣本數如下:

則 p(嫁) = 6/12(總樣本數) = 1/2
p(不帥|嫁)=?

則p(不帥|嫁) = 3/6 = 1/2
p(性格不好|嫁)= ?

則p(性格不好|嫁)= 1/6
p(矮|嫁) = ?

則p(矮|嫁) = 1/6
p(不上進|嫁) = ?

則p(不上進|嫁) = 1/6

下面開始求分母,p(不帥),p(性格不好),p(矮),p(不上進)


p(不帥) = 4/12 = 1/3 p(性格不好) = 4/12 = 1/3 p(身高矮) = 7/12 p(不上進) = 4/12 = 1/3

到這里,要求p(不帥、性格不好、身高矮、不上進|嫁)的所需項全部求出來了,下面我帶入進去即可,

= (1/2 * 1/6 * 1/6 * 1/6 * 1/2) / (1/3 * 1/3* 7/12 * 1/3)

同理可得:

= ((1/6 * 1/2 * 1* 1/2) * 1/2) / (1/3 * 1/3 * 7/12 * 1/3)

結論

很顯然 ((1/6 * 1/2 * 1* 1/2) * 1/2) > (1/2 * 1/6 * 1/6 * 1/6 * 1/2)

于是有p(不嫁|不帥、性格不好、身高矮、不上進) > p(嫁|不帥、性格不好、身高矮、不上進)

所以我們根據樸素貝葉斯算法可以給這個女生答案,是不嫁!!!!

其實不用計算分母p(不帥),p(性格不好),p(矮),p(不上進), 在比較的過程當中會約去的。

樸素貝葉斯分類的優缺點

優點:

  • 算法邏輯簡單,易于實現
  • 分類過程中時空開銷小

缺點:

理論上,樸素貝葉斯模型與其他分類方法相比具有最小的誤差率。但是實際上并非總是如此,這是因為樸素貝葉斯模型假設屬性之間相互獨立,這個假設在實際應用中往往是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果不好。

而在屬性相關性較小時,樸素貝葉斯性能最為良好。對于這一點,有半樸素貝葉斯之類的算法通過考慮部分關聯性適度改進。

《機器學習實戰》樸素貝葉斯的筆記

應用:屏蔽侮辱性言語

準備數據

loadData.py

from numpy import *#準備數據集 def loadDataSet():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] #1 is abusive, 0 notreturn postingList,classVec#把所有單詞混合到一個集合里 def createVocabList(dataSet):vocabSet = set([]) #create empty setfor document in dataSet:vocabSet = vocabSet | set(document) #union of the two setsreturn list(vocabSet)#vocablist副本標記inputSet出現過的 def setOfWords2Vec(vocabList, inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else: print "the word: %s is not in my Vocabulary!" % wordreturn returnVec#------------------------運行上述函數-------------------------------listOfPosts, listClasses = loadDataSet() #print listOfPosts #print listClasses"""[['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']]"""#[0, 1, 0, 1, 0, 1]myVocabList = createVocabList(listOfPosts) #print myVocabList """['cute', 'love', 'help', 'garbage', 'quit', 'I', 'problems', 'is', 'park', 'stop', 'flea', 'dalmation', 'licks', 'food', 'not', 'him', 'buying', 'posting', 'has', 'worthless', 'ate', 'to', 'maybe', 'please', 'dog', 'how', 'stupid', 'so', 'take', 'mr', 'steak', 'my']"""#print listOfPosts[0] #['my', 'dog', 'has', 'flea', 'problems', 'help', 'please']#print setOfWords2Vec(myVocabList, listOfPosts[0]) """[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1]"""

訓練算法

偽代碼:

計算每個類別中的文檔樹對每篇訓練文檔:對每個類別:如果詞條出現在文檔中->增加該詞條的計數值增加所有詞條的計數值對每個類別:對每個詞條:將該詞條的數目除以總詞條數目得到條件概率 返回每個類別的條件概率

trainer.py

from numpy import * from loadData import *#訓練算法 def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix)numWords = len(trainMatrix[0])#侮辱出現的概率pAbusive = sum(trainCategory) / float(numTrainDocs)p0Num = zeros(numWords); p1Num = zeros(numWords)p0Denom = 0.0; p1Denom = 0.0 #change to 2.0for i in range(numTrainDocs):if trainCategory[i] == 1:p1Num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])"""['cute', 'love', 'help', 'garbage', 'quit', 'I', 'problems','is', 'park', 'stop', 'flea', 'dalmation', 'licks', 'food','not', 'him', 'buying', 'posting', 'has', 'worthless', 'ate', 'to', 'maybe', 'please', 'dog', 'how', 'stupid', 'so', 'take', 'mr', 'steak', 'my'][1. 1. 1. 0. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 0. 2. 0. 0. 1. 0. 1. 1. 0. 1.1. 1. 0. 1. 0. 1. 1. 3.][0. 0. 0. 1. 1. 0. 0. 0. 1. 1. 0. 0. 0. 1. 1. 1. 1. 1. 0. 2. 0. 1. 1. 0.2. 0. 3. 0. 1. 0. 0. 0.]"""p1Vect = p1Num/p1Denom #change to log()p0Vect = p0Num/p0Denom #change to log()return p0Vect, p1Vect, pAbusive#--------------------------------------------------------------------------- listOfPosts, listClasses = loadDataSet()myVocabList = createVocabList(listOfPosts) print myVocabListtrainMat = [] for post in listOfPosts:trainMat.append(setOfWords2Vec(myVocabList, post))# print trainMat """[[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]"""p0V, p1V, pAb = trainNB0(trainMat, listClasses)print p0V print p1V print pAb""" [0.04166667 0.04166667 0.04166667 0. 0. 0.041666670.04166667 0.04166667 0. 0.04166667 0.04166667 0.041666670.04166667 0. 0. 0.08333333 0. 0.0.04166667 0. 0.04166667 0.04166667 0. 0.041666670.04166667 0.04166667 0. 0.04166667 0. 0.041666670.04166667 0.125 ] [0. 0. 0. 0.05263158 0.05263158 0.0. 0. 0.05263158 0.05263158 0. 0.0. 0.05263158 0.05263158 0.05263158 0.05263158 0.052631580. 0.10526316 0. 0.05263158 0.05263158 0.0.10526316 0. 0.15789474 0. 0.05263158 0.0. 0. ] 0.5 """

根據實際情況修改分類器

問題1:計算多個概率P(w0|1)P(w1|1)P(w2|1),若其中概率為0,最后乘積也為0

解決:可以將所有詞出現的數初始化為1,分母初始化為2


問題2:由于太多很小的數相乘,造成下溢出(四舍五入到0)

解決:對乘積取自然對數


修改后的訓練器trainer.py

def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix)numWords = len(trainMatrix[0])pAbusive = sum(trainCategory)/float(numTrainDocs)#分子p0Num = ones(numWords); p1Num = ones(numWords) #change to ones() #分母p0Denom = 2.0; p1Denom = 2.0 #change to 2.0for i in range(numTrainDocs):if trainCategory[i] == 1:p1Num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])#取自然對數p1Vect = log(p1Num/p1Denom) #change to log()p0Vect = log(p0Num/p0Denom) #change to log()return p0Vect,p1Vect,pAbusive## 測試算法 ##def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):#print vec2Classify# [0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]#print p0Vec"""[-2.56494936 -2.56494936 -2.56494936 -3.25809654 -3.25809654 -2.56494936-2.56494936 -2.56494936 -3.25809654 -2.56494936 -2.56494936 -2.56494936-2.56494936 -3.25809654 -3.25809654 -2.15948425 -3.25809654 -3.25809654-2.56494936 -3.25809654 -2.56494936 -2.56494936 -3.25809654 -2.56494936-2.56494936 -2.56494936 -3.25809654 -2.56494936 -3.25809654 -2.56494936-2.56494936 -1.87180218]"""#print p1Vec"""[-3.04452244 -3.04452244 -3.04452244 -2.35137526 -2.35137526 -3.04452244-3.04452244 -3.04452244 -2.35137526 -2.35137526 -3.04452244 -3.04452244-3.04452244 -2.35137526 -2.35137526 -2.35137526 -2.35137526 -2.35137526-3.04452244 -1.94591015 -3.04452244 -2.35137526 -2.35137526 -3.04452244-1.94591015 -3.04452244 -1.65822808 -3.04452244 -2.35137526 -3.04452244-3.04452244 -3.04452244]""" #print vec2Classify * p1Vec"""[-0. -3.04452244 -0. -0. -0. -0.-0. -0. -0. -0. -0. -3.04452244-0. -0. -0. -0. -0. -0.-0. -0. -0. -0. -0. -0.-0. -0. -0. -0. -0. -0.-0. -3.04452244]"""#print sum(vec2Classify * p1Vec)# -9.13356731317#前面取自然對數In(a * b) = In a + In bp1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise multp0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)if p1 > p0:return 1else: return 0def testingNB():listOPosts,listClasses = loadDataSet()myVocabList = createVocabList(listOPosts)trainMat=[]for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))"""print array(trainMat)[[0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1][0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 0 0][1 1 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1][0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0][0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 1][0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0]]"""testEntry = ['love', 'my', 'dalmation']thisDoc = array(setOfWords2Vec(myVocabList, testEntry))print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)"""testEntry = ['stupid', 'garbage']thisDoc = array(setOfWords2Vec(myVocabList, testEntry))print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)""" #-------------------運行結果----------------------- testingNB() #['love', 'my', 'dalmation'] classified as: 0 #['stupid', 'garbage'] classified as: 1

詞集模型 與 詞袋模型

詞集模型 set-of-words model:將每個詞的出現與否作為一個特征

bayes.py

def setOfWords2Vec(vocabList, inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else: print "the word: %s is not in my Vocabulary!" % wordreturn returnVec

詞袋模型 bag-of-words model:如果一個詞在文檔中出現不止一次,這可能意味著包含該詞是否出現在文檔中所不能表述的某種信息

def bagOfWords2VecMN(vocabList, inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1return returnVec

在詞袋中,每個單詞可以出現多次,而在詞集中,每個詞只能出現一次。

使用樸素貝葉斯過濾垃圾郵件

bayes.py

#預處理數據文件 def textParse(bigString): #input is big string, #output is word listimport relistOfTokens = re.split(r'\W*', bigString)return [tok.lower() for tok in listOfTokens if len(tok) > 2] def spamTest():docList=[]; classList = []; fullText =[]for i in range(1,26):wordList = textParse(open('email/spam/%d.txt' % i).read())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)#create test setvocabList = createVocabList(docList)#create vocabularytrainingSet = range(50); testSet=[] for i in range(10):randIndex = int(random.uniform(0,len(trainingSet)))testSet.append(trainingSet[randIndex])del(trainingSet[randIndex]) #train the classifier (get probs) trainNB0trainMat=[]; trainClasses = []for docIndex in trainingSet:#train the classifier (get probs) trainNB0trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))trainClasses.append(classList[docIndex])p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))#begin the testerrorCount = 0for docIndex in testSet: #classify the remaining itemswordVector = bagOfWords2VecMN(vocabList, docList[docIndex])if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:errorCount += 1print "classification error",docList[docIndex]print 'the error rate is: ',float(errorCount)/len(testSet)#return vocabList,fullText#---------------------------------------------spamTest()# classification error ['benoit', 'mandelbrot', '1924', '2010', 'benoit', 'mandelbrot', '1924', '2010', 'wilmott', 'team', 'benoit', 'mandelbrot', 'the', 'mathematician', 'the', 'father', 'fractal', 'mathematics', 'and', 'advocate', 'more', 'sophisticated', 'modelling', 'quantitative', 'finance', 'died', '14th', 'october', '2010', 'aged', 'wilmott', 'magazine', 'has', 'often', 'featured', 'mandelbrot', 'his', 'ideas', 'and', 'the', 'work', 'others', 'inspired', 'his', 'fundamental', 'insights', 'you', 'must', 'logged', 'view', 'these', 'articles', 'from', 'past', 'issues', 'wilmott', 'magazine'] # the error rate is: 0.1 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的《机器学习实战》笔记(04):基于概率论的分类方法 - 朴素贝叶斯分类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。