【機器學習實踐】用Python實現樸素貝葉斯分類器
阿新 • • 發佈:2018-12-21
閱讀學習了《機器學習》第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('壞瓜')