04机器学习实战之朴素贝叶斯
樸素貝葉斯 概述
貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理為基礎(chǔ),故統(tǒng)稱為貝葉斯分類。本章首先介紹貝葉斯分類算法的基礎(chǔ)——貝葉斯定理。最后,我們通過(guò)實(shí)例來(lái)討論貝葉斯分類的中最簡(jiǎn)單的一種: 樸素貝葉斯分類。
貝葉斯理論 & 條件概率
貝葉斯理論
我們現(xiàn)在有一個(gè)數(shù)據(jù)集,它由兩類數(shù)據(jù)組成,數(shù)據(jù)分布如下圖所示:
我們現(xiàn)在用 p1(x,y) 表示數(shù)據(jù)點(diǎn) (x,y) 屬于類別 1(圖中用圓點(diǎn)表示的類別)的概率,用 p2(x,y) 表示數(shù)據(jù)點(diǎn) (x,y) 屬于類別 2(圖中三角形表示的類別)的概率,那么對(duì)于一個(gè)新數(shù)據(jù)點(diǎn) (x,y),可以用下面的規(guī)則來(lái)判斷它的類別:
- 如果 p1(x,y) > p2(x,y) ,那么類別為1
- 如果 p2(x,y) > p1(x,y) ,那么類別為2
也就是說(shuō),我們會(huì)選擇高概率對(duì)應(yīng)的類別。這就是貝葉斯決策理論的核心思想,即選擇具有最高概率的決策。
使用條件概率來(lái)分類
上面我們提到貝葉斯決策理論要求計(jì)算兩個(gè)概率 p1(x, y) 和 p2(x, y):
- 如果 p1(x, y) > p2(x, y), 那么屬于類別 1;
- 如果 p2(x, y) > p1(X, y), 那么屬于類別 2.
這并不是貝葉斯決策理論的所有內(nèi)容。使用 p1() 和 p2() 只是為了盡可能簡(jiǎn)化描述,而真正需要計(jì)算和比較的是 p(c1|x, y) 和 p(c2|x, y) .這些符號(hào)所代表的具體意義是: 給定某個(gè)由 x、y 表示的數(shù)據(jù)點(diǎn),那么該數(shù)據(jù)點(diǎn)來(lái)自類別 c1 的概率是多少?數(shù)據(jù)點(diǎn)來(lái)自類別 c2 的概率又是多少?注意這些概率與概率 p(x, y|c1) 并不一樣,不過(guò)可以使用貝葉斯準(zhǔn)則來(lái)交換概率中條件與結(jié)果。具體地,應(yīng)用貝葉斯準(zhǔn)則得到:
使用上面這些定義,可以定義貝葉斯分類準(zhǔn)則為:
- 如果 P(c1|x, y) > P(c2|x, y), 那么屬于類別 c1;
- 如果 P(c2|x, y) > P(c1|x, y), 那么屬于類別 c2.
在文檔分類中,整個(gè)文檔(如一封電子郵件)是實(shí)例,而電子郵件中的某些元素則構(gòu)成特征。我們可以觀察文檔中出現(xiàn)的詞,并把每個(gè)詞作為一個(gè)特征,而每個(gè)詞的出現(xiàn)或者不出現(xiàn)作為該特征的值,這樣得到的特征數(shù)目就會(huì)跟詞匯表中的詞的數(shù)目一樣多。
我們假設(shè)特征之間?相互獨(dú)立?。所謂?獨(dú)立(independence)?指的是統(tǒng)計(jì)意義上的獨(dú)立,即一個(gè)特征或者單詞出現(xiàn)的可能性與它和其他單詞相鄰沒(méi)有關(guān)系,比如說(shuō),“我們”中的“我”和“們”出現(xiàn)的概率與這兩個(gè)字相鄰沒(méi)有任何關(guān)系。這個(gè)假設(shè)正是樸素貝葉斯分類器中 樸素(naive) 一詞的含義。樸素貝葉斯分類器中的另一個(gè)假設(shè)是,每個(gè)特征同等重要。
Note:?樸素貝葉斯分類器通常有兩種實(shí)現(xiàn)方式: 一種基于伯努利模型實(shí)現(xiàn),一種基于多項(xiàng)式模型實(shí)現(xiàn)。這里采用前一種實(shí)現(xiàn)方式。該實(shí)現(xiàn)方式中并不考慮詞在文檔中出現(xiàn)的次數(shù),只考慮出不出現(xiàn),因此在這個(gè)意義上相當(dāng)于假設(shè)詞是等權(quán)重的。
樸素貝葉斯 場(chǎng)景
機(jī)器學(xué)習(xí)的一個(gè)重要應(yīng)用就是文檔的自動(dòng)分類。
在文檔分類中,整個(gè)文檔(如一封電子郵件)是實(shí)例,而電子郵件中的某些元素則構(gòu)成特征。我們可以觀察文檔中出現(xiàn)的詞,并把每個(gè)詞作為一個(gè)特征,而每個(gè)詞的出現(xiàn)或者不出現(xiàn)作為該特征的值,這樣得到的特征數(shù)目就會(huì)跟詞匯表中的詞的數(shù)目一樣多。
樸素貝葉斯是上面介紹的貝葉斯分類器的一個(gè)擴(kuò)展,是用于文檔分類的常用算法。下面我們會(huì)進(jìn)行一些樸素貝葉斯分類的實(shí)踐項(xiàng)目。
樸素貝葉斯 原理
樸素貝葉斯 工作原理
提取所有文檔中的詞條并進(jìn)行去重 獲取文檔的所有類別 計(jì)算每個(gè)類別中的文檔數(shù)目 對(duì)每篇訓(xùn)練文檔: 對(duì)每個(gè)類別: 如果詞條出現(xiàn)在文檔中-->增加該詞條的計(jì)數(shù)值(for循環(huán)或者矩陣相加)增加所有詞條的計(jì)數(shù)值(此類別下詞條總數(shù)) 對(duì)每個(gè)類別: 對(duì)每個(gè)詞條: 將該詞條的數(shù)目除以總詞條數(shù)目得到的條件概率(P(詞條|類別)) 返回該文檔屬于每個(gè)類別的條件概率(P(類別|文檔的所有詞條))樸素貝葉斯 開(kāi)發(fā)流程
收集數(shù)據(jù): 可以使用任何方法。 準(zhǔn)備數(shù)據(jù): 需要數(shù)值型或者布爾型數(shù)據(jù)。 分析數(shù)據(jù): 有大量特征時(shí),繪制特征作用不大,此時(shí)使用直方圖效果更好。 訓(xùn)練算法: 計(jì)算不同的獨(dú)立特征的條件概率。 測(cè)試算法: 計(jì)算錯(cuò)誤率。 使用算法: 一個(gè)常見(jiàn)的樸素貝葉斯應(yīng)用是文檔分類。可以在任意的分類場(chǎng)景中使用樸素貝葉斯分類器,不一定非要是文本。樸素貝葉斯 算法特點(diǎn)
優(yōu)點(diǎn): 在數(shù)據(jù)較少的情況下仍然有效,可以處理多類別問(wèn)題。 缺點(diǎn): 對(duì)于輸入數(shù)據(jù)的準(zhǔn)備方式較為敏感。 適用數(shù)據(jù)類型: 標(biāo)稱型數(shù)據(jù)。相關(guān)閱讀:https://blog.csdn.net/u012162613/article/details/48323777
樸素貝葉斯 項(xiàng)目案例
項(xiàng)目案例1: 屏蔽社區(qū)留言板的侮辱性言論
項(xiàng)目概述
構(gòu)建一個(gè)快速過(guò)濾器來(lái)屏蔽在線社區(qū)留言板上的侮辱性言論。如果某條留言使用了負(fù)面或者侮辱性的語(yǔ)言,那么就將該留言標(biāo)識(shí)為內(nèi)容不當(dāng)。對(duì)此問(wèn)題建立兩個(gè)類別: 侮辱類和非侮辱類,使用 1 和 0 分別表示。
開(kāi)發(fā)流程
收集數(shù)據(jù): 可以使用任何方法 準(zhǔn)備數(shù)據(jù): 從文本中構(gòu)建詞向量 分析數(shù)據(jù): 檢查詞條確保解析的正確性 訓(xùn)練算法: 從詞向量計(jì)算概率 測(cè)試算法: 根據(jù)現(xiàn)實(shí)情況修改分類器 使用算法: 對(duì)社區(qū)留言板言論進(jìn)行分類收集數(shù)據(jù): 可以使用任何方法
本例是我們自己構(gòu)造的詞表:
posting_list = [['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', 'gar e'],['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']] class_vec = [0, 1, 0, 1, 0, 1] # 1 is 侮辱性的文字, 0 is not準(zhǔn)備數(shù)據(jù): 從文本中構(gòu)建詞向量:
def create_vocab_list(data_set):"""獲取所有單詞的集合:param data_set: 數(shù)據(jù)集:return: 所有單詞的集合(即不含重復(fù)元素的單詞列表)"""vocab_set = set() # create empty setfor item in data_set:# | 求兩個(gè)集合的并集,# set()返回一個(gè)不重復(fù)的單詞列表,將該列表加入到# vocab集合中vocab_set = vocab_set | set(item) return list(vocab_set) def set_of_words2vec(vocab_list, input_set):"""遍歷查看該單詞是否出現(xiàn),出現(xiàn)該單詞則將該單詞置1:param vocab_list: 所有單詞集合列表:param input_set: 輸入一條數(shù)據(jù)集,如:posting_list[0]:return: 匹配列表[0,1,0,1...],其中 1與0 表示詞匯表中的單詞是否出現(xiàn)在輸入的數(shù)據(jù)集中"""# 創(chuàng)建一個(gè)和詞匯表等長(zhǎng)的向量,并將其元素都設(shè)置為0result = [0] * len(vocab_list)# 遍歷文檔中的所有單詞,如果出現(xiàn)了詞匯表中的單詞,則將輸出的文檔向量中的對(duì)應(yīng)值設(shè)為1for word in input_set:if word in vocab_list:result[vocab_list.index(word)] = 1else:# 這個(gè)后面應(yīng)該注釋掉,因?yàn)閷?duì)你沒(méi)什么用,這只是為了輔助調(diào)試的# print('the word: {} is not in my vocabulary'.format(word))passreturn result訓(xùn)練算法: 從詞向量計(jì)算概率
現(xiàn)在已經(jīng)知道了一個(gè)詞是否出現(xiàn)在一篇文檔中,也知道該文檔所屬的類別。接下來(lái)我們重寫(xiě)貝葉斯準(zhǔn)則,將之前的 x, y 替換為?w. 粗體的?w?表示這是一個(gè)向量,即它由多個(gè)值組成。在這個(gè)例子中,數(shù)值個(gè)數(shù)與詞匯表中的詞個(gè)數(shù)相同。
我們使用上述公式,對(duì)每個(gè)類計(jì)算該值,然后比較這兩個(gè)概率值的大小。
問(wèn): 上述代碼實(shí)現(xiàn)中,為什么沒(méi)有計(jì)算P(w)?
答:根據(jù)上述公式可知,我們右邊的式子等同于左邊的式子,由于對(duì)于每個(gè)ci,P(w)是固定的。并且我們只需要比較左邊式子值的大小來(lái)決策分類,那么我們就可以簡(jiǎn)化為通過(guò)比較右邊分子值得大小來(lái)做決策分類。
首先可以通過(guò)類別 i (侮辱性留言或者非侮辱性留言)中的文檔數(shù)除以總的文檔數(shù)來(lái)計(jì)算概率 p(ci) 。接下來(lái)計(jì)算 p(w?| ci) ,這里就要用到樸素貝葉斯假設(shè)。如果將 w 展開(kāi)為一個(gè)個(gè)獨(dú)立特征,那么就可以將上述概率寫(xiě)作 p(w0, w1, w2...wn | ci) 。這里假設(shè)所有詞都互相獨(dú)立,該假設(shè)也稱作條件獨(dú)立性假設(shè)(例如 A 和 B 兩個(gè)人拋骰子,概率是互不影響的,也就是相互獨(dú)立的,A 拋 2點(diǎn)的同時(shí) B 拋 3 點(diǎn)的概率就是 1/6 * 1/6),它意味著可以使用 p(w0 | ci)p(w1 | ci)p(w2 | ci)...p(wn | ci) 來(lái)計(jì)算上述概率,這樣就極大地簡(jiǎn)化了計(jì)算的過(guò)程。
樸素貝葉斯分類器訓(xùn)練函數(shù)
import numpy as npdef train_naive_bayes(train_mat, train_category):"""樸素貝葉斯分類修正版, 注意和原來(lái)的對(duì)比,為什么這么做可以查看書(shū):param train_mat: type is ndarray總的輸入文本,大致是 [[0,1,0,1], [], []]:param train_category: 文件對(duì)應(yīng)的類別分類, [0, 1, 0],列表的長(zhǎng)度應(yīng)該等于上面那個(gè)輸入文本的長(zhǎng)度:return: 兩個(gè)條件概率向量,一個(gè)概率"""train_doc_num = len(train_mat)words_num = len(train_mat[0])# 因?yàn)槲耆栊缘谋粯?biāo)記為了1, 所以只要把他們相加就可以得到侮辱性的有多少# 侮辱性文件的出現(xiàn)概率,即train_category中所有的1的個(gè)數(shù),# 代表的就是多少個(gè)侮辱性文件,與文件的總數(shù)相除就得到了侮辱性文件的出現(xiàn)概率pos_abusive = np.sum(train_category) / train_doc_num# 單詞出現(xiàn)的次數(shù)# 原版,變成ones是修改版,這是為了防止數(shù)字過(guò)小溢出# p0num = np.zeros(words_num)# p1num = np.zeros(words_num)p0num = np.ones(words_num)p1num = np.ones(words_num)# 整個(gè)數(shù)據(jù)集單詞出現(xiàn)的次數(shù)(原來(lái)是0,后面改成2了)p0num_all = 2.0p1num_all = 2.0for i in range(train_doc_num):# 遍歷所有的文件,如果是侮辱性文件,就計(jì)算此侮辱性文件中出現(xiàn)的侮辱性單詞的個(gè)數(shù)if train_category[i] == 1:p1num += train_mat[i] # 直接把兩個(gè)list相加,對(duì)應(yīng)位置元素相加,# 最后直接一除就可以得到對(duì)應(yīng)的概率listp1num_all += np.sum(train_mat[i]) # 標(biāo)簽為1的總詞數(shù)else:p0num += train_mat[i]p0num_all += np.sum(train_mat[i]) # 標(biāo)簽為0的總詞數(shù)# 后面改成取 log 函數(shù)p1vec = np.log(p1num / p1num_all)p0vec = np.log(p0num / p0num_all)return p0vec, p1vec, pos_abusive測(cè)試算法: 根據(jù)現(xiàn)實(shí)情況修改分類器
在利用貝葉斯分類器對(duì)文檔進(jìn)行分類時(shí),要計(jì)算多個(gè)概率的乘積以獲得文檔屬于某個(gè)類別的概率,即計(jì)算 p(w0|1) * p(w1|1) * p(w2|1)。如果其中一個(gè)概率值為 0,那么最后的乘積也為 0。為降低這種影響,可以將所有詞的出現(xiàn)數(shù)初始化為 1,并將分母初始化為 2 (取1 或 2 的目的主要是為了保證分子和分母不為0,大家可以根據(jù)業(yè)務(wù)需求進(jìn)行更改)。
另一個(gè)遇到的問(wèn)題是下溢出,這是由于太多很小的數(shù)相乘造成的。當(dāng)計(jì)算乘積 p(w0|ci) * p(w1|ci) * p(w2|ci)... p(wn|ci) 時(shí),由于大部分因子都非常小,所以程序會(huì)下溢出或者得到不正確的答案。(用 Python 嘗試相乘許多很小的數(shù),最后四舍五入后會(huì)得到 0)。一種解決辦法是對(duì)乘積取自然對(duì)數(shù)。在代數(shù)中有 ln(a * b) = ln(a) + ln(b), 于是通過(guò)求對(duì)數(shù)可以避免下溢出或者浮點(diǎn)數(shù)舍入導(dǎo)致的錯(cuò)誤。同時(shí),采用自然對(duì)數(shù)進(jìn)行處理不會(huì)有任何損失。
下圖給出了函數(shù) f(x) 與 ln(f(x)) 的曲線。可以看出,它們?cè)谙嗤瑓^(qū)域內(nèi)同時(shí)增加或者減少,并且在相同點(diǎn)上取到極值。它們的取值雖然不同,但不影響最終結(jié)果。
使用算法: 對(duì)社區(qū)留言板言論進(jìn)行分類
樸素貝葉斯分類函數(shù)
def classify_naive_bayes(vec2classify, p0vec, p1vec, p_class1):"""使用算法:# 將乘法轉(zhuǎn)換為加法乘法:P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn)加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)):param vec2classify: 待測(cè)數(shù)據(jù)[0,1,1,1,1...],即要分類的向量:param p0vec: 類別0,即正常文檔的[log(P(F1|C0)),log(P(F2|C0)),log(P(F3|C0)),log(P(F4|C0)),log(P(F5|C0))....]列表:param p1vec: 類別1,即侮辱性文檔的[log(P(F1|C1)),log(P(F2|C1)),log(P(F3|C1)),log(P(F4|C1)),log(P(F5|C1))....]列表:param p_class1: 類別1,侮辱性文件的出現(xiàn)概率:return: 類別1 or 0"""# 計(jì)算公式 log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C))# 使用 NumPy 數(shù)組來(lái)計(jì)算兩個(gè)向量相乘的結(jié)果,這里的相乘是指對(duì)應(yīng)元素相乘,即先將兩個(gè)向量中的第一個(gè)元素相乘,然后將第2個(gè)元素相乘,以此類推。# 我的理解是:這里的 vec2Classify * p1Vec 的意思就是將每個(gè)詞與其對(duì)應(yīng)的概率相關(guān)聯(lián)起來(lái)# 可以理解為 1.單詞在詞匯表中的條件下,文件是good 類別的概率 也可以理解為 2.在整個(gè)空間下,文件既在詞匯表中又是good類別的概率p1 = np.sum(vec2classify * p1vec) + np.log(p_class1)p0 = np.sum(vec2classify * p0vec) + np.log(1 - p_class1)if p1 > p0:return 1else:return 0測(cè)試
def testing_naive_bayes(list_post, list_classes):"""測(cè)試樸素貝葉斯算法:return: no return """# 1. 創(chuàng)建單詞集合vocab_list = create_vocab_list(list_post)# 2. 計(jì)算單詞是否出現(xiàn)并創(chuàng)建數(shù)據(jù)矩陣train_mat = []for post_in in list_post:train_mat.append(# 返回m*len(vocab_list)的矩陣, 記錄的都是0,1信息# 其實(shí)就是那個(gè)東西的句子向量(就是data_set里面每一行,也不算句子吧) set_of_words2vec(vocab_list, post_in))# 3. 訓(xùn)練數(shù)據(jù)p0v, p1v, p_abusive = train_naive_bayes(np.array(train_mat), np.array(list_classes))# 4. 測(cè)試數(shù)據(jù)test_one = ['love', 'my', 'dalmation']test_one_doc = np.array(set_of_words2vec(vocab_list, test_one))print('the result is: {}'.format(classify_naive_bayes(test_one_doc, p0v, p1v, p_abusive)))test_two = ['stupid', 'garbage']test_two_doc = np.array(set_of_words2vec(vocab_list, test_two))print('the result is: {}'.format(classify_naive_bayes(test_two_doc, p0v, p1v, p_abusive)))?
完整代碼:
In?[19]: posting_list = [['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']] class_vec = [0, 1, 0, 1, 0, 1] # 1 is 侮辱性的文字, 0 is not In?[20]: def create_vocab_list(data_set):""" 獲取所有單詞的集合 :param data_set: 數(shù)據(jù)集 :return: 所有單詞的集合(即不含重復(fù)元素的單詞列表) """vocab_set = set() # create empty setfor item in data_set:# | 求兩個(gè)集合的并集,# set()返回一個(gè)不重復(fù)的單詞列表,將該列表加入到# vocab集合中vocab_set = vocab_set | set(item) return list(vocab_set) In?[21]: vocab_list = create_vocab_list(posting_list) vocab_list Out[21]: ['him','dog','take','cute','ate','love','quit','not','worthless','so','garbage','flea','stop','maybe','licks','how','food','dalmation','has','I','park','posting','help','please','to','problems','stupid','steak','buying','mr','my','is'] In?[22]: def set_of_words2vec(vocab_list, input_set):""" 遍歷查看該單詞是否出現(xiàn),出現(xiàn)該單詞則將該單詞置1 :param vocab_list: 所有單詞集合列表 :param input_set: 輸入一條數(shù)據(jù)集,如:posting_list[0] :return: 匹配列表[0,1,0,1...],其中 1與0 表示詞匯表中的單詞是否出現(xiàn)在輸入的數(shù)據(jù)集中 """# 創(chuàng)建一個(gè)和詞匯表等長(zhǎng)的向量,并將其元素都設(shè)置為0result = [0] * len(vocab_list)# 遍歷文檔中的所有單詞,如果出現(xiàn)了詞匯表中的單詞,則將輸出的文檔向量中的對(duì)應(yīng)值設(shè)為1for word in input_set:if word in vocab_list:result[vocab_list.index(word)] = 1else:# 這個(gè)后面應(yīng)該注釋掉,因?yàn)閷?duì)你沒(méi)什么用,這只是為了輔助調(diào)試的# print('the word: {} is not in my vocabulary'.format(word))passreturn result In?[23]: set_of_words2vec(vocab_list, posting_list[0]) Out[23]: [0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0] In?[24]: import numpy as npdef train_naive_bayes(train_mat, train_category):""" 樸素貝葉斯分類修正版, 注意和原來(lái)的對(duì)比,為什么這么做可以查看書(shū) :param train_mat: type is ndarray 總的輸入文本,大致是 [[0,1,0,1], [], []] :param train_category: 文件對(duì)應(yīng)的類別分類, [0, 1, 0], 列表的長(zhǎng)度應(yīng)該等于上面那個(gè)輸入文本的長(zhǎng)度 :return: 兩個(gè)條件概率向量,一個(gè)概率 """train_doc_num = len(train_mat)words_num = len(train_mat[0])# 因?yàn)槲耆栊缘谋粯?biāo)記為了1, 所以只要把他們相加就可以得到侮辱性的有多少# 侮辱性文件的出現(xiàn)概率,即train_category中所有的1的個(gè)數(shù),# 代表的就是多少個(gè)侮辱性文件,與文件的總數(shù)相除就得到了侮辱性文件的出現(xiàn)概率pos_abusive = np.sum(train_category) / train_doc_num# 單詞出現(xiàn)的次數(shù)# 原版,變成ones是修改版,這是為了防止數(shù)字過(guò)小溢出# p0num = np.zeros(words_num)# p1num = np.zeros(words_num)p0num = np.ones(words_num)p1num = np.ones(words_num)# 整個(gè)數(shù)據(jù)集單詞出現(xiàn)的次數(shù)(原來(lái)是0,后面改成2了)p0num_all = 2.0p1num_all = 2.0for i in range(train_doc_num):# 遍歷所有的文件,如果是侮辱性文件,就計(jì)算此侮辱性文件中出現(xiàn)的侮辱性單詞的個(gè)數(shù)if train_category[i] == 1:p1num += train_mat[i] # 直接把兩個(gè)list相加,對(duì)應(yīng)位置元素相加,# 最后直接一除就可以得到對(duì)應(yīng)的概率listp1num_all += np.sum(train_mat[i]) # 標(biāo)簽為1的總詞數(shù)else:p0num += train_mat[i]p0num_all += np.sum(train_mat[i]) # 標(biāo)簽為0的總詞數(shù)# 后面改成取 log 函數(shù)p1vec = np.log(p1num / p1num_all)p0vec = np.log(p0num / p0num_all)return p0vec, p1vec, pos_abusive In?[25]: def classify_naive_bayes(vec2classify, p0vec, p1vec, p_class1):""" 使用算法: # 將乘法轉(zhuǎn)換為加法 乘法:P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn) 加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) :param vec2classify: 待測(cè)數(shù)據(jù)[0,1,1,1,1...],即要分類的向量 :param p0vec: 類別0,即正常文檔的[log(P(F1|C0)),log(P(F2|C0)),log(P(F3|C0)),log(P(F4|C0)),log(P(F5|C0))....]列表 :param p1vec: 類別1,即侮辱性文檔的[log(P(F1|C1)),log(P(F2|C1)),log(P(F3|C1)),log(P(F4|C1)),log(P(F5|C1))....]列表 :param p_class1: 類別1,侮辱性文件的出現(xiàn)概率 :return: 類別1 or 0 """# 計(jì)算公式 log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C))# 使用 NumPy 數(shù)組來(lái)計(jì)算兩個(gè)向量相乘的結(jié)果,這里的相乘是指對(duì)應(yīng)元素相乘,即先將兩個(gè)向量中的第一個(gè)元素相乘,然后將第2個(gè)元素相乘,以此類推。# 我的理解是:這里的 vec2Classify * p1Vec 的意思就是將每個(gè)詞與其對(duì)應(yīng)的概率相關(guān)聯(lián)起來(lái)# 可以理解為 1.單詞在詞匯表中的條件下,文件是good 類別的概率 也可以理解為 2.在整個(gè)空間下,文件既在詞匯表中又是good類別的概率p1 = np.sum(vec2classify * p1vec) + np.log(p_class1)p0 = np.sum(vec2classify * p0vec) + np.log(1 - p_class1)if p1 > p0:return 1else:return 0 In?[26]: def testing_naive_bayes(list_post, list_classes):""" 測(cè)試樸素貝葉斯算法 :return: no return """# 1. 創(chuàng)建單詞集合vocab_list = create_vocab_list(list_post)# 2. 計(jì)算單詞是否出現(xiàn)并創(chuàng)建數(shù)據(jù)矩陣train_mat = []for post_in in list_post:train_mat.append(# 返回m*len(vocab_list)的矩陣, 記錄的都是0,1信息# 其實(shí)就是那個(gè)東西的句子向量(就是data_set里面每一行,也不算句子吧)set_of_words2vec(vocab_list, post_in))# 3. 訓(xùn)練數(shù)據(jù)p0v, p1v, p_abusive = train_naive_bayes(np.array(train_mat), np.array(list_classes))# 4. 測(cè)試數(shù)據(jù)test_one = ['love', 'my', 'dalmation']test_one_doc = np.array(set_of_words2vec(vocab_list, test_one))print('the result is: {}'.format(classify_naive_bayes(test_one_doc, p0v, p1v, p_abusive)))test_two = ['stupid', 'garbage']test_two_doc = np.array(set_of_words2vec(vocab_list, test_two))print('the result is: {}'.format(classify_naive_bayes(test_two_doc, p0v, p1v, p_abusive))) In?[28]: testing_naive_bayes(posting_list, class_vec) the result is: 0 the result is: 1轉(zhuǎn)載于:https://www.cnblogs.com/xinmomoyan/p/10494444.html
總結(jié)
以上是生活随笔為你收集整理的04机器学习实战之朴素贝叶斯的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MPLS笔记
- 下一篇: VMWare共享文件