1. 程式人生 > >機器學習實戰三(Naive Bayes)

機器學習實戰三(Naive Bayes)

需要 blog bag puts list tps foo 實戰 簡單的

機器學習實戰三(Naive Bayes)

前兩章的兩種分類算法,是確定的分類器,但是有時會產生一些錯誤的分類結果,這時可以要求分類器給出一個最優的猜測結果,估計概率。樸素貝葉斯就是其中一種。

學過概率論的人對於貝葉斯這個名字應該是相當的熟悉,在學條件概率的時候,貝葉斯公式可謂是一針見血。這裏的“樸素貝葉斯”,是因為在計算貝葉斯概率的時候只考慮最原始、最簡單的假設。

Naive Bayes(樸素貝葉斯)

優點:在數據較少的情況下依然有效,可處理多類別問題。

缺點:對於輸入數據的格式要求嚴格。

原理:樸素貝葉斯的原理十分簡單,如果假定數據有兩類,分別計算待分類數據屬於這兩類的概率,p1和p2,如果

  • p1 > p2, 則屬於類別1
  • p1 < p2, 則屬於類別2

略微提及一下貝葉斯公式:
\(p\left( c|x\right) =\dfrac {p\left( x|c\right) p\left( c\right) }{p\left( x\right) }\)

這個公式的強大之處在於,可以將先驗概率和後驗概率進行轉換,看起來簡單,但是使用的時候的確很強大,而且計算很便捷。

先來看樸素貝葉斯的兩個基本假設:

  • 文本之間相互獨立
  • 每個特征同等重要

根據這兩個基本假設,就可以著手構造分類器了。

首先要將文本轉換到向量空間,思路比較清晰。

import feedparser
import numpy as np
import operator
import random
import re

# 加載測試數據
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]
    return postingList, classVec


# 創建詞匯表
def createVocabList(dataSet):
    vocabSet = set()
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)


# 構造文檔向量
def setOfWord2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print(‘the word: {} is not in my Vocabulary!‘.format(word))
    return returnVec

下一步是訓練算法,從詞向量計算概率,但是這裏有幾個小技巧:

  • 分母的初始值設置為2,避免分母為0的情況出現
  • 由於特征之間獨立,在做乘法的時候有時會面臨小數位數過多的下溢出,這時可以將其轉化為對數形式,這是一種比較通常的解決思路
# 訓練函數
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = np.sum(trainCategory) / numTrainDocs
    p0Num = np.ones(numWords)
    p1Num = np.ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += np.sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += np.sum(trainMatrix[i])
    p1Vect = np.log(p1Num / p1Denom)
    p0Vect = np.log(p0Num / p0Denom)
    return p0Vect, p1Vect, pAbusive

這種分類方式稱為詞集模型,只考慮某個詞出不出現,如果一種詞出現不止一次,那麽統計出現的次數無疑會包含更多信息,這種方法稱為詞袋模型

# 詞袋模型
def bagofWords2VecMN(vocabList, inputSet):
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

變化其實並不大。

現在就可以執行分類了,這一步完全就是條件概率公式的應用,註意對數可以將相乘轉換為相加。

# 執行分類
def classifyNB(vect2Classify, p0Vec, p1Vec, pClass1):
    # 對數相乘轉換為相加
    p1 = np.sum(vect2Classify * p1Vec) + np.log(pClass1)
    p0 = np.sum(vect2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

原書中提供的兩個關於樸素貝葉斯應用的例子,一個是過濾垃圾郵件,另一個是從個人廣告中獲取區域傾向,都是很有趣的例子,代碼可以在我的Github中找到。

例子中有幾點需要註意:

1.留存交叉驗證,其實就是從樣本集中隨機選取一部分作為訓練集,剩下的作為預測集來檢驗精度。

2.高頻詞通常移除會帶來更好的分類效果。

3.停用詞也可以選擇剔除。

Naive Bayes存在的問題:

通過降級特征之間的條件獨立性假設降低對數據量的需求,有時這個假設會顯得過於簡單,但是樸素貝葉斯仍是一種有效的分類器,而且使用概率要比使用硬規則更為有效。

Next: 初次接觸優化算法和Logistic回歸


總結:概率在機器學習中的應用是廣泛的,這是因為很多時候我們對於事物的具體發生機理並不了解,這個時候就需要借助概率論和統計的力量。

References:https://github.com/plantree/Machine-Learing-In-Action/tree/master/chapter4

機器學習實戰三(Naive Bayes)