樸素貝葉斯分析
樸素貝葉斯。它是一種簡單但極爲強大的預測建模算法。之所以稱爲樸素貝葉斯,是因爲它假設每個輸入變量是獨立的。這是一個強硬的假設,實際情況並不一定,但是這項技術對於絕大部分的複雜問題仍然非常有效。
樸素貝葉斯模型由兩種類型的概率組成:
每個類別的概率P(Cj);
每個屬性的條件概率P(Ai|Cj)。
假設我有7個棋子,其中3個是白色的,4個是黑色的。那麼棋子是白色的概率就是3/7,黑色的概率就是4/7,這個就是類別概率。
假設我把這7個棋子放到了兩個盒子裏,其中盒子A裏面有2個白棋,2個黑棋;盒子B裏面有1個白棋,2個黑棋。那麼在盒子A中抓到白棋的概率就是1/2,抓到黑棋的概率也是1/2,這個就是條件概率,也就是在某個條件(比如在盒子A中)下的概率。
在樸素貝葉斯中,我們要統計的是屬性的條件概率,也就是假設取出來的是白色的棋子,那麼它屬於盒子A的概率是2/3。
爲了訓練樸素貝葉斯模型,我們需要先給出訓練數據,以及這些數據對應的分類。那麼上面這兩個概率,也就是類別概率和條件概率。他們都可以從給出的訓練數據中計算出來。一旦計算出來,概率模型就可以使用貝葉斯原理對新數據進行預測。
項目實戰
樸素貝葉斯分類最適合的場景就是文本分類、情感分析和垃圾郵件識別
下面用樸素貝葉斯做文檔分類的項目
總共分爲三個階段:
- 加載文檔
- 加載停用詞,計算權重
- 生成分類器預測分類
1.加載文檔
實現讀取文件和分割字符串的方法
def cut_words(file_path):
"""
對文本進行切詞
:param file_path: txt文本路徑
:return: 用空格分詞的字符串
"""
text_with_spaces = ''
text=open(file_path, 'r', encoding='gb18030').read()
textcut = jieba.cut(text)
for word in textcut:
text_with_spaces += word + ' '
return text_with_spaces
def loadfile(file_dir, label):
"""
將路徑下的所有文件加載
:param file_dir: 保存txt文件目錄
:param label: 文檔標籤
:return: 分詞後的文檔列表和標籤
"""
file_list = os.listdir(file_dir)
words_list = []
labels_list = []
for file in file_list:
file_path = file_dir + '/' + file
words_list.append(cut_words(file_path))
labels_list.append(label)
return words_list, labels_list
2.加載停用詞,計算權重
加載停用詞表
stop_words = open('./stop/stopword.txt', 'r', encoding='utf-8').read()
stop_words = stop_words.encode('utf-8').decode('utf-8-sig') # 列表頭部\ufeff處理
stop_words = stop_words.split('\n') # 根據分隔符分隔
計算權重
tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5)
features = tf.fit_transform(train_contents)
這裏max_df參數用來描述單詞在文檔中的最高出現率。假設max_df=0.5,代表一個單詞在50%的文檔中都出現過了,那麼它只攜帶了非常少的信息,因此就不作爲分詞統計。
3.生成分類器預測分類
# 多項式貝葉斯分類器
clf = MultinomialNB(alpha=0.001).fit(features, train_labels)
#得到測試集的特徵矩陣test_features
test_features=tf.transform(test_words_list)
#訓練好的分類器對新數據做預測
predicted_labels=clf.predict(test_features)
#計算準確率
print(metrics.accuracy_score(test_labels, predicted_labels))
完整代碼
# 中文文本分類
import os
import jieba
import warnings
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics
def cut_words(file_path):
"""
對文本進行切詞
:param file_path: txt文本路徑
:return: 用空格分詞的字符串
"""
text_with_spaces = ''
text=open(file_path, 'r', encoding='gb18030').read()
textcut = jieba.cut(text)
for word in textcut:
text_with_spaces += word + ' '
return text_with_spaces
def loadfile(file_dir, label):
"""
將路徑下的所有文件加載
:param file_dir: 保存txt文件目錄
:param label: 文檔標籤
:return: 分詞後的文檔列表和標籤
"""
file_list = os.listdir(file_dir)
words_list = []
labels_list = []
for file in file_list:
file_path = file_dir + '/' + file
words_list.append(cut_words(file_path))
labels_list.append(label)
return words_list, labels_list
# 訓練數據
train_words_list1, train_labels1 = loadfile('./train/女性', '女性')
train_words_list2, train_labels2 = loadfile('./train/體育', '體育')
train_words_list3, train_labels3 = loadfile('./train/文學', '文學')
train_words_list4, train_labels4 = loadfile('./train/校園', '校園')
train_words_list = train_words_list1 + train_words_list2 + train_words_list3 + train_words_list4
train_labels = train_labels1 + train_labels2 + train_labels3 + train_labels4
# 測試數據
test_words_list1, test_labels1 = loadfile('./test/女性', '女性')
test_words_list2, test_labels2 = loadfile('./test/體育', '體育')
test_words_list3, test_labels3 = loadfile('./test/文學', '文學')
test_words_list4, test_labels4 = loadfile('./test/校園', '校園')
test_words_list = test_words_list1 + test_words_list2 + test_words_list3 + test_words_list4
test_labels = test_labels1 + test_labels2 + test_labels3 + test_labels4
#加載停用詞表
stop_words = open('./stop/stopword.txt', 'r', encoding='utf-8').read()
stop_words = stop_words.encode('utf-8').decode('utf-8-sig') # 列表頭部\ufeff處理
stop_words = stop_words.split('\n') # 根據分隔符分隔
#計算權重
tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5)
features = tf.fit_transform(train_words_list)
# 多項式貝葉斯分類器
clf = MultinomialNB(alpha=0.001).fit(features, train_labels)
#得到測試集的特徵矩陣test_features
test_features=tf.transform(test_words_list)
#訓練好的分類器對新數據做預測
predicted_labels=clf.predict(test_features)
#計算準確率
print(metrics.accuracy_score(test_labels, predicted_labels))