本次梳理基於Datawhale 第12期組隊學習 -CS224n-預訓練模塊
詳細課程內容參考(2019)斯坦福CS224n深度學習自然語言處理課程
1. 寫在前面
自然語言處理( NLP )是信息時代最重要的技術之一,也是人工智能的重要組成部分。NLP的應用無處不在,因爲人們幾乎用語言交流一切:網絡搜索、廣告、電子郵件、客戶服務、語言翻譯、醫療報告等。近年來,深度學習方法在許多不同的NLP任務中獲得了非常高的性能,使用了不需要傳統的、任務特定的特徵工程的單個端到端神經模型。 而【NLP CS224N】是入門NLP的經典課程, 所以這次藉着Datawhale組織的NLP學習的機會學習這門課程, 並從細節層面重新梳理NLP的知識。
今天是組隊學習任務的第三篇, 一下跳到了CS224N的課程12, 所以知識點上感覺有了一點跳躍, 但是問題不大, 因爲這節課並沒有涉及太多的深度學習理論, 而是基於之前的詞模型介紹了幾種子詞模型, 因爲詞模型會存在一些問題, 所以我們需要更細的粒度去學習詞的表徵。 今天就先整理Lecture12, 中間落下的這些課程筆記後面也會慢慢的補上來。 爲了更好的和第二節課的內容更好的銜接, 首先會先補充一點Word2Vec的東西, 前面的兩篇筆記在說Word2Vec的原理並重點介紹了其中的一種訓練方式skip-gram Model和一種高級的訓練方式negative sample,具體內容可以參考第一篇和第二篇筆記, 而這次會簡單介紹另一種訓練的方式CBOW和另外一種高效的訓練方式hierarchical softmax, 然後在分析一下這種基於詞的這種語言模型的一些問題,引出更細粒度學習詞表徵的一些模型, 比如Character-Level Model, Subword Model, 以及兩者的混合模型Hybrid Model,fastText, 並分別就其工作原理進行簡述(太深的我也不太瞭解, 這個需要讀相應的論文, 所以建議就是先明白每個模型針對什麼樣的問題, 運作原理,等後面遇到具體任務感覺用相應模型了,再去研究具體的細節, 當然專門搞NLP的除外哈 😉)
大綱如下:
- Word2Vec之CBOW和hierarchical softmax
- 基於word的模型問題和Character-Level Model
- Subword Model 與 Byte Pair Encoding
- Hybrid Model與fastText算法
Ok, let’s go!
2.Word2Vec之CBOW和hierarchical softmax
前面一直在說Word2Vec的工作原理, 下面簡單的回顧一下, 首先Word2Vec是一種計算單詞詞向量的一種方式, 核心思想是預測每個單詞和上下文單詞之間的關係。具體實現算法有Skip-gram和CBOW兩種模型。前面已經介紹了前者, Skip-gram Model的輸入是中心詞, 而去預測對應的上下文向量, 通過這種方式去訓練得到單詞的表徵, 並且前面也介紹了這種方法的計算量很大, 因爲它的輸出是做了一個softmax分類, 而類別是詞庫中單詞的個數。 所以後面有了兩個高級的算法進行訓練,一個是負採樣的方式, 這個的工作原理是判斷選取的context word和target word是否構成一組正確的context-target對,每次訓練一般包含一個正樣本和k個負樣本, 這樣就把softmax的多分類問題轉換成了k+1個二分類的問題, 從而大大減少了計算。這就是前面介紹的一些內容。
2.1 CBOW模型
這次再介紹點新的東西, 也就是Word2Vec的另一種訓練模型CBOW, 這個正好與Skip-Model相反, 是基於上下文去預測中心詞。 還有另外一種減少計算量的方式叫做層級Softmax的方式, 它是通過構建哈夫曼樹來做層級的softmax, 從而減少計算。 這樣Word2Vec這塊就全乎點了, 這裏的邏輯就是skip-gram和CBOW是Word2Vec的兩種具體算法模型, 兩者是平級的, 而負採樣和層級softmax是對前面兩者的改進算法, 是更高級的訓練方式, 這兩個也是平級。(不要搞混了哈)
CBOW模型的訓練輸入是某一箇中心詞的上下文相關的詞對應的詞向量,而輸出中心詞。比如下面這段話,我們的上下文大小取值爲4,中心詞是"Learning",也就是我們需要的輸出詞向量,上下文對應的詞有8個,前後各4個,這8個詞是我們模型的輸入。由於CBOW使用的是詞袋模型,因此這8個詞都是平等的,也就是不考慮他們和我們關注的詞之間的距離大小,只要在我們上下文之內即可。
這樣我們這個CBOW的例子裏,我們的輸入是8個詞向量,輸出是所有詞的softmax概率(訓練的目標是期望訓練樣本中心詞對應的softmax概率最大),對應的CBOW神經網絡模型輸入層有8個神經元,輸出層有詞彙表大小個神經元。隱藏層的神經元個數我們可以自己指定。通過DNN的反向傳播算法,我們可以求出DNN模型的參數,同時得到所有的詞對應的詞向量。這樣當我們有新的需求,要求出某8個詞對應的最可能的輸出中心詞時,我們可以通過一次DNN前向傳播算法並通過softmax激活函數找到概率最大的詞對應的神經元即可。這樣的一個感覺:
細節層面就是我們的輸入會是多個上下文向量, 比如上面的例子中我們有8個上下文詞, 那麼就是一個的一個矩陣, 每一列代表着每個詞的One-Hot編碼,然後經過一個詞向量矩陣, 這個大小是的, 這樣通過就是一個的一個矩陣, 正好對應着8個上下文詞的詞向量形式。 然後再經過一個, 這是一個的矩陣, 通過得到一個的矩陣, 然後再經過softmax, 每一列代表了某個上下文詞作爲輸入的時候對應的輸出。 這樣我們希望中心詞的概率最大, 就會有損失出來,然後更新參數就可以了。
所以CBOW的工作方式和skip-gram正好相反, 前者是由上下文去預測中心詞, 而後者是中心詞預測上下文詞。 對比一下的話, skip-gram Model張下面這樣, 並且skip-gram是一箇中心詞對應多個上下文詞, 所以可能訓練的時候要花時間長一些。
所以有了skip-gram的基礎理解CBOW並不難, 同時也可以發現, 兩者最後都是做了一個softmax多分類的問題, 這個輸出維度都是, 所以才存在着計算量大的問題, 因爲這個真實訓練的時候可是上百萬。 所以有兩種改進方式, 負採樣和層級softmax, 這裏主要介紹後者了。
2.2 Hierarchical softmax模型
Hierarchical softmax,通過構建哈夫曼tree來做層級softmax, 可以把複雜度從降低到, 那麼是怎麼做到的呢? 這個東西又是如何訓練的呢?
再介紹層級softmax的原理之前, 得先回憶如何去構建一棵哈夫曼樹, 假設我們有(a, b, c, d, e, f)六個單詞, 它們在句子中裏面出現的頻率是(20, 4, 8, 6, 16, 3), 那麼我們就可以根據詞頻去構造哈夫曼樹, 首先是挑兩個最小的(4, 3), 進行合併, 得到一個新樹, 然後原節點中把4, 3去掉, 把兩者的權值相加7作爲新節點的權重,就成了5個節點, 權重是(20, 8, 6, 16, 7),然後再挑兩個小的節點合併, 節點去掉, 新權值新節點加入, 直到最後只有一棵樹爲止:
編碼的時候, 我們假設左子樹是0, 右子樹是1, 就能把每個單詞進行編碼, 如上圖的左下角那樣, 就會發現每個單詞的編碼都是獨一無二, 每個單詞都會在葉子節點, 且出現頻率最高的單詞離根節點最近。
層次softmax其實就是上面的一種思想, 也是在skip-gram或者CBOW的基礎上修改了後半部分也損失函數, 負採樣其實也是這麼做的, 前面的輸入到獲得詞向量的那部分是不變的, 變得就是獲得單詞的詞向量之後,也就是從隱藏層到輸出層這部分的變化, 像原始的skip-gram或者CBOW就直接通過了一個矩陣然後得到V個輸出。 而負採樣是在上採樣了k個負樣本和一個正樣本, 然後在那上面做二分類問題, 損失函數變成了
的形式, 那麼層級softmax是怎麼做的呢?
Hierarchical softmax模型是從隱藏層到輸出這塊建成了一種哈夫曼樹映射的一種形式, 如下圖:
前面的那部分依然是從One-Hot經過詞向量矩陣獲得詞向量, 只不過詞向量到輸出的這部分換成了哈夫曼樹, 因爲通過上面的分析, 我們知道通過建立哈夫曼樹,正好可以把詞庫裏面所有的單詞都放到葉子節點上, 並且會有不同的編碼, 且頻率大的離着根節點最近, 而這裏的根節點就是我們隱藏層得到的詞向量。 在哈夫曼樹上, 從根節點的詞向量到詞庫中的每個單詞只有一條路徑, 比如下圖中:
詞的path爲, 其中表示詞的path上的第個節點。在哈夫曼樹中,隱藏層到輸出層的softmax映射不是一下子完成的,而是沿着哈夫曼樹一步步完成的,因此這種softmax取名爲"Hierarchical Softmax"。你發現了嗎? 層級softmax, 其實從根節點開始, 每經過一箇中間節點都是做一個二分類的任務。
那麼怎麼才能走到我們想要輸出的那個詞呢? 就得想辦法讓那個詞的節點的概率最大, 比如上面圖中的例子, 我們想要輸出, 就得想辦法讓這個概率最大, 怎麼計算這個概率呢? 從根節點開始, 因爲每一次都是二分類的任務, 那麼就定義從中間節點走左邊的概率:
其中表示中間節點的向量, 表示左邊路上的參數, 走右邊的概率:
那麼從根節點走到, 我們可以計算概率值:
我們要最大化這個概率, 當然實際的損失函數依然是取對數變負進行化簡。具體詳細的推導過程這裏就不說了, 下面會有鏈接。 這裏主要是看看這個東西具體是怎麼過程, 下面拿個栗子走一遍:
假設我們的詞典有word [the, of ,respond, active, plutonium, ascetic, arbitrarily, chupacabra] 共8個單詞, 我們看看如何做層級的softmax。
- 預處理: 構建哈夫曼樹
根據語料中的每個word的詞頻構建赫夫曼tree,詞頻越高,則離樹根越近,路徑越短。如下圖:
詞典中的每個word都在葉子節點, 每個word需要計算兩個信息: 路徑和哈夫曼編碼, 比如"respond"的路徑經過的節點是(6,4,3), 編碼label是(1,0,0)。 建完樹之後, 每個葉子節點都有唯一的路徑和編碼。 - 模型的輸入
輸入部分, 和之前的一樣, 在在cbow或者skip-gram模型,要麼是上下文word對應的id詞向量平均,要麼是中心詞對應的id向量,作爲hidden層的輸出向量。 - 樣本label
在層級softmax中每個葉子節點的word,對應的label是哈夫曼編碼, 一般長度不超過, 在訓練的時候, 每個葉子節點的label統一編碼到一個固定的長度, 不足的可以進行pad。 - 訓練過程
假設有下面一個樣本:
假設基於skip-gram模型, 首先會用“chupacabra”的one-hout編碼乘以矩陣得到詞向量表示, 也是隱藏層的輸出。 根據目標詞“active”從哈夫曼樹中得到它的path, 即經過的節點是(6,4,3), 而這些中間節點的向量是模型參數需要學習, 共有個, 通過對應的節點id, 取出相應的向量, 這個例子中, 我們的是一個的大小,這樣與hidden的輸出相乘,就會得到一個的矩陣, 經過sigmoid,就會得到的score, 然後與樣本實際的label[1,0,1]對比得到損失, 進行參數更新。這裏就能發現,每次訓練也是隻經過了部分的節點,從而減少計算量。
這就是層級softmax的工作原理了,當然有些細節部分沒有進行整理,比如目標函數的推導, 如何求取梯度等, 這些問題會放到下面的鏈接中。
3. 基於word的模型問題和Character-Level Model
之前的我們討論的表徵詞的這些算法和模型Word2Vec也好, Count-Based也好, Glove也好, 都是基於單詞作爲基本單位的, 也就是我們會先事先計算出每個單詞的詞向量表示, 然後再去一些任務, 比如機器翻譯等工作。 但是這種以單詞爲單位的模型有個很大的問題就是(OOV), 也就是不能很好的解決out-of-vocabulary(不在詞庫)的單詞。且對於單詞的一些詞法上的修飾處理的也不是很好。 一個自然的想法就是能夠利用比word更細粒度爲單位來建立模型,以更好的解決這些問題。一種思路就是字符作爲基本的單位, 建立Character-level model。拿課程裏面的一張PPT看一下:
關於詳細的內容可以參考這篇論文Fully Character-Level Neural Machine Translation without Explicit Segmentation, 上面這是個完全字符級別的模型。輸入的字符先被映射到character embedding。然後與窗口大小不同的卷積核進行卷積操作再將輸出聯結起來,例如上圖中有三種窗口大小分別爲3,4,5的卷積核,相當於學習了基於字符的3-grams, 4-grams, 5-grams。然後對卷積的輸出進行max pooling操作,相當於選擇最顯著的特徵產生segment embedding。由此我們從最基礎的輸入的character embedding得到了系統中認爲語言學上有意義的segment embedding。然後將這些特徵經過Highway Network(有些類似於Residual network,方便深層網絡中信息的流通,不過加入了一些控制信息流量的gate)和雙向的GRU,這樣得到最終的encoder output。之後decoder再利用Attention機制以及character level GRU進行decode。
實驗結果顯示,基於字符的模型能更好的處理OOV的問題,而且對於多語言場景,能更好的學習各語言間通用的詞素。當然這種方法帶來的問題就是感覺粒度又過細了,因爲基本單位換成字符之後, 相比單詞, 輸入的序列會更長, 使得數據更稀疏且長程的依賴關係更難學習,訓練速度也會降低。 所以後來就又有了Subword Model。
4. Subword Model 與 Byte Pair Encoding
基本單元介於字符與單詞之間的模型稱作Subword Model。比較典型的一種方法就是Byte Pair Encoding(BPE), 基本思路就是把經常出現的byte pair用新的byte來代替, 例如假設字符(‘A’, ‘B’)經常順序出現, 那麼就可以用一個新標誌’AB’代替它們。
具體是這樣做的, 給定了文本庫,我們的初始詞彙庫僅包含所有的單個的字符,然後不斷的將出現頻率最高的n-gram pair作爲新的ngram加入到詞彙庫中,直到詞彙庫的大小達到我們所設定的某個目標爲止。
比如, 假設我們的文本庫中出現的單詞及出現的次數爲{‘low’: 5, ‘lower’: 2, ‘newest’: 6, ‘widest’: 3}, 那我們的初始詞庫爲{‘l’, ‘o’, ‘w’, ‘e’, ‘r’, ‘n’, ‘w’, ‘s’, ‘t’, ‘i’, ‘d’}。這是字符的級別。
我們發現最高頻連續字節“e”和“s”出現了9次, 所以合併成"es", 輸出{‘l o w’: 5, ‘l o w e r’: 2, ‘n e w es t’: 6, ‘w i d es t’: 3}, 這時候“es”成了一個整體
這時候出現頻率最高的是(‘es’, ‘t’), 也是9次, 就把’est’看成整體, {‘l o w’: 5, ‘l o w e r’: 2, ‘n e w est’: 6, ‘w i d est’: 3}
這時候出現最高的是(‘l’, ‘o’)7次, 將’lo’合併, 得到{‘lo w’: 5, ‘lo w e r’: 2, ‘n e w est’: 6, ‘w i d est’: 3}。
依次類推, 直到達到subword詞表大小或下一個最高頻的字節對出現頻率爲1.
具體實現可以參考這篇博客理解 NLP Subword算法:BPE、WordPiece、ULM, 這裏面還有編碼和解碼,都寫的挺詳細。 谷歌的NMT模型用了BPE的變種,稱作wordpiece model,BPE中利用了n-gram count來更新詞彙庫,而wordpiece model中則用了一種貪心算法來最大化語言模型概率,即選取新的n-gram時都是選擇使得混亂度減少最多的ngram(這裏考慮字符構成單詞的概率有多大)。進一步的,sentencepiece model將詞間的空白也當成一種標記(_
),可以直接處理sentence,而不需要將其pre-tokenize成單詞。
BERT使用了wordpiece模型的一個變體, 常用詞還是用的常用詞, 而不常用的詞用的wordpieces組成, 比如hypatia=h ## yp ## ati ## a, 所以具體使用的時候, 得注意一下。
5. Hybrid Model與fastText算法
5.1 Hybrid Model
這裏說一下Hybrid Model, 這個是詞級模型和字符級模型的一個組合, 這個採用的思路是大多數情況下還是採用word level模型,而只在遇到OOV的情況才採用character level模型。
但是再說這個之前, 先看看,如何通過字符級的嵌入來得到單詞級的嵌入:
下面看混合模型, 張這個樣子:
這個的工作原理就是大部分情況下, 還是基於比價高效的word level模型, 但遇到例子中的"cute"這樣的OOV詞彙,我們就需要建立一個character level的表示,decode時遇到這個表示OOV的特殊標記時,就需要character level的decode,訓練過程是end2end的,不過損失函數是word部分與character level部分損失函數的加權疊加。這個模型的效果要比前面的那些好。
5.2 FastText
fasttext是facebook開源的一個詞向量與文本分類工具,在2016年開源,典型應用場景是“帶監督的文本分類問題”, fastText結合了自然語言處理和機器學習中最成功的理念。這些包括了使用詞袋以及n-gram袋錶徵語句,還有使用子詞(subword)信息,並通過隱藏表徵在類別間共享信息。我們另外採用了一個softmax層級(利用了類別不均衡分佈的優勢)來加速運算過程。
5.2.1 模型架構
fastText的架構和word2vec中的CBOW的架構類似, 這也就是爲啥上面先上來說CBOW的原因, CBOW的架構張這樣:輸入的是的上下文2d個詞,經過隱藏層後,輸出的是。
word2vec將上下文關係轉化爲多分類任務,進而訓練邏輯迴歸模型,這裏的類別數量是 |V| 詞庫大小。通常的文本數據中,詞庫少則數萬,多則百萬,在訓練中直接訓練多分類邏輯迴歸並不現實。所以提供了兩種針對大規模多分類問題的優化手段, negative sampling 和 hierarchical softmax。在優化中,negative sampling 只更新少量負面類,從而減輕了計算量。hierarchical softmax 將詞庫表示成前綴樹,從樹根到葉子的路徑可以表示爲一系列二分類器,一次多分類計算的複雜度從|V|降低到了樹的高度。
下面看fastTest的模型架構:
其中表示一個文本中的n-gram向量,每個特徵是詞向量的平均值。這和前文中提到的cbow相似,cbow用上下文去預測中心詞,而此處用全部的n-gram去預測指定類別。
5.2.2 層次Softmax
對於有大量類別的數據集,fastText使用了一個分層分類器(而非扁平式架構)。不同的類別被整合進樹形結構中(想象下二叉樹而非 list)。在某些文本分類任務中類別很多,計算線性分類器的複雜度高。爲了改善運行時間,fastText 模型使用了層次 Softmax 技巧。層次 Softmax 技巧建立在哈弗曼編碼的基礎上,對標籤進行編碼,能夠極大地縮小模型預測目標的數量。
fastText 也利用了類別(class)不均衡這個事實(一些類別出現次數比其他的更多),通過使用 Huffman 算法建立用於表徵類別的樹形結構。因此,頻繁出現類別的樹形結構的深度要比不頻繁出現類別的樹形結構的深度要小,這也使得進一步的計算效率更高。
5.2.3 N-gram子詞特徵
fastText 可以用於文本分類和句子分類。不管是文本分類還是句子分類,我們常用的特徵是詞袋模型。但詞袋模型不能考慮詞之間的順序,因此 fastText 還加入了 N-gram 特徵。
在 fasttext 中,每個詞被看做是 n-gram字母串包。爲了區分前後綴情況,"<", ">"符號被加到了詞的前後端。除了詞的子串外,詞本身也被包含進了 n-gram字母串包。以 where 爲例,n=3 的情況下,其子串分別爲<wh, whe, her, ere, re>
,<where>
。對於word ,其n-gram集合用 [公式] 表示,每個n-gram的矢量表示爲 ,則每個單詞可以表示成其所有n-gram的矢量和的形式,而中心詞和上下文的分數就可以表示成
之後, 就可以用經典的Word2Vec算法訓練得到這些特徵向量。
這種方式既保持了word2vec計算速度快的優點,又解決了遇到training data中沒見過的oov word的表示問題,可謂一舉兩得。
下面是fast-text和word2vec的區別:
6. 總結
簡單梳理一下這篇文章, 這篇文章類似於科普性的一篇,主要在說單詞模型的一些弊端以及目前存在的一些更細粒度的模型, 比如純字符型, subword Model, 以及混合型的, 這些模型層層遞進以更好的解決問題, 單純的詞模型對於OOV問題不好辦, 而純字符型的又字符太長, 不好訓練, 於是慢慢的演化到了字符與單詞之間爲單元的subword Model, 後來又出現了單詞和字符組合的模型。
首先補充了Word2Vec裏面的另一種訓練模型CBOW,並介紹了另一種高效的訓練方式層級softmax, 畢竟後面的模型都是基於Word2Vec進行一系列的衍生, 然後從字符模型,subword Model, 到混合模型到fastText, 它們的原理都進行了簡單的介紹。
參考:
- 12 Information from parts of words Subword Models
- CS224N筆記(十二):Subword模型
- 層次softmax (hierarchical softmax)理解
- word2vec原理(二) 基於Hierarchical Softmax的模型
- 理解 NLP Subword算法:BPE、WordPiece、ULM
- SentencePiece,subword-nmt,bpe算法
- FastText算法原理解析
- Hierarchical Softmax(層次Softmax)
- Character Level NMT論文
- Byte Pair Encoding論文
- Hybrid模型論文
- FastText論文