n-gram 之後的重要技術是 NNLM(Neural Network Language Model),由Yoshua Bengio等人在 2003 年提出,原本只是想用神經網絡改進語言建模,卻意外地發明了詞嵌入。
表示問題:從順序編碼到 one-hot#
在深入 NNLM 之前,需要先理解一個更基礎的問題:如何讓計算機理解詞彙?
機器學習發展初期,研究者面臨一個根本性問題:計算機只能理解數字,但現實世界中大量的數據是分類別的。比如性別有男 / 女,顏色有紅 / 綠 / 藍 / 黑等等。
最初的想法很簡單粗暴:給每個類別分配一個數字。比如性別類中男 = 1、女 = 2,顏色類中紅 = 1、綠 = 2、藍 = 3。但這種順序編碼有個嚴重問題 —— 它隱含了實體之間的大小關係和距離關係。
舉個例子,如果紅 = 1、綠 = 2、藍 = 3,在機器學習中進行距離計算時:
- 紅色和綠色之間的距離:|1-2|=1
- 紅色和藍色之間的距離:|1-3|=2
- 綠色和藍色之間的距離:|2-3|=1
模型會認為紅色和綠色更相似,紅色和藍色差異較大。但其實紅綠藍三原色之間應該是等距離關係,沒有誰更接近誰。
為了解決這種語義歧義問題,one-hot 編碼應運而生。它的核心思想是用向量的正交性表示類別的獨立性。還是以紅綠藍為例:
- 紅:[1, 0, 0]
- 綠:[0, 1, 0]
- 藍:[0, 0, 1]
每個類別都是一個正交向量,彼此之間距離相等,沒有隱含的大小關係。這種思想對應了線性代數中的基向量概念 —— 每個類別都是高維空間中的一個標準基向量,互相正交且模長相等。
one-hot 的困境#
one-hot 編碼解決了順序編碼的問題,但帶來了新的困擾:
維度災難:對於一個擁有 10000 個詞的詞彙表,使用 one-hot 編碼需要 10000 維的向量空間。現實中的詞彙表往往更大,編碼空間會變得非常龐大。
稀疏性:當維度過大時,整個向量中有效信息特別少。一個 10000 維的向量裡只有 1 個位置是 1,其餘全是 0,這種稀疏性不利於計算和存儲。
語義鴻溝:one-hot 徹底拋棄了實體之間真正的關聯關係。比如 "狗" 和 "貓" 都是動物,語義上有相似性,但在 one-hot 編碼中它們的距離和 "狗" 與 "汽車" 的距離是一樣的。
這些問題在語言建模中尤為突出。無論是 n-gram 的精確匹配方法,還是神經網絡中的 one-hot 編碼,都無法捕捉詞彙間的語義相似性,導致模型泛化能力差。
NNLM 的解決思路#
NNLM 的出現同時解決了兩個問題:n-gram 的維度詛咒和 one-hot 編碼的局限性。
n-gram 面臨的維度詛咒:當測試的詞序列在訓練數據中從未出現過時,傳統方法很難給出合理的概率估計。就像背書一樣,只能記住見過的句子模式,遇到新的組合就無能為力。
NNLM 的想法很巧妙:如果一個詞序列由語義相似的詞組成,即使這個序列從未見過,也應該得到較高的概率。比如說,如果模型見過 "I love cats",那麼對於 "I adore dogs" 也應該給出合理的概率,因為 "love" 和 "adore"、"cats" 和 "dogs" 在語義上是相似的。
要實現這種能力,模型需要學習詞彙之間的相似性,而這就需要將詞彙表示為某種連續的向量空間,而不是 one-hot 那種離散的正交向量。
NNLM 的工作機制#
NNLM 的架構並不複雜,由兩層 MLP 組成。它同時學習兩個東西:每個詞的向量表示,以及基於這些向量的概率預測。
嵌入層:從稀疏到密集的轉換#
假設要預測句子中的下一個詞,NNLM 先把前面幾個詞(比如前 3 個詞)的 one-hot 向量通過一個嵌入矩陣 C 轉換成低維的密集向量:
假設詞彙表大小是 V=10000,嵌入維度是 d=300,那麼 C 就是一個 300×10000 的矩陣。當我們有一個詞的 one-hot 向量(維度是 10000×1,只有第 j 位是 1,其餘都是 0)時,矩陣乘法實際上就是取出矩陣 C 的第 j 列,得到一個 300 維的向量。
換句話說,嵌入矩陣 C 的每一列對應詞彙表中一個詞的向量表示。訓練開始時這些向量是隨機初始化的,但隨著訓練的進行,語義相似的詞會逐漸在這個 300 維空間中聚集在一起。
拼接層:構建上下文表示#
接下來把這些詞向量拼接起來,形成完整的上下文表示:
如果每個詞向量是 300 維,拼接 3 個詞後,就變成了 900 維的向量。
為什麼是簡單拼接而不是相加或者其他操作?
拼接保留了詞序信息,讓模型能夠區分 "A B C" 和 "B A C" 這樣的不同組合。
隱藏層:非線性特徵提取#
拼接好的向量 X 被送入隱藏層進行非線性變換:
這個隱藏層的作用是提取更高級的特徵。線性變換將 900 維的輸入映射到隱藏層維度(比如 500 維),然後激活函數引入非線性。
為什麼需要非線性?
如果沒有激活函數,整個網絡就是一系列線性變換的組合,等價於一個單層的線性模型,表達能力會大打折扣。tanh 函數能夠讓模型學習到詞彙組合的複雜模式。
輸出層:概率分佈計算#
最後,隱藏層的輸出被映射到詞彙表大小的向量,然後通過 softmax 得到概率分佈:
這裡是 500×10000 的矩陣,將隱藏層的 500 維輸出映射到 10000 維(詞彙表大小)。函數確保所有詞的概率和為 1:
其中是第 i 個詞對應的 logit 值(得分)。
參數更新#
訓練時使用交叉熵損失函數,目標是最大化正確詞的概率。反向傳播會同時更新所有參數:,以及最關鍵的嵌入矩陣 C。
嵌入矩陣 C 的更新是最重要的部分。為了更好地預測下一個詞,梯度會 "鼓勵" 語義相似的詞在向量空間中距離更近。比如,如果 "cat" 和 "dog" 經常出現在相似的上下文中,它們的向量表示就會逐漸靠近。
維度變化的完整流程
整個過程中的維度變化是這樣的:
輸入:3 個 10000 維的 one-hot 向量
嵌入後:3 個 300 維的密集向量
拼接後:1 個 900 維的向量
隱藏層:1 個 500 維的向量
輸出層:1 個 10000 維的概率分佈
這樣的架構能夠學習到語義相似性,是因為模型被迫在有限的嵌入空間中為每個詞找到合適的位置,而預測任務會自然地將出現在相似上下文中的詞聚集在一起。
意外的收穫#
當時 Bengio 他們的主要目標是改進語言建模,但訓練完模型後發現,那個嵌入矩陣 C 學到了非常有意思的東西。相似的詞確實在向量空間中聚集在一起,而且這些向量還能進行數學運算,比如著名的 king - man + woman ≈ queen。
這個發現一舉解決了 one-hot 編碼的三個主要問題:
- 維度問題:從 10000 維降到幾百維
- 稀疏性問題:變成了密集向量
- 語義鴻溝問題:相似詞在空間中距離相近
雖然當時還沒有 "詞嵌入" 這個專門術語,但這個想法很快就被其他研究者注意到了。2008 年,Collobert 和 Weston 證明了預訓練詞向量在下游任務中的威力。到了 2013 年,Mikolov 等人發布了 Word2Vec 工具包,專門用來學習詞向量,這時候詞嵌入技術才真正普及開來。
Word2Vec 簡化了 NNLM 的架構,提出了兩種模型:CBOW(根據上下文預測目標詞)和 Skip-gram(根據目標詞預測上下文)。Skip-gram 在小數據集和稀有詞上表現更好,CBOW 訓練更快,在頻繁詞上效果更佳。
NNLM 的優勢和局限#
相比 n-gram,NNLM 最大的優勢就是泛化能力。在 Bengio 他們的實驗中,NNLM 在兩個文本語料庫上都顯著超越了當時最先進的 trigram 模型。而且詞嵌入這個 "副產品" 後來證明價值巨大。
但 NNLM 也有不少問題。
首先是計算複雜度,訓練神經網絡比簡單的 n-gram 計數要慢得多。其次,雖然不再受馬爾可夫假設限制,但還是只能看固定長度的歷史,無法處理任意長的上下文。另外,每個詞只有一個固定的向量表示,處理不了多義詞的問題。
還有一個實際的問題是在大詞表上計算 softmax 很慢。
這些問題啟發了後續的研究。
一些思考#
從表示學習的角度看,NNLM 證明了:好的表示是解決問題的關鍵。從順序編碼到 one-hot 再到詞嵌入,每一步都在優化數據的表示方式,而表示的改進往往能帶來性能的顯著提升。
技術的進步是漸進的,每一代都在前一代的基礎上解決問題。順序編碼解決了基本的數值化問題,one-hot 解決了語義歧義問題,詞嵌入解決了稀疏性和語義相似性問題。並且,有時結果可能不是那麼重要,反而是過程才是最重要的,就像由 NNLM 衍生的Word2Vec一樣。