Compare with MultinomialNB / SVM / Decision tree(CART)

栏目: R语言 · 发布时间: 5年前

Source: Deep Learning on Medium

Compare MultinomialNB、SVM、Decision tree(CART) with f1-scrore、precision、recall

  • Using TFIDF( term frequency–inverse document frequency) for vectorized.
  • Using 10-fold for cross validation to get the better split.

首先import要用到的package,接著就可以開始我們的分析

import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import KFold
from sklearn import metrics

1. Data preprocessing

今天的目標是要從新聞報導中,正確的分類至相對應的文章類別,有三種類別分別是Sports, Politics, Health,接著我會用三種不同的分類器,來看看三者的效能差異。

首先,先來看看資料長怎樣呢

Compare with MultinomialNB / SVM / Decision tree(CART)
Raw data

可以看得出來是直接爬下來的data,每段的開頭是他的分類,那我們把它存成excel格式並分成categorize和content兩類。

colnames = ['categorize', 'content']
news = pd.read_csv('news_files.csv',names=colnames,encoding = 'utf8')

現在我們的資料存進去news的dataframe了,為了方便我們分類,將三種類別標示為0, 1, 2 並存到target的column

news['target'] = pd.Series(0, index=news.index)
news_data =news.iloc[:6000]

如果直接做slicing存過去,可能會遇到error — SettingWithCopyWarning,所以我們用.at填值

for i in range(len(news_data)+1):
 if news_data.iloc[i]['categorize']=='sports':
 news_data.at[i,'target'] = 0
 elif news_data.iloc[i]['categorize']=='politics':
 news_data.at[i,'target'] = 1
 else:
 news_data.at[i,'target'] = 2

2. KFold

怎麼分training和validation的data是個很重要的議題,分得好不好會影響到我們模型效能,我們這邊用KFold來分,但同時我也寫了Random分類後的結果,這邊是random分類的function,需要的也可以測試看看。

def Separate_TrainAndTest(data_raw):
 n=int(data_raw.shape[0])
 tmp_train=(np.random.rand(n)>=0.5)
 return data_raw.iloc[np.where(tmp_train==True)[0]],data_raw.iloc[np.where(tmp_train==False)[0]]

他的效能如下

Compare with MultinomialNB / SVM / Decision tree(CART)
Randomly separate

接著我們繼續本文的部分,這邊希望用KFold就是為了避免依賴某一特定的訓練和測試資料產生偏差,那我們快速看一下KFold是怎麼做

Compare with MultinomialNB / SVM / Decision tree(CART)
KFold

我們將資料分成 10 等份,從Round 1開始先拿第 1 等分用來做Validation,其餘拿來training,下一輪我們繼續拿第 2 等分做Validation,其餘 9 份一樣拿來訓練,總共做 10 次,如果想要取不同的fold也可以,但是10次是比較普遍的用法,也不會訓練太久。

接著將10次的Accuracy平均,所得到平均值,我們可以自信的說這個數值就是我們的準確度,相對隨機來的沒有偏差。

實作 Time.

這邊用sklearn裡面的KFold,裡面的參數設定是KFold(n_splits=’warn’, shuffle=False, random_state=None),想知道更詳細的話,詳見: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html

from sklearn.naive_bayes import MultinomialNB
kfold = KFold(10, True)
predicted = []
expected = []
for train, test in kfold.split(np.arange(len(news_data))+1):
 # train、test為index
 news_train = news_data.iloc[train]
 news_test = news_data.iloc[test]

上面我們用predicted和expected分別存10次的結果給後面做評分用

3. Vectorized

接下來是向量化(vectorized)的部分,這邊用的是TF-IDF,此演算法包含了兩個部分: 詞頻 (term frequency,TF)跟 逆向文件頻率 (inverse document frequency,IDF)。

詞頻指的是某一個給定的詞語在該文件中出現的頻率,第t個詞出現在第d篇文件的頻率記做

Compare with MultinomialNB / SVM / Decision tree(CART)

舉例來說,如果文件 1 總共有100個字,而第 1 個字在文件 1 出現的次數是12次,因此

Compare with MultinomialNB / SVM / Decision tree(CART)

而逆向文件頻率則是用來處理常用字的問題。假設詞彙t總共在第d篇文章中出現過,則詞彙t的 IDF 定義成

Compare with MultinomialNB / SVM / Decision tree(CART)

舉例來說,假設文字 1 總共出現在 25 篇不同的文件,則

Compare with MultinomialNB / SVM / Decision tree(CART)

所以如果詞彙t在非常多篇文章中都出現過,代表dt很大,此時idf就會比較小。

接著,我們將第t個詞彙對於第d篇文件的TF-IDF權重定義為

Compare with MultinomialNB / SVM / Decision tree(CART)

如此一來, 當詞彙t很常出現在文件d時,他的tf項就會比較大,而如果詞彙t也很少出現在其他篇文章,則idf項也會比較大,使Wtd整體來說更大,代表詞彙t對於文件d來說是很重要的

實作 Time.

這邊用sklearn.feature_extraction.text的TfidfVectorizer()直接計算,要注意的是需要將格式轉換成unicode,以下我以astype轉換

vectorizer = TfidfVectorizer()
 vectors_training = vectorizer.fit_transform(news_train['content'].values.astype('U'))
 vectors_test = vectorizer.transform(news_test['content'].values.astype('U'))

4. Classification

終於到了最後分類的階段,這邊會接續從MultinomialNB、SVM、CART分別進行training,並直接使用metric來計算三個分數,再分別列出,詳細的公式先不在這篇文章討論~

model = MultinomialNB(alpha=.01)
 model.fit(vectors_training,news_train.target)

 expected.extend(news_test.target)
 predicted.extend(model.predict(vectors_test))
print("---------Naive Bayes---------") 
print("Macro-average: {0}".format(metrics.f1_score(expected,predicted,average='macro')))
print("Micro-average: {0}".format(metrics.f1_score(expected,predicted,average='micro')))
print(metrics.classification_report(expected,predicted))
print(metrics.confusion_matrix(expected, predicted))
Compare with MultinomialNB / SVM / Decision tree(CART)
Multinomial NB score
from sklearn import svm
predicted = []
expected = []
for train, test in kfold.split(np.arange(len(news_data))+1):
 news_train = news_data.iloc[train]
 news_test = news_data.iloc[test]

 vectorizer = TfidfVectorizer()
 vectors_training = vectorizer.fit_transform(news_train['content'].values.astype('U'))
 vectors_test = vectorizer.transform(news_test['content'].values.astype('U'))

 model = svm.SVC(kernel = 'linear')
 model.fit(vectors_training,news_train.target)
 #test process
 #SVM
 expected.extend(news_test.target)
 predicted.extend(model.predict(vectors_test))
print("---------SVM---------") 
print("Macro-average: {0}".format(metrics.f1_score(expected,predicted,average='macro')))
print("Micro-average: {0}".format(metrics.f1_score(expected,predicted,average='micro')))
print(metrics.classification_report(expected,predicted,target_names = ['sports','politics','health'] ))
Compare with MultinomialNB / SVM / Decision tree(CART)
SVM score
from sklearn import tree
predicted = []
expected = []
for train, test in kfold.split(np.arange(len(news_data))+1):
 news_train = news_data.iloc[train]
 news_test = news_data.iloc[test]
 vectorizer = TfidfVectorizer()

 vectors_training = vectorizer.fit_transform(news_train['content'].values.astype('U'))
 vectors_test = vectorizer.transform(news_test['content'].values.astype('U'))

 model = tree.DecisionTreeClassifier() #不調參數 default = CART
 model.fit(vectors_training,news_train.target)

 # predict
 expected.extend(news_test.target)
 predicted.extend(model.predict(vectors_test))

#Decision Tree
print("---------Decision Tree---------")
print("Macro-average: {0}".format(metrics.f1_score(expected,predicted,average='macro')))
print("Micro-average: {0}".format(metrics.f1_score(expected,predicted,average='micro')))
print(metrics.classification_report(expected,predicted,target_names = ['sports','politics','health'] ))
print("-----------------------------")
Compare with MultinomialNB / SVM / Decision tree(CART)
CART score

Conclusion

很明顯的可以看到用10-fold所得到的結果比Random好很多,其中Accuracy又以SVM>NB>Decision Tree,但是SVM需要的時間也相對多很多,所以就看怎麼取決了,本文為第一個NLP的小實驗,有甚麼建議可以留言哦~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程匠艺

编程匠艺

Pete Goodliffe / 韩江、陈玉 / 电子工业出版社 / 2011-11 / 85.00元

如果你可以编写出合格的代码,但是想更进一步、创作出组织良好而且易于理解的代码,并希望成为一名真正的编程专家或提高现有的职业技能,那么Pete Goodliffe编写的这本本书都会为你给出答案。本书的内容涵盖编程的各个要素,如代码风格、变量命名、错误处理和安全性等。此外,本书还对一些更广泛的编程问题进行了探讨,如有效的团队合作、开发过程和文档编写,等等。本书各章的末尾均提供一些思考问题,这些问题回顾......一起来看看 《编程匠艺》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换