鄭捷《機器學習算法原理與編程實踐》學習筆記(第二章 中文文本分類(二)—樸素貝葉斯算法)

(上接第二章)算法

  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

  

  

參考資料及版權全部:鄭捷《機器學習算法原理與編程實踐》

相關文章
相關標籤/搜索