1. 程式人生 > 實用技巧 >NLP——天池新聞文字分類 TASK3

NLP——天池新聞文字分類 TASK3

NLP——新聞文字處理:TASK3 TF-IDF+機器學習分類器

在Task1中已經對最終得分表示F1-score有了部分介紹,這裡給出TF-IDF的介紹以及機器學習分類器相關程式碼:

1.TF-IDF

一個詞語在一篇文章中出現次數越多, 同時在所有文件中出現次數越少, 越能夠代表該文章.這就是TF-IDF的含義.
應用例項:
http://www.ruanyifeng.com/blog/2013/03/tf-idf.html

2.文字表示方法

在機器學習演算法的訓練過程中,假設給定 N個樣本,每個樣本有 M個特徵,這樣組成了 N×M的樣本矩陣,然後完成演算法的訓練和預測。同樣的在計算機視覺中可以將圖片的畫素看作特徵,每張圖片看作hight×width×3的特徵圖,一個三維的矩陣來進入計算機進行計算。
但是在自然語言領域,上述方法卻不可行:文字是不定長度的。文字表示成計算機能夠運算的數字或向量的方法一般稱為詞嵌入(Word Embedding)方法。詞嵌入將不定長的文字轉換到定長的空間內,是文字分類的第一步。

One-hot

這裡的One-hot與資料探勘任務中的操作是一致的,即將每一個單詞使用一個離散的向量表示。具體將每個字/詞編碼一個索引,然後根據索引進行賦值。

One-hot表示方法的例子如下:

句子1:我 愛 北 京 天 安 門
句子2:我 喜 歡 上 海
首先對所有句子的字進行索引,即將每個字確定一個編號:

{
'我': 1, '愛': 2, '北': 3, '京': 4, '天': 5,
'安': 6, '門': 7, '喜': 8, '歡': 9, '上': 10, '海': 11
}
在這裡共包括11個字,因此每個字可以轉換為一個11維度稀疏向量:

我:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
愛:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
...
海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

Bag of Words

Bag of Words(詞袋錶示),也稱為Count Vectors,每個文件的字/詞可以使用其出現次數來進行表示。

句子1:我 愛 北 京 天 安 門
句子2:我 喜 歡 上 海
直接統計每個字出現的次數,並進行賦值:

句子1:我 愛 北 京 天 安 門
轉換為 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]

句子2:我 喜 歡 上 海
轉換為 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
在sklearn中可以直接CountVectorizer來實現這一步驟:

from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()

N-gram

N-gram與Count Vectors類似,不過加入了相鄰單詞組合成為新的單詞,並進行計數。

如果N取值為2,則句子1和句子2就變為:

句子1:我愛 愛北 北京 京天 天安 安門
句子2:我喜 喜歡 歡上 上海

TF-IDF

TF-IDF 分數由兩部分組成:第一部分是詞語頻率(Term Frequency),第二部分是逆文件頻率(Inverse Document Frequency)。其中計算語料庫中文件總數除以含有該詞語的文件數量,然後再取對數就是逆文件頻率。

TF(t)= 該詞語在當前文件出現的次數 / 當前文件中詞語的總數
IDF(t)= log_e(文件總數 / 出現該詞語的文件總數)

3.sklearn程式實現

TF-IDF+嶺分類

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import f1_score
#TF-IDF+嶺迴歸
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

clf = RidgeClassifier()
#clf=LogisticRegression()
#clf=SVC()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
#用10000之前的作為訓練,10000之後的做預測
val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))

程式為選取前15000個樣本進行訓練,最終得到結果為:0.8721
sklearn中封裝好的各種演算法使用前都要 fit
在TF-IDF中:
fit :根據訓練集生成詞典和逆文件詞頻,由fit 方法計算每個特徵的權重儲存在modelidf_屬性中。
transform :使用fit 學習的詞彙和文件頻率,將文件轉換為文件——詞矩陣。

TF-IDF+LogisticRegression

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import f1_score
#TF-IDF+嶺迴歸
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

#clf = RidgeClassifier()
clf=LogisticRegression()
#clf=SVC()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
#用10000之前的作為訓練,10000之後的做預測
val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))

得到結果:0.84988

TF-IDF+SVM

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import f1_score
#TF-IDF+嶺迴歸
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

#clf = RidgeClassifier()
#clf=LogisticRegression()
clf=SVC()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
#用10000之前的作為訓練,10000之後的做預測
val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))

得到結果:
0.87618

TF-IDF+Xgboost

import pandas as pd
from xgboost import XGBClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import f1_score
#TF-IDF+嶺迴歸
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

#clf = RidgeClassifier()
#clf=LogisticRegression()
#clf=SVC()
xgbc = XGBClassifier()
xgbc.fit(train_test[:10000], train_df['label'].values[:10000])
#用10000之前的作為訓練,10000之後的做預測
val_pred = xgbc.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))

得到結果:0.8818