监督学习 | 朴素贝叶斯之Sklearn实现
文章目錄
- 1. Sklearn 實(shí)現(xiàn)樸素貝葉斯
- 1.1 數(shù)據(jù)導(dǎo)入
- 1.2 數(shù)據(jù)預(yù)處理
- 1.3 拆分訓(xùn)練集和測(cè)試集
- 1.4 Bag of Words
- 1.4.1 Sklearn 實(shí)現(xiàn) Bag of Words:CountVectorizer
- 1.4.1.1 count_vector = CountVectorizer(lowercase='True', token_pattern, stop_words)
- 1.4.1.2 count_vector.fit(data)
- 1.4.1.3 count_vector.transform(data)
- 1.4.1.4 結(jié)果可視化:
- 1.5 使用 Scikit-learn 實(shí)現(xiàn)樸素貝葉斯
- 1.6 評(píng)估模型
- 2. 總結(jié)
- 參考資料
相關(guān)文章:
機(jī)器學(xué)習(xí) | 目錄
監(jiān)督學(xué)習(xí) | 樸素貝葉斯原理及Python實(shí)現(xiàn)
1. Sklearn 實(shí)現(xiàn)樸素貝葉斯
1.1 數(shù)據(jù)導(dǎo)入
使用來(lái)自 UCI 機(jī)器學(xué)習(xí)資源庫(kù)中的數(shù)據(jù)集,該資源庫(kù)有大量供實(shí)驗(yàn)性研究的數(shù)據(jù)集。這是直接數(shù)據(jù)鏈接。
下面是該數(shù)據(jù)的預(yù)覽:
數(shù)據(jù)集中的列目前沒有命名,可以看出有 2 列。
第一列有兩個(gè)值:“ham”,表示信息不是垃圾信息,以及“spam”,表示信息是垃圾信息。
第二列是被分類的信息的文本內(nèi)容。
首先導(dǎo)入數(shù)據(jù):
import pandas as pd df = pd.read_csv('smsspamcollection/SMSSpamCollection',sep='\t', header=None, names=['label', 'sms_message']) df.head(5)| ham | Go until jurong point, crazy.. Available only ... |
| ham | Ok lar... Joking wif u oni... |
| spam | Free entry in 2 a wkly comp to win FA Cup fina... |
| ham | U dun say so early hor... U c already then say... |
| ham | Nah I don't think he goes to usf, he lives aro... |
1.2 數(shù)據(jù)預(yù)處理
我們已經(jīng)大概了解數(shù)據(jù)集的結(jié)構(gòu),現(xiàn)在將標(biāo)簽轉(zhuǎn)換為二元變量,0 表示“ham”(即非垃圾信息),1表示“spam”,這樣比較方便計(jì)算。
由于Scikit-learn 只處理數(shù)字值,因此如果標(biāo)簽值保留為字符串,scikit-learn 會(huì)自己進(jìn)行轉(zhuǎn)換(更確切地說,字符串標(biāo)簽將轉(zhuǎn)型為未知浮點(diǎn)值)。
如果標(biāo)簽保留為字符串,模型依然能夠做出預(yù)測(cè),但是稍后計(jì)算效果指標(biāo)(例如計(jì)算精確率和召回率分?jǐn)?shù))時(shí)可能會(huì)遇到問題。因此,為了避免稍后出現(xiàn)意外的陷阱,最好將分類值轉(zhuǎn)換為整數(shù),再傳入模型中。
說明:
- 使用映射方法將“標(biāo)簽”列中的值轉(zhuǎn)換為數(shù)字值,如下所示:
{‘ham’:0, ‘spam’:1} 這樣會(huì)將“ham”值映射為 0,將“spam”值映射為 1。 - 此外,為了知道我們正在處理的數(shù)據(jù)集有多大,使用“shape”輸出行數(shù)和列數(shù)
| 0 | Go until jurong point, crazy.. Available only ... |
| 0 | Ok lar... Joking wif u oni... |
| 1 | Free entry in 2 a wkly comp to win FA Cup fina... |
| 0 | U dun say so early hor... U c already then say... |
| 0 | Nah I don't think he goes to usf, he lives aro... |
1.3 拆分訓(xùn)練集和測(cè)試集
說明:
通過在 sklearn 中使用 train_test_split 方法,將數(shù)據(jù)集拆分為訓(xùn)練集和測(cè)試集。使用以下變量拆分?jǐn)?shù)據(jù):
- X_train 是 ‘sms_message’ 列的訓(xùn)練數(shù)據(jù)。
- y_train 是 ‘label’ 列的訓(xùn)練數(shù)據(jù)
- X_test 是 ‘sms_message’ 列的測(cè)試數(shù)據(jù)。
- y_test 是 ‘label’ 列的測(cè)試數(shù)據(jù)。
輸出每個(gè)訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)的行數(shù)。
1.4 Bag of Words
我們的數(shù)據(jù)集中有大量文本數(shù)據(jù)(572 行數(shù)據(jù))。大多數(shù)機(jī)器學(xué)習(xí)算法都要求傳入的輸入是數(shù)字?jǐn)?shù)據(jù),而電子郵件/信息通常都是文本。
現(xiàn)在我們要介紹 Bag of Words (BoW) 這個(gè)概念,它用來(lái)表示要處理的問題具有“大量單詞”或很多文本數(shù)據(jù)。BoW 的基本概念是拿出一段文本,計(jì)算該文本中單詞的出現(xiàn)頻率。注意:BoW 平等地對(duì)待每個(gè)單詞,單詞的出現(xiàn)順序并不重要。
利用我們將介紹的流程,我們可以將文檔集合轉(zhuǎn)換成矩陣,每個(gè)文檔是一行,每個(gè)單詞(令牌)是一列,對(duì)應(yīng)的(行,列)值是每個(gè)單詞或令牌在此文檔中出現(xiàn)的頻率。
例如:
X_train.head() 710 4mths half price Orange line rental & latest c... 3740 Did you stitch his trouser 2711 Hope you enjoyed your new content. text stop t... 3155 Not heard from U4 a while. Call 4 rude chat pr... 3748 ü neva tell me how i noe... I'm not at home in... Name: sms_message, dtype: object我們的目標(biāo)是將這組文本轉(zhuǎn)換為頻率分布矩陣,如下所示:
從圖中可以看出,文檔在行中進(jìn)行了編號(hào),每個(gè)單詞是一個(gè)列名稱,相應(yīng)的值是該單詞在文檔中出現(xiàn)的頻率。
我們?cè)敿?xì)講解下,看看如何使用一小組文檔進(jìn)行轉(zhuǎn)換。
1.4.1 Sklearn 實(shí)現(xiàn) Bag of Words:CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer# Instantiate the CountVectorizer method count_vector = CountVectorizer(token_pattern='(?u)\\b\\w\\w+\\b', stop_words='english')# 擬合并轉(zhuǎn)換訓(xùn)練集(不能將測(cè)試集也fit,這違背了基本原則) training_data = count_vector.fit_transform(X_train)# Transform testing data and return the matrix. Note we are not fitting the testing data into the CountVectorizer() testing_data = count_vector.transform(X_test)1.4.1.1 count_vector = CountVectorizer(lowercase=‘True’, token_pattern, stop_words)
要處理這一步,我們使用 sklearns
count vectorizer 方法,該方法的作用如下所示:
- 它會(huì)令牌化字符串(將字符串劃分為單個(gè)單詞)并為每個(gè)令牌設(shè)定一個(gè)整型 ID。
- 它會(huì)計(jì)算每個(gè)令牌的出現(xiàn)次數(shù)。
參數(shù)設(shè)置:
- lowercase='True':CountVectorizer 方法會(huì)自動(dòng)將所有令牌化單詞轉(zhuǎn)換為小寫形式,避免區(qū)分“He”和“he”等單詞。
- token_pattern:CountVectorizer 方法會(huì)自動(dòng)忽略所有標(biāo)點(diǎn)符號(hào),避免區(qū)分后面有標(biāo)點(diǎn)的單詞(例如“hello!”)和前后沒有標(biāo)點(diǎn)的同一單詞(例如“hello”)token_pattern 參數(shù)具有默認(rèn)正則表達(dá)式值 (?u)\\b\\w\\w+\\b,它會(huì)忽略所有標(biāo)點(diǎn)符號(hào)并將它們當(dāng)做分隔符,并將長(zhǎng)度大于等于 2 的字母數(shù)字字符串當(dāng)做單個(gè)令牌或單詞。
- stop_words:停用詞是指某個(gè)語(yǔ)言中最常用的字詞,包括“am”、“an”、“and”、“the”等。 通過將此參數(shù)值設(shè)為 english,CountVectorizer 將自動(dòng)忽略(輸入文本中)出現(xiàn)在 scikit-learn 中的內(nèi)置英語(yǔ)停用詞列表中的所有單詞。這非常有用,因?yàn)楫?dāng)我們嘗試查找表明是垃圾內(nèi)容的某些單詞時(shí),停用詞會(huì)使我們的結(jié)論出現(xiàn)偏差。
1.4.1.2 count_vector.fit(data)
fit() 將文檔數(shù)據(jù)集與 CountVectorizer 對(duì)象進(jìn)行擬合
1.4.1.3 count_vector.transform(data)
transform() 方法會(huì)返回一個(gè) numpy 整數(shù)矩陣,可以使用 toarray() 將其轉(zhuǎn)換為數(shù)組
1.4.1.4 結(jié)果可視化:
get_feature_names() 方法會(huì)返回此數(shù)據(jù)集的特征名稱,即組成數(shù)據(jù)詞匯表的單詞集合。
transform() 方法會(huì)返回一個(gè) numpy 整數(shù)矩陣,可以使用 toarray() 將其轉(zhuǎn)換為數(shù)組
doc_array = count_vector.transform(X_train).toarray() count_vector.get_feature_names() frequency_matrix = pd.DataFrame(doc_array, columns=count_vector.get_feature_names()) frequency_matrix.head(5)| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 7204 columns
1.5 使用 Scikit-learn 實(shí)現(xiàn)樸素貝葉斯
-
GaussianNB[1]:應(yīng)用于任意連續(xù)數(shù)據(jù)
-
Bernoullinb:假定輸入數(shù)據(jù)為二分類數(shù)據(jù)(主要用于文本數(shù)據(jù)分類)
-
MultinomialNB:假定輸入數(shù)據(jù)為計(jì)數(shù)數(shù)據(jù)(主要用于文本數(shù)據(jù)分類)
1.6 評(píng)估模型
我們已經(jīng)對(duì)測(cè)試集進(jìn)行了預(yù)測(cè),下一個(gè)目標(biāo)是評(píng)估模型的效果。我們可以采用各種衡量指標(biāo),但首先快速總結(jié)下這些指標(biāo)。
準(zhǔn)確率衡量的是分類器做出正確預(yù)測(cè)的概率,即正確預(yù)測(cè)的數(shù)量與預(yù)測(cè)總數(shù)(測(cè)試數(shù)據(jù)點(diǎn)的數(shù)量)之比。
精確率指的是分類為垃圾信息的信息實(shí)際上是垃圾信息的概率,即真正例(分類為垃圾內(nèi)容并且實(shí)際上是垃圾內(nèi)容的單詞)與所有正例(所有分類為垃圾內(nèi)容的單詞,無(wú)論是否分類正確)之比,換句話說,是以下公式的比值結(jié)果:
[True Positives/(True Positives + False Positives)]
召回率(敏感性)表示實(shí)際上為垃圾信息并且被分類為垃圾信息的信息所占比例,即真正例(分類為垃圾內(nèi)容并且實(shí)際上是垃圾內(nèi)容的單詞)與所有為垃圾內(nèi)容的單詞之比,換句話說,是以下公式的比值結(jié)果:
[True Positives/(True Positives + False Negatives)]
對(duì)于偏態(tài)分類分布問題(我們的數(shù)據(jù)集就屬于偏態(tài)分類),例如如果有 100 條信息,只有 2 條是垃圾信息,剩下的 98 條不是,則準(zhǔn)確率本身并不是很好的指標(biāo)。我們將 90 條信息分類為非垃圾信息(包括 2 條垃圾信息,但是我們將其分類為非垃圾信息,因此它們屬于假負(fù)例),并將 10 條信息分類為垃圾信息(所有 10 條都是假正例),依然會(huì)獲得比較高的準(zhǔn)確率分?jǐn)?shù)。對(duì)于此類情形,精確率和召回率非常實(shí)用。可以通過這兩個(gè)指標(biāo)獲得 F1 分?jǐn)?shù),即精確率和召回率分?jǐn)?shù)的加權(quán)平均值。該分?jǐn)?shù)的范圍是 0 到 1,1 表示最佳潛在 F1 分?jǐn)?shù)。
我們將使用所有四個(gè)指標(biāo)確保我們的模型效果很好。這四個(gè)指標(biāo)的值范圍都在 0 到 1 之間,分?jǐn)?shù)盡量接近 1 可以很好地表示模型的效果如何。
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score print('Accuracy score: ', format(accuracy_score(y_test, predictions))) print('Precision score: ', format(precision_score(y_test, predictions))) print('Recall score: ', format(recall_score(y_test, predictions))) print('F1 score: ', format(f1_score(y_test, predictions))) Accuracy score: 0.9877961234745154 Precision score: 0.9615384615384616 Recall score: 0.9459459459459459 F1 score: 0.95367847411444142. 總結(jié)
和其他分類算法相比,樸素貝葉斯具有的一大主要優(yōu)勢(shì)是能夠處理大量特征。在我們的示例中,有數(shù)千個(gè)不同的單詞,每個(gè)單詞都被當(dāng)做一個(gè)特征。此外,即使存在不相關(guān)的特征也有很好的效果,不容易受到這種特征的影響。另一個(gè)主要優(yōu)勢(shì)是相對(duì)比較簡(jiǎn)單。樸素貝葉斯完全可以直接使用,很少需要調(diào)整參數(shù),除非通常分布數(shù)據(jù)已知的情況需要調(diào)整。
它很少會(huì)過擬合數(shù)據(jù)。另一個(gè)重要優(yōu)勢(shì)是相對(duì)于它能處理的數(shù)據(jù)量來(lái)說,訓(xùn)練和預(yù)測(cè)速度很快。總之,樸素貝葉斯是非常實(shí)用的算法!
參考資料
[1] ls秦.Python機(jī)器學(xué)習(xí) — 樸素貝葉斯算法(Naive Bayes)[EB/OL].https://blog.csdn.net/qq_38328378/article/details/80771469, 2018-07-10.
總結(jié)
以上是生活随笔為你收集整理的监督学习 | 朴素贝叶斯之Sklearn实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言中字符数组的初始化与注意事项
- 下一篇: 6.5 不同类型的数据集