1. 程式人生 > >機器學習之樸素貝葉斯分類器實現

機器學習之樸素貝葉斯分類器實現

問題如下

比如:有如下的需求,要判斷某一句英語是不是侮辱性語句

分析思路

對於機器來說,可能不容易分辨出某一句話是不是侮辱性的句子,但是機器可以機械的進行分析,何為機械的進行分析,就是判斷某一個句子中侮辱性的單詞是不是達到一定數量(當然這個只是判決準則中很簡單的一種)。這個方法叫詞集法!

程式碼思路

規定標記:w0 (值為0)表示非侮辱性句子 w1(值為1) 表示侮辱性句子

1、收集侮辱性的句子和反例若干

構造資料集,分類是侮辱性 or 非侮辱性

def loadDataset () :
    postingList=[['my', 'dog', 'has', 'flea'
, 'problems', 'help', 'please'], ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'], ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'], ['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

2、統計出所有單詞,構造一個單詞表wordlist

# 建立一個包涵所有詞彙的列表 , 為後面建立詞條向量使用
def createlist (dataset) :
    vovabset = set ([])
    for
vec in dataset : vovabset = vovabset | set (vec) return list (vovabset)

3、計算先驗概率、類條件概率

注意,這裡的類條件分佈用對數表示

  • 這裡的先驗概率,指的是隨機給一個句子,是侮辱性句子的概率或者非侮辱性句子的概率
    (當然,這裡說的概率就是樣本中的頻率)
  • 對於類條件概率,就是指已經知道某個句子是侮辱性句子,或者非侮辱性句子,假設已經知道某個句子是侮辱性句子,則該句子的單詞在單詞表中的概率分佈就是類條件概率!

程式碼如下

# 建立貝葉斯分類器
def trainNBO (dataset, classlebels) :
    num_of_sample = len (dataset)
    num_of_feature = len (dataset[0])
    pAusuive = sum (classlebels) / num_of_sample # 侮辱性語言的概率
    p0Num = np.ones (num_of_feature)
    p1Num = np.ones (num_of_feature)
    p0tot = num_of_feature
    p1tot = num_of_feature
    for i in range (num_of_sample) :
        if classlebels[i] == 1 :
            p1Num += dataset[i]
            p1tot += sum (dataset[i])
        else :
            p0Num += dataset[i]
            p0tot += sum (dataset[i])
    p0Vec = p0Num / p0tot
    p1Vec = p1Num / p1tot
    for i in range (num_of_feature) :
        p0Vec[i] = math.log (p0Vec[i])
        p1Vec[i] = math.log (p1Vec[i])
    return p0Vec, p1Vec, pAusuive

返回的結果pAusuive就是先驗分佈,p0Vec,p1Vec就是類條件分佈。
對於本題,計算出先驗概率和後驗概率就相當於把貝葉斯分類器訓練出來了

4、測試

給定一個句子,求其後驗概率p(w0|x),p(w1|x)
如果p(w0|x)>p(w1|x),則該句子屬於非侮辱性句子,反之屬於侮辱性句子。
如何求解後驗分佈,可以根據已經求得的先驗分佈和類條件分佈進行求解!
程式碼如下:

#  定義分類器
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + math.log(pClass1)      #element-wise mult
    p0 = sum(vec2Classify * p0Vec) + math.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

該函式引數p0Vec,p1Vec指的是類條件概率,pClass1指的是先驗概率
返回的是該句子屬於哪一個類,值為0,即w0,值為1,即w1。

程式碼實現如下

import numpy as np
import math
# 使用詞集法進行貝葉斯分類
# 構造資料集,分類是侮辱性 or 非侮辱性
def loadDataset () :
    postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                 ['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


# 建立一個包涵所有詞彙的列表 , 為後面建立詞條向量使用
def createlist (dataset) :
    vovabset = set ([])
    for vec in dataset :
        vovabset = vovabset | set (vec)
    return list (vovabset)

# 將詞條轉化為向量的形式
def changeword2vec (inputdata, wordlist) :
    returnVec = [0] * len (wordlist)
    for word in inputdata :
        if word in wordlist :
            returnVec[wordlist.index(word)] = 1
    return returnVec

# 建立貝葉斯分類器
def trainNBO (dataset, classlebels) :
    num_of_sample = len (dataset)
    num_of_feature = len (dataset[0])
    pAusuive = sum (classlebels) / num_of_sample # 侮辱性語言的概率
    p0Num = np.ones (num_of_feature)
    p1Num = np.ones (num_of_feature)
    p0tot = num_of_feature
    p1tot = num_of_feature
    for i in range (num_of_sample) :
        if classlebels[i] == 1 :
            p1Num += dataset[i]
            p1tot += sum (dataset[i])
        else :
            p0Num += dataset[i]
            p0tot += sum (dataset[i])
    p0Vec = p0Num / p0tot
    p1Vec = p1Num / p1tot
    for i in range (num_of_feature) :
        p0Vec[i] = math.log (p0Vec[i])
        p1Vec[i] = math.log (p1Vec[i])
    return p0Vec, p1Vec, pAusuive


#  定義分類器
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + math.log(pClass1)      #element-wise mult
    p0 = sum(vec2Classify * p0Vec) + math.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

# 測試程式碼
dataset,classlebels = loadDataset ()
wordlist = createlist(dataset)
print (wordlist)
print (changeword2vec (dataset[0], wordlist))
trainmat = []
for temp in dataset :
    trainmat.append (changeword2vec (temp,wordlist))
p0V, p1V, pAb = trainNBO (trainmat, classlebels)
print(p0V)
print(p1V)
print(pAb)

# 對訓練集進行測試
dataset,classlebels = loadDataset()
vec2Classify = changeword2vec(dataset[0], wordlist)
print(classifyNB(vec2Classify, p0V, p1V, pAb))