NLP的基本執行步驟(II) — Bag of Words 詞袋語言模型

文字怎麼轉換成數字表現?

Derek Liao
9 min readMar 25, 2020
(from nlphackers.io)

上一篇提到自然語言處理的第一個步驟 — 繁瑣但又重要的語料預處理。我們知道在正式進行語料分析之前,需要先進行網路爬蟲語句斷詞兩樣工作,如果對這兩個名詞還很陌生的話,請去參考前面一篇文章囉。

今天的內容會圍繞在斷詞完後所要執行的下一個步驟 — 建立語言模型,以及簡單介紹每個語言模型可以用來執行什麼樣的NLP任務。

如果讀前幾篇文章已經感到有點無法理解的朋友們,可能要有點心理準備了,因為本篇所介紹的內容會比之前更抽象一點,且會引入較多的數學概念做說明。雖然聽起來好像很難,但語言模型卻是搭起資料輸入以及輸出的橋樑,預處理完成的語料一定要經過某種語言模型的轉換,才可以變成後續能被電腦分析的資料形式。因此大家更要花一點時間理解語言模型的概念,之後實際操作NLP時才不會有思路的斷層!

不過大家不用擔心!我自己也是從語言學的角度出發學習資料科學,所以我不會真的給大家看艱深的數學式子,而是從一般人的角度去描述這些模型背後的運作概念是什麼。我們事不宜遲趕快進入今天的主題吧!

語言模型(Language Models)是什麼?

語言模型被定義成:

「可以用來表示一段文字的機率或概率模型。」

一開始看完這段話你可能跟我有一樣的感覺:誰知道這是什麼意思??

幫各位翻譯一下,其實語言模型指的就是一種將文字轉為數字表達的方法

為什麼要這麼做呢?因為不管使用什麼樣的資料分析方法,電腦只能處理數字形式的資料。若是直接把純文字或字串餵給電腦,電腦是沒辦法消化的。所以語言模型就是各式各樣用數值去取代文字的方法,這樣電腦在分析那些數字時,就好像在分析文字一樣。

那接下來就簡單介紹其中一種語言模型(再講一次:文字轉數字的方法!!):Bag of Words詞袋模型。而這個大模型底下又衍生著許多變形,我們一起來看看吧。

詞袋模型(Bag of Words Model, 簡稱BoW)

詞袋模型大概是自然語言處理中歷史最久遠的語言模型之一,它的概念和做法也非常簡單,大家先參考以下的圖:

(from medium.com)

一張圖勝千言萬語,個人覺得這張圖做得太好了。

詞袋的概念就是將像圖片左方的一段文字所包含的所有字詞都整理出來後,丟進一個袋子裡面裝起來(圖中間)。為什麼用袋子呢?因為袋子裡的東西都是同時裝在一起的,並沒有一個排列的順序關係,重要的是有包含哪些字

因此這邊就可以做成像右邊的表,顯示每個字在文章中出現幾次。這就是詞袋模型最主要的概念。

那怎麼利用詞袋去將文字轉換成數字呢?假設一個語料庫包含以下兩句:

  • a. 看到他我就不爽。(先斷詞)=>看到/他/我/就/不爽
  • b. 看到他我就火大。(先斷詞)=>看到/他/我/就/火大

這個語料庫的詞袋長這樣:(就 ,他 , 看到, 我 , 火大, 不爽)
注意詞袋裡的詞是沒有絕對的順序關係的,這邊只是一個隨機排法
接著,如果一個詞在句子中有出現,我們就幫他做一個記號,如下:

a 句可以表示成:[1, 1, 1, 1, 0, 1] (a句沒有「火大」,標示為0)
b 句可以表示成:[1, 1, 1, 1, 1, 0] (b句沒有「不爽」,標示為0)

像這樣用1跟0來表示句子中詞語有沒有出現的方式有個酷炫名字:
獨熱編碼(One-hot encoding)
利用獨熱編碼的方式,一個句子可以被轉換成一個向量的形式表達(向量“vector,” 就是一列數字而已),就可以達成簡單的文字轉換成數字。

這邊提供一張圖給大家做參考:

(from medium.com)

但傳統BOW的缺點非常多:

  • 容易造成維度災難(curse of dimensionality):
    像上面 a, b句綜合起來只包含六個詞,也就是一個句子最多只要用6個數字就可以完整表達(fancy一點的說法是:a,b 句的向量都只有6個維度)。但如果今天語料很龐大,詞袋裡一次就包含2000個不同的詞呢?那每個句子不就要用2000個1和0才能表達嗎?(一個向量的長度是2000欸,超長),因此就會造成電腦一次要處理2000個維度的資料,對電腦來說是一個很大的負擔,這個現象就是one-hot encoding容易造成所謂的維度災難。
  • 向量表達過於稀疏(sparse)
    假設今天有一個句子:「我不爽。」以上面的詞袋為例,要用向量表達這個句子的話只要在「我」及「不爽」的地方標上1就好,其他4個詞的位置都會被標上0。你應該能猜到我要講什麼了:
    那今天如果有2000個詞,一個向量就有2000個位置要標記1或0,如果只有「我」和「不爽」是1,那向量裡會有其他1998個0欸!這樣的向量表達太沒效率了,由於沒有出現的詞就會被標上0,可能會造成一個向量大部分都會是0,這就是稀疏向量。
  • 無法表達語意
    如同我上面提到的,詞袋是沒有絕對的順序關係的,因此獨熱編碼的表達方式純粹就是將有出現的詞標上1而已,詞與詞之間的順序完全被忽略掉。但詞的順序對於語意的表達是非常重要的,例如「我打他」和「他打我」所包含的詞一樣,因此獨熱編碼會是一樣的,但兩句意思截然不同。此外,上面的a句與b句,其實「不爽」和「火大」語意上表達相同概念,但在向量表達中卻是正交關係([0,1]和[1,0]會互相抵消)。

因此為了解決這些缺點,BoW有幾個不同的衍生模型:

詞袋模型衍生 1:TF-IDF

TF-IDF如同詞袋模型由向量的形式表達一份文件,但並非以獨熱(1和0)的形式,而TF-IDF由兩個部分所組成:

  • TF (Term Frequency)「詞頻」指的是一個詞在一個文件中出現的頻率,因此一個詞TF越高,可能就代表他在這篇文章中沒那麼重要,例如英文的 “the”, “a” 還有中文的「的」、「了」等等,這些字都很常出現,但沒什麼意義。
  • IDF (Inverse Document Frequency)「逆文件詞頻」指的是所有文件的數量和包含特定詞文件的數量的比率。大家可以想像,如果一個詞在一個文件中很常出現,但在別的文件中非常少出現,那是不是就代表這個詞對這篇文章來說很重要呢?

TF-IDF即是將TF乘上IDF,獲取一個能代表一個詞在文件中重要程度的數值,這個數值就是TF-IDF值。而每篇文件可以用一系列的TF-IDF代表,形成一個向量表達這篇文件。如此一來帶入了詞的重要程度的概念,但卻還是有可能發生維度災難,且TF-IDF向量依然是一個稀疏向量,因此之後還需要搭配別的方法來進一步提取比重要更重要的那些詞。

詞袋模型衍生2:CBoW(Continuous Bag of Words)

CBoW指的是連續詞袋模型,這個模型運用了神經網路的概念,是一個淺層的類神經網路。相較於傳統詞袋模型,CBoW的輸入一樣是獨熱的形式,但不同的點是,CBoW模型會將一開始每個詞都透過中間的隱藏層作轉換,讓每個詞的詞向量中不再只包含0與1,而是有意義的數值。(什麼叫有意義的數值?這個與類神經網路中用來更新權重的梯度下降法有關,有興趣的朋友可以google一下,這邊不多作解釋。)

那中間的隱藏層轉換又是怎麼進行的呢?簡單的說法是:CBoW會同時參考一個詞前後的語境來決定那個詞所代表的詞向量是什麼。用上面的例子來看:「不爽」和「火大」前面所接的詞都是「看到」、「他」、「我」、「就」,因此模型就會判斷:「不爽」和「火大」可能表現出相似的語意和句法結構,這個兩個詞就會被賦予非常接近的詞向量。

  • Word2vec 模型

除此之外一定要提到,連續詞袋模型CBoW是構成word2vec模型的兩種演算法其中之一(另一種為skip-gram,一樣有興趣可以google),因此他的地位到現在都蠻高的。你可能會問:word2vec是什麼?

(from jishuwen.com)

Word2vec模型是由Google的Mikolov等人在2013年提出的,word2vec如字面上所示,即是word to vector,把字詞換成向量表達的一個模型。這邊用一個直覺化的比喻來解釋:

還記得上面提到的那篇由2000個字詞所組成的文件嗎?如果我們今天要將這份文件轉換成數字的形式表達,我們就要先使用word2vec來賦予這2000個字詞的詞向量,每一個詞都擁有一個專屬詞向量。在word2vec中,一般會有一個預設的向量維度,可能是300或400(根據所需調整),假設我們讓這2000個字詞散落在400個維度之中,一個維度就會有5個詞,算是剛好的大小。如此一來,一個詞只要用一個有400個數字的列表就可以表達,且意思相近的詞在這400個維度中會比較靠近彼此。以此類推,這份文件也只需要一個400維的向量就可以完整表達了,跟原始的2000比起來變得有效率非常多!

不過其實TF-IDF也是可以跟word2vec混合使用增加詞向量訓練品質的,但這邊我就以後再提,相信大家已經頭昏腦脹了(包括我自己寫到這裡也是QQ)

其實語言模型還包含非常多種類,例如n元語法、skip-gram、深度學習的CNN、RNN、LSTM都可以拿來做自然語言處理,真的包羅萬象,我也只打算寫這一篇介紹最古早的bag of words模型。其他的以後有機會再寫,這裡主要是想引出word2vec的概念。

長篇大論系列的文章應該到此為止,大家看完這幾篇應該對於NLP的一些基本元素也有概念了。其實理解了詞袋模型,懂了怎麼把文字轉換成數字運算之後,接下來就變得比較容易了:開始找一個你有興趣的議題,找一個合適的分析方法,把這些向量代進去code裡面,結果很快就會出來了。所以接下來我也不再做太多的文字解釋,會直接開始寫一些包含code的文章,讓大家可以實際開始操作運用前面講到的東西。

那下一篇,就從網路爬蟲、Requests, Beautiful Soup, Scrapy 這些開始吧!

--

--

Derek Liao

Hi! 我是Derek,我在這裡分享我對nlp/data science的一些見解,也希望透過寫作幫助自己和大家更瞭解語言學、數據科學、和自然語言處理。