實(shí)戰(zhàn):手把手教你用樸素貝葉斯對(duì)文檔進(jìn)行分類
點(diǎn)擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
本文轉(zhuǎn)自|視覺算法
樸素貝葉斯分類最適合的場(chǎng)景就是文本分類、情感分析和垃圾郵件識(shí)別。其中情感分析和垃圾郵件識(shí)別都是通過(guò)文本來(lái)進(jìn)行判斷。所以樸素貝葉斯也常用于自然語(yǔ)言處理 NLP 的工具。
sklearn 機(jī)器學(xué)習(xí)包
sklearn 的全稱叫 Scikit-learn,它給我們提供了 3 個(gè)樸素貝葉斯分類算法,分別是高斯樸素貝葉斯(GaussianNB)、多項(xiàng)式樸素貝葉斯MultinomialNB)和伯努利樸素貝葉斯(BernoulliNB)。
這三種算法適合應(yīng)用在不同的場(chǎng)景下,我們應(yīng)該根據(jù)特征變量的不同選擇不同的算法:
高斯樸素貝葉斯:特征變量是連續(xù)變量,符合高斯分布,比如說(shuō)人的身高,物體的長(zhǎng)度。
多項(xiàng)式樸素貝葉斯:特征變量是離散變量,符合多項(xiàng)分布,在文檔分類中特征變量體現(xiàn)在一個(gè)單詞出現(xiàn)的次數(shù),或者是單詞的 TF-IDF 值等。
伯努利樸素貝葉斯:**特征變量是布爾變量,符合 0/1 分布**,在文檔分類中特征是單詞是否出現(xiàn)。
伯努利樸素貝葉斯是以文件為粒度,如果該單詞在某文件中出現(xiàn)了即為 1,否則為 0。而多項(xiàng)式樸素貝葉斯是以單詞為粒度,會(huì)計(jì)算在某個(gè)文件中的具體次數(shù)。
> 如身高、體重這種自然界的現(xiàn)象就比較適合用高斯樸素貝葉斯來(lái)處理。而文本分類是使用多項(xiàng)式樸素貝葉斯或者伯努利樸素貝葉斯。
什么是 TF-IDF 值呢?
TF-IDF 是一個(gè)統(tǒng)計(jì)方法,用來(lái)評(píng)估某個(gè)詞語(yǔ)對(duì)于一個(gè)文件集或文檔庫(kù)中的其中一份文件的重要程度。
詞頻 TF計(jì)算了一個(gè)單詞在文檔中出現(xiàn)的次數(shù),它認(rèn)為一個(gè)單詞的重要性和它在文檔中出現(xiàn)的次數(shù)呈正比。
逆向文檔頻率 IDF,是指一個(gè)單詞在文檔中的區(qū)分度。它認(rèn)為一個(gè)單詞出現(xiàn)在的文檔數(shù)越少,就越能通過(guò)這個(gè)單詞把該文檔和其他文檔區(qū)分開。IDF 越大就代表該單詞的區(qū)分度越大。
所以 TF-IDF 實(shí)際上是詞頻 TF 和逆向文檔頻率 IDF 的乘積。這樣我們傾向于找到 TF 和 IDF 取值都高的單詞作為區(qū)分,即這個(gè)單詞在一個(gè)文檔中出現(xiàn)的次數(shù)多,同時(shí)又很少出現(xiàn)在其他文檔中。這樣的單詞適合用于分類。
TF-IDF 如何計(jì)算


些單詞可能不會(huì)存在文檔中,為了避免分母為 0,統(tǒng)一給單詞出現(xiàn)的文檔數(shù)都加 1。
舉個(gè)例子
假設(shè)一個(gè)文件夾里一共有 10 篇文檔,其中一篇文檔有 1000 個(gè)單詞,“this”這個(gè)單詞出現(xiàn) 20 次,“bayes”出現(xiàn)了 5 次。“this”在所有文檔中均出現(xiàn)過(guò),而“bayes”只在 2 篇文檔中出現(xiàn)過(guò)。
針對(duì)“this”,計(jì)算 TF-IDF 值:
所以 TF-IDF=0.02*(-0.0414)=-8.28e-4。
針對(duì)“bayes”,計(jì)算 TF-IDF 值:
TF-IDF=0.005*0.5229=2.61e-3。
很明顯“bayes”的 TF-IDF 值要大于“this”的 TF-IDF 值。這就說(shuō)明用“bayes”這個(gè)單詞做區(qū)分比單詞“this”要好。
如何求 TF-IDF
在 sklearn 中我們直接使用 TfidfVectorizer 類,它可以幫我們計(jì)算單詞 TF-IDF 向量的值。
在這個(gè)類中,取 sklearn 計(jì)算的對(duì)數(shù) log 時(shí),底數(shù)是 e,不是 10。
創(chuàng)建 TfidfVectorizer 的方法是:
TfidfVectorizer(stop_words=stop_words, token_pattern=token_pattern)


當(dāng)我們創(chuàng)建好 TF-IDF 向量類型時(shí),可以用 fit_transform 幫我們計(jì)算,返回給我們文本矩陣,該矩陣表示了每個(gè)單詞在每個(gè)文檔中的 TF-IDF 值。

在我們進(jìn)行 fit_transform 擬合模型后,我們可以得到更多的 TF-IDF 向量屬性,比如,我們可以得到詞匯的對(duì)應(yīng)關(guān)系(字典類型)和向量的 IDF 值,當(dāng)然也可以獲取設(shè)置的停用詞 stop_words。
現(xiàn)在想要計(jì)算文檔里都有哪些單詞,這些單詞在不同文檔中的 TF-IDF 值是多少呢?
首先我們創(chuàng)建 TfidfVectorizer 類:
from sklearn.feature_extraction.text import TfidfVectorizertfidf_vec = TfidfVectorizer()documents = ['this is the bayes document','this is the second second document','and the third one','is this the document']tfidf_matrix = tfidf_vec.fit_transform(documents)print('不重復(fù)的詞:', tfidf_vec.get_feature_names())print('每個(gè)單詞的 ID:', tfidf_vec.vocabulary_)#輸出每個(gè)單詞在每個(gè)文檔中的 TF-IDF 值,向量里的順序是按照詞語(yǔ)的 id 順序來(lái)的:print('每個(gè)單詞的 tfidf 值:', tfidf_matrix.toarray())輸出不重復(fù)的詞: ['and', 'bayes', 'document', 'is', 'one', 'second', 'the', 'third', 'this']每個(gè)單詞的 ID: {'this': 8, 'is': 3, 'the': 6, 'bayes': 1, 'document': 2, 'second': 5, 'and': 0, 'third': 7, 'one': 4}每個(gè)單詞的 tfidf 值: [[0. 0.63314609 0.40412895 0.40412895 0. 0.0.33040189 0. 0.40412895][0. 0. 0.27230147 0.27230147 0. 0.853225740.22262429 0. 0.27230147][0.55280532 0. 0. 0. 0.55280532 0.0.28847675 0.55280532 0. ][0. 0. 0.52210862 0.52210862 0. 0.0.42685801 0. 0.52210862]]
如何對(duì)文檔進(jìn)行分類
1. 基于分詞的數(shù)據(jù)準(zhǔn)備,包括分詞、單詞權(quán)重計(jì)算、去掉停用詞;
2. 應(yīng)用樸素貝葉斯分類進(jìn)行分類,首先通過(guò)訓(xùn)練集得到樸素貝葉斯分類器,然后將分類器應(yīng)用于測(cè)試集,并與實(shí)際結(jié)果做對(duì)比,最終得到測(cè)試集的分類準(zhǔn)確率。
一般來(lái)說(shuō) NTLK 包適用于英文文檔,而 jieba 適用于中文文檔。我們可以根據(jù)文檔選擇不同的包,對(duì)文檔提取分詞。這些分詞就是貝葉斯分類中最重要的特征屬性?;谶@些分詞,我們得到分詞的權(quán)重,即特征矩陣。
在這個(gè)鏈接下下載數(shù)據(jù)集:github.com/cystanford/t

train_contents=[]train_labels=[]test_contents=[]test_labels=[]# 導(dǎo)入文件import osimport iostart=os.listdir(r'C:/Users/baihua/Desktop/text classification/train')for item in start:test_path='C:/Users/baihua/Desktop/text classification/test/'+item+'/'train_path='C:/Users/baihua/Desktop/text classification/train/'+item+'/'for file in os.listdir(test_path):with open(test_path+file,encoding="GBK") as f:test_contents.append(f.readline())#print(test_contents)test_labels.append(item)for file in os.listdir(train_path):with open(train_path+file,encoding='gb18030', errors='ignore') as f:train_contents.append(f.readline())train_labels.append(item)print(len(train_contents),len(test_contents))# 導(dǎo)入stop wordimport jiebafrom sklearn import metricsfrom sklearn.naive_bayes import MultinomialNB#stop_words = [line.strip() for line in io.open(r'C:/Users/baihua/Desktop/stopword.txt').readlines()]with open(r'C:/Users/baihua/Desktop/stopword.txt', 'rb') as f:stop_words = [line.strip() for line in f.readlines()]# 分詞方式使用jieba,計(jì)算單詞的權(quán)重tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5)##注意數(shù)據(jù)結(jié)構(gòu):stop_words是list,過(guò)濾詞token_parten是正則表達(dá)式train_features = tf.fit_transform(train_contents)#該函數(shù)返回文本矩陣,表示每個(gè)單詞在每個(gè)文檔中的TF-IDF值print(train_features.shape)#模塊 4:生成樸素貝葉斯分類器# 多項(xiàng)式貝葉斯分類器clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels)#模塊 5:使用生成的分類器做預(yù)測(cè)test_tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5, vocabulary=tf.vocabulary_)test_features=test_tf.fit_transform(test_contents)predicted_labels=clf.predict(test_features)#模塊六,計(jì)算準(zhǔn)確性from sklearn import metricsprint (metrics.accuracy_score(test_labels, predicted_labels))#print(test_features.shape)#print(metrics.accuracy_score(test_labels, predicted_labels))

交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

