1. 程式人生 > >【機器學習實踐】用Python實現樸素貝葉斯分類器

【機器學習實踐】用Python實現樸素貝葉斯分類器

       閱讀學習了《機器學習》第7章的貝葉斯分類器後,為了加深理解和加強python的程式碼能力,因此嘗試使用Python實現樸素貝葉斯分類器,由於初學Python的緣故,程式碼的一些實現方法可能比較繁瑣,可閱讀性有待提高。程式碼如下:

#import numpy as np 
import math

def loadDataset () :
    #西瓜資料集2.0
    postingList=[['青綠', '蜷縮', '濁響', '清晰', '凹陷', '硬滑'],
                 ['烏黑', '蜷縮', '沉悶', '清晰', '凹陷', '硬滑'],
                 ['烏黑', '蜷縮', '濁響', '清晰', '凹陷', '硬滑'],
                 ['青綠', '蜷縮', '沉悶', '清晰', '凹陷', '硬滑'],
                 ['淺白', '蜷縮', '濁響', '清晰', '凹陷', '硬滑'],
                 ['青綠', '稍蜷', '濁響', '清晰', '稍凹', '軟粘'],
                 ['烏黑', '稍蜷', '濁響', '稍糊', '稍凹', '軟粘'],
                 ['烏黑', '稍蜷', '濁響', '清晰', '稍凹', '硬滑'],
                 ['烏黑', '稍蜷', '沉悶', '稍糊', '稍凹', '硬滑'],
                 ['青綠', '硬挺', '清脆', '清晰', '平坦', '軟粘'],
                 ['淺白', '硬挺', '清脆', '稍糊', '平坦', '硬滑'],
                 ['淺白', '蜷縮', '濁響', '模糊', '平坦', '軟粘'],
                 ['青綠', '稍蜷', '濁響', '稍糊', '凹陷', '硬滑'],
                 ['淺白', '稍蜷', '沉悶', '稍糊', '凹陷', '硬滑'],
                 ['烏黑', '稍蜷', '濁響', '清晰', '稍凹', '軟粘'],
                 ['淺白', '蜷縮', '濁響', '模糊', '平坦', '硬滑'],
                 ['青綠', '蜷縮', '沉悶', '稍糊', '稍凹', '硬滑']]
    classVec = [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0]    #1表示好瓜, 0表示壞瓜
    return postingList, classVec

def extractInfo(dataset):
    #提取西瓜資料集2.0的資訊
    feature_num=[]                            #記錄每項屬性的全部屬性取值的數目
    feature_sort=[]                           #記錄每項屬性的全部的屬性取值
    
    for i in range(len(dataset[0])):
        temp=set(x[i] for x in dataset)       #一列代表一項屬性,取一項屬性
        feature_sort.append(list(temp))
        feature_num.append(len(temp))

    return feature_num, feature_sort

#訓練樸素貝葉斯分類器
def trainBYS(dataset, feature_num, feature_sort, classLabel):
    T_data=[]                                 #記錄好瓜的資料集
    F_data=[]                                 #記錄壞瓜的資料集
    sort_num=len(set(classLabel))             #類別的數目,如好瓜和壞瓜,只有兩個類別
    for i in range(len(classLabel)):          #將總資料集分類成好瓜資料集和壞瓜資料集
        if classLabel[i]==1:
            T_data.append(dataset[i])
        else:
            F_data.append(dataset[i])
            
    #計算加入拉普拉斯修正的先驗概率和似然概率
    Pc=(sum(classLabel) + 1) / (len(classLabel) + sort_num)   #樣本中好瓜的概率,即先驗概率
    p1num={}                                  #用於記錄好瓜資料集中各屬性取值的概率
    p0num={}                                  #用於記錄壞瓜資料集中各屬性取值的概率
    for i in range(len(feature_num)):         #統計資料,計算概率
        temp1=[x[i] for x in T_data]
        temp2=[x[i] for x in F_data]
        for sort_value in feature_sort[i]:    #初始化概率,加入了拉普拉斯修正
            if sort_value not in p1num.keys():
                p1num[sort_value] = 1 / (len(temp1) + feature_num[i])
            if sort_value not in p0num.keys():
                p0num[sort_value] = 1 / (len(temp2) + feature_num[i])
        
        for y in temp1:                       #統計正樣本的各屬性取值概率
            p1num[y]+= 1 / (len(temp1) + feature_num[i])
           
        for y in temp2:                       #統計負樣本的各屬性取值概率
            p0num[y]+= 1 / (len(temp2) + feature_num[i])

    return p0num,p1num,Pc

#對輸入的測試樣本進行計算比較後驗概率
def classifyBYS(inputdata, p0num, p1num, Pc, length):    
    input_length=len(inputdata)               
    sample_length=length
    if input_length != sample_length:
        print('輸入資料格式不對')
        return -1
    Pt=math.log(Pc)                           #避免連乘造成下溢,使用對數似然
    Pf=math.log(1-Pc)
    for x in inputdata:
        Pt += math.log(p1num.get(x))
        Pf += math.log(p0num.get(x))
    if Pt >= Pf:
        return 1
    else:
        return 0
    
    
#測試程式碼  
dataset, classLabel=loadDataset()
feature_num, feature_sort = extractInfo(dataset)
#print(feature_sort)
p0num, p1num, Pc = trainBYS(dataset, feature_num, feature_sort, classLabel)
#print(p1num)
inputdata = ['淺白', '稍蜷', '沉悶', '稍糊', '凹陷', '硬滑']
result=classifyBYS(inputdata, p0num, p1num, Pc, len(dataset[0]))
if result == 1:
    print('好瓜')
elif result == 0:
    print('壞瓜')