【火爐煉AI】機器學習039-NLP文本分類器

【火爐煉AI】機器學習039-NLP文本分類器

(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, NLTK 3.3)html

前面咱們學習了不少用NLP進行文本的分詞,文本分塊,建立詞袋模型等,這些步驟能夠認爲是NLP文本處理的基礎,此處咱們來看NLP的一個很是重要的應用,對文本使用監督學習進行自動分類。git


1. 20 Newsgroups數據集介紹

本文要使用NLP中很是經典的一個數據集:20 Newsgroups。這個數據集是國際標準數據集之一,專門用於文本分類,文本挖掘,和信息檢索等領域,相似於傳統機器學習所用的Iris鳶尾花數據集同樣,能夠經過官方網址來下載和了解具體內容。github

20 Newsgroups包含有20個類別的已經標註好的樣本,總樣本數量大約2萬。這20個類別分別爲:dom

這個數據集有三個版本,其主要內容和區別爲:機器學習

  1. 20news-19997.tar.gz: 最原始的沒有修改過的一個版本。
  2. 20news-bydate.tar.gz: bydate版本,按照時間分類,分爲訓練集(60%)和測試集(40%)兩部分,不包含重複文檔和新聞組名。一共有18846個樣本(或稱爲文檔)
  3. 20news-18828.tar.gz: 不包含重複樣本,只有來源和主題,一共有18828個樣本。

sklearn中有兩種加載方式,第一種是sklearn.dataset.fetch_20newsgroups,返回一個能夠被文本特徵提取器(CountVectorizer)自定義參數提取特徵的原始文本序列,第二種是sklearn.datasets.fetch_20newsgroups_vectorized,返回一個已提取特徵的文本序列,即不須要使用特徵提取器。函數

注:以上內容主要參考博客學習

此處咱們只下載第二個版本,下載後獲得20news-bydate.tar.gz文件,解壓後獲得兩個文件夾,以下:測試

這兩個文件夾每個都有20個子文件夾,對應於20個不一樣類別。每一個類別下面有幾百個文檔,即樣本,每一個文檔都不長,好比一個文檔(樣本)的內容爲:fetch

這個數據集的加載方式已經被sklearn集成到代碼中了,主要的接口是sklearn.dataset.fetch_20newsgroups,其默認加載第二個版本。這個函數的參數有:subset有三個選擇train、test、all,選擇數據的類型。category是選擇新聞的類型,remove是能夠選擇去除(‘headers’, ‘footers’, ‘quotes’)這三個文章的選項。其餘不重要。優化

# 認識20newsgroups數據集
from sklearn.datasets import fetch_20newsgroups
# dataset=fetch_20newsgroups(subset='all') 
# 自動下載第二個版本20news-bydate.tar.gz
# print(len(dataset.data)) # dataset_X 的樣本數
# print(dataset.target_names) # dataset_y的名稱,標籤名稱

# train_set=fetch_20newsgroups(subset='train') # 僅僅提取中間的train set
# test_set=fetch_20newsgroups(subset='test')

# 若是僅僅須要其中的某幾個類別,能夠用
sample_cate = ['alt.atheism', 'soc.religion.christian',
               'comp.graphics', 'sci.med', 'rec.sport.baseball'] # 只取5個類別
train_set = fetch_20newsgroups(subset='train',categories=sample_cate,
                               shuffle=True, random_state=42,
                               remove = ('headers', 'footers', 'quotes'))
test_set = fetch_20newsgroups(subset='test', categories=sample_cate,
                              shuffle=True, random_state=42,
                              remove = ('headers', 'footers', 'quotes'))
print(len(train_set.data), len(test_set.data)) # 2854 1899
print(train_set.target_names) # 只有五個類別
複製代碼

-------------------------------------輸---------出--------------------------------

2854 1899 ['alt.atheism', 'comp.graphics', 'rec.sport.baseball', 'sci.med', 'soc.religion.christian']

--------------------------------------------完-------------------------------------


2. 構建分類器

2.1 準備數據集

# 1, 準備數據集
category_map = {'misc.forsale': 'Sales', 'rec.motorcycles': 'Motorcycles', 
        'rec.sport.baseball': 'Baseball', 'sci.crypt': 'Cryptography', 
        'sci.space': 'Space'}
from sklearn.datasets import fetch_20newsgroups
train_set=fetch_20newsgroups(subset='train',categories=category_map.keys(),
                             shuffle=True,random_state=42,
                            remove = ('headers', 'footers', 'quotes'))
test_set=fetch_20newsgroups(subset='test',categories=category_map.keys(),
                             shuffle=True,random_state=42,
                           remove = ('headers', 'footers', 'quotes'))
# 獲取到的train_set包含有2968個樣本,
print('train sample num: ', len(train_set.data)) # 2968
print(train_set.target_names) # 確保是咱們要提取的這五個類別

print('test sample num: ', len(test_set.data)) # 1975
複製代碼

--------------輸---------出----------

train sample num: 2968 ['misc.forsale', 'rec.motorcycles', 'rec.sport.baseball', 'sci.crypt', 'sci.space'] test sample num: 1975

-------------------完-----------------

2.2 特徵提取

此處咱們用TfidfVectorizer來進行特徵提取,關於TfidfVectorizer能夠參考個人上一篇文章【火爐煉AI】機器學習038-NLP建立詞袋模型.

直接上代碼:

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(stop_words='english',lowercase=True)
train_vector = vectorizer.fit_transform(train_set.data)
print(train_vector.shape) # (2968, 31206)
# 此處至關於有2968個詞袋,對這些詞袋進行TfidfVectorizer進行特徵提取,
# 獲得最具典型的一些單詞,這些單詞的個數有31206個,故而獲得(2968, 30206)矩陣
# 矩陣中的元素表示這個單詞在該詞袋中出現的tf-idf權重,值越大,表示該單詞越重要。
複製代碼

2.3 定義模型,訓練模型

# 定義模型,訓練特徵
from sklearn.naive_bayes import MultinomialNB
classifier=MultinomialNB(alpha=.01, fit_prior = False)
classifier.fit(train_vector,train_set.target)
複製代碼

2.4 查看模型在測試集上的表現

# 查看這個數據集在test_set上的表現
from sklearn import metrics
test_vector=vectorizer.transform(test_set.data)
print(test_vector.shape)
pred=classifier.predict(test_vector)
F1_score=metrics.f1_score(test_set.target, pred, average='micro')
print('test set F1 score: ',F1_score)
複製代碼

------------------輸---------出-------------

(1975, 31206) test set F1 score: 0.8774683544303797

-------------------------完----------------


3. 用GridSearch優化參數

# 用GridSearchCV優化參數
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report

parameters = {'fit_prior':(True, False), 'alpha':(0.01,0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0)}
clf = GridSearchCV(classifier,parameters,cv=5,scoring='precision_macro',n_jobs=-1)
clf.fit(train_vector, train_set.target)
print("Best param_set found on train set: {}".format(clf.best_params_))

print("Detailed classification report on test set:")
y_true, y_pred = test_set.target, clf.predict(test_vector)
print(classification_report(y_true, y_pred))
複製代碼

-------------------------------------輸---------出--------------------------------

Best param_set found on train set: {'alpha': 0.05, 'fit_prior': True} Detailed classification report on test set: precision recall f1-score support

0       0.92      0.89      0.91       390
      1       0.80      0.91      0.85       398
      2       0.93      0.88      0.91       397
      3       0.90      0.88      0.89       396
      4       0.91      0.88      0.89       394
複製代碼

avg / total 0.89 0.89 0.89 1975

--------------------------------------------完-------------------------------------

從分類報告中能夠看出,結果最好的是第0類和第2類,F1爲0.91,最差的是第1類,F1值只有0.85。

########################小**********結###############################

1,用NLP進行文本分類,和傳統機器學習的主要區別在於前面特徵的提取,一旦提取特徵,後面模型的創建,訓練,測試,分類報告等都同樣。

2,對文本進行特徵的提取有兩種:CountVectorizer和TfidfVectorizer,可是TfidfVectorizer使用的最多,對文本量很是大的狀況更加準確,故而此處我只用TfidfVectorizer來提取特徵。

3,有一個地方很容易忽視:測試集在用predict以前,必定要用vectorizer.transform進行轉換,這個過程就像是對數據進行歸一化等,須要對train_X和test_X都要進行處理。

#################################################################


注:本部分代碼已經所有上傳到(個人github)上,歡迎下載。

參考資料:

1, Python機器學習經典實例,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章
相關標籤/搜索