一般對文本預處理或者叫做特徵提取,首先是要分詞,分詞之後就是向量化,也就是訓練詞向量(其實就是將詞和詞頻對應起來,做成矩陣向量的形式)。下面我們要講的就是向量化。
1 詞袋模型
講向量化之前,先講一下詞袋模型(Bag of Words,BoW)。詞袋模型假設我們不考慮文本中詞與詞之間的上下文關係,僅僅考慮所有詞的權重,而權重與詞在文本中出現的頻率有關。
詞袋模型首先會進行分詞,之後,通過統計每個詞在文本中出現的次數就可以得到該文本基於詞的特徵,再將各個文本的詞和對應的詞頻放在一起,就是我們所說的向量化。向量化之後,一般也會使用TF-IDF進行特徵的權重修正,再將特徵進行標準化等等一些的特徵工程手段,就可以將數據帶入機器學習算法中進行分類和聚類了。
總結起來,詞袋模型就是三板斧:
- 分詞(tokenizing)
- 統計修訂詞特徵值(counting,或者就記住TF-IDF)
- 標準化(normalizing)
當然,詞袋模型有很大的侷限,僅僅考慮了詞頻,忽略了上下文關係,丟失一部分語義。但是在大多數時候,如果我們的目的是分類聚類,詞袋模型的表現還是很好的。
2 向量化
在詞袋模型的統計詞頻這一步,我們會得到該文本所有詞的詞頻,有了詞頻,我們就能用詞向量來表示該文本了。我們直接用中的類做演示,這個類可以幫我們完成文本的詞頻統計和向量化。且看代碼:
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
corpus = [
'This is the first document.',
'This is the second second document.',
'And the third one.',
'Is this the first document?',
]
print(vectorizer.fit_transform(corpus))
輸出如下:個文本的詞頻已經統計出來了,左邊括號裏第個數字代表文本的序號,第個數字代表這個詞在詞表中的序號,注意詞的序號是基於所有文檔的。第個數字就是這個詞的詞頻了。
(0, 1) 1
(0, 2) 1
(0, 6) 1
(0, 3) 1
(0, 8) 1
(1, 5) 2
(1, 1) 1
(1, 6) 1
(1, 3) 1
(1, 8) 1
(2, 4) 1
(2, 7) 1
(2, 0) 1
(2, 6) 1
(3, 1) 1
(3, 2) 1
(3, 6) 1
(3, 3) 1
(3, 8) 1
這裏面有些東西還是需要再詳細解釋一下的。
我們進一步看看每個文本的詞向量和各個特徵代表的詞:
print(vectorizer.get_feature_names())
print(vectorizer.fit_transform(corpus).toarray())
"""
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
[[0 1 1 1 0 0 1 0 1]
[0 1 0 1 0 2 1 0 1]
[1 0 0 0 1 0 1 1 0]
[0 1 1 1 0 0 1 0 1]]
"""
我們可以看到一共有個詞,也就是說每個文本都被表示成了維的特徵向量,每一維的向量依次對應這個個詞。另外需要注意一點:英文文本在經過處理的時候會有去除停用詞的操作,比如這個單詞代表“我”,是英文的停用詞,不參與詞頻的統計。
將文本做了詞頻統計後,我們通常會通過TF-IDF進行詞特徵值權重修正,這個下一篇博客再寫。
向量化方法很好用,也很直接,但是在有些場景下很難使用。比如分詞後的詞彙表非常大,達到萬以上,此時如果直接使用向量化的方法,將對應的樣本的特徵矩陣載入內存,內存就有可能爆掉。這種情況我們應該怎麼辦呢?第一反應自然就是對特徵進行降維,Hash Trick就是非常常用的文本特徵降維方法。
3 Hash Trick
在特徵處理中,經常利用笛卡爾乘積的方法來構造組合特徵,這個方法簡單,會使特徵數量爆炸式增長。比如一個可以取個不同值的類別特徵與一個可以取個不同值的類別特徵做笛卡爾乘積,就能構造出個組合特徵。在大規模文本中,特徵的維度對應着分詞後詞表的大小,所以維度自然而然地爆炸了,這時候就需要降維了。
Hash Trick是一種簡單地降維方法,它的目標是把原始的高維特徵向量壓縮成較低維的特徵向量,且儘量不損失原始特徵的表達能力。
=====================================================