文字分類學習
一、學習目標
學會TF-IDF的原理和使用
使用sklearn的機器學習模型完成文字分類
機器學習模型
機器學習是對能通過經驗自動改進的計算機演算法的研究。機器學習通過歷史資料訓練出模型對應於人類對經驗進行歸納的過程,機器學習利用模型對新資料進行預測對應於人類利用總結的規律對新問題進行預測的過程。
機器學習有很多種分支,對於學習者來說應該優先掌握機器學習演算法的分類,然後再其中一種機器學習演算法進行學習。由於機器學習演算法的分支和細節實在是太多,所以如果你一開始就被細節迷住了眼,你就很難知道全域性是什麼情況的。
如果你是機器學習初學者,你應該知道如下的事情:
機器學習能解決一定的問題,但不能奢求機器學習是萬能的;
每種機器學習演算法有一定的偏好,需要具體問題具體分析;
二、文字表示方法
在機器學習演算法的訓練過程中,假設給定 N個樣本,每個樣本有 M個特徵,這樣組成了 N*M
的樣本矩陣,然後完成演算法的訓練和預測。同樣的在計算機視覺中可以將圖片的畫素看作特徵,每張圖片看作hight×width×3的特徵圖,一個三維的矩陣來進入計算機進行計算。
但是在自然語言領域,上述方法卻不可行:文字是不定長度的。文字表示成計算機能夠運算的數字或向量的方法一般稱為詞嵌入(Word Embedding)方法。詞嵌入將不定長的文字轉換到定長的空間內,是文字分類的第一步。
(1)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]
(2)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()
(3)N-gram
N-gram與Count Vectors類似,不過加入了相鄰單詞組合成為新的單詞,並進行計數。
如果N取值為2,則句子1和句子2就變為:
句子1:我愛 愛北 北京 京天 天安 安門
句子2:我喜 喜歡 歡上 上海
(4)TF-IDF
TF-IDF 分數由兩部分組成:第一部分是詞語頻率(Term Frequency),第二部分是逆文件頻率(Inverse Document Frequency)。其中計算語料庫中文件總數除以含有該詞語的文件數量,然後再取對數就是逆文件頻率。
TF(t)= 該詞語在當前文件出現的次數 / 當前文件中詞語的總數
IDF(t)= log_e(文件總數 / 出現該詞語的文件總數)
TF-IDF = TF*IDF
基於機器學習的文字分類
接下來我們將對比不同文字表示演算法的精度,通過本地構建驗證集計算F1得分。
三、實踐 :TF-IDF + RidgeClassifier
# TF-IDF + RidgeClassifier import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.metrics import f1_score train_df = pd.read_csv('../data/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.fit(train_test[:10000], train_df['label'].values[:10000]) val_pred = clf.predict(train_test[10000:]) print(f1_score(train_df['label'].values[10000:], val_pred, average='macro')) # 0.87