成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

機器學習算法實踐:樸素貝葉斯 (Naive Bayes)

開發 后端 算法
本文中我將一步步實現一個樸素貝葉斯分類器,并采用SMS垃圾短信語料庫中的數據進行模型訓練,對垃圾短信進行過濾,在最后對分類的錯誤率進行了計算。

[[197761]]

前言

上一篇《機器學習算法實踐:決策樹 (Decision Tree)》總結了決策樹的實現,本文中我將一步步實現一個樸素貝葉斯分類器,并采用SMS垃圾短信語料庫中的數據進行模型訓練,對垃圾短信進行過濾,在***對分類的錯誤率進行了計算。

正文

與決策樹分類和k近鄰分類算法不同,貝葉斯分類主要借助概率論的知識來通過比較提供的數據屬于每個類型的條件概率, 將他們分別計算出來然后預測具有***條件概率的那個類別是***的類別。當然樣本越多我們統計的不同類型的特征值分布就越準確,使用此分布進行預測則會更加準確。

貝葉斯準則

樸素貝葉斯分類器中最核心的便是貝葉斯準則,他用如下的公式表示:

 

此公式表示兩個互換的條件概率之間的關系,他們通過聯合概率關聯起來,這樣使得我們知道p(B|A) 的情況下去計算p(A|B) 成為了可能,而我們的貝葉斯模型便是通過貝葉斯準則去計算某個樣本在不同類別條件下的條件概率并取具有***條件概率的那個類型作為分類的預測結果。

使用條件概率來進行分類

這里我通俗的介紹下如何通過條件概率來進行分類,假設我們看到了一個人的背影,想通過他背影的一些特征(數據)來判斷這個人的性別(類別),假設其中涉及到的特征有: 是否是長發, 身高是否在170以上,腿細,是否穿裙子。當我們看到一個背影便會得到一個特征向量用來描述上述特征(1表示是,0表示否): ω=[0,1,1,0]

貝葉斯分類便是比較如下兩個條件概率:

  • p(男生|ω) ,ω 等于 [0,1,1,0 的條件下此人是男生的概率
  • p(女生|ω)) ,ω 等于 [0,1,1,0] 的條件下此人是女生的概率

若p(男生|ω)>p(女生|ω) , 則判定此人為男生, 否則為女生

那么p(男生|ω) 怎么求呢? 這就要上貝葉斯準則了

根據貝葉斯準則,

 

寫成好理解些的便是:

 

如果特征之間都是相互獨立的(條件獨立性假設),那么便可以將上述條件概率改寫成:

 

這樣我們就能計算當前這個背影屬于男生和屬于女生的條件概率了。

實現自己的貝葉斯分類器

貝葉斯分類器實現起來非常的簡單, 下面我以進行文本分類為目的使用Python實現一個樸素貝葉斯文本分類器.

為了計算條件概率,我們需要計算各個特征的在不同類別下的條件概率以及類型的邊際概率,這就需要我們通過大量的訓練數據進行統計獲取近似值了,這也就是我們訓練我們樸素貝葉斯模型的過程.

針對不同的文本,我們可以將所有出現的單詞作為數據特征向量,統計每個文本中出現詞條的數目(或者是否出現某個詞條)作為數據向量。這樣一個文本就可以處理成一個整數列表,并且長度是所有詞條的數目,這個向量也許會很長,用于本文的數據集中的短信詞條大概一共3000多個單詞。

  1. def get_doc_vector(words, vocabulary): 
  2.  
  3.     ''' 根據詞匯表將文檔中的詞條轉換成文檔向量 
  4.  
  5.   
  6.  
  7.     :param words: 文檔中的詞條列表 
  8.  
  9.     :type words: list of str 
  10.  
  11.   
  12.  
  13.     :param vocabulary: 總的詞匯列表 
  14.  
  15.     :type vocabulary: list of str 
  16.  
  17.   
  18.  
  19.     :return doc_vect: 用于貝葉斯分析的文檔向量 
  20.  
  21.     :type doc_vect: list of int 
  22.  
  23.     ''
  24.  
  25.     doc_vect = [0]*len(vocabulary) 
  26.  
  27.   
  28.  
  29.     for word in words: 
  30.  
  31.         if word in vocabulary: 
  32.  
  33.             idx = vocabulary.index(word) 
  34.  
  35.             doc_vect[idx] = 1 
  36.  
  37.   
  38.  
  39.     return doc_vect  

統計訓練的過程的代碼實現如下:

  1. def train(self, dataset, classes): 
  2.  
  3.     ''' 訓練樸素貝葉斯模型 
  4.  
  5.   
  6.  
  7.     :param dataset: 所有的文檔數據向量 
  8.  
  9.     :type dataset: MxN matrix containing all doc vectors. 
  10.  
  11.   
  12.  
  13.     :param classes: 所有文檔的類型 
  14.  
  15.     :type classes: 1xN list 
  16.  
  17.   
  18.  
  19.     :return cond_probs: 訓練得到的條件概率矩陣 
  20.  
  21.     :type cond_probs: dict 
  22.  
  23.   
  24.  
  25.     :return cls_probs: 各種類型的概率 
  26.  
  27.     :type cls_probs: dict 
  28.  
  29.     ''
  30.  
  31.     # 按照不同類型記性分類 
  32.  
  33.     sub_datasets = defaultdict(lambda: []) 
  34.  
  35.     cls_cnt = defaultdict(lambda: 0) 
  36.  
  37.   
  38.  
  39.     for doc_vect, cls in zip(dataset, classes): 
  40.  
  41.         sub_datasets[cls].append(doc_vect) 
  42.  
  43.         cls_cnt[cls] += 1 
  44.  
  45.   
  46.  
  47.     # 計算類型概率 
  48.  
  49.     cls_probs = {k: v/len(classes) for k, v in cls_cnt.items()} 
  50.  
  51.   
  52.  
  53.     # 計算不同類型的條件概率 
  54.  
  55.     cond_probs = {} 
  56.  
  57.     dataset = np.array(dataset) 
  58.  
  59.     for cls, sub_dataset in sub_datasets.items(): 
  60.  
  61.         sub_dataset = np.array(sub_dataset) 
  62.  
  63.         # Improve the classifier. 
  64.  
  65.         cond_prob_vect = np.log((np.sum(sub_dataset, axis=0) + 1)/(np.sum(dataset) + 2)) 
  66.  
  67.         cond_probs[cls] = cond_prob_vect 
  68.  
  69.   
  70.  
  71.     return cond_probs, cls_probs  

注意這里對于基本的條件概率直接相乘有兩處改進:

  1. 各個特征的概率初始值為1,分母上統計的某一類型的樣本總數的初始值是1,這是為了避免如果有一個特征統計的概率為0,則聯合概率也為零那自然沒有什么意義了, 如果訓練樣本足夠大時,并不會對比較結果產生影響.
  2. 由于各個獨立特征的概率都是小于1的數,累積起來必然會是個更小的書,這會遇到浮點數下溢的問題,因此在這里我們對所有的概率都取了對數處理,這樣在保證不會有損失的情況下避免了下溢的問題。

獲取了統計概率信息后,我們便可以通過貝葉斯準則預測我們數據的類型了,這里我并沒有直接計算每種情況的概率,而是通過統計得到的向量與數據向量進行內積獲取條件概率的相對值并進行相對比較做出決策的。

  1. def classify(self, doc_vect, cond_probs, cls_probs): 
  2.  
  3.     ''' 使用樸素貝葉斯將doc_vect進行分類. 
  4.  
  5.     ''
  6.  
  7.     pred_probs = {} 
  8.  
  9.     for cls, cls_prob in cls_probs.items(): 
  10.  
  11.         cond_prob_vect = cond_probs[cls] 
  12.  
  13.         pred_probs[cls] = np.sum(cond_prob_vect*doc_vect) + np.log(cls_prob) 
  14.  
  15.     return max(pred_probs, key=pred_probs.get)  

進行短信分類

已經構建好了樸素貝葉斯模型,我們就可以使用此模型來統計數據并用來預測了。這里我使用了SMS垃圾短信語料庫中的垃圾短信數據, 并隨機抽取90%的數據作為訓練數據,剩下10%的數據作為測試數據來測試我們的貝葉斯模型預測的準確性。

當然在建立模型前我們需要將數據處理成模型能夠處理的格式:

  1. ENCODING = 'ISO-8859-1' 
  2.  
  3. TRAIN_PERCENTAGE = 0.9 
  4.  
  5.   
  6.  
  7. def get_doc_vector(words, vocabulary): 
  8.  
  9.     ''' 根據詞匯表將文檔中的詞條轉換成文檔向量 
  10.  
  11.   
  12.  
  13.     :param words: 文檔中的詞條列表 
  14.  
  15.     :type words: list of str 
  16.  
  17.   
  18.  
  19.     :param vocabulary: 總的詞匯列表 
  20.  
  21.     :type vocabulary: list of str 
  22.  
  23.   
  24.  
  25.     :return doc_vect: 用于貝葉斯分析的文檔向量 
  26.  
  27.     :type doc_vect: list of int 
  28.  
  29.     ''
  30.  
  31.     doc_vect = [0]*len(vocabulary) 
  32.  
  33.   
  34.  
  35.     for word in words: 
  36.  
  37.         if word in vocabulary: 
  38.  
  39.             idx = vocabulary.index(word) 
  40.  
  41.             doc_vect[idx] = 1 
  42.  
  43.   
  44.  
  45.     return doc_vect 
  46.  
  47.   
  48.  
  49. def parse_line(line): 
  50.  
  51.     ''' 解析數據集中的每一行返回詞條向量和短信類型. 
  52.  
  53.     ''
  54.  
  55.     cls = line.split(',')[-1].strip() 
  56.  
  57.     content = ','.join(line.split(',')[: -1]) 
  58.  
  59.     word_vect = [word.lower() for word in re.split(r'\W+', content) if word] 
  60.  
  61.     return word_vect, cls 
  62.  
  63.   
  64.  
  65. def parse_file(filename): 
  66.  
  67.     ''' 解析文件中的數據 
  68.  
  69.     ''
  70.  
  71.     vocabulary, word_vects, classes = [], [], [] 
  72.  
  73.     with open(filename, 'r', encoding=ENCODING) as f: 
  74.  
  75.         for line in f: 
  76.  
  77.             if line: 
  78.  
  79.                 word_vect, cls = parse_line(line) 
  80.  
  81.                 vocabulary.extend(word_vect) 
  82.  
  83.                 word_vects.append(word_vect) 
  84.  
  85.                 classes.append(cls) 
  86.  
  87.     vocabulary = list(set(vocabulary)) 
  88.  
  89.   
  90.  
  91.     return vocabulary, word_vects, classes  

有了上面三個函數我們就可以直接將我們的文本轉換成模型需要的數據向量,之后我們就可以劃分數據集并將訓練數據集給貝葉斯模型進行統計。

  1. # 訓練數據 & 測試數據 
  2.  
  3. ntest = int(len(classes)*(1-TRAIN_PERCENTAGE)) 
  4.  
  5.   
  6.  
  7. test_word_vects = [] 
  8.  
  9. test_classes = [] 
  10.  
  11. for i in range(ntest): 
  12.  
  13.     idx = random.randint(0, len(word_vects)-1) 
  14.  
  15.     test_word_vects.append(word_vects.pop(idx)) 
  16.  
  17.     test_classes.append(classes.pop(idx)) 
  18.  
  19.   
  20.  
  21. train_word_vects = word_vects 
  22.  
  23. train_classes = classes 
  24.  
  25.   
  26.  
  27. train_dataset = [get_doc_vector(words, vocabulary) for words in train_word_vects]  

訓練模型:

  1. cond_probs, cls_probs = clf.train(train_dataset, train_classes) 

剩下我們用測試數據來測試我們貝葉斯模型的預測準確度:

  1. # 測試模型 
  2.  
  3. error = 0 
  4.  
  5. for test_word_vect, test_cls in zip(test_word_vects, test_classes): 
  6.  
  7.     test_data = get_doc_vector(test_word_vect, vocabulary) 
  8.  
  9.     pred_cls = clf.classify(test_data, cond_probs, cls_probs) 
  10.  
  11.     if test_cls != pred_cls: 
  12.  
  13.         print('Predict: {} -- Actual: {}'.format(pred_cls, test_cls)) 
  14.  
  15.         error += 1 
  16.  
  17.   
  18.  
  19. print('Error Rate: {}'.format(error/len(test_classes)))  

隨機測了四組,錯誤率分別為:0, 0.037, 0.015, 0. 平均錯誤率為1.3%

測完了我們嘗試下看看不同類型短信各個詞條的概率分布是怎樣的吧:

  1. # 繪制不同類型的概率分布曲線 
  2.  
  3. fig = plt.figure() 
  4.  
  5. ax = fig.add_subplot(111) 
  6.  
  7. for cls, probs in cond_probs.items(): 
  8.  
  9.     ax.scatter(np.arange(0, len(probs)), 
  10.  
  11.                probs*cls_probs[cls], 
  12.  
  13.                label=cls, 
  14.  
  15.                alpha=0.3) 
  16.  
  17.     ax.legend() 
  18.  
  19.   
  20.  
  21. plt.show() 

 

試試決策樹

上一篇我們基于ID3算法實現了決策樹,同樣是分類問題,我們同樣可以使用我們的文本數據來構建用于分類短信的決策樹,當然唯一比較麻煩的地方在于如果按照與貝葉斯相同的向量作為數據,則屬性可能會非常多,我們在構建決策樹的時候每層樹結構都是遞歸通過遍歷屬性根據信息增益來選取***屬性進行樹分裂的,這樣很多的屬性可能會對構建決策樹這一過程來說會比較耗時.那我們就試試吧…

  1. # 生成決策樹 
  2.  
  3. if not os.path.exists('sms_tree.pkl'): 
  4.  
  5.     clf.create_tree(train_dataset, train_classes, vocabulary) 
  6.  
  7.     clf.dump_tree('sms_tree.pkl'
  8.  
  9. else
  10.  
  11.     clf.load_tree('sms_tree.pkl'
  12.  
  13.   
  14.  
  15. # 測試模型 
  16.  
  17. error = 0 
  18.  
  19. for test_word_vect, test_cls in zip(test_word_vects, test_classes): 
  20.  
  21.     test_data = get_doc_vector(test_word_vect, vocabulary) 
  22.  
  23.     pred_cls = clf.classify(test_data, feat_names=vocabulary) 
  24.  
  25.     if test_cls != pred_cls: 
  26.  
  27.         print('Predict: {} -- Actual: {}'.format(pred_cls, test_cls)) 
  28.  
  29.         error += 1 
  30.  
  31.   
  32.  
  33. print('Error Rate: {}'.format(error/len(test_classes)))  

隨機測了兩次,錯誤率分別為:0.09, 0.0

效果還算不錯

我們還是用Graphviz可視化看一下決策樹都選取了那些詞條作為判別標準(這時候決策樹的好處就體現出來了)。

   

 

可見決策樹的深度并不是很深,如果分類類型一多,估計深度增加上去決策樹可能會有些麻煩。

總結

本文我們使用Python一步步實現了樸素貝葉斯分類器,并對短信進行了垃圾短信過濾,同樣的數據我們同決策樹的分類效果進行了簡單的比較。本文相關代碼實現:https://github.com/PytLab/MLBox/tree/master/naive_bayes 。決策樹過濾垃圾短信的腳本在https://github.com/PytLab/MLBox/tree/master/decision_tree

參考

  • 《Machine Learning in Action》
  • 實例詳解貝葉斯推理的原理
  • 大道至簡:樸素貝葉斯分類器

相關閱讀

 

責任編輯:龐桂玉 來源: Python開發者
相關推薦

2012-09-24 10:13:35

貝葉斯

2017-03-29 14:50:18

2023-01-31 15:49:51

機器學習函數評分函數

2021-08-30 11:53:36

機器學習人工智能計算機

2021-07-29 13:06:29

Python機器學習編程語言

2020-05-21 14:50:37

算法深度學習人工智能

2021-04-18 09:57:45

Java樸素貝葉斯貝葉斯定理

2019-03-20 07:50:47

機器學習算法線性回歸

2018-09-13 12:51:58

數據挖掘算法樸素貝葉斯

2017-07-12 11:27:05

樸素貝葉斯情感分析Python

2022-01-03 20:18:37

定理應用貝葉斯

2023-11-28 12:08:56

機器學習算法人工智能

2020-10-19 12:55:59

機器學習技術人工智能

2017-06-22 09:53:01

機器學習Python樸素貝葉斯

2018-10-18 09:00:00

機器學習機器學習算法數據科學家

2017-08-07 13:02:32

全棧必備貝葉斯

2017-11-07 11:17:40

樸素貝葉斯畫像數據數據挖掘

2018-07-03 15:26:35

算法機器學習數據

2020-10-09 12:41:04

算法優化場景

2012-02-14 10:55:24

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中日av| 欧美日韩精品一区二区三区四区 | 免费观看www | 国产高清视频一区 | 日本欧美黄色片 | 国产无人区一区二区三区 | 狠狠综合久久av一区二区小说 | 色在线免费视频 | 欧美亚洲国产精品 | 欧美精品在线一区二区三区 | 久夜精品 | 日本视频中文字幕 | av在线一区二区 | 自拍偷拍中文字幕 | 国产成人精品一区二区三区在线 | 久久av网 | 一区在线观看视频 | 蜜桃在线一区二区三区 | 日韩免费一区 | 一区二区三区四区在线 | 色综合色综合色综合 | 福利视频1000 | 国产精品一区二区在线免费观看 | 特一级毛片 | 久久久久一区二区三区 | 欧美日韩在线视频一区 | 成人18亚洲xxoo| 中文字幕日韩欧美一区二区三区 | 日本久久久久久 | 一区在线视频 | 国产视频一区二区在线观看 | 久久综合一区 | h片在线观看免费 | gav成人免费播放视频 | 久久午夜国产精品www忘忧草 | 国产精品欧美一区二区三区 | 国产精品免费一区二区 | 国产精品日韩一区二区 | 精品久久久一区 | 亚洲高清av | 九九99靖品 |