1. 程式人生 > >詞袋模型和詞向量模型

詞袋模型和詞向量模型

在自然語言處理和文字分析的問題中,詞袋(Bag of Words, BOW)和詞向量(Word Embedding)是兩種最常用的模型。更準確地說,詞向量只能表徵單個詞,如果要表示文字,需要做一些額外的處理。下面就簡單聊一下兩種模型的應用。

所謂BOW,就是將文字/Query看作是一系列詞的集合。由於詞很多,所以咱們就用袋子把它們裝起來,簡稱詞袋。至於為什麼用袋子而不用筐(basket)或者桶(bucket),這咱就不知道了。舉個例子:

                   文字1:蘇寧易購/是/國內/著名/的/B2C/電商/之一

這是一個短文字。“/”作為詞與詞之間的分割。從中我們可以看到這個文字包含“蘇寧易購”,“B2C”,“電商”等詞。換句話說,該文字的的詞袋由“蘇寧易購”,“電商”等詞構成。就像這樣:


但計算機不認識字,只認識數字,那在計算機中怎麼表示詞袋模型呢?其實很簡單,給每個詞一個位置/索引就可以了。例如,我們令“蘇寧易購”的索引為0,“電商”的索引為1,其他以此類推。則該文字的詞袋就變成了:


是的,詞袋變成了一串數字的(索引)的集合。這樣計算機就能讀懂了。如果用程式來描述的話,就會像:Set<int>(0,1,2…)。當然,剛才的例子中像“蘇寧易購”等詞只出現了一次,如果出現多次,可能就需要支援重複元素的容器了,如Java/C++中的MultiSet。

可是,在實際的應用中(如:文字的相似度計算),用剛才說的容器是非常不方便的(如果要用,需要額外用Map容器來儲存一本字典來表徵詞和索引的對映關係)。因此我們考慮用更簡單的資料結構來組織詞袋模型。既然剛才說詞是用數字(索引)來表示的,那自然我們會想到陣列。例如:

         Intwords[10000] = {1,20,500,0,……}

                                     索引:{0,1,2,3,……}

                                     詞:   {蘇寧易購,是,國內,B2C,……}

陣列的下標表示不同的詞,陣列中的元素表示詞的權重(如:TF,TF-IDF)。更為一般的,詞的索引可以用詞的HashCode來計算,即:Index(蘇寧易購) = HashCode(蘇寧易購)。將詞雜湊到陣列的某個位置,並且是固定的(理論上會有衝突,需要考慮衝突的問題)。因此,HashCode這個函式起到了字典的作用。轉化成了陣列,接下來計算餘弦相似度啥的就好辦多了。這就是詞袋模型。

下面講講詞向量模型。實際上,單個詞的詞向量不足以表示整個文字,能表示的僅僅是這個詞本身。往往,這個詞向量是個高維的向量(幾萬甚至幾十萬)。先不說它是如何得到的,單說它的應用應該是很廣泛的。再舉文字相似度的例子,既然詞可以用一串數字表示,那麼自然可以用餘弦相似度或歐式距離計算與之相近的詞。這樣,詞的聚類什麼的都可以做了。那長文字怎麼辦呢?一個簡單的辦法是把這個文字中包含的詞的詞向量相加。這樣長文字也就表示成了一串數字。可是這種處理方法總讓我們覺得怪怪的。看到過有同學做的測試,當文字只有十幾個字的時候,這種處理方法還算湊合,字多了,結果就很難看了。至於詞向量是怎麼獲得,咱下回再說。目前word2vec有多種版本可供大家使用。至於像doc2vec,sentence2vec的效果還有待評估。