貝葉斯分類器(Python實現+詳細完整原始碼和原理)
在概率和統計學領域,貝葉斯理論基於對某一事件證據的認識來預測該事件的發生概率,
由結果推測原因的概率大小
首先,理解這個公式的前提是理解條件概率,因此先複習條件概率。
P(A|B)=P(AB)/P(B)
貝葉斯公式:
在機器學習領域,貝葉斯分類器是基於貝葉斯理論並假設各特徵相互獨立的分類方法,
基本方法是:使用特徵向量來表徵某個實體,並在該實體上繫結一個標籤來代表其所屬的類別。
優點:只需要極少數的訓練資料,就可以建立起分類所需要的所有引數
抽象而言就是:貝葉斯分類器就是條件概率:給定一個實體,求解這個實體屬於某一類的概率,這個實體用
一個長度為n的向量來表示,向量中的每一個元素表示相互獨立的特徵值的
=====================================================================================
以下是對水果分類的python程式碼實現:
類別 | 較長 | 不長 | 甜 | 不甜 | 黃色 | 不是黃色 | 總數 |
香蕉 | 400 | 100 | 350 | 150 | 450 | 50 | 500 |
橘子 | 0 | 300 | 150 | 150 | 300 | 0 | 300 |
其他水果 | 100 | 100 | 150 | 50 | 50 | 150 | 200 |
總數 | 500 | 500 |
650 | 350 | 800 | 200 | 1000 |
python檔案結構:都在一個包下(Bayes)
bayes_classfier.py
#!/usr/bin/env python # encoding: utf-8 """ @Company:華中科技大學電氣學院聚變與等離子研究所 @version: V1.0 @author: YEXIN @contact: [email protected] 2018--2020 @software: PyCharm @file: bayes_classfier.py @time: 2018/8/16 16:49 @Desc:貝葉斯分類器 """ ###貝葉斯分類器原始碼 ####訓練資料集---->合適引數 datasets = {'banala':{'long':400,'not_long':100,'sweet':350,'not_sweet':150,'yellow':450,'not_yellow':50}, 'orange':{'long':0,'not_long':300,'sweet':150,'not_sweet':150,'yellow':300,'not_yellow':0}, 'other_fruit':{'long':100,'not_long':100,'sweet':150,'not_sweet':50,'yellow':50,'not_yellow':150} } def count_total(data): '''計算各種水果的總數 return {‘banala’:500 ...}''' count = {} total = 0 for fruit in data: '''因為水果要麼甜要麼不甜,可以用 這兩種特徵來統計總數''' count[fruit] = data[fruit]['sweet'] + data[fruit]['not_sweet'] total += count[fruit] return count,total #categories,simpleTotal = count_total(datasets) #print(categories,simpleTotal) ########################################################### def cal_base_rates(data): '''計算各種水果的先驗概率 return {‘banala’:0.5 ...}''' categories,total = count_total(data) cal_base_rates = {} for label in categories: priori_prob = categories[label]/total cal_base_rates[label] = priori_prob return cal_base_rates #Prio = cal_base_rates(datasets) #print(Prio) ############################################################ def likelihold_prob(data): '''計算各個特徵值在已知水果下的概率(likelihood probabilities) {'banala':{'long':0.8}...}''' count,_ = count_total(data) likelihold = {} for fruit in data: '''建立一個臨時的字典,臨時儲存各個特徵值的概率''' attr_prob = {} for attr in data[fruit]: #計算各個特徵值在已知水果下的概率 attr_prob[attr] = data[fruit][attr]/count[fruit] likelihold[fruit] = attr_prob return likelihold #LikeHold = likelihold_prob(datasets) #print(LikeHold) ############################################################ def evidence_prob(data): '''計算特徵的概率對分類結果的影響 return {'long':50%...}''' #水果的所有特徵 attrs = list(data['banala'].keys()) count,total = count_total(data) evidence_prob = {} #計算各種特徵的概率 for attr in attrs: attr_total = 0 for fruit in data: attr_total += data[fruit][attr] evidence_prob[attr] = attr_total/total return evidence_prob #Evidence_prob = evidence_prob(datasets) #print(Evidence_prob) ########################################################## #以上是訓練資料用到的函式,即將資料轉化為程式碼計算概率 ########################################################## class navie_bayes_classifier: '''初始化貝葉斯分類器,例項化時會呼叫__init__函式''' def __init__(self,data=datasets): self._data = datasets self._labels = [key for key in self._data.keys()] self._priori_prob = cal_base_rates(self._data) self._likelihold_prob = likelihold_prob(self._data) self._evidence_prob = evidence_prob(self._data) #下面的函式可以直接呼叫上面類中定義的變數 def get_label(self,length,sweetness,color): '''獲取某一組特徵值的類別''' self._attrs = [length,sweetness,color] res = {} for label in self._labels: prob = self._priori_prob[label]#取某水果佔比率 #print("各個水果的佔比率:",prob) for attr in self._attrs: #單個水果的某個特徵概率除以總的某個特徵概率 再乘以某水果佔比率 prob*=self._likelihold_prob[label][attr]/self._evidence_prob[attr] #print(prob) res[label] = prob #print(res) return res ============================================================================================
generate_attires.py
#!/usr/bin/env python
# encoding: utf-8
"""
@Company:華中科技大學電氣學院聚變與等離子研究所
@version: V1.0
@author: YEXIN
@contact: [email protected] 2018--2020
@software: PyCharm
@file: generate_attires.py
@time: 2018/8/17 13:43
@Desc:產生測試資料集來測試貝葉斯分類器的預測能力
"""
import random
def random_attr(pair):
#生成0-1之間的隨機數
return pair[random.randint(0,1)]
def gen_attrs():
#特徵值的取值集合
sets = [('long','not_long'),('sweet','not_sweet'),('yellow','not_yellow')]
test_datasets = []
for i in range(20):
#使用map函式來生成一組特徵值
test_datasets.append(list(map(random_attr,sets)))
return test_datasets
#print(gen_attrs())
======================================================================================
classfication.py
#!/usr/bin/env python
# encoding: utf-8
"""
@Company:華中科技大學電氣學院聚變與等離子研究所
@version: V1.0
@author: YEXIN
@contact: [email protected] 2018--2020
@software: PyCharm
@file: classfication.py
@time: 2018/8/17 13:55
@Desc:使用貝葉斯分類器對測試結果進行分類
"""
import operator
import bayes_classfier
import generate_attires
def main():
test_datasets = generate_attires.gen_attrs()
classfier = bayes_classfier.navie_bayes_classifier()
for data in test_datasets:
print("特徵值:",end='\t')
print(data)
print("預測結果:", end='\t')
res=classfier.get_label(*data)#表示多參傳入
print(res)#預測屬於哪種水果的概率
print('水果類別:',end='\t')
#對後驗概率排序,輸出概率最大的標籤
print(sorted(res.items(),key=operator.itemgetter(1),reverse=True)[0][0])
if __name__ == '__main__':
#表示模組既可以被匯入(到 Python shell 或者其他模組中),也可以作為指令碼來執行。
#當模組被匯入時,模組名稱是檔名;而當模組作為指令碼獨立執行時,名稱為 __main__。
#讓模組既可以匯入又可以執行
main()
=====================================================================================
結果展示:
特徵值: ['not_long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.08571428571428573, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['not_long', 'sweet', 'not_yellow']
預測結果: {'banala': 0.1076923076923077, 'orange': 0.0, 'other_fruit': 0.8653846153846153}
水果類別: other_fruit
特徵值: ['not_long', 'sweet', 'yellow']
預測結果: {'banala': 0.24230769230769234, 'orange': 0.5769230769230769, 'other_fruit': 0.07211538461538461}
水果類別: orange
特徵值: ['not_long', 'sweet', 'yellow']
預測結果: {'banala': 0.24230769230769234, 'orange': 0.5769230769230769, 'other_fruit': 0.07211538461538461}
水果類別: orange
特徵值: ['not_long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.08571428571428573, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.7714285714285716, 'orange': 0.0, 'other_fruit': 0.04464285714285715}
水果類別: banala
特徵值: ['not_long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.1928571428571429, 'orange': 1.0714285714285714, 'other_fruit': 0.04464285714285715}
水果類別: orange
特徵值: ['not_long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.1928571428571429, 'orange': 1.0714285714285714, 'other_fruit': 0.04464285714285715}
水果類別: orange
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['not_long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.1928571428571429, 'orange': 1.0714285714285714, 'other_fruit': 0.04464285714285715}
水果類別: orange
特徵值: ['not_long', 'sweet', 'not_yellow']
預測結果: {'banala': 0.1076923076923077, 'orange': 0.0, 'other_fruit': 0.8653846153846153}
水果類別: other_fruit
特徵值: ['long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.7714285714285716, 'orange': 0.0, 'other_fruit': 0.04464285714285715}
水果類別: banala
特徵值: ['not_long', 'sweet', 'yellow']
預測結果: {'banala': 0.24230769230769234, 'orange': 0.5769230769230769, 'other_fruit': 0.07211538461538461}
水果類別: orange
特徵值: ['long', 'not_sweet', 'not_yellow']
預測結果: {'banala': 0.3428571428571429, 'orange': 0.0, 'other_fruit': 0.5357142857142858}
水果類別: other_fruit
特徵值: ['not_long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.1928571428571429, 'orange': 1.0714285714285714, 'other_fruit': 0.04464285714285715}
水果類別: orange
特徵值: ['long', 'not_sweet', 'yellow']
預測結果: {'banala': 0.7714285714285716, 'orange': 0.0, 'other_fruit': 0.04464285714285715}
水果類別: banala