Python機器學習 — 樸素貝葉斯演算法(Naive Bayes)
一、樸素貝葉斯演算法 -- 簡介
樸素貝葉斯法是基於貝葉斯定理與特徵條件獨立假設的分類方法。最為廣泛的兩種分類模型是決策樹模型(Decision Tree Model)和樸素貝葉斯模型(Naive Bayesian Model,NBM)。
和決策樹模型相比,樸素貝葉斯分類器(Naive Bayes Classifier,或 NBC)發源於古典數學理論,有著堅實的數學基礎,以及穩定的分類效率。同時,NBC模型所需估計的引數很少,對缺失資料不太敏感,演算法也比較簡單。
理論上,NBC模型與其他分類方法相比具有最小的誤差率。但是實際上並非總是如此,這是因為NBC模型假設屬性之間相互獨立,這個假設在實際應用中往往是不成立的,這給NBC模型的正確分類帶來了一定影響。
演算法步驟:
1)收集資料;
2)準備資料:需要數值型或布林型資料。如果是文字檔案,要解析成詞條向量bai;
3)分析資料:有大量特徵時,用直方圖分析效果更好;
4)訓練演算法:計算不同的獨立特徵的條件概率;
5)測試演算法:計算錯誤率;
6)使用演算法:一個常見的樸素貝葉斯應用是文件分類。
二、貝葉斯定理
條件概率就是事件 A 在另外一個事件 B 已經發生條件下的發生概率。條件概率表示為P(A|B),讀作“在 B 發生的條件下 A 發生的概率”。
聯合概率表示兩個事件共同發生(數學概念上的交集)的概率。A 與 B 的聯合概率表示為。
推導:
我們可以從條件概率的定義推匯出貝葉斯定理。
根據條件概率的定義,在事件 B 發生的條件下事件 A 發生的概率為:
同樣地,在事件 A 發生的條件下事件 B 發生的概率為:
結合這兩個方程式,我們可以得到:
這個引理有時稱作概率乘法規則。上式兩邊同除以 P(A),若P(A)是非零的,我們可以得到貝葉斯定理:
三、高斯樸素貝葉斯(GaussianNB)
在高斯樸素貝葉斯中,每個特徵都是連續的,並且都呈高斯分佈。高斯分佈又稱為正態分佈。圖畫出來以後像一個倒掛的鐘,以均值為軸對稱,如下圖所示:
GaussianNB 實現了運用於分類的高斯樸素貝葉斯演算法。特徵的可能性(即概率)假設為高斯分佈:
引數和使用最大似然法估計。
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf = clf.fit(iris.data, iris.target)
y_pred=clf.predict(iris.data)
print("高斯樸素貝葉斯,樣本總數: %d 錯誤樣本數 : %d" % (iris.data.shape[0],(iris.target != y_pred).sum()))
四、多項分佈樸素貝葉斯(MultinomialNB)
MultinomialNB實現服從多項分佈資料(multinomially)的貝葉斯演算法,是一個經典的樸素貝葉斯文字分類中使用的變種(其中的資料是通常表示為詞向量的數量,雖然TF-IDF向量在實際專案中表現得很好),對於每一個y來說,分佈通過向量引數化,n是類別的數目(在文字分類中,表示詞彙量的長度) 表示標籤i出現的樣本屬於類別y的概率。
該引數 是一個平滑的最大似然估計,即相對頻率計數:
表示標籤i在樣本集T中屬於類別y的 數目
表示在所有標籤中類別y出現的數目
先驗平滑先驗 α >=0表示學習樣本中不存在的特徵並防止在計算中概率為0,設定 α = 1被稱為拉普拉斯平滑(Lapalce smoothing),當α<1稱為利德斯通平滑(Lidstone smoothing)
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB()
clf = clf.fit(iris.data, iris.target)
y_pred=clf.predict(iris.data)
print("多項分佈樸素貝葉斯,樣本總數: %d 錯誤樣本數 : %d" % (iris.data.shape[0],(iris.target != y_pred).sum()))
引數說明如下:
alpha:浮點型可選引數,預設為1.0,其實就是新增拉普拉斯平滑,即為上述公式中的λ ,如果這個引數設定為0,就是不新增平滑;
fit_prior:布林型可選引數,預設為True。布林引數fit_prior表示是否要考慮先驗概率,如果是false,則所有的樣本類別輸出都有相同的類別先驗概率。否則可以自己用第三個引數class_prior輸入先驗概率,或者不輸入第三個引數class_prior讓MultinomialNB自己從訓練集樣本來計算先驗概率,此時的先驗概率為P(Y=Ck)=mk/m。其中m為訓練集樣本總數量,mk為輸出為第k類別的訓練集樣本數。
class_prior:可選引數,預設為None。
總結如下:
fit_prior class_prior 最終先驗概率
False 填或不填沒有意義 P(Y = Ck) = 1 / k
True 不填 P(Y = Ck) = mk / m
True 填 P(Y = Ck) = class_prior
五、伯努利分佈樸素貝葉斯(BernoulliNB)
BernoulliNB 實現了用於多重伯努利分佈資料的樸素貝葉斯訓練和分類演算法,即有多個特徵,但每個特徵 都假設是一個二元 (Bernoulli, boolean) 變數。 因此,這類演算法要求樣本以二元值特徵向量表示;如果樣本含有其他型別的資料, 一個 BernoulliNB 例項會將其二值化(取決於 binarize 引數)。
伯努利樸素貝葉斯的決策規則基於:
與多項分佈樸素貝葉斯的規則不同 伯努利樸素貝葉斯明確地懲罰類 y 中沒有出現作為預測因子的特徵 i ,而多項分佈分佈樸素貝葉斯只是簡單地忽略沒出現的特徵。
在文字分類的例子中,詞頻向量(word occurrence vectors)(而非詞數向量(word count vectors))可能用於訓練和用於這個分類器。 BernoulliNB 可能在一些資料集上可能表現得更好,特別是那些更短的文件。 如果時間允許,建議對兩個模型都進行評估。
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import BernoulliNB
clf = BernoulliNB()
clf = clf.fit(iris.data, iris.target)
y_pred=clf.predict(iris.data)
print("伯努利樸素貝葉斯,樣本總數: %d 錯誤樣本數 : %d" % (iris.data.shape[0],(iris.target != y_pred).sum()))
六、樸素貝葉斯 -- 程式碼實現
對於新聞分類,屬於多分類問題。我們可以使用MultinamialNB()完成我們的新聞分類問題。
import numpy as np
"""
這個指南的目的是在一個實際任務上探索scikit-learn的主要工具,在二十個不同的主題上分析一個文字集合。
在這一節中,可以看到:
1、載入文字檔案和類別
2、適合機器學習的特徵向量提取
3、訓練線性模型進行分類
4、使用網格搜尋策略,找到一個很好的配置的特徵提取元件和分類器
"""
"""
1、Loading the 20 newsgroups dataset 載入20個新聞組資料集
為了獲得更快的執行時間為第一個例子,我們將工作在部分資料集只有4個類別的資料集中:
"""
categories = ['alt.atheism', 'soc.religion.christian', 'comp.graphics', 'sci.med']
from sklearn.datasets import fetch_20newsgroups
twenty_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)
print(twenty_train.target)
print(twenty_train.target_names) # 訓練集中類別的名字,這裡只有四個類別
print(len(twenty_train.data)) # 訓練集中資料的長度
print(len(twenty_train.filenames)) # 訓練集檔名長度
print('-----')
print("\n".join(twenty_train.data[0].split("\n")[:3]))
print('-----')
print(twenty_train.target_names[twenty_train.target[0]])
print('-----')
print(twenty_train.target[:10]) # 前十個的類別
print('-----')
for t in twenty_train.target[:10]:
print(twenty_train.target_names[t]) # 類別的名字
print('-----')
"""
2、Extracting features from text files 從文字檔案中提取特徵
為了在文字檔案中使用機器學習演算法,首先需要將文字內容轉換為數值特徵向量
"""
"""
Bags of words 詞袋
最直接的方式就是詞袋錶示法
1、為訓練集的任何文件中的每個單詞分配一個固定的整數ID(例如通過從字典到整型索引建立字典)
2、對於每個文件,計算每個詞出現的次數,並儲存到X[i,j]中。
詞袋錶示:n_features 是語料中不同單詞的數量,這個數量通常大於100000.
如果 n_samples == 10000,儲存X的陣列就需要10000*10000*4byte=4GB,這麼大的儲存在今天的計算機上是不可能實現的。
幸運的是,X中的大多數值都是0,基於這種原因,我們說詞袋是典型的高維稀疏資料集,我們可以只儲存那些非0的特徵向量。
scipy.sparse 矩陣就是這種資料結構,而scikit-learn內建了這種資料結構。
"""
"""
Tokenizing text with scikit-learn 使用scikit-learn標記文字
文字處理、分詞、過濾停用詞都在這些高階元件中,能夠建立特徵字典並將文件轉換成特徵向量。
"""
from sklearn.feature_extraction.text import CountVectorizer # sklearn中的文字特徵提取元件中,匯入特徵向量計數函式
count_vect = CountVectorizer() # 特徵向量計數函式
X_train_counts = count_vect.fit_transform(twenty_train.data) # 對文字進行特徵向量處理
print(X_train_counts) # 特徵向量和特徵標籤
print(X_train_counts.shape) # 形狀
print('-----')
"""
CountVectorizer支援計算單詞或序列的N-grams,一旦合適,這個向量化就可以建立特徵詞典。
在整個訓練預料中,詞彙中的詞彙索引值與其頻率有關。
"""
print(count_vect.vocabulary_.get(u'algorithm'))
print('-----')
"""
From occurrences to frequencies 從事件到頻率
計數是一個好的開始,但是也存在一個問題:較長的文字將會比較短的文字有很高的平均計數值,即使他們所表示的話題是一樣的。
為了避免潛在的差異,它可以將文件中的每個單詞出現的次數在文件的總字數的比例:這個新的特徵叫做詞頻:tf
tf-idf:詞頻-逆文件頻率
"""
from sklearn.feature_extraction.text import TfidfTransformer # sklearn中的文字特徵提取元件中,匯入詞頻統計函式
tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts) # 建立詞頻統計函式,注意這裡idf=False
print(tf_transformer) # 輸出函式屬性 TfidfTransformer(norm=u'l2', smooth_idf=True, sublinear_tf=False, use_idf=False)
print('-----')
X_train_tf = tf_transformer.transform(X_train_counts) # 使用函式對文字文件進行tf-idf頻率計算
print(X_train_tf)
print('-----')
print(X_train_tf.shape)
print('-----')
"""
在上面的例子中,使用fit()方法來構建基於資料的預測器,然後使用transform()方法來將計數矩陣用tf-idf表示。
這兩個步驟可以通過跳過冗餘處理,來更快的達到相同的最終結果。
這些可以通過使用fit_transform()方法來實現:
"""
tfidf_transformer = TfidfTransformer() # 這裡使用的是tf-idf
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
print(X_train_tfidf)
print(X_train_tfidf.shape)
print('-----')
"""
Training a classifier 訓練一個分類器
既然已經有了特徵,就可以訓練分類器來試圖預測一個帖子的類別,先使用貝葉斯分類器,貝葉斯分類器提供了一個良好的基線來完成這個任務。
scikit-learn中包括這個分類器的許多變數,最適合進行單詞計數的是多項式變數。
"""
from sklearn.naive_bayes import MultinomialNB # 使用sklearn中的貝葉斯分類器,並且載入貝葉斯分類器
# 中的MultinomialNB多項式函式
clf = MultinomialNB() # 載入多項式函式
x_clf = clf.fit(X_train_tfidf, twenty_train.target) # 構造基於資料的分類器
print(x_clf) # 分類器屬性:MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
print('-----')
"""
為了預測輸入的新的文件,我們需要使用與前面相同的特徵提取鏈進行提取特徵。
不同的是,在轉換中,使用transform來代替fit_transform,因為訓練集已經構造了分類器
"""
docs_new = ['God is love', 'OpenGL on the GPU is fast'] # 文件
X_new_counts = count_vect.transform(docs_new) # 構建文件計數
X_new_tfidf = tfidf_transformer.transform(X_new_counts) # 構建文件tfidf
predicted = clf.predict(X_new_tfidf) # 預測文件
print(predicted) # 預測類別 [3 1],一個屬於3類,一個屬於1類
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, twenty_train.target_names[category])) # 將文件和類別名字對應起來
print('-----')
"""
Building a pipeline 建立管道
為了使向量轉換更加簡單(vectorizer => transformer => classifier),scikit-learn提供了pipeline類來表示為一個複合分類器
"""
from sklearn.pipeline import Pipeline
text_clf = Pipeline([('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', MultinomialNB())])
text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
print(text_clf) # 構造分類器,分類器的屬性
predicted = text_clf.predict(docs_new) # 預測新文件
print(predicted) # 獲取預測值
print('-----')
"""
分析總結:
1、載入資料集,主要是載入訓練集,用於對資料進行訓練
2、文字特徵提取:
對文字進行計數統計 CountVectorizer
詞頻統計 TfidfTransformer (先計算tf,再計算tfidf)
3、訓練分類器:
貝葉斯多項式訓練器 MultinomialNB
4、預測文件:
通過構造的訓練器進行構造分類器,來進行文件的預測
5、最簡單的方式:
通過使用pipeline管道形式,來講上述所有功能通過管道來一步實現,更加簡單的就可以進行預測
"""
"""
Evaluation of the performance on the test set 測試集效能評價
評估模型的預測精度同樣容易:
"""
import numpy as np
twenty_test = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)
docs_test = twenty_test.data
predicted = text_clf.predict(docs_test)
print(np.mean(predicted == twenty_test.target)) # 預測的值和測試值的比例,mean就是比例函式
print('-----') # 精度已經為0.834886817577
"""
精度已經實現了83.4%,那麼使用支援向量機(SVM)是否能夠做的更好呢,支援向量機(SVM)被廣泛認為是最好的文字分類演算法之一。
儘管,SVM經常比貝葉斯要慢一些。
我們可以改變學習方式,使用管道來實現分類:
"""
from sklearn.linear_model import SGDClassifier
text_clf = Pipeline(
[('vect', CountVectorizer()), ('tfidf', TfidfTransformer()),
('clf', SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3, n_iter=5, random_state=42))])
# _ = text_clf.fit(twenty_train.data, twenty_train.target) # 和下面一句的意思一樣,一個槓,表示本身
text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
predicted = text_clf.predict(docs_test)
print(np.mean(predicted == twenty_test.target)) # 精度 0.912782956059
print('-----')
"""
sklearn進一步提供了結果的更詳細的效能分析工具:
"""
from sklearn import metrics
print(metrics.classification_report(twenty_test.target, predicted, target_names=twenty_test.target_names))
print(metrics.confusion_matrix(twenty_test.target, predicted))
相關文章
- 機器學習演算法(二): 樸素貝葉斯(Naive Bayes)機器學習演算法AI
- Python機器學習筆記:樸素貝葉斯演算法Python機器學習筆記演算法
- 機器學習Sklearn系列:(四)樸素貝葉斯機器學習
- 機器學習之樸素貝葉斯分類機器學習
- 樸素貝葉斯和半樸素貝葉斯(AODE)分類器Python實現Python
- 樸素貝葉斯演算法演算法
- 機器學習經典演算法之樸素貝葉斯分類機器學習演算法
- 監督學習之樸素貝葉斯
- 100天搞定機器學習|Day15 樸素貝葉斯機器學習
- 樸素貝葉斯模型模型
- 分類演算法-樸素貝葉斯演算法
- 04_樸素貝葉斯演算法演算法
- 樸素貝葉斯分類
- ML-樸素貝葉斯
- 有監督學習——支援向量機、樸素貝葉斯分類
- 樸素貝葉斯與Laplace平滑
- 樸素貝葉斯—印第安人
- Sklearn中的樸素貝葉斯分類器`
- 《統計學習方法》——樸素貝葉斯程式碼實現
- 樸素貝葉斯/SVM文字分類文字分類
- 機器學習——貝葉斯演算法機器學習演算法
- 樸素貝葉斯演算法的實現與推理演算法
- [譯] Sklearn 中的樸素貝葉斯分類器
- 【資料科學系統學習】機器學習演算法 # 西瓜書學習記錄 [6] 樸素貝葉斯實踐資料科學機器學習演算法
- 樸素貝葉斯實現文件分類
- 簡單易懂的樸素貝葉斯分類演算法演算法
- 【機器學習基礎】樸素貝葉斯對B站彈幕分類(是否永久封禁)機器學習
- 機器學習(三):樸素貝葉斯+貝葉斯估計+BP人工神經網路習題手算|手工推導與習題計算機器學習神經網路
- 樸素貝葉斯深度解碼:從原理到深度學習應用深度學習
- 使用樸素貝葉斯過濾垃圾郵件
- 樸素貝葉斯分類流程圖介紹流程圖
- 高階人工智慧系列(一)——貝葉斯網路、機率推理和樸素貝葉斯網路分類器人工智慧
- HanLP-樸素貝葉斯分類預測缺陷HanLP
- 樸素貝葉斯--新浪新聞分類例項
- 【火爐煉AI】機器學習013-用樸素貝葉斯分類器估算個人收入階層AI機器學習
- 【火爐煉AI】機器學習010-用樸素貝葉斯分類器解決多分類問題AI機器學習
- 演算法金 | AI 基石,無處不在的樸素貝葉斯演算法演算法AI
- 【機器學習】--貝葉斯網路機器學習