(上接第二章)算法
2.3 分類算法:樸素貝葉斯編程
2.3.1 貝葉斯公式推導(略)數據結構
分類的流程: less
第一階段:訓練數據生成訓練樣本集:TF-IDF機器學習
第二階段:對每一個類別計算p(yi)。函數
第三個階段:對每一個特徵屬性計算全部劃分的條件機率post
第四個階段:對每一個類別計算P(x|yi)P(yi)。學習
第五個階段:以P(x|yi)P(yi)的最大項做爲x的所屬類別。測試
2.3.2 樸素貝葉斯算法實現ui
建立Nbayes_lib.py的文件,這個文件用來導入數據和樸素貝葉斯類的代碼。
使用簡單的英文語料做爲數據集:
def loadDataSet(): postingList =[['my','dog','has','flea','problem','help','please'], ['maybe','not','take','him','to','dog','park','stupid'], ['my','dalmation','is','so','cute','I','love','him','my'], ['stop','posting','stupid','worthless','garbage'], ['mr','licks','ate','my','steak','how','to','stop','him'], ['quit','buying','worthless','dog','food','stupid']] classVec = [0,1,0,1,0,1] #1 is abusive,0 not return postingList,classVec
posstingList 是訓練集文本,classVec是每一個文本對應的分類:
(1)編寫一個貝葉斯算法類,並建立默認的構造方法:
class NBayes(object): def __init__(self): self.vocabulary = [] #詞典 self.idf = 0 #詞典的IDF權值向量 self.tf = 0 #訓練值的權值矩陣 self.tdm = 0 #P(x|yi) self.Pcates = {} #P(yi)是一個類別字典 self.labels = [] #對應每一個文本的分類,是一個外部導入的列表 self.doclength = 0 #訓練集文本數 self.vocablen = 0 #詞典詞長 self.testset = 0 #測試集
(2)導入和訓練數據集,生成算法必需的參數和數據結構
def train_set(self,trainset,classVec): self.cate_prob(classVec) #計算每一個分類在數據集中的機率P(yi) self.doclength = len(trainset) tempset = set() [tempset.add(word) for doc in trainset for word in doc] #生成詞典 self.vocabulary = list(tempset) self.vocablen = len(self.vocabulary)
self.calc_wordfreq(trainset)
self.build_tdm() #按分類累計向量空間的每維值P(x|yi)
(3)cate_prob函數:計算在數據集中每一個分類的機率P(yi)
def cate_prob(self,classVec): self.labels = classVec labeltemps = set(self.labels) #獲取所有分類 for labeltemp in labeltemps: #統計列表中重複的分類: self.labels.count(labeltemp) self.Pcates[labeltemp] = float(self.labels.count(labeltemp))/float(len(self.labels))
(4)calc_wordfreq函數:生成普通的詞頻向量
def calc_wordfreq(self,trainset): self.idf = np.zeros([1,self.vocablen]) #1*詞典數 self.tf = np.zeros([self.doclength,self.vocablen]) #訓練集文件數*詞典數 for indx in xrange(self.doclength): #遍歷全部的文本 for word in trainset[indx]: #遍歷文本中的每一個詞 #找到文本的詞在字典中的位置+1 self.tf[indx,self.vocabulary.index(word)] += 1 for signleword in set(trainset[indx]): #idf詞數 self.idf[0,self.vocabulary.index(signleword)] += 1
(5)Build_tdm函數:按分類累計計算向量空間的每維值P(x|yi)
def build_tdm(self): self.tdm = np.zeros([len(self.Pcates),self.vocablen]) #類別行*詞典列 sumlist = np.zeros([len(self.Pcates),1]) #統計每一個分類的總值 for indx in xrange(self.doclength): #將同一類別的詞向量空間值加總 self.tdm[self.labels[indx]] += self.tf[indx] #統計每一個分類的總值--是一個標量 sumlist[self.labels[indx]] = np.sum(self.tdm[self.labels[indx]]) self.tdm = self.tdm/sumlist #生成P(x|yi)
(6)map2vocab函數:將測試集映射到當前詞典
# (6)map2vocab函數:將測試集映射到當前詞典 def map2vocab(self,testdata): self.testset = np.zeros([1,self.vocablen]) for word in testdata: self.testset[0,self.vocabulary.index(word)] += 1
(7)predict函數:預測分類結果,輸出預測的分類類別
def predict(self,testset): if np.shape(testset)[1] != self.vocablen: #若是測試集長度與詞典不相等,則退出程序 print "輸入錯誤" exit(0) predvalue = 0 #初始化類別機率 predclass = "" #初始化類別名稱 for tdm_vect,keyclass in zip(self.tdm,self.Pcates): #P(x|yi)*P(yi) #變量tdm,計算最大分類值 temp = np.sum(testset*tdm_vect*self.Pcates[keyclass]) if temp > predvalue: predvalue = temp predclass = keyclass return predclass
2.3.3 算法的改進
此算法的改進是爲普通的詞頻向量使用TF-IDF策略,使之有能力修正多種誤差
calc_tfidf函數:以TF-IDF方式生成向量空間。
#生成tf-idf def calc_tfidf(self,trainset): self.idf = no.zeros([1,self.vocablen]) self.tf = np.zeros([self.doclength,self.vocablen]) for indx in xrange(self.doclength): for word in trainset[indx]: self.tf[indx,self.vocabulary.index(word)] += 1 #消除不一樣句長致使的誤差 self.tf[indx] = self.tf[indx]/float(len(trainset[indx])) for signleword in set(trainset[indx]): self.idf[0,self.vocabulary.index(signleword)] += 1 self.idf = np.log(float(self.doclength)/self.idf) self.tf = np.multiply(self.tf,self.idf) #矩陣與向量的點乘 TF*IDF
2.3.4 評估分類結果
#coding:utf-8 import sys import os from numpy import * import numpy as np from Nbayes_lib import * #評估分類結果 dataSet,listClasses = loadDataSet() #導入外部數據集 #dataSet:句子的詞向量 #listClass是句子所屬的類別[0,1,0,1,0,1] nb = NBayes() #實例化 nb.train_set(dataSet,listClasses) #訓練數據集 nb.map2vocab(dataSet[0]) #隨機選擇一個測試語句 print nb.predict(nb.testset)
分類結果以下:
1
參考資料及版權全部:鄭捷《機器學習算法原理與編程實踐》