100天搞定機器學習|Day15 樸素貝葉斯

Day15,開始學習樸素貝葉斯,先了解一下貝爺,以示敬意。python

托馬斯·貝葉斯 (Thomas Bayes),英國神學家、數學家、數理統計學家和哲學家,1702年出生於英國倫敦,作過神甫;1742年成爲英國皇家學會會員;1763年4月7日逝世。貝葉斯曾是對機率論與統計的早期發展有重大影響的兩位(貝葉斯和布萊斯·帕斯卡Blaise Pascal)人物之一。正則表達式

貝葉斯在數學方面主要研究機率論。他首先將概括推理法用於機率論基礎理論,並創立了貝葉斯統計理論,對於統計決策函數、統計推斷、統計的估算等作出了貢獻。1763年發表了這方面的論著,對於現代機率論和數理統計都有很重要的做用。貝葉斯的《An essay towards solving a problem in the doctrine of chances》發表於1758年,貝葉斯所採用的許多術語被沿用至今。貝葉斯對統計推理的主要貢獻是使用了"逆機率"這個概念,並把它做爲一種廣泛的推理方法提出來,即貝葉斯定理。算法

1、回顧機率統計基礎知識

獨立事件:在一次實驗中,一個事件的發生不會影響到另外一事件發生的機率,兩者沒有任何關係。若是A1,A2,A3…An相互獨立,則A1~ An同時發生的機率:app

條件機率:指在A事件發生的條件下,事件B發生的機率,用符號表示:dom

全機率公式:若是事件A一、A二、A3…An 構成一個完備事件組,即它們兩兩互不相容,其和爲全集Ω;而且P(Ai) > 0,則對任一試驗B有:機器學習

其餘機率基礎,你們若有興趣請移步:ide

【溫故知新】機率筆記1——獨立事件下的簡單機率函數

【溫故知新】機率筆記2——古典概型學習

【溫故知新】機率筆記3——幾何概型測試

【溫故知新】機率筆記4——重要公式

【溫故知新】機率筆記5——機率分佈

2、貝葉斯定理

貝葉斯定理(Bayes’s Rule):若是有k個互斥且有窮個事件 B1,B2···,Bk,而且,P (B1) + P(B2) + · · · + P(Bk) = 1和一個能夠觀測到的事件A,那麼有:

這就是貝葉斯公式,其中:

P(Bi) 爲先驗機率,即在獲得新數據前某一假設的機率;

P(Bi|A) 爲後驗機率,即在觀察到新數據後計算該假設的機率;

P(A|Bi)爲似然度,即在該假設下獲得這一數據的機率;

P(A)爲標準化常量,即在任何假設下獲得這一數據的機率。

證實起來也不復雜

一、根據條件機率的定義,在事件 B 發生的條件下事件 A 發生的機率爲:

二、一樣地,在事件 A 發生的條件下事件 B 發生的機率爲:

三、結合這兩個方程式,咱們能夠獲得:

四、上式兩邊同除以 P(A),若P(A)是非零的,咱們能夠獲得貝葉斯定理:

在B出現的前提下,A出現的機率等於A出現的前提下B出現的機率乘以A出現的機率再除以 B 出現的機率。經過聯繫 A 與 B,計算從一個事件發生的狀況下另外一事件發生的機率,即從結果上溯到源頭(也即逆向機率)。

貝葉斯公式以及由此發展起來的一整套理論與方法,在機率統計中被稱爲貝葉斯學派,與機率學派有着徹底不一樣思考問題方式。

頻率學派:研究的是事件自己,因此研究者只能反覆試驗去逼近它從而獲得結果。好比:想要計算拋擲一枚硬幣時正面朝上的機率,咱們須要不斷地拋擲硬幣,當拋擲次數趨向無窮時正面朝上的頻率即爲正面朝上的機率。

貝葉斯學派:研究的是觀察者對事物的見解,因此你能夠用先驗知識和收集到的信息去描述他,而後用一些證據去證實它。仍是好比拋硬幣,當小明知道一枚硬幣是均勻的,而後賦予下一次拋出結果是正面或反面都是50%的可信度(機率分佈),多是出於認爲均勻硬幣最多見這種信念,而後好比小明隨機拋了1000次,發現結果正是這樣,那麼它就經過這些證據驗證了本身的先驗知識。(也有存在修改的時候,好比發現硬幣的材質不一致,總之就是這麼一個過程)

舉個例子

假設有兩個各裝了100個球的箱子,甲箱子中有70個紅球,30個綠球,乙箱子中有30個紅球,70個綠球。假設隨機選擇其中一個箱子,從中拿出一個球記下球色再放回原箱子,如此重複12次,記錄獲得8次紅球,4次綠球。問題來了,你認爲被選擇的箱子是甲箱子的機率有多大?

剛開始選擇甲乙兩箱子的先驗機率都是50%,由於是隨機二選一(這是貝葉斯定理二選一的特殊形式)。即有:

P(甲) = 0.5, P(乙) = 1 - P(甲);

這時在拿出一個球是紅球的狀況下,咱們就應該根據這個信息來更新選擇的是甲箱子的先驗機率:

P(甲|紅球1) = P(紅球|甲) × P(甲) / (P(紅球|甲) × P(甲) + (P(紅球|乙) × P(乙)))

P(紅球|甲):甲箱子中拿到紅球的機率

P(紅球|乙):乙箱子中拿到紅球的機率

所以在出現一個紅球的狀況下,選擇的是甲箱子的先驗機率就可被修正爲:

P(甲|紅球1) = 0.7 × 0.5 / (0.7 × 0.5 + 0.3 × 0.5) = 0.7

即在出現一個紅球以後,甲乙箱子被選中的先驗機率就被修正爲:

P(甲) = 0.7, P(乙) = 1 - P(甲) = 0.3;

如此重複,直到經歷8次紅球修正(機率增長),4此綠球修正(機率減小)以後,選擇的是甲箱子的機率爲:96.7%。

Python 代碼來解這個問題:

def bayesFunc(pIsBox1, pBox1, pBox2):
return (pIsBox1 * pBox1)/((pIsBox1 * pBox1) + (1 - pIsBox1) * pBox2)
def redGreenBallProblem():
pIsBox1 = 0.5
# consider 8 red ball
for i in range(1, 9):
pIsBox1 = bayesFunc(pIsBox1, 0.7, 0.3)
print " After red %d > in 甲 box: %f" % (i, pIsBox1)
# consider 4 green ball
for i in range(1, 5):
pIsBox1 = bayesFunc(pIsBox1, 0.3, 0.7)
print " After green %d > in 甲 box: %f" % (i, pIsBox1)
redGreenBallProblem()複製代碼

運行結果以下:

After red 1 > in 甲 box: 0.700000
After red 2 > in 甲 box: 0.844828
After red 3 > in 甲 box: 0.927027
After red 4 > in 甲 box: 0.967365
After red 5 > in 甲 box: 0.985748
After red 6 > in 甲 box: 0.993842
After red 7 > in 甲 box: 0.997351
After red 8 > in 甲 box: 0.998863
After green 1 > in 甲 box: 0.997351
After green 2 > in 甲 box: 0.993842
After green 3 > in 甲 box: 0.985748
After green 4 > in 甲 box: 0.967365複製代碼

很明顯能夠看到紅球的出現是增長選擇甲箱子的機率,而綠球則相反。

3、樸素貝葉斯算法

樸素貝葉斯(Naive Bayesian)是基於貝葉斯定理和特徵條件獨立假設的分類方法,它經過特徵計算分類的機率,選取機率大的狀況進行分類,所以它是基於機率論的一種機器學習分類方法。由於分類的目標是肯定的,因此也是屬於監督學習。樸素貝葉斯假設各個特徵之間相互獨立,因此稱爲樸素。它簡單、易於操做,基於特徵獨立性假設,假設各個特徵不會相互影響,這樣就大大減少了計算機率的難度。

  1. 樸素貝葉斯算法的執行流程以下:
    1)設
    爲待分類項,其中a爲x的一個特徵屬性

2)類別集合爲:

3)根據貝葉斯公式,計算

4)若是,則x屬於這一類.

  1. 高斯樸素貝葉斯(通常使用在特徵屬性連續的狀況下)
上面的算法流程中能夠看出,樸素貝葉斯算法就是對貝葉斯公式的一種運用,它沒有進行任何的改變.

複製代碼
在計算條件機率時,對於離散的數據特徵可使用大數定理(頻率代替機率的思想).可是,怎麼處理連續的特徵呢?這裏咱們通常使用高斯樸素貝葉斯.

複製代碼

所謂高斯樸素貝葉斯,就是當特徵屬性爲連續值而且服從高斯分佈時,可使用高斯分佈的機率公式直接計算條件機率的值。

![](http://pv7b47pv6.bkt.clouddn.com/FgRK7v56zRYRJxTGhcPZNSSYkze6)複製代碼
此時,咱們只須要計算各個類別下的特徵劃分的均值和標準差.

複製代碼
  1. 多項式樸素貝葉斯(通常使用在特徵屬性離散的狀況下)
所謂多項式樸素貝葉斯,就是特徵屬性服從多項式分佈,進而對於每個類別y,參數![](http://pv7b47pv6.bkt.clouddn.com/Fq7i2mbWOItWwUyfuu79mCX9B4Oa)
,其中n爲特徵屬性數目,那麼P(xi|y)的機率爲θyi。複製代碼

  1. 伯努利樸素貝葉斯(通常使用在缺失值較多的狀況下)
與多項式模型同樣,伯努利模型適用於離散特徵的狀況,所不一樣的是,伯努利模型中每一個特徵的取值只能是1和0(以文本分類爲例,某個單詞在文檔中出現過,則其特徵值爲1,不然爲0).複製代碼

4、樸素貝葉斯實戰

sklearn中有3種不一樣類型的樸素貝葉斯:

高斯分佈型:用於classification問題,假定屬性/特徵服從正態分佈的。

多項式型:用於離散值模型裏。好比文本分類問題裏面咱們提到過,咱們不光看詞語是否在文本中出現,也得看出現次數。若是總詞數爲n,出現詞數爲m的話,有點像擲骰子n次出現m次這個詞的場景。

伯努利型:最後獲得的特徵只有0(沒出現)和1(出現過)。

極簡Scikit-Learn入門

例1 咱們使用iris數據集進行分類

from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import cross_val_score
from sklearn import datasets
iris = datasets.load_iris()
gnb = GaussianNB()
scores=cross_val_score(gnb, iris.data, iris.target, cv=10)
print("Accuracy:%.3f"%scores.mean())複製代碼

輸出: Accuracy:0.953

例2 Kaggle比賽之「舊金山犯罪分類預測」

題目背景:『水深火熱』的大米國,在舊金山這個地方,一度犯罪率還挺高的,而後不少人都經歷過大到暴力案件,小到東西被偷,車被劃的事情。當地警方也是努力地去總結和想辦法下降犯罪率,一個挑戰是在給出犯罪的地點和時間的以後,要第一時間肯定這多是一個什麼樣的犯罪類型,以肯定警力等等。後來乾脆一不作二不休,直接把12年內舊金山城內的犯罪報告都丟帶Kaggle上,說『你們折騰折騰吧,看看誰能幫忙第一時間預測一下犯罪類型』。犯罪報告裏面包括日期,描述,星期幾,所屬警區,處理結果,地址,GPS定位等信息。固然,分類問題有不少分類器能夠選擇,咱們既然剛講過樸素貝葉斯,恰好就拿來練練手好了。

(1) 首先咱們來看一下數據

import pandas as pd  
import numpy as np  
from sklearn import preprocessing  
from sklearn.metrics import log_loss  
from sklearn.cross_validation import train_test_split
train = pd.read_csv('/Users/liuming/projects/Python/ML數據/Kaggle舊金山犯罪類型分類/train.csv', parse_dates = ['Dates'])  
test = pd.read_csv('/Users/liuming/projects/Python/ML數據/Kaggle舊金山犯罪類型分類/test.csv', parse_dates = ['Dates'])  
train  複製代碼

咱們依次解釋一下每一列的含義:

Date: 日期Category: 犯罪類型,好比 Larceny/盜竊罪 等.Descript: 對於犯罪更詳細的描述DayOfWeek: 星期幾PdDistrict: 所屬警區Resolution: 處理結果,好比說『逮捕』『逃了』Address: 發生街區位置X and Y: GPS座標train.csv中的數據時間跨度爲12年,包含了將近90w的記錄。另外,這部分數據,你們從上圖上也能夠看出來,大部分都是『類別』型,好比犯罪類型,好比星期幾。(2)特徵預處理sklearn.preprocessing模塊中的 LabelEncoder函數能夠對類別作編號,咱們用它對犯罪類型作編號;pandas中的get_dummies( )能夠將變量進行二值化01向量,咱們用它對」街區「、」星期幾「、」時間點「進行因子化。

#對犯罪類別:Category; 用LabelEncoder進行編號  
leCrime = preprocessing.LabelEncoder()  
crime = leCrime.fit_transform(train.Category)   #39種犯罪類型  
#用get_dummies因子化星期幾、街區、小時等特徵  
days=pd.get_dummies(train.DayOfWeek)  
district = pd.get_dummies(train.PdDistrict)  
hour = train.Dates.dt.hour  
hour = pd.get_dummies(hour)  
#組合特徵  
trainData = pd.concat([hour, days, district], axis = 1)  #將特徵進行橫向組合  
trainData['crime'] = crime   #追加'crime'列  
days = pd.get_dummies(test.DayOfWeek)  
district = pd.get_dummies(test.PdDistrict)  
hour = test.Dates.dt.hour  
hour = pd.get_dummies(hour)  
testData = pd.concat([hour, days, district], axis=1)  
trainData 複製代碼

特徵預處理後,訓練集feature,以下圖所示:

(3) 建模

from sklearn.naive_bayes import BernoulliNB
import time
features=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'BAYVIEW', 'CENTRAL', 'INGLESIDE', 'MISSION',  
 'NORTHERN', 'PARK', 'RICHMOND', 'SOUTHERN', 'TARAVAL', 'TENDERLOIN']  
X_train, X_test, y_train, y_test = train_test_split(trainData[features], trainData['crime'], train_size=0.6)  
NB = BernoulliNB()  
nbStart = time.time()  
NB.fit(X_train, y_train)  
nbCostTime = time.time() - nbStart  
#print(X_test.shape)  
propa = NB.predict_proba(X_test)   #X_test爲263415*17;那麼該行就是將263415分到39種犯罪類型中,每一個樣本被分到每一種的機率  
print("樸素貝葉斯建模%.2f秒"%(nbCostTime))  
predicted = np.array(propa)  
logLoss=log_loss(y_test, predicted)  
print("樸素貝葉斯的log損失爲:%.6f"%logLoss)  複製代碼

輸出:樸素貝葉斯建模0.55秒樸素貝葉斯的log損失爲:2.582561

例3 文本分類——垃圾郵件過濾

收集數據:提供文本文件準備數據:將文本文件解析成詞條向量分析數據;檢查詞條確保解析的正確性訓練算法:使用以前創建的trainNB0()函數測試算法:使用classifyNB(),而且構建一個新的測試函數來計算文檔集的錯誤率使用算法:構建一個完整的程序對一組文檔進行分類,將錯分的文檔輸出到屏幕上

準備數據:切分文本

使用正則表達式切分,其中分隔符是除單詞、數字外的任意字符

import re
mySent = 'This book is the best book on Python or M.L. I have ever laid eyes upon.'
regEx = re.compile('\\W*')
listOfTokens = regEx.split(mySent)
# 去掉長度小於0的單詞,並轉換爲小寫
[tok.lower() for tok in listOfTokens if len(tok) > 0]
[out]
['this', 'book', 'is', 'the', 'best', 'book', 'on', 'python', 'or', 'm', 'l', 'i', 'have', 'ever', 'laid', 'eyes', 'upon']複製代碼

切分郵件

emailText = open('email/ham/6.txt').read()
listOfTokens = regEx.split(emailText)複製代碼

測試算法:使用樸素貝葉斯進行交叉驗證

import randomdef textParse(bigString):
    '''
    字符串解析
    '''
    import re    # 根據非數字字母的任意字符進行拆分
    listOfTokens = re.split(r'\W*', bigString)    # 拆分後字符串長度大於2的字符串,並轉換爲小寫
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]def spamTest():
    '''
    貝葉斯分類器對垃圾郵件進行自動化處理
    '''
    docList = []
    classList = []
    fullText = []    for i in range(1, 26):        # 讀取spam文件夾下的文件,並轉換爲特徵和標籤向量
        wordList = textParse(open('email/spam/%d.txt' % i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)        # 讀取ham文件夾下的文件,並轉換爲特徵和標籤向量
        wordList = textParse(open('email/ham/%d.txt' % i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)    # 轉換爲詞列表
    vocabList = createVocabList(docList)    # 初始化訓練集和測試集
    trainingSet = range(50);
    testSet = []    # 隨機抽取測試集索引
    for i in range(10):
        randIndex = int(random.uniform(0, len(trainingSet)))
        testSet.append(trainingSet[randIndex])        del(trainingSet[randIndex])

    trainMat = []
    trainClasses = []    # 構造訓練集
    for docIndex in trainingSet:
        trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))
        trainClasses.append(classList[docIndex])    # 樸素貝葉斯分類模型訓練
    p0V, p1V, pSpam = trainNB0(np.array(trainMat), np.array(trainClasses))
    errorCount = 0

    # 樸素貝葉斯分類模型測試
    for docIndex in testSet:
        wordVector = setOfWords2Vec(vocabList, docList[docIndex])        if classifyNB(np.array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
            errorCount += 1
            print 'classification error', docList[docIndex]    print 'the error rate is: ',float(errorCount)/len(testSet)複製代碼

因爲SpamTest()構造的測試集和訓練集是隨機的,因此每次運行的分類結果可能不同。若是發生錯誤,函數會輸出錯分文檔的詞表,這樣就能夠了解到底哪篇文檔發生了錯誤。這裏出現的錯誤是將垃圾郵件誤判爲了正常郵件。

import randomdef textParse(bigString):
    '''
    字符串解析
    '''
    import re    # 根據非數字字母的任意字符進行拆分
    listOfTokens = re.split(r'\W*', bigString)    # 拆分後字符串長度大於2的字符串,並轉換爲小寫
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]def spamTest():
    '''
    貝葉斯分類器對垃圾郵件進行自動化處理
    '''
spamTest()
[out]
classification error ['benoit', 'mandelbrot', '1924', '2010', 'benoit', 'mandelbrot', '1924', '2010', 'wilmott', 'team', 'benoit', 'mandelbrot', 'the', 'mathematician', 'the', 'father', 'fractal', 'mathematics', 'and', 'advocate', 'more', 'sophisticated', 'modelling', 'quantitative', 'finance', 'died', '14th', 'october', '2010', 'aged', 'wilmott', 'magazine', 'has', 'often', 'featured', 'mandelbrot', 'his', 'ideas', 'and', 'the', 'work', 'others', 'inspired', 'his', 'fundamental', 'insights', 'you', 'must', 'logged', 'view', 'these', 'articles', 'from', 'past', 'issues', 'wilmott', 'magazine']
the error rate is:  0.1spamTest()
[out]
the error rate is:  0.0複製代碼

參考文獻:

https://blog.csdn.net/fisherming/article/details/79509025https://blog.csdn.net/qq_32241189/article/details/80194653http://blog.csdn.net/kesalin/article/details/40370325

相關文章
相關標籤/搜索