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

機器學習之樸素貝葉斯分類方法

本文轉載自http://holynull.leanote.com/post/Logistic-2

樸素貝葉斯分類方法

前言

樸素貝葉斯分類演算法是機器學習領域最基本的幾種演算法之一。但是對於作者這樣沒有什麼資料基礎的老碼農來說,理解起來確實有一些困難。所以撰寫此文幫助自己理解演算法,同時也希望對同樣在機器學習起跑線上的同仁有所幫助。

開篇我們就不對所涉及的技術要求做說明了,假設您具備高中數學的基礎,或者像作者一樣,還能回憶起一些數學基礎知識,對python語言基礎有一定的瞭解,那麼您在閱讀本文時就不會有任何困難。

另外,本文參考了《機器學習實戰》中第四章《基於概率論的分類方法:樸素貝葉斯》中的內容。這裡向作者致以崇高的敬意。

問題

這裡我們使用一個例子來一步一步分析,並用python來實現分類演算法。

我們假設在某網站的評論區中,我們需要實現對使用者的評論進行分類。簡單來說,一類為合法的評論,一類為存在不文明用語的評論。我們的問題是,現在管理員工作壓力很大,每天要處理數以千計或者數以萬計的評論分類,那麼我們如何來幫助他們呢?

第一個想到的方法肯定是讓機器能夠通過評論的內容,自動對評論進行分類。聽起來很美,但是實現起來貌似沒那麼簡單。那麼接下來,我們來看一下這個最好的但貌似並不簡單的想法怎麼來實現呢?

解決方法

第一步 樣本資料

我們將管理員之前的分類資料提取出來。然後再將我們關心的資料清洗出來,做為我們研究解決方案的樣本資料。我們可以將每一條評論中的單詞全部提取出來,用來觀察這些單詞的組合和分類的關係,我們建立一個數組postingList如下:

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]

我們用這樣的一個一維陣列來表示上面評論的分類情況。就是說,第一條postingList[0]評論[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’]的分類資訊是classVec[0],這裡0表示合法評論,1表示不文明用語。

這個樣本資料,就形成了我們下面所涉及到的概率計算的樣本空間,即下文中設計到的概率,都是在樣本資料組成的樣本空間中計算得到的。

第二步 應用樸素貝葉斯演算法

樸素貝葉斯演算法是貝葉斯決策論的一部分,這看起來很高深。貌似沒學過,或者老師講過但是完全忘記了。沒關係,我來簡單解釋一下。樸素貝葉斯就是說,根據資料屬於分類的概率,來給資料分類。在我們的問題中,就是我們要計算一下,一個評論可能被評定為合法評論的概率p0和被評定為不文明用語的概率p1這兩個概率的大小,哪個概率高就被評定為哪一類。貌似又是一個聽起來簡單,實現起來很難的問題啊。不用擔心,我們接下來一步一步將問題的原理闡明。

這個分類的概率怎麼計算呢?這裡我們要說明一個概率方面的概念,叫做“條件概率”。具體的數學定義請看這裡。嚴謹的數學概念很難理解和記住,那麼我們就以下面的公式符號做個簡單說明:
在這裡插入圖片描述

這個條件概率的符號表示,事件B發生的前題下事件A發聲的概率。

那麼,在我們的問題中,我們要計算的兩個概率應該怎麼表示呢?首先我們將評論中出現單詞組合w事件定義為Ww;被評定為不文明用語,即評論被分為c1類的事件定義為C1;被評定為合法評論,即評論被評定為c0類的事件定義為C0;

p1:評論被評定為不文明用語的概率,如下表示:
在這裡插入圖片描述
p0:評論被評定為合法評論的概率,如下表示:
在這裡插入圖片描述
又混亂了?好吧。拋開上面那些定義。我們單看p1,根據簡單的條件概率的理解。p1表示Ww發生的前提下,C1事件發生的概率。再結合我們的定義,p1就是表示,出現w單詞組合的前提下,評論被評定成c1類的概率,即被評定為不文明用語的概率。不難理解,p0就表示出現w單詞組合的情況下,評論被評定為合法評論的概率。

說到這裡,還是不知道怎麼計算這兩個概率。不要著急,下面我們接著引入一個貝葉斯準則公式。這個公式的目的是幫助我們在計算條件概率時,來計算條件反轉後的概率的。其現實意義可以打個比方,我們已知B事件發生時A事件發生的概率,我們通過這個公式就能夠得到,A事件發生時B事件也發生的概率。
在這裡插入圖片描述
這個準則公式的原理這裡就不多介紹了,感興趣的朋友可以深入瞭解和驗證一下這個公式。這裡我們只需要使用這個公式計算我們需要的兩個概率值。

套入我們的問題中,p1和p0如下所示:
在這裡插入圖片描述
從上面我們推匯出的結果可以看出,我們要比較p1和p0的大小,其實比較分子即可,即比較如下兩個值:
在這裡插入圖片描述
現在,我們距離我們要計算的結果就剩一層窗戶紙了。下面讓我們來捅破這層窗戶紙。

v1和v0計算的過程中,我們看看我們需要的引數。其中,P(C1)和P(C0)分別代表評論被評定成不文明用語和評定成合法評論的概率,我們在樣本資料中很容易就可以統計出來。接下來看一下剩下的P(Ww|C1)和P(Ww|C0)如何計算。

我們假定每個單詞都是相對獨立的,那麼一個單詞組合出現的概率就等於每一個單詞出現的概率相乘。換到條件概率中也是適用的。所以,我們有如下推導:
在這裡插入圖片描述
不難看出,我們完全可以在樣本資料中,統計出目標評論(我們需要分類的資料)中的每個單詞在分類前提下出現的概率。

好了,看來我們找到了計算p1和p0的方法了,確切的說是找到對比它們大小的方法了。我們接下來就可以設計程式了。

第三步 設計程式前簡化公式

我們設計的程式的目的是要計算上一步中v1和v0,然後對比大小。由於計算機計算時由於累加或者累乘時,結果超大或者超小造成資料溢位,導致資料不準確。我們對v1和v0進行了取自然對數操作,而取自然對數不會對結果有任何影響。這裡提前說明簡化公式,以便於理解程式的實現。

我們重新定義v1和v0,如下:
在這裡插入圖片描述
繼續推導至評論中每個單詞出現的概率:
在這裡插入圖片描述
第四步 設計程式
我們可以看到第一步中我們得到的樣本資料。

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]

要想統計各種概率,用這樣的樣本資料看來是很不適用的,要寫很多程式碼才能實現。那麼我們把樣本資料轉化成一種方便統計的資料結構,其中包含:

一個詞表wordlist,樣本資料中出現過的所有單詞

樣本資料每一行評論,對應一個詞表向量wordlistVec。這個向量反應詞表中單詞在評論中出現的情況,因此長度與詞表相等。1為出現,0為未出現。例如,我們現在有一個詞表[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’],那麼評論“my dog has problems”的詞表向量就是[1,1,1,0,1,0,0]。我們不難看出詞表向量反映出了詞表中單詞在評論中出現的情況。

一個分類向量classVec,每一個元素表示對應的評論所屬的分類
我們把所有的評論的詞表向量依次放入一個數組中,形成一個“評論數*詞表長度”的矩陣,再配合評論分類向量,結構如下表:
在這裡插入圖片描述

在這樣的一個矩陣中,我們就可以研究評論中出現的單詞組合和分類之間的規律了。或者說,我們可以通過計算矩陣中0和1的個數,就可以得到我們需要的樣本概率。

首先,在bayes.py檔案中,我們來寫一個函式,用來來準備我們的樣本資料:

#coding=utf-8
from numpy import *
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 不文明用語, 0 非不文明用語
    return postingList,classVec

然後,我們寫一個函式,通過樣本資料中的所有評論生成一個詞表:

# 從dataSet中獲取一個單詞列表(詞表),記錄每一個出現過的單詞
def createWordList(dataSet):      
    vocabSet=set([])
    for row in dataSet:
        vocabSet = vocabSet|set(row)
    return list(vocabSet)

編寫一個能將評論轉化為詞表向量的函式:

'''
將詞表轉化成,表示在wordArray中是否出現的向量
返回一個向量,向量的元素為wordList中對應角標單詞在陣列wordArray中是否出現
1出現
0未出現
'''
def wordList2Vector(wordList,wordArray):
    result=[0]*len(wordList)
    for word in wordArray:
        if word in wordList:
            result[wordList.index(word)] = 1
    return result

這時,我們就可以生成一個所有評論的詞表向量矩陣,然後列印一下,檢視一下結果:

if __name__=='__main__':
    dataSet,classVec=loadDataSet()
    print '樣本資料:',dataSet
    print '分類向量:',classVec
    wordlist=createWordList(dataSet)
    print '詞表:',wordlist
    exMat=[]
    for row in dataSet:
        exMat.append(wordList2Vector(wordlist,row))
    print '樣本資料的詞表向量矩陣:',exMat

我們看一下結果顯示:

樣本資料: [['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']]
分類向量: [0, 1, 0, 1, 0, 1]
詞表: ['cute', 'love', 'help', 'garbage', 'quit', 'I', 'problems', 'is', 'park', 'stop', 'flea', 'dalmation', 'licks', 'food', 'not', 'him', 'buying', 'posting', 'has', 'worthless', 'ate', 'to', 'maybe', 'please', 'dog', 'how', 'stupid', 'so', 'take', 'mr', 'steak', 'my']
樣本資料的詞表向量矩陣: [[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]

我們在第三步中最後,得到我們要計算的兩個值v1和v0:
在這裡插入圖片描述

因為我們只分了2個型別,所以:
在這裡插入圖片描述
所以我們接下來要實現的函式,計算得到3個結果即可
在這裡插入圖片描述

'''
通過樣本資料,計算出分類出現的概率,以及樣本資料中每個單詞,在每個分類出現的情況下,出現的概率
exampleMat  一個二位陣列,每一行表示從樣本資料中抽取的詞表中每個單詞,是否在樣本資料中對應行出現,1為出現,0為未出現
exampleCategory 一個一維陣列,記錄exampleMat中每一行詞表出現情況所表示的分類,1為不文明用語,0為文明用語
pAbusive 不文明用語出現的概率
p1 不文明用語分類前提下,每個單詞出現的概率向量
p0 文明用語分類前提下,每個單詞出現的概率向量
'''
def trainNB0(exampleMat,exampleCategory):
    rowNum=len(exampleMat)
    colNUm=len(exampleMat[0])
    pAbusive=sum(exampleCategory)/float(rowNum) #計算出不文明用語在樣本中出現的概率
    p1num=ones(colNUm)
    p0num=ones(colNUm)
    cnt1=2.0
    cnt0=2.0
    for i in range(rowNum):
        if exampleCategory[i]==1:
            p1num += exampleMat[i]
            cnt1 += sum(exampleMat[i])
        else :
            p0num += exampleMat[i]
            cnt0 += sum(exampleMat[i])
    p1=log(p1num/cnt1)
    p0=log(p0num/cnt0)
    return p1,p0,pAbusive

這個函式的返回值中,p1是一個由概率的自然對陣列成的向量,每個元素表示詞表中每個單詞出現的概率(C1條件下)的自然對數。同樣p0也是一個道理,只是概率是條件是C0。pAbusive即P(C1)的結果。我們獲得整個詞表的條件概率的自然對數向量有什麼用呢?後面我們會說名的。

注意

p1num=ones(colNUm) 
p0num=ones(colNUm) 
cnt1=2.0 
cnt0=2.0 

這段程式碼變數的初始值並不是0,這是防止計算後數值過小而產生溢位,不會對結果有任何影響。

下面我們來實現一個負責分類的函式,即一個分類器。這是實現分類的最後一步了,那麼輸入的引數應該是我們需要分類的評論內容,我們稱作目標評論,返回值是分類的值(0或者1)。這裡我們用評論的詞表向量來代替評論內容,我們稱作目標詞表向量,即評論的詞表向量的分類就是評論的分類。上面我們取得了詞表中所有單詞的條件概率的自然對數向量p1和p0。用這個向量乘以目標詞表向量,就得到目標評論中每個單詞的條件概率的自然對陣列成的向量(目標評論中沒有出現的單詞,值為0)。再經過求和運算即得到
在這裡插入圖片描述

def classifyNb(classifyVec,p0vec,p1vec,pc):
    v0=sum(classifyVec*p0vec)+log(pc)   
    v1=sum(classifyVec*p1vec)+log(1.0-pc)
    if(v1>v0):
        return 1
    else:
        return 0

這個函式的第二、三、四個引數,就可以使用我們上面計算出來3個樣本空間的概率結果。第一個引數即通過評論內容轉化的詞表向量。

下面我們來完成驗證我們實現的分類器部分的程式碼:

if __name__=='__main__':
    dataSet,classVec=loadDataSet()
    print '樣本資料:',dataSet
    print '分類向量:',classVec
    wordlist=createWordList(dataSet)
    print '詞表:',wordlist
    exMat=[]
    for row in dataSet:
        exMat.append(wordList2Vector(wordlist,row))
    print '樣本資料的詞表向量矩陣:',exMat
    p1v,p0v,pa=trainNB0(exMat,classVec)
    print 'p1:\n',p1v
    print 'p0:\n',p0v
    print 'pa:\n',pa
    testArg=['love','my','dalmation']
    thisdoc=array(wordList2Vector(wordlist,testArg))
    print testArg,'分類結果:',classifyNb(thisdoc,p0v,p1v,pa)
    testArg=['stupid','garbage']
    thisdoc=array(wordList2Vector(wordlist,testArg))
    print testArg,'分類結果:',classifyNb(thisdoc,p0v,p1v,pa)

我們來檢視一下結果:

樣本資料: [['my', 'dog', 'has', 'flea'
            
           

相關推薦

機器學習樸素分類方法

本文轉載自http://holynull.leanote.com/post/Logistic-2 樸素貝葉斯分類方法 前言 樸素貝葉斯分類演算法是機器學習領域最基本的幾種演算法之一。但是對於作者這樣沒有什麼資料基礎的老碼農來說,理解起來確實有一些困難。所以撰寫此文幫

機器學習樸素分類器附C++程式碼

一、基本概念: 先驗概率(prior probability):是指根據以往經驗和分析得到的概率,如全概率公式,它往往作為"由因求果"問題中的"因"出現的概率。比如,拋一枚硬幣,正面朝上的概率P(A)=1/2,就是先驗概率。聯合概率:表示兩個事件共同發生的概率。A與B的

機器學習樸素分類器實現

問題如下 比如:有如下的需求,要判斷某一句英語是不是侮辱性語句 分析思路 對於機器來說,可能不容易分辨出某一句話是不是侮辱性的句子,但是機器可以機械的進行分析,何為機械的進行分析,就是判斷某一個句子中侮辱性的單詞是不是達到一定數量(當然這

機器學習樸素(附垃圾郵件分類

樸素貝葉斯分類器介紹概述  樸素貝葉斯分類器技術基於貝葉斯定理,特別適用於輸入維數較高的情況。儘管樸素貝葉斯方法簡單,但它通常比更復雜的分類方法更勝一籌。                  

機器學習樸素(NB)分類演算法與Python實現

樸素貝葉斯(Naive Bayesian)是最為廣泛使用的分類方法,它以概率論為基礎,是基於貝葉斯定理和特徵條件獨立假設的分類方法。 一、 概述 1.1 簡介 樸素貝葉斯(Naive Bayesian)是基於貝葉斯定理和特徵條件獨立假

機器學習系列——樸素分類器(二)

表示 -h line log ima 條件 code 樸素貝葉斯 spa 貝葉斯定理: 其中: 表示事件B已經發生的前提下,事件A發生的概率,叫做事件B發生下事件A的條件概率。其基本求解公式為:。 機器學習系列——樸素貝葉斯分類器(二)

機器學習】--機器學習樸素從初始到應用

rac AC 一個 pam 數據 ast 出現 相對 解決方法 一、前述 機器學習算法中,有種依據概率原則進行分類的樸素貝葉斯算法,正如氣象學家預測天氣一樣,樸素貝葉斯算法就是應用先前事件的有關數據來估計未來事件發生的概率。 二、具體 1、背景--貝葉斯定理引入對於兩個關聯

sklearn庫學習樸素分類

樸素貝葉斯模型 樸素貝葉斯模型的泛化能力比線性模型稍差,但它的訓練速度更快。它通過單獨檢視每個特徵來學習引數,並從每個特徵中收集簡單的類別統計資料。想要作出預測,需要將資料點與每個類別的統計資料進行比較,並將最匹配的類別作為預測結果。 GaussianNB應用於任意連續資料,

機器學習多項式分類器multinomialNB

機器學習之多項式貝葉斯分類器multinomialNB # -*- coding: utf-8 -*- """ Created on Sun Nov 25 11:28:25 2018 @author: muli """ from sklearn import nai

機器學習樸素(Naive Bayes)

貝葉斯概率以18世紀的一位神學家托馬斯·貝葉斯(Thomas Bayes)的名字命名。 一、為什麼叫樸素貝葉斯? 樸素貝葉斯是經典機器學習演算法之一,是基於概率論的分類演算法,其原理簡單,易於實現,多使用於文字分類,如垃圾郵件過濾、新聞分類等。 樸素貝葉斯中的樸素是來源

機器學習樸素演算法與程式碼實現

                                    樸素貝葉斯演算法與程式碼實現 演算法原理 樸素貝葉斯是經典的機器學習演算法之一,也是為數不多的基於概率論的分類演算法。樸素貝葉斯原理簡單,也很容易實現,多用於文字分類,比如垃圾郵件過濾。 該演算法的優點在於簡單易懂、學習效率高、在某些領

機器學習樸素分類器,決策函式向量化處理,mask使用技巧

文章目錄 前面實現的樸素貝葉斯分類器,決策函式是非向量化的: 藉助於numpy向量化處理,相當於平行計算,注意mask使用技巧,用途較廣: 前面實現的樸素貝葉斯分類器,決策函式是非向量化的: 前面提到過大資料處理,儘量避免個人的遍歷等一些函式

機器學習樸素分類器程式碼實現,決策函式非向量化方式

文章目錄 樸素貝葉斯離散型的演算法描述: 程式碼實現: 實現一個NaiveBayes的基類,以便擴充套件: 實現離散型樸素貝葉斯MultiomialNB類: 實現從檔案中讀取資料: 測試資料: 程式碼測試:

機器學習實戰——樸素分類

準備資料:從文字中構建詞向量 前期測試函式用的資料 def loadDataSet(): '''建立一些實驗樣本''' postingList = [['my','dog','has','flea','problems','help','

機器學習樸素模型及程式碼示例

一、樸素貝葉斯的推導 樸素貝葉斯學習(naive Bayes)是一種有監督的學習,訓練時不僅要提供訓練樣本的特徵向量X,而且還需提供訓練樣本的實際標記Y,是一種基於貝葉斯定理和特徵條件獨立假設的分類方法。 1. 貝葉斯定理: 貝葉斯定理: 。 對於分

機器學習樸素分類

前言:在正式講述樸素貝葉斯分類器之前,先介紹清楚兩個基本概念:判別學習方法(Discriminative Learning Algorithm)和生成學習方法(Generative Learning Algorithm)。 上篇博文我們使用Logist

大資料Spark(七)--- Spark機器學習樸素,酒水評估和分類案例學習,垃圾郵件過濾學習案例,電商商品推薦,電影推薦學習案例

一、Saprk機器學習介紹 ------------------------------------------------------------------ 1.監督學習 a.有訓練資料集,符合規範的資料 b.根據資料集,產生一個推斷函式

Python機器學習與實戰筆記樸素分類

1聯合概率分佈 p(x,y)=p(y)P(x|y)  或者p(A交B)=p(A)xp(B)  p(A交B)不容易求,假設條件獨立拆分成兩個事件的乘積 2基本假設條件獨立性 3利用貝葉斯定理 p(y|x)=P(x,y)/p(x)=p(y)P(x|y)/sum(y-i)[p(

【python】機器學習實戰樸素分類

一,引言   前兩章的KNN分類演算法和決策樹分類演算法最終都是預測出例項的確定的分類結果,但是,有時候分類器會產生錯誤結果;本章要學的樸素貝葉斯分類演算法則是給出一個最優的猜測結果,同時給出猜測的概率估計值。 1 準備知識:條件概率公式 相信學過概率論的同學對於概

機器學習經典演算法樸素分類

很多人都聽說過貝葉斯原理,在哪聽說過?基本上是在學概率統計的時候知道的。有些人可能會說,我記不住這些概率論的公式,沒關係,我儘量用通俗易懂的語言進行講解。 /*請尊重作者勞動成果,轉載請標明原文連結:*/ /* https://www.cnblogs.com/jpcflyer/p/11069659