4-5-機器學習-朴素貝葉斯算法(分類算法)


總結

貝葉斯算法

  • 我們希望模型在分類的時候不是直接返回分類,而是返回屬於某個分類的概率
  • 特征與特征之間條件獨立(特征之間無任何關聯),就可以使用貝葉斯算法,朴素指的就是條件獨立
  • 朴素貝葉斯模型常用於文本分類

在sk-learn中提供了三種不同類型的貝葉斯模型算法

  • 高斯模型(基於高斯分布實現分類概率的計算) - 連續型特征:from sklearn.naive_bayes import GaussianNB
    • 公式:  
    • 高斯分布,也就是正態分布,是一種連續型變量的概率分布(高手模型是用來處理連續型特征的)
    • 生活中有很多現象或事件發生的概率均服從正態分布
    • 高斯分布模型作用:通過訓練集樣本數據求出它的均值和標准差,有了這個倆個參數就可以估計某個特征屬於某個類別的條件概率,以最大化的P為目標,高斯函數會為我們求解公式中的參數𝜇y和𝛔y。求解出參數后,帶入一個xi的值,就能夠得到一個P的概率取值,然后將每一個特征分到每一個類別的最大概率進行標簽(類別)的均值計算和方差計算返回屬於每一個特征的權重系數w。
    • 模型作用簡單來說:可以幫我們把高斯函數中的均值𝜇y和標准差𝛔y求出來,有了這倆個參數就可以對高斯函數求解,將要預測的數據帶入高斯函數中,得出每個特征分到不同類別的條件概率。
    • 高斯函數作用:返回每個特征屬於不同類別的條件概率(將一個數據特征數據代入高斯函數,返回這個數據分到每個類別的概率)
  • 多項式模型 (類別較少的分類)- 離散型特征:from sklearn.naive_bayes import MultinomialNB
    • 公式:
    • 原理:(條件概率)在某個條件下求出某個東西的所屬類別,例如一篇文章可能屬於軍事,科技,人文等類別,在這些類別條件的下,求出它屬於某個類別的概率,取最大概率的類別作為它的類別
    • P(C):每個文檔類別的概率(某個文檔類別文章的數量/總文檔數量)
    • P(W|C):給定類別下特征的概率,此處的特征就是預測文檔中出現的詞語
      • P(W|C)的計算方法:
        • P(F1|C)=Ni/N:F1為預測文檔中的某一個詞,C為指定的類別
          • Ni:F1這個詞在C類別所有文檔中出現的次數
          • N:所屬類別C下的文檔所有詞出現的次數和
    • TF-IDF(詞頻-逆文檔頻率): from sklearn.feature_extraction.text import TfidfVectorizer
  • 伯努利模型(只能做二分類) - 特征數據為二項分布: from sklearn.naive_bayes import BernoulliNB
    • 作用:判斷某一文章是否屬於某一類別
    • 二值化操作:需要將特征轉化為二項分布,0,1

朴素貝葉斯算法

  • 概率基礎
  • 算法介紹

引出

  • 在許多分類算法應用中,特征和標簽之間的關系並非是決定性的。比如說,我們想預測一個人究竟是否會在泰坦尼克號海難中生存下來,那我們可以建立某個分類模型來學習我們的訓練集。在訓練中,其中一個人的特征為:30歲,男,普 通艙,他最后在泰坦尼克號海難中去世了。當我們測試的時候,我們發現有另一個人的特征也為:30歲,男,普通 艙。基於在訓練集中的學習,我們的模型必然會給這個人打上標簽:去世。然而這個人的真實情況一定是去世了嗎?並非如此。也許這個人是心臟病患者,得到了上救生艇的優先權。又有可能,這個人就是擠上了救生艇,活了下來。對分類算法 來說,基於訓練的經驗,這個人“很有可能”是沒有活下來,但算法永遠也無法確定”這個人一定沒有活下來“。即便這 個人最后真的沒有活下來,算法也無法確定基於訓練數據給出的判斷,是否真的解釋了這個人沒有存活下來的真實情況。
  • 這就是說,算法得出的結論,永遠不是100%確定的,更多的是判斷出了一種“樣本的標簽更可能是某類的可能性”,而非一種“確定”。我們通過模型算法的某些規定,來強行讓算法為我們返回一個固定的分類結果。但許多時候,我們也希望能夠理解算法判斷出結果的可能性概率。
  • 無論如何,我們都希望使用真正的概率來衡量可能性,因此就有了真正的概率算法:朴素貝葉斯。
  • 朴素貝葉斯是一種直接衡量標簽和特征之間的概率關系的有監督學習算法,是一種專注分類的算法。朴素貝葉斯的算法根源就是基於概率論和數理統計的貝葉斯理論,因此它是根正苗紅的概率模型。接下來,我們就來認識一下這個簡單快速的概率算法。
  • 現在我們對郵箱的郵件和文章進行分類:
    • 我們是直接將郵件分到指定類別好呢,還是計算出郵件屬於不同類別的概率好呢?

      image.png

    image.png

 上圖所示,哪個類別占的比例比較大,則將郵件或者文章歸為哪一類,這里的占比指的是分類的概率

概率基礎

  • 概念:概率定義為一件事情發生的可能性。
    • 扔一個硬幣,正面朝上
    • 某天是陰天

  image.png

  • 女神喜歡一個人的概率:
    • 4/7
  • 職業是程序員並且體型勻稱的概率:
    • 3/7 * 4/7 == 12/49
  • 在女神喜歡的條件下,職業是程序員的概率:
    • 1/2
  • 在女神喜歡的條件下,職業是產品,體重超重的概率:
    • 1/2 * 1/4 = 1/8
  • 概率計算准則:聯合概率和條件概率

    image.png

  • 注意:
    • 上述的求概率公式只適用於各個特征之間是條件獨立(每個特征之間沒有必然關系)的。條件不獨立指的是特征之間有關聯的比如,體重和是否喜歡吃零食這兩個條件之間就有關聯。
    • 朴素貝葉斯只適用於特征之間是條件獨立的情況下。否則分類效果不好。這里的朴素指的就是條件獨立
    • 朴素貝葉斯主要被廣泛的適用於文檔分類中!

朴素貝葉斯的分類

  • 在sk-learn中提供了三種不同類型的貝葉斯模型算法
    • 高斯模型
    • 多項式模型
    • 伯努利模型

高斯模型 (連續特征的概率計算)

  • 介紹:
    • 大家在學習高等數學時,應該學過高斯分布,也就是正態分布,是一種連續型變量的概率分布。簡單來說,高斯分布就是當頻率直方圖的區間變得特別小時的擬合曲線,像座小山峰,其中兩端的特別小,越往中間越高。
    • 所謂正態分布,就是正常形態的分布,它是自然界的一種規律。
      • 現實生活中有很多現象均服從高斯分布,比如收入,身高,體重等,大部分都處於中等水平,特別少和特別多的比例都會比較低。

高斯分布(正太分布)

  • 一起玩一個游戲拋硬幣,游戲規則為:
    • 定義每個拋出硬幣正面記+1分,反面記-1分
    • 此時我們可以得知拋一次硬幣為正面的概率和為反面的概率各位50%,那也就是會有一半概率+1分,一半概率-1分。
  • 如果我們連續拋10次硬幣,則得到的記分統計為:

    image.png

  • 當然,同樣畫個圖感受一下:

    image.png

  • 如果拋100次,甚至是無窮多次呢?平均分數分布情況大概是什么樣呢?畫個圖感受一下:

    image.png

  ---發現,某一事件發生的概率出現了正太分布

  • 為什么在我們的現實生活中正太分布如此常見呢?
    • 通常情況下一個事物的影響因素往往有多個,比如身高的影響有:
      • 家庭的飲食習慣
      • 家庭長輩的身高
      • 運動情況
      • ......
    • 其中的每一個因素,都會對身高產生一定的影響,要么是正向的影像,要么是反向的影響。所有因素最終讓整體身高接近於正太分布。
    • 在數學中正太分布往往被稱為高斯分布
  • 總結
    • 正太分布就是一種連續性變量的概率分布
    • 一個事件發生(樣本屬於哪個類別)的概率也滿足正太分布
  • 高斯分布
    • 通過假設P(xi|Y)是服從高斯分布(也就是正態分布),來估計訓練集數據的每個特征分到每個類別Y的條件概率P是多少(估計每個特征下對應每個類別的條件概率)。對於每個特征下的對應每個分類結果概率的取值,高斯朴素貝葉斯有如下公式:
    • exp函數為高等數學里以自然常數e為底的指數函數

      image.png

    • Y:分類的類別
    • x為分類的特征
    • 特征所屬標簽的均值(𝜇)和標准差(𝛔)
    • 每個特征x分到每個類別Y的條件概率P,比如一個人的身高,體重,三維三個特征,其中一個特征占這個丑美類別的概率
  • 什么是連續性變量和離散型變量
    • 離散變量:是指其數值只能用自然數或整數單位計算的則為離散變量.例如,企業個數,職工人數,設備台數等,只能按計量單位數計數,這種變量的數值一般用計數方法取得.
    • 連續性變量:在一定區間內可以任意取值的變量叫連續變量,其數值是連續不斷的,相鄰兩個數值可作無限分割,即可取無限個數值.例如,生產零件的規格尺寸,人體測量的身高,體重,胸圍等為連續變量,其數值只能用測量或計量的方法取得.
  • 高斯分布模型的作用:
    • 在貝葉斯分類中,高斯模型就是用來處理連續型特征變量的,當使用此模型時,我們會假定特征屬於高斯分布,然后基於訓練樣本計算特征所屬標簽的均值(𝜇)和標准差(𝛔)這樣就可以估計某個特征屬於某個類別的概率
      • 比如:判斷一個人帥還是丑,則帥&丑就是分類的標簽,一個人的特征假設有身高、體重,三圍,則高斯分布函數會計算身高的特征分到帥的條件概率P和丑的條件概率P,在計算體重的特征分到帥和丑的條件概率,以此類推。
    • 對於任意一個Y的取值,高斯函數都以求解最大化的P為目標,這樣我們才能夠比較在不同標簽下我們的樣本究竟更靠近哪一個取值。以最大化P為目標,高斯函數會為我們求解公式中的參數𝜇y和𝛔y。求解出參數后,帶入一個xi的值,就能夠得到一個P的概率取值。
      • 比如基於上述案例,將高斯函數將身高這個特征分到帥的概率為70%,分到丑的概率為30%,則基於最大化P的准則,高斯函數返回的結果為70%,就表示特征身高偏向於讓帶有身高特征的樣本數據分到帥的類別。剩下的體重和三維以此類推。然后將每一個特診分到每一個類別的最大概率進行標簽(類別)的均值計算和方差計算返回類似每一個特征的系數w。
        • 最后就相當於於基於訓練數據就可以求解出每一個特征對應的高斯函數的結果,該結果就表示該特征更偏向於將該條樣本分到哪一個類別,也可以將每一個特征的高斯函數返回值作為類似線性回歸中的系數w。

  

  • 高斯模型API
    • from sklearn.naive_bayes import GaussianNB
    • 實例化模型對象的時候,我們不需要對高斯朴素貝葉斯類輸入任何的參數,可以說是一個非常輕量級的類,操作非常容易。但過於簡單也意味着貝葉斯沒有太多的參數可以調整,因此貝葉斯算法的成長空間並不是太大,如果貝葉斯算法的效果不是太理想,我們一般都會考慮換模型。
    • predict_proba(): 給出每一個測試集樣本屬於每個類別的概率,最大的就是分類結果
    • predict_log_proba(): predict_proba的對數轉化,最大的就是分類結果

 將高斯模型作用到鳶尾花分類中

from sklearn.naive_bayes import GaussianNB
from sklearn import datasets
from sklearn.model_selection import train_test_split

# 提取樣本數據
iris = datasets.load_iris()
feature = iris.data
target = iris.target

# 切分數據
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)

# 訓練模型
g = GaussianNB()
g.fit(x_train, y_train)

g.score(x_test,y_test)  # 0.8333333333333334

# 查看第一條測試數據的分類
g.predict(x_test[0].reshape((1,-1)))   # array([2]) 屬於類別2

# 給出每一個測試集樣本屬於每個類別的概率,最大的就是分類結果
g.predict_proba(x_test[0].reshape((1,-1)))
# 下邊第一個數據對應分到0類別的概率,依次類推,得知第三個類別對應的概率最大,所以上邊返回的是2類別
array([[8.89223754e-234, 3.44645792e-009, 9.99999997e-001]])

# predict_proba的對數轉化,最大的就是分類結果
g.predict_log_proba(x_test[0].reshape((1,-1)))
array([[-5.36619733e+02, -1.94859188e+01, -3.44645801e-09]])

 高斯模型作用在手寫數字識別案例中

import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB

# 提取樣本數據
digist = datasets.load_digits()
feature = digist.data
target = digist.target

feature.shape  # (1797, 64)
target.shape  # (1797,)
feature[3]   # 8*8像素  1*64

# 切分數據
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.1,random_state=2020)

# 訓練模型
g = GaussianNB()
g.fit(x_train,y_train)
g.score(x_test,y_test)  # 0.8333333333333334

# 測試模型
y_pred = g.predict(x_test)
print('真實分類結果',y_test[:10])
print('模型分類結果',y_pred[:10])
真實分類結果 [4 3 6 4 8 7 2 2 1 2]
模型分類結果 [4 3 6 4 8 7 2 8 1 1]

y_test[3]  # 4

g.predict_log_proba(x_test[3].reshape((1,-1)))  # 需要傳入大寫X,單個元素是1維數據,需要變為2維

array([[-1.42975581e+03, -2.33112575e+01, -2.21201344e+02,
        -5.00236423e+02, -1.54472863e-05, -6.20715298e+01,
        -5.74683561e+02, -1.10780898e+01, -7.29616360e+01,
        -8.69033822e+01]])

g.predict_log_proba(x_test[3].reshape((1,-1))).max()
-1.5447286294545393e-05

多項式模型 (離散特征的概率計算)

  • 介紹:
    • 與高斯分布相反,多項式模型主要適用於離散特征的概率計算,且sklearn的多項式模型不接受輸入負值。雖然sk-learn中的多項式模型也可以被用作在連續性特征概率計算中,但是我們如果想要處理連續性變量則最好選擇使用高斯模型。
      • 注意:因為多項式不接受負值的輸入,所以如果樣本數據的特征為數值型數據的話,務必要進行歸一化處理保證特征數據中無負值出現!!!
  • 原理:計算出一篇文章為某些類別的概率(文章是固定的,也就是說在該文章為前提下求出所屬類別的概率,因此文章就是概率論中條件概率的條件),最大概率的類型就是該文章的類別。
    • P(類別|文章):類別可以為軍事,財經,體育等等,文章其實就是一個又一個的詞語
      • P(體育|詞1,詞2,詞3......)==1/6
      • P(財經|詞1,詞2,詞3......)==1/3
      • 則該文章屬於財經類別,那么P(財經|詞1,詞2,詞3......)如何計算值呢?如何計算多個條件下一個結果的概率呢?

    image.png

  • 朴素貝葉斯算法公式:

    image.png

    image.png

  • 細節解釋:
    • w為給定文檔的特征,也就是文章中拆分出來的不同詞語
    • c為文檔的類別(財經,體育,軍事......)
  • 那么:一篇文檔為財經和軍事的概率計算如下
    • P(財經|詞1,詞2,詞3)==》P(詞1,詞2,詞3|財經)*P(財經)/P(W)
    • P(軍事|詞1,詞2,詞3)==》P(詞1,詞2,詞3|軍事)*P(軍事)/P(W)
    • 上述兩個公式中都有想用的P(W),可以抵消,則公式簡化為:
      • P(詞1,詞2,詞3|財經)P(財經)==》P(W|C)P(C)
      • P(詞1,詞2,詞3|軍事)P(軍事)==>P(W|C)P(C)
      • 這樣的公式我們是可以進行計算的,這就是條件概率
    • P(C):每個文檔類別的概率(某個文檔類別文章的數量/總文檔數量)
    • P(W|C):給定類別下特征的概率,此處的特征就是預測文檔中出現的詞語
      • P(W|C)的計算方法:
        • P(F1|C)=Ni/N:F1為預測文檔中的某一個詞,C為指定的類別
          • Ni:F1這個詞在C類別所有文檔中出現的次數
          • N:所屬類別C下的文檔所有詞出現的次數和
  • 實例推導,請看題:

    image.png

  • 歸屬概率 = P(W|C)P(C)
  • 解釋:上圖的表格為訓練集的統計結果,訓練集中一共有30篇科技文章,60篇娛樂文章,共計90篇文章。這些文章中根據tf-idf提取出重要的詞語分別有(商場,影院,支付寶和雲計算),然后這些詞分別在不同訓練集中不同類別文章中出現的次數也統計出來了。
    • 現在有一個將要被預測的文章,該文章中出現重要的次為影院,支付寶和雲計算,則計算該文章屬於科技、娛樂的概率分別是多少?

    image.png

  • 思考:屬於某個類別的概率為0,合適嗎?
    • 肯定不合適,雖然被預測文章中沒有出現雲計算這個詞語,但是出現娛樂類別中的其他詞,所以概率為0不合適!那么如何處理呢?

      image.png

  • 多項式朴素貝葉斯API
    • from sklearn.naive_bayes import MultinomialNB
    • MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None)
      • alpha:拉普拉斯平滑系數
  • sklearn文本特征提取——TfidfVectorizer(求出Ni/N的值)
    • 什么是TF-IDF
      • 在信息檢索中,tf-idf(詞頻-逆文檔頻率)是一種統計方法,用以評估一個單詞在一個文檔集合或語料庫中的重要程度。
    • 原理:
      • TF-IDF實際上是:TF * IDF。主要思想是:如果某個詞或短語在一篇文章中出現的頻率高(即TF高),並且在其他文章中很少出現(即IDF高),則認為此詞或者短語具有很好的類別區分能力,適合用來分類。
    • TF:表示一個給定詞語t在一篇給定文檔d中出現的頻率。TF越高,則詞語t對文檔d來說越重要,TF越低,則詞語t對文檔d來說越不重要。那是否可以以TF作為文本相似度評價標准呢?答案是不行的,舉個例子,常用的中文詞語如“我”,“了”,“是”等,在給定的一篇中文文檔中出現的頻率是很高的,但這些中文詞幾乎在每篇文檔中都具有非常高的詞頻,如果以TF作為文本相似度評價標准,那么幾乎每篇文檔都能被命中。
      • TF(w)=(詞w在文檔中出現的次數)/(文檔的總詞數) == P(F1|C)=Ni/N
    • IDF:逆向文章頻率。有些詞可能在文本中頻繁出現,但並不重要,也即信息量小,如is,of,that這些單詞或者“我”,“了”,“是”等,這些單詞在語料庫中出現的頻率也非常大,我們就可以利用這點,降低其權重。

 實戰

數據使用- 實戰:數據使用fetch_20newsgroups中的數據,包含了20個主題的18000個新聞組的帖子

  • 流程:
    • 加載20類新聞數據,並進行樣本分割
    • 生成文章特征詞
    • 使用模型進行文章分類
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB

news = datasets.fetch_20newsgroups(data_home='./')
# 樣本數據提取
feature = news.data
target = news.target

# 特征抽取,對文章進行特征抽取,特征值化(TF_IDF)文檔抽取
# 參數,input可以手動寫內容
t = TfidfVectorizer()
feature_t = t.fit_transform(feature)  # 返回的是比例Ni/N

x_train,x_test,y_train,y_test = train_test_split(feature_t,target,test_size=0.01,random_state=2020)

m = MultinomialNB()
m.fit(x_train, y_train)

m.score(x_test,y_test)  # 0.8701413427561837

m.predict(x_test[10])  # array([4])

m.predict_log_proba(x_test[10]).max()  # -0.6914775692961541

伯努利模型BernoulliNB - (只能做二分類) - 特征數據為二項分布

  • 介紹
    • 多項式朴素貝葉斯可同時處理二項分布(拋硬幣)和多項分布(擲骰子),其中二項分布又叫做伯努利分布,它是一種現實中常見,並且擁有很多優越數學性質的分布。因此,既然有着多項式朴素貝葉斯,我們自然也就又專門用來處理二項分布的朴素貝葉斯:伯努利朴素貝葉斯。
    • 與多項式模型一樣,伯努利模型適用於離散特征的情況,所不同的是,數據集中可以存在多個特征,但每個特征都是二分類的.伯努利模型中每個特征的取值只能是1和0(以文本分類為例,某個單詞在文檔中出現過,則其特征值為1,否則為0).伯努利模型需要比MultinomialNB多定義一個二值化的方法,該方法會接受一個閾值並將輸入的特征二值化(1,0).當然也可以直接采用MultinomialNB,但需要預先將輸入的特征二值化.
  • 作用:
    • 伯努利朴素貝葉斯與多項式朴素貝葉斯非常相似,都常用於處理文本分類數據。但由於伯努利朴素貝葉斯是處理二項 分布,所以它更加在意的是“是與否”。判定一篇文章是否屬於體育資訊,而不是說屬於體育類還是娛樂類。
  • API:
    • class sklearn.naive_bayes.BernoulliNB (alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None)
    • 參數介紹:
      • alpha:拉普拉斯平滑系數
      • binarize:可以是數值或者不輸入。如果不輸入,則BernoulliNB認為每個數據特征都已經是二元(二值化)的。否則的話,小於binarize的會歸為一類,大於binarize的會歸為另外一類

二值化操作

# 將特征數據轉化為0,1
from sklearn import preprocessing
import numpy as np
 
X = np.array([[1,-2,2,3,1,10],
             [1,2,3,33,4,-90],
             [11,29,90,-80,0,4]])
binarizer = preprocessing.Binarizer(threshold=3)
X_binarizer = binarizer.transform(X)
print("二值化(閘值:5)",X_binarizer)

二值化(閘值:5) [[0 0 0 0 0 1]  # 大於5的轉化為1,小於轉化為0
 [0 0 0 1 1 0]
 [1 1 1 0 0 1]]

新聞案例應用

#樣本分割
feature = news.data#返回的是列表,列表中為一篇篇的文章
target = news.target#返回的ndarray,存儲的是每一篇文章的類別
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.25)

#對數據集進行特征抽取
tf = TfidfVectorizer()
x_train = tf.fit_transform(x_train)#返回訓練集所有文章中每個詞的重要性
x_test = tf.transform(x_test)#返回測試集所有文章中每個詞的重要性

# print(tf.get_feature_names())#所有文章中出現的詞語
mlt = BernoulliNB()
mlt.fit(x_train,y_train)
y_predict = mlt.predict(x_test)
print('預測文章類別為:',y_predict)
print('真是文章類別為:',y_test)
print('准確率為:',mlt.score(x_test,y_test))

預測文章類別為: [ 6 17  9 ...  5 11  3]
真是文章類別為: [16 17  9 ...  5 11  2]
准確率為: 0.6373276776246023

模型的優缺點

  

 

 

(只能做二分類) - 特征數據為二項分布


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM