【机器学习入门】(2) 朴素贝叶斯算法:原理、实例应用(文档分类预测)附python完整代码及数据集
各位同學好,今天我向大家介紹python機器學習中的樸素貝葉斯算法。內容有:算法的基本原理;案例實戰--新聞文檔的分類預測。
案例簡介:新聞數據有20個主題,有10萬多篇文章,每篇文章對應不同的主題,要求是任意輸入一篇新的文章,模型輸出這篇文章屬于哪個主題。
1. 算法原理
1.1 樸素貝葉斯方法
樸素貝葉斯方法涉及一些概率論知識,我們先來復習一下。
聯合概率:包含多個條件,并且所有的條件同時成立的概率,公式為:
條件概率:事件A在另一個事件B已經發生的前提下發生的概率,記作P(A|B),如果有多個條件,
那記作:
樸素貝葉斯一般公式:
我舉個小例子幫助大家理解:
某學校有N名學生,男生占60%,女生占40%。男生都留短發,女生一半留短發,一半留長發。
問題1:隨機一個學生,知道性別的情況下,他(她)留短發的概率是多少??
答:男:P(短發|男生)=1;女:P(短發|女生)=0.5
問題2:隨機一個學生,只知道他留短發,他是男生的概率是多少?
答:設 B=短發;A=男生
要求的是?
P(B|A)=1, P(A)=0.6, P(B)=0.6*1+0.4*0.5=0.8
P(A|B)=1*0.6/0.8=0.75
1.2 文檔分類方法
文檔分類是在已經分類好了的文檔中提取關鍵字,在以后遇到新的文檔時,從這些關鍵字中預測這篇新文章是哪個類別。
在文檔分類中,樸素貝葉斯公式為:
P(C|W)?:某個關鍵字屬于某個分類的概率
P(W|C)?:某個分類下,某個關鍵字出現的概率
P(C) :? ? ?某個類別的概率(某個類別的文檔數/總文檔數)
P(W) :??? 這個關鍵字在需要預測的文檔中出現的概率
1.3 拉普拉斯平滑系數
? ? ? ?假如現在有一新的篇文章,它的主題包括‘影院’‘云計算’等關鍵字,我計算它屬于娛樂類文章的概率。公式如下:
P(娛樂類|影院,云計算) = P(影院,云計算|娛樂類)*P(娛樂類)/P(影院,云計算),
其中P(影院,云計算|科技類)=P(影院|科技類)* P(云計算|科技類)
? ? ? ?然而對于預測之前建立的分類模型,如果在已經分類好的文章中娛樂類文章種沒有出現過云計算這個關鍵字,那么P(云計算|娛樂類)=0,導致P(影院,云計算|娛樂類)=0,結果就是一篇包括‘影院’‘云計算’等關鍵字的文章屬于娛樂類的概率為0,這肯定不對。只要它里面包含了任何一個和娛樂類相關的詞,都有可能是娛樂類。
?????? 因此引入拉普拉斯平滑系數來避免出現0概率的情況。方法如下:
將 P(W|C) 更改為?
Ni:該W詞在C類別所有文檔中出現的次數,即云計算在娛樂類文章中出現了多少次。
N: C類別的文檔所有詞出現的次數和,即娛樂類一共有多少詞。
a: 指定系數,一般為1。
m:訓練文檔中統計出現的特征詞個數,即整個文檔有多少詞。
1.4 特征向量化方法
將一篇文章中出現的所有詞進行特征向量化,將單詞提取出來,計算它們一共出現了多少次。首先要從sklearn庫中導入該方法?from sklearn.feature_extraction.text import CountVectorizer。
特征向量化方法:vect.fit_transform()
上式可理解為:fit表示提取特征,transform表示變成sparss矩陣
下面我用兩個字符串例子來演示一下這個方法:
# 導入特征向量化方法
from sklearn.feature_extraction.text import CountVectorizer
# 定義兩個字符串
word1 = 'i love python, python makes me happy'
word2 = 'hello world, i love the world'
# 變量vect接收特征向量化方法
vect = CountVectorizer()
# 將2個變量傳入特征向量化方法,用于提取每個單詞出現的次數
words = vect.fit_transform([word1,word2])
words變量接收的是sprase類型的矩陣,sparse矩陣只會標記word1和word2中不為0的地方,為0的地方不顯示,即空格符就不計數直接跳過。如'i','love'等詞,sparse矩陣會對這些詞進行標記,標記方式為該詞出現的次數。下面用代碼幫助大家理解。
使用?vect.get_feature_names()?命令來獲取word1和word2中出現的所有單詞。
使用 .toarray() 將sparse矩陣轉換成正常的數組形式,便于觀察
# 查看提取了哪些單詞
names = vect.get_feature_names() #提取word1和word2中出現過的所有單詞
# 將sparse矩陣轉換成正常的數組形式
arr = words.toarray()
解釋:arr變量中第0行表示word1某單詞出現次數,第1行表示word2,某出現次數與names列表中的對應。即name列表中的'happy'在word1中出現了1次,在word2中出現了0次,‘world’這個詞在word1中出現了0次,在word2中出現了2次。
2. 文檔分類實戰
2.1 數據獲取
? ? ? ?使用sklearn內部數據集獲取新聞分組數據,下載到指定文件夾。有關系統內部數據集的獲取方法可以參考我的前一篇文章機器學習-K近鄰算法,或者該網頁sklearn數據集,本篇文章就不進行詳述。如果找不到數據集的,文末有數據集,有需要的自取。
# 使用sklearn內部數據集,獲取新聞分組數據
from sklearn.datasets import fetch_20newsgroups
# 指定文件下載位置,把新聞數據下載到里面
filepath = 'C:\\Users\\admin\\.spyder-py3\\test\\文件處理\\newsgroup'
newsgroups = fetch_20newsgroups(data_home = filepath) #返回值是一個.Bunch類型數據
? ? ? ?我們得到的newsgroups是一個.Bunch類型的數據;data中存放的是11314篇新聞文章;DESCR是對這個數據集的描述;filename是文件路徑,可以忽視;target存放的是這11314篇文章的分類,一共有20個類別記作0到19;target_names記錄的是20種分類的名稱。
2.2 數據處理
? ? ? ? 首先從.Bunch數據中提取我們需要的,news_data相當于預測所需的特征值x,news_target相當于預測目標y。
# news_data中存放具體的文章,相當于x
news_data = newsgroups.data
# news_target中存放數據的目標值,即分類的結果,相當于y
news_target = newsgroups.target
? ? ? ? 從數據中提取最后10行用于結果驗證,news_predict_data 存放最后十個的文章數據,用作最后預測函數的輸入值,news_predict_target 存放最后十個主題分類,用于和最終預測結果比較,驗證是否正確。然后將建模所用的數據剔除最后10行,即將?news_data?和?news_target?都刪除最后10行數據。
# 取最后10行特征值作為驗證集。用于預測的x
news_predict_data = news_data[-10:]
# 最后10行目標作為驗證預測結果的準確性。用于驗證的y
news_predict_target = news_target[-10:]
# 用于建模的特征值刪除最后10行,x
news_data = news_data[:-10]
# 用于建模的目標值刪除最后10行,y
news_target = news_target[:-10]
到此我們已經劃分出驗證所用數據和建模所用數據。
2.3 劃分訓練集和測試集
一般采用75%的數據用于訓練,25%用于測試,因此把數據進行訓練之前,先要對數據劃分。
使用?sklearn.model_selection.train_test_split 進行分割
劃分方式:
x_train,x_test,y_train,y_test = train_test_split(x數據,y數據,test_size=數據占比)
train_test_split() 參數
x:數據集特征值(news_data)
y:數據集目標值(news_target)
test_size: 測試數據占比,用小數表示
train_test_split() 返回值
x_train:訓練部分特征值
x_test:?測試部分特征值
y_train:訓練部分目標值
y_test: 測試部分目標值
# 劃分測試集和訓練集
from sklearn.model_selection import train_test_split
# 數據的75%用于訓練,25%用于測試
x_train,x_test,y_train,y_test = train_test_split(news_data,news_target,test_size=0.25)
2.4 特征提取
? ? ? ?為了統計每一篇文章中各個單詞出現的次數,哪些分類中哪些單詞出現的比較多,從而建立分類模型,同1.4所述。因此導入特征向量化方法CountVectorizer()
? ? ? ? 然后,對用于訓練的新聞數據 x_train?進行 .fit_transform() 操作,先進行fit提取特征值,再transform 將數據sparse矩陣化,統計各個單詞出現次數,特征向量化方法見1.4。
? ? ? ?那么為什么對于測試用的新聞數據 x_test 只需要進行?transform?操作,而不需要 fit 提取特征值呢?可以簡單理解為,x_train?是用來建立模型的,我需要知道它有哪些特征,這些特征值如何與目標值 y_train 相對應。模型建立完成之后,測試數據 x_test 是用來檢測這個模型的準確率,相當于我給這個模型傳一個 sparse 矩陣,這么模型自己就會進行一個特征的提取,內部會對我對輸入值進行一系列處理得到預測結果。同理,我們也需要對驗證所用的x數據 news_predict_data 進行sparse矩陣化。
# 導入特征向量化方法
from sklearn.feature_extraction.text import CountVectorizer
# news_vect 接收特征向量化方法
news_vect = CountVectorizer()
# 將x_train傳入特征向量化方法
x_train = news_vect.fit_transform(x_train) #用于訓練
# 測試數據矩陣化
x_test = news_vect.transform(x_test) #用于測試
# 把驗證數據變成sparss矩陣,輸入sparss矩陣,輸出預測結果
news_predict_data = news_vect.transform(news_predict_data)
2.5 樸素貝葉斯方法預測
首先導入樸素貝葉斯方法庫 from sklearn.naive_bayes import MultinomialNB
樸素貝葉斯函數:??MultinomialNB()
MultinomialNB() 接收的參數 (alpha=1,fit_prior=True,class_prior=None)
alpha:拉普拉斯平滑系數,默認為1
樸素貝葉斯訓練方法:??.fit(self, x_train, y_train, sample_weight=None)
傳入的x可以是數組、列表、sparss矩陣
# 導入樸素貝葉斯方法
from sklearn.naive_bayes import MultinomialNB
# nb接收樸素貝葉斯方法
nb = MultinomialNB()
# 訓練,傳入訓練的特征sparss矩陣,訓練的目標值
nb.fit(x_train,y_train)
# 評分法看模型準確率,傳入測試值特征sparss矩陣,和測試目標值
accuracy = nb.score(x_test,y_test)
# 預測,輸入預測所需的特征值x
result = nb.predict(news_predict_data)
評分法計算模型準確率:? .score(x_test, y_test)
根據x_test預測結果,把預測結果和真實的y_test比較,計算準確率
樸素貝葉斯預測方法:? .predict(預測所需的x數據)
此處的x數據需要輸入sparse矩陣
accuracy 存放模型準確率,result?存放分類結果,最終準確率為83%,result和實際結果news_predict_target有微小偏差。
新聞數據集自取:
https://download.csdn.net/download/dgvv4/41914595
完整代碼如下,只需更改filepath文件下載路徑即可運行
# 文檔分類實戰#(1)數據獲取
# 使用sklearn內部數據集,獲取新聞分組數據
from sklearn.datasets import fetch_20newsgroups
# 指定文件下載位置,把新聞數據下載到里面
filepath = 'C:\\Users\\admin\\.spyder-py3\\test\\文件處理\\newsgroup'
newsgroups = fetch_20newsgroups(data_home = filepath) #返回值是一個.Bunch類型數據#(2)數據預處理
# news_names存放分類,一共20類
news_names = newsgroups.target_names
# news_data中存放具體的文章,相當于x
news_data = newsgroups.data
# news_target中存放數據的目標值,即分類的結果,相當于y
news_target = newsgroups.target# 取最后10行特征值作為驗證集。用于預測的x
news_predict_data = news_data[-10:]
# 最后10行目標作為驗證預測結果的準確性。用于驗證的y
news_predict_target = news_target[-10:]
# 用于建模的特征值刪除最后10行,x
news_data = news_data[:-10]
# 用于建模的目標值刪除最后10行,y
news_target = news_target[:-10]#(3)劃分測試集和訓練集
from sklearn.model_selection import train_test_split
# 數據的75%用于訓練,25%用于測試
x_train,x_test,y_train,y_test = train_test_split(news_data,news_target,test_size=0.25)#(4)特征抽取
# 導入特征向量化方法
from sklearn.feature_extraction.text import CountVectorizer
news_vect = CountVectorizer() # news_vect 接收特征向量化方法
# 將x_train傳入特征向量化方法,用于統計x_train中每篇文章的單詞出現了多少次,返回sparss矩陣
# fit先提取x_train的特征,transform將x_train中的數據進行sparss矩陣化
x_train = news_vect.fit_transform(x_train) #用于訓練
# 上面已經進行過提取特征的操作,這一步不需要fit,直接進行transform矩陣化即可
x_test = news_vect.transform(x_test) #用于測試,我給模型一個sparss矩陣,模型給我一個預測結果
# 同理,我也需要把驗證數據變成sparss矩陣,輸入sparss矩陣,輸出預測結果
news_predict_data = news_vect.transform(news_predict_data) #(5)樸素貝葉斯方法預測
from sklearn.naive_bayes import MultinomialNB # 導入樸素貝葉斯方法
# MultinomialNB接收的參數(alpha=1,fit_prior=True,class_prior=None)
# alpha:拉普拉斯平滑系數,默認為1
# 用于訓練時的fit()方法,fit(self,x,y,sample_weight=None)
# 傳入的x可以是數組、列表、sparss矩陣nb = MultinomialNB() # nb接收樸素貝葉斯方法
# 訓練,傳入訓練的特征sparss矩陣,訓練的目標值
# 樸素貝葉斯訓練時,只需要提取特征值fit,不需要transform對特征進行一系列操作
nb.fit(x_train,y_train)
# 評分法看模型準確率,傳入測試值特征sparss矩陣,和測試目標值
accuracy = nb.score(x_test,y_test) # 根據x_test預測結果,把預測結果和真實的y_test比較,計算準確率
# 預測,輸入預測所需的特征值x(非sparss矩陣)
result = nb.predict(news_predict_data)
總結
以上是生活随笔為你收集整理的【机器学习入门】(2) 朴素贝叶斯算法:原理、实例应用(文档分类预测)附python完整代码及数据集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【机器学习入门】(1) K近邻算法:原理
- 下一篇: 【机器学习入门】(3) 朴素贝叶斯算法: