文本表示是自然語言處理中的基礎工作,文本表示的好壞直接影響到整個自然語言處理系統的性能。在自然語言處理研究領域,文本向量化是文本表示的一種重要方式。
顧名思義,文本向量化就是將文本表示成一系列能夠表達文本語義的向量。無論中文還是英文,詞語都是表達文本處理的最基本單元。
當前階段,對文本向量化都是通過詞向量化實現的。當然也有將文章或者句子作為文本處理的基本單元,像doc2vec和str2vec技術。
接下來主要是討論以詞語作為基本單元的word2vec技術,將先從onehot編碼到word2vec,再從glove詞向量到fasttext
什么是one hot編碼
one-hot編碼,又稱獨熱編碼、一位有效編碼。其方法是使用N位狀態寄存器來對N個狀態進行編碼,每個狀態都有它獨立的寄存器位,並且在任意時候,其中只有一位有效。舉個例子,假設我們有四個樣本(行),每個樣本有三個特征(列),如下圖:
上圖中我們已經對每個特征進行了普通的數字編碼:我們的feature_1有兩種可能的取值,比如是男/女,這里男用1表示,女用2表示。那么one-hot編碼是怎么搞的呢?
我們再拿feature_2來說明:這里feature_2 有4種取值(狀態),我們就用4個狀態位來表示這個特征,one-hot編碼就是保證每個樣本中的單個特征只有1位處於狀態1,其他的都是0。
1 -> 0001; 2 -> 0010; 3 -> 0100; 4 -> 1000;
對於2種狀態、3種狀態、甚至更多狀態都可以這樣表示,所以我們可以得到這些樣本特征的新表示,如下圖:
one-hot編碼將每個狀態位都看成一個特征。對於前兩個樣本我們可以得到它的特征向量分別為:
Sample1 ->[0,1,1,0,0,0,1,0,0] Sample2 ->[1,0,0,1,0,0,0,1,0]
one-hot在提取文本特征中的應用
one hot在特征提取上屬於詞袋模型(bag of words)。關於如何使用one-hot抽取文本特征向量我們通過以下例子來說明。假設我們的語料庫中有三段話:
- 我愛中國
- 爸爸媽媽愛我
- 爸爸媽媽愛中國
我們首先對上面語料進行分詞,並獲取其中的所有的詞,然后對每個詞進行編號:
1 我; 2 愛; 3 爸爸; 4 媽媽; 5 中國
然后使用one-hot對每段話提取特征向量:
因此我們得到了最終的特征向量為:
我愛中國 -> ( 1,1,0,0,1 )
爸爸媽媽愛我 ->( 1,1,1,1,0 )
爸爸媽媽愛中國 ->( 0,1,1,1,1 )
在實際應用過程中,我們對多篇文本進行分詞,並統計詞頻,生成的詞典中詞數有幾萬,十幾萬,甚至更多,如果都進行one-hot進行編碼肯定是行不通的,這時一般會根據詞頻選取前5K或50K的詞進行向量化,摒棄寫低頻詞,提高效率。當然5K或50K對於one-hot編碼已經很大了,后面會用word2vec對其進行處理。
優缺點分析:
優點:
一是解決了分類器不好處理離散數據的問題;
二是在一定程度上也起到了擴充特征的作用(上面樣本特征數從3擴展到了9)。
缺點:
1. 它是一個詞袋模型,不考慮詞與詞之間的順序,無法保留詞序信息;
2. 它假設詞與詞相互獨立,存在語義鴻溝問題(在大多數情況下,詞與詞是相互影響的);
3. 它得到的特征是離散稀疏的;
4. 維度災難:很顯然,如果上述例子詞典中包含10K個單詞,那么每個需要用10000維的向量表示,采用one-hot編碼,對角線元素均設為1,其余為0,也就是說除了文本中出現的詞語位置不為0,其余9000多的位置均為0,如此高緯度的向量會嚴重影響計算速度。
one-hot編程實現
1 import numpy as np 2 3 contents = ['我 畢業 於 **大學','我 就職 於 **公司'] 4 word_dict = {} 5 6 for content in contents: 7 for word in content.split(): 8 if word not in word_dict: 9 word_dict[word] = len(word_dict) 10 print(word_dict) 11 12 res = np.zeros((len(contents), len(word_dict))) 13 14 for i, content in enumerate(contents): 15 for word in content.split(): 16 j = word_dict.get(word) 17 res[i, j] = 1 18 19 print(res)
2、Keras中one-hot編碼的實現
1 from keras.preprocessing.text import Tokenizer 2 contents = ['我 畢業 於 **大學','我 就職 於 **公司'] 3 4 #構建單詞索引 5 6 tokenizer =Tokenizer() 7 tokenizer.fit_on_texts(contents) 8 9 word_index = tokenizer.word_index 10 print(word_index) 11 # print(len(word_index)) 12 13 sequences = tokenizer.texts_to_sequences(contents) 14 # print(sequences) 15 16 one_hot_result = tokenizer.texts_to_matrix(contents) 17 print(one_hot_result)