00 預訓練語言模型的前世今生(全文 24854 個詞)


預訓練語言模型的前世今生 - 從Word Embedding到BERT

本篇文章共 25027 個詞,一個字一個字手碼的不容易,轉載請標明出處:
預訓練語言模型的前世今生 - 從Word Embedding到BERT - 二十三歲的有德

Bert 最近很火,應該是最近最火爆的 AI 進展,網上的評價很高,從模型創新角度看一般,創新不算大。但是架不住效果太好了,基本刷新了很多 NLP 的任務的最好性能,有些任務還被刷爆了,這個纔是關鍵。另外一點是 Bert 具備廣泛的通用性,就是說絕大部分 NLP 任務都可以採用類似的兩階段模式直接去提升效果,這個第二關鍵。客觀的說,把 Bert 當做最近兩年 NLP 重大進展的集大成者更符合事實。

本文的主題是預訓練語言模型的前世今生,會大致說下 NLP 中的預訓練技術是一步一步如何發展到 Bert 模型的,從中可以很自然地看到 Bert 的思路是如何逐漸形成的,Bert 的歷史沿革是什麼,繼承了什麼,創新了什麼,爲什麼效果那麼好,主要原因是什麼,以及爲何說模型創新不算太大,爲何說 Bert 是近年來 NLP 重大進展的集大成者。

預訓練語言模型的發展並不是一蹴而就的,而是伴隨着諸如詞嵌入、序列到序列模型及 Attention 的發展而產生的。

DeepMind 的計算機科學家 Sebastian Ruder 給出了 21 世紀以來,從神經網絡技術的角度分析,自然語言處理的里程碑式進展,如下表所示:

年份 2013 年 2014 年 2015 年 2016 年 2017 年
技術 word2vec GloVe LSTM/Attention Self-Attention Transformer
年份 2018 年 2019 年 2020 年
技術 GPT/ELMo/BERT/GNN XLNet/BoBERTa/GPT-2/ERNIE/T5 GPT-3/ELECTRA/ALBERT

本篇文章將會通過上表顯示的 NLP 中技術的發展史一一敘述,由於 19 年後的技術大都是 BERT 的變體,在這裏不會多加敘述,讀者可以自行加以瞭解。

一、預訓練

1.1 圖像領域的預訓練

在介紹圖像領域的預訓練之前,我們首先介紹下卷積神經網絡(CNN),CNN 一般用於圖片分類任務,並且CNN 由多個層級結構組成,不同層學到的圖像特徵也不同,越淺的層學到的特徵越通用(橫豎撇捺),越深的層學到的特徵和具體任務的關聯性越強(人臉-人臉輪廓、汽車-汽車輪廓),如下圖所示:

由此,當領導給我們一個任務:阿貓、阿狗、阿虎的圖片各十張,然後讓我們設計一個深度神經網絡,通過該網絡把它們三者的圖片進行分類。

對於上述任務,如果我們親手設計一個深度神經網絡基本是不可能的,因爲深度學習一個弱項就是在訓練階段對於數據量的需求特別大,而領導只給我們合計三十張圖片,顯然這是不夠的。

雖然領導給我們的數據量很少,但是我們是否可以利用網上現有的大量已做好分類標註的圖片。比如 ImageNet 中有 1400 萬張圖片,並且這些圖片都已經做好了分類標註。

上述利用網絡上現有圖片的思想就是預訓練的思想,具體做法就是:

  1. 通過 ImageNet 數據集我們訓練出一個模型 A
  2. 由於上面提到 CNN 的淺層學到的特徵通用性特別強,我們可以對模型 A 做出一部分改進得到模型 B(兩種方法):
    1. 凍結:淺層參數使用模型 A 的參數,高層參數隨機初始化,淺層參數一直不變,然後利用領導給出的 30 張圖片訓練參數
    2. 微調:淺層參數使用模型 A 的參數,高層參數隨機初始化,然後利用領導給出的 30 張圖片訓練參數,但是在這裏淺層參數會隨着任務的訓練不斷髮生變化

通過上述的講解,對圖像預訓練做個總結(可參照上圖):對於一個具有少量數據的任務 A,首先通過一個現有的大量數據搭建一個 CNN 模型 A,由於 CNN的淺層學到的特徵通用性特別強,因此在搭建一個 CNN 模型 B,其中模型 B 的淺層參數使用模型 A 的淺層參數,模型 B 的高層參數隨機初始化,然後通過凍結或微調的方式利用任務 A 的數據訓練模型 B,模型 B 就是對應任務 A 的模型。

1.2 預訓練的思想

有了圖像領域預訓練的引入,我們在此給出預訓練的思想:任務 A 對應的模型 A 的參數不再是隨機初始化的,而是通過任務 B 進行預先訓練得到模型 B,然後利用模型 B 的參數對模型 A 進行初始化,再通過任務 A 的數據對模型 A 進行訓練。注:模型 B 的參數是隨機初始化的。

二、語言模型

想了解預訓練語言模型,首先得了解什麼是語言模型。

語言模型通俗點講就是計算一個句子的概率。也就是說,對於語言序列 \(w_1,w_2,\cdots,w_n\),語言模型就是計算該序列的概率,即 \(P(w_1,w_2,\cdots,w_n)\)

下面通過兩個實例具體瞭解上述所描述的意思:

  1. 假設給定兩句話 “判斷這個詞的磁性” 和 “判斷這個詞的詞性”,語言模型會認爲後者更自然。轉化成數學語言也就是:\(P(判斷,這個,詞,的,詞性) \gt P(判斷,這個,詞,的,磁性)\)
  2. 假設給定一句話做填空 “判斷這個詞的____”,則問題就變成了給定前面的詞,找出後面的一個詞是什麼,轉化成數學語言就是:\(P(詞性|判斷,這個,詞,的) \gt P(磁性|判斷,這個,詞,的)\)

通過上述兩個實例,可以給出語言模型更加具體的描述:給定一句由 \(n\) 個詞組成的句子 \(W=w_1,w_2,\cdots,w_n\),計算這個句子的概率 \(P(w_1,w_2,\cdots,w_n)\),或者計算根據上文計算下一個詞的概率 \(P(w_n|w_1,w_2,\cdots,w_{n-1})\)

下面將介紹語言模型的兩個分支,統計語言模型和神經網絡語言模型。

2.1 統計語言模型

統計語言模型的基本思想就是計算條件概率

給定一句由 \(n\) 個詞組成的句子 \(W=w_1,w_2,\cdots,w_n\),計算這個句子的概率 \(P(w_1,w_2,\cdots,w_n)\) 的公式如下(條件概率乘法公式的推廣,鏈式法則):

\[\begin{align*} P(w_1,w_2,\cdots,w_n) & = P(w_1)P(w_2|w_1)P(w_3|w_1,w_2)\cdots p(w_n|w_1,w_2,\cdots,w_{n-1}) \\ & = \prod_i P(w_i|w1,w_2,\cdots,w_{i-1}) \end{align*} \]

對於上一節提到的 “判斷這個詞的詞性” 這句話,利用上述的公式,可以得到:

\[\begin{align*} & P(判斷,這個,詞,的,詞性) = \\ & P(判斷)P(這個|判斷)P(詞|判斷,這個) \\ & P(的|判斷,這個,詞)P(詞性|判斷,這個,詞,的)P(判斷,這個,詞,的,詞性) \end{align*} \]

對於上一節提到的另外一個問題,當給定前面詞的序列 “判斷,這個,詞,的” 時,想要知道下一個詞是什麼,可以直接計算如下概率:

\[P(w_{next}|判斷,這個,詞,的)\quad\text{公式(1)} \]

其中,\(w_{next} \in V\) 表示詞序列的下一個詞,\(V\) 是一個具有 \(|V|\) 個詞的詞典(詞集合)。

對於公式(1),可以展開成如下形式:

\[P(w_{next}|判斷,這個,詞,的) = \frac{count(w_{next},判斷,這個,詞,的)}{count(判斷,這個,詞,的)} \quad\text{公式(2)} \]

對於公式(2),可以把字典 \(V\) 中的多有單詞,逐一作爲 \(w_{next}\),帶入計算,最後取最大概率的詞作爲 \(w_{next}\) 的候選詞。

如果 \(|V|\) 特別大,公式(2)的計算將會非常困難,但是我們可以引入馬爾科夫鏈的概念(當然,在這裏只是簡單講講如何做,關於馬爾科夫鏈的數學理論知識可以自行查看其他參考資料)。

假設字典 \(V\) 中有 “火星” 一詞,可以明顯發現 “火星” 不可能出現在 “判斷這個詞的” 後面,因此(火星,判斷,這個,詞,的)這個組合是不存在的,並且詞典中會存在很多類似於 “火星” 這樣的詞。

進一步,可以發現我們把(火星,判斷,這個,詞,的)這個組合判斷爲不存在,是因爲 “火星” 不可能出現在 “詞的” 後面,也就是說我們可以考慮是否把公式(1)轉化爲

\[P(w_{next}|判斷,這個,詞,的) \approx P(w_{next}|詞,的)\quad\text{公式(3)} \]

公式(3)就是馬爾科夫鏈的思想:假設 \(w_{next}\) 只和它之前的 \(k\) 個詞有相關性\(k=1\) 時稱作一個單元語言模型,\(k=2\) 時稱爲二元語言模型。

可以發現通過馬爾科夫鏈後改寫的公式計算起來將會簡單很多,下面我們舉個簡單的例子介紹下如何計算一個二元語言模型的概率。

其中二元語言模型的公式爲:

\[P(w_i|w_{i-1})=\frac{count(w_{i-1},w_i)}{count(w_{i-1})}\quad\text{公式(4)} \]

假設有一個文本集合:

“詞性是動詞”
“判斷單詞的詞性”
“磁性很強的磁鐵”
“北京的詞性是名詞”

對於上述文本,如果要計算 \(P(詞性|的)\) 的概率,通過公式(4),需要統計 “的,詞性” 同時按序出現的次數,再除以 “的” 出現的次數:

\[P(詞性|的) = \frac{count(的,詞性)}{count(的)} = \frac{2}{3}\quad\text{公式(5)} \]

上述文本集合是我們自定製的,然而對於絕大多數具有現實意義的文本,會出現數據稀疏的情況,例如訓練時未出現,測試時出現了的未登錄單詞

由於數據稀疏問題,則會出現概率值爲 0 的情況(填空題將無法從詞典中選擇一個詞填入),爲了避免 0 值的出現,會使用一種平滑的策略——分子和分母都加入一個非 0 正數,例如可以把公式(4)改爲:

\[P(w_i|w_{i-1}) = \frac{count(w_{i-1},w_i)+1}{count(w_{i-1})+|V|}\quad\text{公式(6)} \]

2.2 神經網絡語言模型

上一節簡單的介紹了統計語言模型,並且在結尾處講到統計語言模型存在數據稀疏問題,針對該問題,我們也提出了平滑方法來應對這個問題。

神經網絡語言模型則引入神經網絡架構來估計單詞的分佈,並且通過詞向量的距離衡量單詞之間的相似度,因此,對於未登錄單詞,也可以通過相似詞進行估計,進而避免出現數據稀疏問題

上圖爲神經網絡語言模型結構圖,它的學習任務是輸入某個句中單詞 \(w_t = bert\) 前的 \(t-1\) 個單詞,要求網絡正確預測單詞 “bert”,即最大化:

\[P(w_t=bert|w_1,w_2,\cdots,w_{t-1};\theta)\quad\text{公式(7)} \]

上圖所示的神經網絡語言模型分爲三層,接下來我們詳細講解這三層的作用:

  1. 神經網絡語言模型的第一層,爲輸入層。首先將前 \(n-1\) 個單詞用 Onehot 編碼(例如:0001000)作爲原始單詞輸入,之後乘以一個隨機初始化的矩陣 Q 後獲得詞向量 \(C(w_i)\),對這 \(n-1\) 個詞向量處理後得到輸入 \(x\),記作 \(x=(C(w_1),C(w_2),\cdots,C(w_{t-1}))\)
  2. 神經網絡語言模型的第二層,爲隱層,包含 \(h\) 個隱變量,\(H\) 代表權重矩陣,因此隱層的輸出爲 \(Hx+d\),其中 \(d\) 爲偏置項。並且在此之後使用 \(tanh\) 作爲激活函數。
  3. 神經網絡語言模型的第三層,爲輸出層,一共有 \(|V|\) 個輸出節點(字典大小),直觀上講,每個輸出節點 \(y_i\) 是詞典中每一個單詞概率值。最終得到的計算公式爲:\(y = softmax(b+Wx+U\tanh(d+Hx))\),其中 \(W\) 是直接從輸入層到輸出層的權重矩陣,\(U\) 是隱層到輸出層的參數矩陣。

三、詞向量

在描述神經網絡語言模型的時候,提到 Onehot 編碼和詞向量 \(C(w_i)\),但是並沒有具體提及他們到底是什麼玩意。

由於他們對於未來 BERT 的講解非常重要,所以在這裏重開一章來描述詞向量到底是什麼,如何表示。

3.1 獨熱(Onehot)編碼

把單詞用向量表示,是把深度神經網絡語言模型引入自然語言處理領域的一個核心技術。

在自然語言處理任務中,訓練集大多爲一個字或者一個詞,把他們轉化爲計算機適合處理的數值類數據非常重要。

早期,人們想到的方法是使用獨熱(Onehot)編碼,如下圖所示:

對於上圖的解釋,假設有一個包含 8 個次的字典 \(V\),“time” 位於字典的第 1 個位置,“banana” 位於字典的第 8 個位置,因此,採用獨熱表示方法,對於 “time” 的向量來說,除了第 1 個位置爲 1,其餘位置爲 0;對於 “banana” 的向量來說,除了第 8 個位置爲 1,其餘位置爲 0。

但是,對於獨熱表示的向量,如果採用餘弦相似度計算向量間的相似度,可以明顯的發現任意兩者向量的相似度結果都爲 0,即任意二者都不相關,也就是說獨熱表示無法解決詞之間的相似性問題。

3.2 Word Embedding

由於獨熱表示無法解決詞之間相似性問題,這種表示很快就被詞向量表示給替代了,這個時候聰明的你可能想到了在神經網絡語言模型中出現的一個詞向量 \(C(w_i)\),對的,這個 \(C(w_i)\) 其實就是單詞對應的 Word Embedding 值,也就是我們這節的核心——詞向量。

在神經網絡語言模型中,我們並沒有詳細解釋詞向量是如何計算的,現在讓我們重看神經網絡語言模型的架構圖:

上圖所示有一個 \(V×m\) 的矩陣 \(Q\),這個矩陣 \(Q\) 包含 \(V\) 行,\(V\) 代表詞典大小,每一行的內容代表對應單詞的 Word Embedding 值。

只不過 \(Q\) 的內容也是網絡參數,需要學習獲得,訓練剛開始用隨機值初始化矩陣 \(Q\),當這個網絡訓練好之後,矩陣 \(Q\) 的內容被正確賦值,每一行代表一個單詞對應的 Word embedding 值。

但是這個詞向量有沒有解決詞之間的相似度問題呢?爲了回答這個問題,我們可以看看詞向量的計算過程:

\[\begin{bmatrix} 0&0&0&1&0 \end{bmatrix} \begin{bmatrix} 17&24&1\\ 23&5&7\\ 4&6&13\\ 10&12&19\\ 11&18&25 \end{bmatrix} = \begin{bmatrix} 10&12&19 \end{bmatrix} \quad\text{公式(8)} \]

通過上述詞向量的計算,可以發現第 4 個詞的詞向量表示爲 \([10\,12\,19]\)

如果再次採用餘弦相似度計算兩個詞之間的相似度,結果不再是 0 ,既可以一定程度上描述兩個詞之間的相似度。

下圖給了網上找的幾個例子,可以看出有些例子效果還是很不錯的,一個單詞表達成 Word Embedding 後,很容易找出語義相近的其它詞彙。

四、Word2Vec 模型

2013 年最火的用語言模型做 Word Embedding 的工具是 Word2Vec ,後來又出了Glove(由於 Glove 和 Word2Vec 的作用類似,並對 BERT 的講解沒有什麼幫助,之後不再多加敘述),Word2Vec是怎麼工作的呢?看下圖:

Word2Vec 的網絡結構其實和神經網絡語言模型(NNLM)是基本類似的,只是這個圖長得清晰度差了點,看上去不像,其實它們是親兄弟。不過這裏需要指出:儘管網絡結構相近,而且都是做語言模型任務,但是他們訓練方法不太一樣。

Word2Vec 有兩種訓練方法:

  1. 第一種叫 CBOW,核心思想是從一個句子裏面把一個詞摳掉,用這個詞的上文和下文去預測被摳掉的這個詞;
  2. 第二種叫做 Skip-gram,和 CBOW 正好反過來,輸入某個單詞,要求網絡預測它的上下文單詞。

而你回頭看看,NNLM 是怎麼訓練的?是輸入一個單詞的上文,去預測這個單詞。這是有顯著差異的。

爲什麼 Word2Vec 這麼處理?原因很簡單,因爲 Word2Vec 和 NNLM 不一樣,NNLM 的主要任務是要學習一個解決語言模型任務的網絡結構,語言模型就是要看到上文預測下文,而 Word Embedding只是 NNLM 無心插柳的一個副產品;但是 Word2Vec 目標不一樣,它單純就是要 Word Embedding 的,這是主產品,所以它完全可以隨性地這麼去訓練網絡。

爲什麼要講 Word2Vec 呢?這裏主要是要引出 CBOW 的訓練方法,BERT 其實跟它有關係,後面會講解它們之間的關係,當然它們的關係 BERT 作者沒說,是我猜的,至於我猜的對不對,你看完這篇文章之後可以自行判斷。

五、自然語言處理的預訓練模型

突然在文章中插入這一段,其實就是給出一個問題:Word Embedding 這種做法能算是預訓練嗎?這其實就是標準的預訓練過程。要理解這一點要看看學會 Word Embedding 後下遊任務是怎麼使用它的。

假設如上圖所示,我們有個NLP的下游任務,比如 QA,就是問答問題,所謂問答問題,指的是給定一個問題 X,給定另外一個句子 Y,要判斷句子 Y 是否是問題 X 的正確答案。

問答問題假設設計的網絡結構如上圖所示,這裏不展開講了,懂得自然懂,不懂的也沒關係,因爲這點對於本文主旨來說不關鍵,關鍵是網絡如何使用訓練好的 Word Embedding 的。

它的使用方法其實和前面講的 NNLM 是一樣的,句子中每個單詞以 Onehot 形式作爲輸入,然後乘上學好的 Word Embedding 矩陣 Q,就直接取出單詞對應的 Word Embedding 了。

這乍看上去好像是個查表操作,不像是預訓練的做法是吧?其實不然,那個Word Embedding矩陣Q其實就是網絡 Onehot 層到 embedding 層映射的網絡參數矩陣。

所以你看到了,使用 Word Embedding 等價於什麼?等價於把 Onehot 層到 embedding 層的網絡用預訓練好的參數矩陣 Q 初始化了。這跟前面講的圖像領域的低層預訓練過程其實是一樣的,區別無非 Word Embedding 只能初始化第一層網絡參數,再高層的參數就無能爲力了

下游NLP任務在使用 Word Embedding 的時候也類似圖像有兩種做法,一種是 Frozen,就是 Word Embedding 那層網絡參數固定不動;另外一種是 Fine-Tuning,就是 Word Embedding 這層參數使用新的訓練集合訓練也需要跟着訓練過程更新掉。

上面這種做法就是18年之前NLP領域裏面採用預訓練的典型做法,並且 Word Embedding 其實對於很多下游 NLP 任務是有幫助的,只是幫助沒有大到閃瞎忘記戴墨鏡的圍觀羣衆的雙眼而已。

六、RNN 和 LSTM

爲什麼要在這裏穿插一個 RNN(Recurrent Neural Network) 和 LSTM(Long Short-Term Memory) 呢?

因爲接下來要介紹的 ELMo(Embeddings from Language Models) 模型在訓練過程中使用了雙向長短期記憶網絡(Bi-LSTM)。

當然,這裏只是簡單地介紹,想要詳細瞭解的可以去查看網上鋪天蓋地的參考資料。

6.1 RNN

傳統的神經網絡無法獲取時序信息,然而時序信息在自然語言處理任務中非常重要

例如對於這一句話 “我吃了一個蘋果”,“蘋果” 的詞性和意思,在這裏取決於前面詞的信息,如果沒有 “我吃了一個” 這些詞,“蘋果” 也可以翻譯爲喬布斯搞出來的那個被咬了一口的蘋果。

也就是說,RNN 的出現,讓處理時序信息變爲可能。

RNN 的基本單元結構如下圖所示:

上圖左邊部分稱作 RNN 的一個 timestep,在這個 timestep 中可以看到,在 \(t\) 時刻,輸入變量 \(x_t\),通過 RNN 的一個基礎模塊 A,輸出變量 \(h_t\),而 \(t\) 時刻的信息,將會傳遞到下一個時刻 \(t+1\)

如果把模塊按照時序展開,則會如上圖右邊部分所示,由此可以看到 RNN 爲多個基礎模塊 A 的互連,每一個模塊都會把當前信息傳遞給下一個模塊

RNN 解決了時序依賴問題,但這裏的時序一般指的是短距離的,首先我們先介紹下短距離依賴和長距離依賴的區別:

  • 短距離依賴:對於這個填空題 “我想看一場籃球____”,我們很容易就判斷出 “籃球” 後面跟的是 “比賽”,這種短距離依賴問題非常適合 RNN。
  • 長距離依賴:對於這個填空題 “我出生在中國的瓷都景德鎮,小學和中學離家都很近,……,我的母語是____”,對於短距離依賴,“我的母語是” 後面可以緊跟着 “漢語”、“英語”、“法語”,但是如果我們想精確答案,則必須回到上文中很長距離之前的表述 “我出生在中國的瓷都景德鎮”,進而判斷答案爲 “漢語”,而 RNN 是很難學習到這些信息的。

6.2 RNN 的梯度消失問題

在這裏我簡單講解下 RNN 爲什麼不適合長距離依賴問題。

如上圖所示,爲RNN模型結構,前向傳播過程包括:

  • 隱藏狀態:\(h^{(t)} = \sigma (z^{(t)}) = \sigma(Ux^{(t)} + Wh^{(t-1)} + b)\) ,此處激活函數一般爲 \(tanh\)
  • 模型輸出:\(o^{(t)} = Vh^{(t)} + c\)
  • 預測輸出:\(\hat{y}^{(t)} = \sigma(o^{(t)})\) ,此處激活函數一般爲softmax。
  • 模型損失:\(L = \sum_{t = 1}^{T} L^{(t)}\)

RNN 所有的 timestep 共享一套參數 \(U,V,W\),在 RNN 反向傳播過程中,需要計算 \(U,V,W\) 等參數的梯度,以 \(W\) 的梯度表達式爲例(假設 RNN 模型的損失函數爲 \(L\)):

\[\frac{\partial L}{\partial W} = \sum_{t = 1}^{T} \frac{\partial L}{\partial y^{(T)}} \frac{\partial y^{(T)}}{\partial o^{(T)}} \frac{\partial o^{(T)}}{\partial h^{(T)}} \left( \prod_{k=t + 1}^{T} \frac{\partial h^{(k)}}{\partial h^{(k - 1)}} \right) \frac{\partial h^{(t)}}{\partial W} \ \\ = \sum_{t = 1}^{T} \frac{\partial L}{\partial y^{(T)}} \frac{\partial y^{(T)}}{\partial o^{(T)}} \frac{\partial o^{(T)}}{\partial h^{(T)}} \left( \prod_{k=t+1}^{T} tanh^{'}(z^{(k)}) W \right) \frac{\partial h^{(t)}}{\partial W} \ \\ \quad\text{公式(9)} \]

對於公式(9)中的 \(\left( \prod_{k=t + 1}^{T} \frac{\partial h^{(k)}}{\partial h^{(k - 1)}} \right) = \left( \prod_{k=t+1}^{T} tanh^{'}(z^{(k)}) W \right)\)\(\tanh\) 的導數總是小於 1 的,由於是 \(T-(t+1)\) 個 timestep 參數的連乘,如果 \(W\) 的主特徵值小於 1,梯度便會消失;如果 \(W\) 的特徵值大於 1,梯度便會爆炸。

需要注意的是,RNN和DNN梯度消失和梯度爆炸含義並不相同。

RNN中權重在各時間步內共享,最終的梯度是各個時間步的梯度和,梯度和會越來越大。因此,RNN中總的梯度是不會消失的,即使梯度越傳越弱,也只是遠距離的梯度消失。 從公式(9)中的 \(\left( \prod_{k=t+1}^{T} tanh^{'}(z^{(k)}) W \right)\) 可以看到,RNN所謂梯度消失的真正含義是,梯度被近距離(\(t+1 趨向於 T\))梯度主導,遠距離(\(t+1 遠離 T\))梯度很小,導致模型難以學到遠距離的信息。

6.3 LSTM

爲了解決 RNN 缺乏的序列長距離依賴問題,LSTM 被提了出來,首先我們來看看 LSTM 相對於 RNN 做了哪些改進:

如上圖所示,爲 LSTM 的 RNN 門控結構(LSTM 的 timestep),LSTM 前向傳播過程包括:

  • 遺忘門:決定了丟棄哪些信息,遺忘門接收 \(t-1\) 時刻的狀態 \(h_{t-1}\),以及當前的輸入 \(x_t\),經過 Sigmoid 函數後輸出一個 0 到 1 之間的值 \(f_t\)
    • 輸出: \(f_{t} = \sigma(W_fh_{t-1} + U_fx_{t} + b_f)\)
  • 輸入門:決定了哪些新信息被保留,並更新細胞狀態,輸入們的取值由 \(h_{t-1}\)\(x_t\) 決定,通過 Sigmoid 函數得到一個 0 到 1 之間的值 \(i_t\),而 \(\tanh\) 函數則創造了一個當前細胞狀態的候選 \(a_t\)
    • 輸出:\(i_{t} = \sigma(W_ih_{t-1} + U_ix_{t} + b_i)\) , \(\tilde{C_{t} }= tanhW_ah_{t-1} + U_ax_{t} + b_a\)
  • 細胞狀態:舊細胞狀態 \(C_{t-1}\) 被更新到新的細胞狀態 \(C_t\) 上,
    • 輸出:\(C_{t} = C_{t-1}\odot f_{t} + i_{t}\odot \tilde{C_{t} }\)
  • 輸出門:決定了最後輸出的信息,輸出門取值由 \(h_{t-1}\)\(x_t\) 決定,通過 Sigmoid 函數得到一個 0 到 1 之間的值 \(o_t\),最後通過 \(\tanh\) 函數決定最後輸出的信息
    • 輸出:\(o_{t} = \sigma(W_oh_{t-1} + U_ox_{t} + b_o)\) , \(h_{t} = o_{t}\odot tanhC_{t}\)
  • 預測輸出:\(\hat{y}_{t} = \sigma(Vh_{t}+c)\)

6.4 LSTM 解決 RNN 的梯度消失問題

明白了 RNN 梯度消失的原因之後,我們看 LSTM 如何解決問題的呢?

RNN 梯度消失的原因是,隨着梯度的傳導,梯度被近距離梯度主導,模型難以學習到遠距離的信息。具體原因也就是 \(\prod_{k=t+1}^{T}\frac{\partial h_{k}}{\partial h_{k - 1}}\) 部分,在迭代過程中,每一步 \(\frac{\partial h_{k}}{\partial h_{k - 1}}\) 始終在 [0,1) 之間或者始終大於 1。

而對於 LSTM 模型而言,針對 \(\prod _{k=t+1}^{T} \frac{\partial C_{k}}{\partial C_{k-1}}\) 求得:

\[\begin{align} & \frac{\partial C_{k}}{\partial C_{k-1}} = f_k + other \\ & \prod _{k=t+1}^{T} \frac{\partial C_{k}}{\partial C_{k-1}} = f_{k}f_{k+1}...f_{T} + other \\ \end{align} \]

在 LSTM 迭代過程中,針對 \(\prod_{k=t+1}^{T} \frac{\partial C_{k}}{\partial C_{k-1}}\) 而言,每一步\(\frac{\partial C_{k}}{\partial C_{k-1}}\) 可以自主的選擇在 [0,1] 之間,或者大於1,因爲 \(f_{k}\) 是可訓練學習的。那麼整體 \(\prod _{k=t+1}^{T} \frac{\partial C_{k}}{\partial C_{k-1}}\) 也就不會一直減小,遠距離梯度不至於完全消失,也就能夠解決 RNN 中存在的梯度消失問題。

LSTM 遺忘門值 \(f_t\) 可以選擇在 [0,1] 之間,讓 LSTM 來改善梯度消失的情況。也可以選擇接近 1,讓遺忘門飽和,此時遠距離信息梯度不消失;也可以選擇接近 0,此時模型是故意阻斷梯度流,遺忘之前信息。

另外需要強調的是LSTM搞的這麼複雜,除了在結構上天然地克服了梯度消失的問題,更重要的是具有更多的參數來控制模型;通過四倍於RNN的參數量,可以更加精細地預測時間序列變量。

此外,我記得有一篇文章講到,LSTM 在 200左右長度的文本上,就已經捉襟見肘了

七、ELMo 模型

7.1 ELMo 的預訓練

在講解 Word Embedding 時,細心地讀者一定已經發現,這些詞表示方法本質上是靜態的,每一個詞都有一個唯一確定的詞向量,不能根據句子的不同而改變,無法處理自然語言處理任務中的多義詞問題。

如上圖所示,例如多義詞 Bank,有兩個常用含義,但是 Word Embedding 在對 bank 這個單詞進行編碼的時候,是區分不開這兩個含義的。

因爲儘管這兩句含有 bank 的句子中 bank 上下文環境中出現的單詞不同,但是在用語言模型訓練的時候,不論什麼上下文的句子經過 Word2Vec,都是預測相同的單詞 bank,而同一個單詞佔用的是同一行的參數空間,這會導致兩種不同的上下文信息都會編碼到相同的 Word Embedding 空間裏,進而導致Word Embedding 無法區分多義詞的不同語義。

所以對於比如 Bank 這個詞,它事先學好的 Word Embedding 中混合了幾種語義 ,在應用中來了個新句子,即使從上下文中(比如句子包含 money 等詞)明顯可以看出它代表的是 “銀行” 的含義,但是對應的 Word Embedding 內容也不會變,它還是混合了多種語義。

針對 Word Embedding 中出現的多義詞問題,ELMo 提供了一個簡潔優雅的解決方案。

ELMo 的本質思想是:我事先用語言模型學好一個單詞的 Word Embedding,此時多義詞無法區分,不過這沒關係。在我實際使用 Word Embedding 的時候,單詞已經具備了特定的上下文了,這個時候我可以根據上下文單詞的語義再去調整單詞的 Word Embedding 表示,這樣經過調整後的 Word Embedding 更能表達在這個上下文中的具體含義,自然也就解決了多義詞的問題了。所以 ELMo 本身是個根據當前上下文對 Word Embedding 動態調整的思路。

ELMo 採用了典型的兩階段過程:

  1. 第一個階段是利用語言模型進行預訓練;
  2. 第二個階段是在做下游任務時,從預訓練網絡中提取對應單詞的網絡各層的 Word Embedding 作爲新特徵補充到下游任務中。

上圖展示的是其第一階段預訓練過程,它的網絡結構採用了雙層雙向 LSTM,目前語言模型訓練的任務目標是根據單詞 \(w_i\) 的上下文去正確預測單詞 \(w_i\)\(w_i\) 之前的單詞序列 Context-before 稱爲上文,之後的單詞序列 Context-after 稱爲下文。

圖中左端的前向雙層 LSTM 代表正方向編碼器,輸入的是從左到右順序的除了預測單詞外 \(W_i\) 的上文 Context-before;右端的逆向雙層 LSTM 代表反方向編碼器,輸入的是從右到左的逆序的句子下文Context-after;每個編碼器的深度都是兩層 LSTM 疊加。

這個網絡結構其實在 NLP 中是很常用的。使用這個網絡結構利用大量語料做語言模型任務就能預先訓練好這個網絡,如果訓練好這個網絡後,輸入一個新句子 \(s_{new}\) ,句子中每個單詞都能得到對應的三個 Embedding:

  • 最底層是單詞的 Word Embedding;
  • 往上走是第一層雙向 LSTM 中對應單詞位置的 Embedding,這層編碼單詞的句法信息更多一些;
  • 再往上走是第二層 LSTM 中對應單詞位置的 Embedding,這層編碼單詞的語義信息更多一些。

也就是說,ELMo 的預訓練過程不僅僅學會單詞的 Word Embedding,還學會了一個雙層雙向的 LSTM 網絡結構,而這兩者後面都有用。

7.2 ELMo 的 Feature-based Pre-Training

上面介紹的是 ELMo 的第一階段:預訓練階段。那麼預訓練好網絡結構後,如何給下游任務使用呢?

上圖展示了下游任務的使用過程,比如我們的下游任務仍然是 QA 問題,此時對於問句 X:

  1. 我們可以先將句子 X 作爲預訓練好的 ELMo 網絡的輸入,這樣句子 X 中每個單詞在 ELMO 網絡中都能獲得對應的三個 Embedding;
  2. 之後給予這三個 Embedding 中的每一個 Embedding 一個權重 a,這個權重可以學習得來,根據各自權重累加求和,將三個 Embedding 整合成一個;
  3. 然後將整合後的這個 Embedding 作爲 X 句在自己任務的那個網絡結構中對應單詞的輸入,以此作爲補充的新特徵給下游任務使用。
  4. 對於上圖所示下游任務 QA 中的回答句子 Y 來說也是如此處理。

因爲 ELMo 給下游提供的是每個單詞的特徵形式,所以這一類預訓練的方法被稱爲 “Feature-based Pre-Training”。

至於爲何這麼做能夠達到區分多義詞的效果,原因在於在訓練好 ELMo 後,在特徵提取的時候,每個單詞在兩層 LSTM 上都會有對應的節點,這兩個節點會編碼單詞的一些句法特徵和語義特徵,並且它們的 Embedding 編碼是動態改變的,會受到上下文單詞的影響,周圍單詞的上下文不同應該會強化某種語義,弱化其它語義,進而就解決了多義詞的問題。

八、Attention

上面巴拉巴拉了一堆,都在爲 BERT 的講解做鋪墊,而接下來要敘述的 Attention 和 Transformer 同樣如此,它們都只是 BERT 構成的一部分。

8.1 人類的視覺注意力

Attention 是注意力的意思,從它的命名方式看,很明顯借鑑了人類的注意力機制,因此,我們首先介紹人類的視覺注意力。

視覺注意力機制是人類視覺所特有的大腦信號處理機制。人類視覺通過快速掃描全局圖像,獲得需要重點關注的目標區域,也就是一般所說的注意力焦點,而後對這一區域投入更多注意力資源,以獲取更多所需要關注目標的細節信息,而抑制其他無用信息。

這是人類利用有限的注意力資源從大量信息中快速篩選出高價值信息的手段,是人類在長期進化中形成的一種生存機制,人類視覺注意力機制極大地提高了視覺信息處理的效率與準確性。

上圖形象化展示了人類在看到一副圖像時是如何高效分配有限的注意力資源的,其中紅色區域表明視覺系統更關注的目標,很明顯對於上圖所示的場景,人們會把注意力更多投入到人的臉部,文本的標題以及文章首句等位置。

深度學習中的注意力機制從本質上講和人類的選擇性視覺注意力機制類似,核心目標也是從衆多信息中選擇出對當前任務目標更關鍵的信息。

8.2 Attention 的本質思想

從人類的視覺注意力可以看出,注意力模型 Attention 的本質思想爲:從大量信息中有選擇地篩選出少量重要信息並聚焦到這些重要信息上,忽略不重要的信息。

在詳細講解 Attention之前,我們在講講 Attention的其他作用。之前我們講解 LSTM 的時候說到,雖然 LSTM 解決了序列長距離依賴問題,但是單詞超過 200 的時候就會失效。而 Attention 機制可以更加好的解決序列長距離依賴問題,並且具有並行計算能力。現在不明白這點不重要,隨着我們對 Attention 的慢慢深入,相信你會明白。

首先我們得明確一個點,注意力模型從大量信息 Values 中篩選出少量重要信息,這些重要信息一定是相對於另外一個信息 Query 而言是重要的,例如對於上面那張嬰兒圖,Query 就是觀察者。也就是說,我們要搭建一個注意力模型,我們必須得要有一個 Query 和一個 Values,然後通過 Query 這個信息從 Values 中篩選出重要信息。

通過 Query 這個信息從 Values 中篩選出重要信息,簡單點說,就是計算 Query 和 Values 中每個信息的相關程度。

再具體點,通過上圖,Attention 通常可以進行如下描述,表示爲將 Query(Q) 和 key-value pairs(把 Values 拆分成了鍵值對的形式) 映射到輸出上,其中 query、每個 key、每個 value 都是向量,輸出是 V 中所有 values 的加權,其中權重是由 Query 和每個 key 計算出來的,計算方法分爲三步:

  1. 第一步:計算比較 Q 和 K 的相似度,用 f 來表示:\(f(Q,K_i)\quad i=1,2,\cdots,m\),一般第一步計算方法包括四種
    1. 點乘(Transformer 使用):\(f(Q,K_i) = Q^T K_i\)
    2. 權重:\(f(Q,K_i) = Q^TWK_i\)
    3. 拼接權重:\(f(Q,K_i) = W[Q^T;K_i]\)
    4. 感知器:\(f(Q,K_i)=V^T \tanh(WQ+UK_i)\)
  2. 第二步:將得到的相似度進行 softmax 操作,進行歸一化:\(\alpha_i = softmax(\frac{f(Q,K_i)}{\sqrt d_k})\)
    1. 這裏簡單講解除以 \(\sqrt d_k\) 的作用:假設 \(Q\) , \(K\) 裏的元素的均值爲0,方差爲 1,那麼 \(A^T=Q^TK\) 中元素的均值爲 0,方差爲 d。當 d 變得很大時, \(A\) 中的元素的方差也會變得很大,如果 \(A\) 中的元素方差很大(分佈的方差大,分佈集中在絕對值大的區域),在數量級較大時, softmax 將幾乎全部的概率分佈都分配給了最大值對應的標籤,由於某一維度的數量級較大,進而會導致 softmax 未來求梯度時會消失。總結一下就是 \(\operatorname{softmax}\left(A\right)\) 的分佈會和d有關。因此 \(A\) 中每一個元素乘上 \(\frac{1}{\sqrt{d_k}}\) 後,方差又變爲 1,並且 \(A\) 的數量級也將會變小。
  3. 第三步:針對計算出來的權重 \(\alpha_i\),對 \(V\) 中的所有 values 進行加權求和計算,得到 Attention 向量:\(Attention = \sum_{i=1}^m \alpha_i V_i\)

8.3 Self Attention 模型

上面已經講了 Attention 就是從一堆信息中篩選出重要的信息,現在我們來通過 Self Attention 模型來詳細講解如何找到這些重要的信息。

Self Attention 模型的架構如下圖所示,接下來我們將按照這個模型架構的順序來逐一解釋。

首先可以看到 Self Attention 有三個輸入 Q、K、V:對於 Self Attention,Q、K、V 來自句子 X 的 詞向量 x 的線性轉化,即對於詞向量 x,給定三個可學習的矩陣參數 \(W_Q,W_k,W_v\),x 分別右乘上述矩陣得到 Q、K、V

接下來爲了表示的方便,我們先通過向量的計算敘述 Self Attention 計算的流程,然後再描述 Self Attention 的矩陣計算過程

  1. 第一步,Q、K、V 的獲取

    上圖操作:兩個單詞 Thinking 和 Machines。通過線性變換,即 \(x_i\)\(x_2\) 兩個向量分別與\(W_q,W_k,W_v\) 三個矩陣點乘得到 ${q_1,q_2},{k_1,k_2},{v_1,v_2} $ 共 6 個向量。矩陣 Q 則是向量 \(q_1,q_2\) 的拼接,K、V 同理。

  2. 第二步,MatMul

    1. 上圖操作:向量 \({q_1,k_1}\) 做點乘得到得分 112, \({q_1,k_2}\) 做點乘得到得分96。注意:這裏是通過 \(q_1\) 這個信息找到 \(x_1,x_2\) 中的重要信息。

  3. 第三步和第四步,Scale + Softmax

    上圖操作:對該得分進行規範,除以 \(\sqrt {d_k} = 8\)

  4. 第五步,MatMul

用得分比例 [0.88,0.12] 乘以 \([v_1,v_2]\) 值得到一個加權後的值,將這些值加起來得到 \(z_1\)

上述所說就是 Self Attention 模型所做的事,仔細感受一下,用 \(q_1\)\(K=[k_1,k_2]\) 去計算一個 Thinking 相對於 Thinking 和 Machine 的權重,再用權重乘以 Thinking 和 Machine 的 \(V=[v_1,v_2]\) 得到加權後的 Thinking 和 Machine 的 \(V=[v_1,v_2]\),最後求和得到針對各單詞的輸出 \(z_1\)

同理可以計算出 Machine 相對於 Thinking 和 Machine 的加權輸出 \(z_2\),拼接 \(z_1\)\(z_2\) 即可得到 Attention 值 \(Z=[z_1,z_2]\),這就是 Self Attention 的矩陣計算,如下所示。

之前的例子是單個向量的運算例子。這張圖展示的是矩陣運算的例子,輸入是一個 [2x4] 的矩陣(句子中每個單詞的詞向量的拼接),每個運算是 [4x3] 的矩陣,求得 Q、K、V。

Q 對 K 轉製做點乘,除以 \(\sqrt d_k\),做一個 softmax 得到合爲 1 的比例,對 V 做點乘得到輸出 Z。那麼這個 Z 就是一個考慮過 Thinking 周圍單詞 Machine 的輸出。

注意看這個公式,\(QK^T\) 其實就會組成一個 word2word 的 attention map!(加了 softmax 之後就是一個合爲 1 的權重了)。比如說你的輸入是一句話 "i have a dream" 總共 4 個單詞,這裏就會形成一張 4x4 的注意力機制的圖:

這樣一來,每一個單詞對應每一個單詞都會有一個權重,這也是 Self Attention 名字的來源,即 Attention 的計算來源於 Source(源句) 和 Source 本身,通俗點講就是 Q、K、V 都來源於輸入 X 本身。

8.4 Self Attention 和 RNN、LSTM 的區別

引入 Self Attention 有什麼好處呢?或者說通過 Self Attention 到底學到了哪些規律或者抽取出了哪些特徵呢?我們可以通過下述兩幅圖來講解:

從上述兩張圖可以看出,Self Attention 可以捕獲同一個句子中單詞之間的一些句法特徵(例如第一張圖展示的有一定距離的短語結構)或者語義特徵(例如第二張圖展示的 its 的指代對象爲 Law)。

有了上述的講解,我們現在可以來看看 Self Attention 和 RNN、LSTM 的區別:

  • RNN、LSTM:如果是 RNN 或者 LSTM,需要依次序列計算,對於遠距離的相互依賴的特徵,要經過若干時間步步驟的信息累積才能將兩者聯繫起來,而距離越遠,有效捕獲的可能性越小
  • Self Attention:
    • 通過上述兩幅圖,很明顯的可以看出,引入 Self Attention 後會更容易捕獲句子中長距離的相互依賴的特徵,因爲 Self Attention 在計算過程中會直接將句子中任意兩個單詞的聯繫通過一個計算步驟直接聯繫起來,所以遠距離依賴特徵之間的距離被極大縮短,有利於有效地利用這些特徵
    • 除此之外,Self
      Attention 對於一句話中的每個單詞都可以單獨的進行 Attention 值的計算,也就是說 Self Attention 對計算的並行性也有直接幫助作用,而對於必須得依次序列計算的 RNN 而言,是無法做到並行計算的。

從上面的計算步驟和圖片可以看出,無論句子序列多長,都可以充分捕獲近距離上往下問中的任何依賴關係,進而可以很好的提取句法特徵還可以提取語義特徵;而且對於一個句子而言,每個單詞的計算是可以並行處理的

理論上 Self-Attention (Transformer 50 個左右的單詞效果最好)解決了 RNN 模型的長序列依賴問題,但是由於文本長度增加時,訓練時間也將會呈指數增長,因此在處理長文本任務時可能不一定比 LSTM(200 個左右的單詞效果最好) 等傳統的 RNN 模型的效果好。

上述所說的,則是爲何 Self Attention 逐漸替代 RNN、LSTM 被廣泛使用的原因所在。

8.5 Masked Self Attention 模型

趁熱打鐵,我們講講 Transformer 未來會用到的 Masked Self Attention 模型,這裏的 Masked 就是要在做語言模型(或者像翻譯)的時候,不給模型看到未來的信息,它的結構如下圖所示:

上圖中和 Self Attention 重複的部分此處就不講了,主要講講 Mask 這一塊。

假設在此之前我們已經通過 scale 之前的步驟得到了一個 attention map,而 mask 就是沿着對角線把灰色的區域用0覆蓋掉,不給模型看到未來的信息,如下圖所示:

詳細來說:

  1. "i" 作爲第一個單詞,只能有和 "i" 自己的 attention;
  2. "have" 作爲第二個單詞,有和 "i、have" 前面兩個單詞的 attention;
  3. "a" 作爲第三個單詞,有和 "i、have、a" 前面三個單詞的 attention;
  4. "dream" 作爲最後一個單詞,纔有對整個句子 4 個單詞的 attention。

並且在做完 softmax 之後,橫軸結果合爲 1。如下圖所示:

具體爲什麼要 mask,未來再講解 Transformer 的時候我們會詳細解釋。

8.6 Multi-head Self Attention 模型

由於 Transformer 使用的都是 Self Attention 的進階版 Multi-head Self Attention,我們簡單講講 Multi-head Self Attention 的架構,並且在該小節結尾處講講它的優點。

Multi-Head Attention 就是把 Self Attention 得到的注意力值 \(Z\) 切分成 n 個 \(Z_1,Z_2,\cdots,Z_n\),然後通過全連接層獲得新的 \(Z'\).

我們還是以上面的形式來解釋,我們對 \(Z\) 進行 8 等份的切分得到 8 個 \(Z_i\) 矩陣:

爲了使得輸出與輸入結構相同,拼接矩陣 \(Z_i\) 後乘以一個線性 \(W_0\) 得到最終的Z:

可以通過下圖看看 multi-head attention 的整個流程:

上述操作有什麼好處呢?多頭相當於把原始信息 Source 放入了多個子空間中,也就是捕捉了多個信息,對於使用 multi-head(多頭) attention 的簡單回答就是,多頭保證了 attention 可以注意到不同子空間的信息,捕捉到更加豐富的特徵信息。其實本質上是論文原作者發現這樣效果確實好。

九、Position Embedding

在 Attention 和 RNN、LSTM 的對比中,我們說到 Attention 解決了長距離依賴問題,並且可以支持並行化,但是它就真的百利而無一害了嗎?

其實不然,我們往前回顧,Self Attention 的 Q、K、V 三個矩陣是由同一個輸入 \(X_1=(x_1,x_2,\cdots,x_n)\) 線性轉換而來,也就是說對於這樣的一個被打亂序列順序的 \(X_2=(x_2,x_1,\cdots,x_n)\) 而言,由於 Attention 值的計算最終會被加權求和,也就是說兩者最終計算的 Attention 值都是一樣的,進而也就表明了 Attention 丟掉了 \(X_1\) 的序列順序信息。

如上圖所示,爲了解決 Attention 丟失的序列順序信息,Transformer 的提出者提出了 Position Embedding,也就是對於輸入 \(X\) 進行 Attention 計算之前,在 \(X\) 的詞向量中加上位置信息,也就是說 \(X\) 的詞向量爲 \(X_{final\_embedding} = Embedding + Positional\, Embedding\)

但是如何得到 \(X\) 的位置向量呢?

其中位置編碼公式如下圖所示:

其中 pos 表示位置、i 表示維度、\(d_{model}\)表示位置向量的向量維度 、\(2i、2i+1\) 表示的是奇偶數(奇偶維度),上圖所示就是偶數位置使用 \(\sin\) 函數,奇數位置使用 \(\cos\) 函數。

有了位置編碼,我們再來看看位置編碼是如何嵌入單詞編碼的(其中 512 表示編碼維度),通過把單詞的詞向量和位置向量進行疊加,這種方式就稱作位置嵌入,如下圖所示:

Position Embedding 本身是一個絕對位置的信息,但在語言模型中,相對位置也很重要。那麼爲什麼位置嵌入機制有用呢?

我們不要去關心三角函數公式,可以看看下圖公式(3)中的第一行,我們做如下的解釋,對於 “我愛喫蘋果” 這一句話,有 5 個單詞,假設序號分別爲 1、2、3、4、5。

假設 \(pos=1=我、k=2=愛、pos+k=3=喫\),也就是說 \(pos+k=3\) 位置的位置向量的某一維可以通過 \(pos=1\) 位置的位置向量的某一維線性組合加以線性表示,通過該線性表示可以得出 “喫” 的位置編碼信息蘊含了相對於前兩個字 “我” 的位置編碼信息。

總而言之就是,某個單詞的位置信息是其他單詞位置信息的線性組合,這種線性組合就意味着位置向量中蘊含了相對位置信息。

十、Transformer

10.1 Transformer 的結構

萬事俱備,只欠東風,下面我們來講講我們的重點之一,Transformer,你可以先記住這一句話:Transformer 簡單點看其實就是 self-attention 模型的疊加,首先我們來看看 Transformer 的整體框架。

Transformer 的整體框架如下圖所示:

上圖所示的整體框架乍一眼一看非常複雜,由於 Transformer 起初是作爲翻譯模型,因此我們以翻譯舉例,簡化一下上述的整體框架:

從上圖可以看出 Transformer 相當於一個黑箱,左邊輸入 “Je suis etudiant”,右邊會得到一個翻譯結果 “I am a student”。

再往細裏講,Transformer 也是一個 Seq2Seq 模型(Encoder-Decoder 框架的模型),左邊一個 Encoders 把輸入讀進去,右邊一個 Decoders 得到輸出,如下所示:

在這裏,我們穿插描述下 Encoder-Decoder 框架的模型是如何進行文本翻譯的:

  1. 將序列 \((x_1,x_2,\cdots,x_n)\) 作爲 Encoders 的輸入,得到輸出序列 \((z_1,z_2,\cdots,z_n)\)
  2. 把 Encoders 的輸出序列 \((z_1,z_2,\cdots,z_n)\) 作爲 Decoders 的輸入,生成一個輸出序列 \((y_1,y_2,\cdots,y_m)\)。注:Decoders 每個時刻輸出一個結果

第一眼看到上述的 Encodes-Decoders 框架圖,隨之產生問題就是 Transformer 中 左邊 Encoders 的輸出是怎麼和右邊 Decoders 結合的。因爲decoders 裏面是有N層的,再畫張圖直觀的看就是這樣:

也就是說,Encoders 的輸出,會和每一層的 Decoder 進行結合

現在我們取其中一層進行詳細的展示:

通過上述分析,發現我們想要詳細瞭解 Transformer,只要瞭解 Transformer 中的 Encoder 和 Decoder 單元即可,接下來我們將詳細闡述這兩個單元。

10.2 Encoder

有了上述那麼多知識的鋪墊,我們知道 Eecoders 是 N=6 層,通過上圖我們可以看到每層 Encoder 包括兩個 sub-layers:

  • 第一個 sub-layer 是 multi-head self-attention,用來計算輸入的 self-attention;
  • 第二個 sub-layer 是簡單的前饋神經網絡層 Feed Forward;

注意:在每個 sub-layer 我們都模擬了殘差網絡(在下面的數據流示意圖中會細講),每個sub-layer的輸出都是 \(LayerNorm(x+Sub\_layer(x))\),其中 \(sub\_layer\) 表示的是該層的上一層的輸出

現在我們給出 Encoder 的數據流示意圖,一步一步去剖析

  1. 深綠色的 \(x_1\) 表示 Embedding 層的輸出,加上代表 Positional Embedding 的向量之後,得到最後輸入 Encoder 中的特徵向量,也就是淺綠色向量 \(x_1\)
  2. 淺綠色向量 \(x_1\) 表示單詞 “Thinking” 的特徵向量,其中 \(x_1\) 經過 Self-Attention 層,變成淺粉色向量 \(z_1\)
  3. \(x_1\) 作爲殘差結構的直連向量,直接和 \(z_1\) 相加,之後進行 Layer Norm 操作,得到粉色向量 \(z_1\)
    1. 殘差結構的作用:避免出現梯度消失的情況
    2. Layer Norm 的作用:爲了保證數據特徵分佈的穩定性,並且可以加速模型的收斂
  4. \(z_1\) 經過前饋神經網絡(Feed Forward)層,經過殘差結構與自身相加,之後經過 LN 層,得到一個輸出向量 \(r_1\)
    1. 該前饋神經網絡包括兩個線性變換和一個ReLU激活函數:\(FFN(x) = max(0,xW_1+b_1)W_2+b2\)
  5. 由於 Transformer 的 Encoders 具有 6 個 Encoder,\(r_1\) 也將會作爲下一層 Encoder 的輸入,代替 \(x_1\) 的角色,如此循環,直至最後一層 Encoder。

需要注意的是,上述的 \(x、z、r\) 都具有相同的維數,論文中爲 512 維。

10.3 Decoder

Decoders 也是 N=6 層,通過上圖我們可以看到每層 Decoder 包括 3 個 sub-layers:

  • 第一個 sub-layer 是 Masked multi-head self-attention,也是計算輸入的 self-attention;
    • 在這裏,先不解釋爲什麼要做 Masked,後面在 “Transformer 動態流程展示” 這一小節會解釋
  • 第二個 sub-layer 是 Encoder-Decoder Attention 計算,對 Encoder 的輸入和 Decoder 的Masked multi-head self-attention 的輸出進行 attention 計算;
    • 在這裏,同樣不解釋爲什麼要對 Encoder 和 Decoder 的輸出一同做 attention 計算,後面在 “Transformer 動態流程展示” 這一小節會解釋
  • 第三個 sub-layer 是前饋神經網絡層,與 Encoder 相同。

10.4 Transformer 輸出結果

以上,就講完了 Transformer 編碼和解碼兩大模塊,那麼我們迴歸最初的問題,將 “機器學習” 翻譯成 “machine learing”,解碼器的輸出是一個浮點型的向量,怎麼轉化成 “machine learing” 這兩個詞呢?讓我們來看看 Encoders 和 Decoders 交互的過程尋找答案:

從上圖可以看出,Transformer 最後的工作是讓解碼器的輸出通過線性層 Linear 後接上一個 softmax

  • 其中線性層是一個簡單的全連接神經網絡,它將解碼器產生的向量 A 投影到一個更高維度的向量 B 上,假設我們模型的詞彙表是10000個詞,那麼向量 B 就有10000個維度,每個維度對應一個惟一的詞的得分。
  • 之後的softmax層將這些分數轉換爲概率。選擇概率最大的維度,並對應地生成與之關聯的單詞作爲此時間步的輸出就是最終的輸出啦!

假設詞彙表維度是 6,那麼輸出最大概率詞彙的過程如下:

十一、Transformer 動態流程展示

首先我們來看看拿 Transformer 作翻譯時,如何生成翻譯結果的:

繼續進行:

假設上圖是訓練模型的某一個階段,我們來結合 Transformer 的完整框架描述下這個動態的流程圖:

  1. 輸入 “je suis etudiant” 到 Encoders,然後得到一個 \(K_e\)\(V_e\) 矩陣;
  2. 輸入 “I am a student” 到 Decoders ,首先通過 Masked Multi-head Attention 層得到 “I am a student” 的 attention 值 \(Q_d\),然後用 attention 值 \(Q_d\) 和 Encoders 的輸出 \(K_e\)\(V_e\) 矩陣進行 attention 計算,得到第 1 個輸出 “I”;
  3. 輸入 “I am a student” 到 Decoders ,首先通過 Masked Multi-head Attention 層得到 “I am a student” 的 attention 值 \(Q_d\),然後用 attention 值 \(Q_d\) 和 Encoders 的輸出 \(K_e\)\(V_e\) 矩陣進行 attention 計算,得到第 2 個輸出 “am”;
  4. ……

現在我們來解釋我們之前遺留的兩個問題。

11.1 爲什麼 Decoder 需要做 Mask

  • 訓練階段:我們知道 “je suis etudiant” 的翻譯結果爲 “I am a student”,我們把 “I am a student” 的 Embedding 輸入到 Decoders 裏面,翻譯第一個詞 “I” 時

    • 如果對 “I am a student” attention 計算不做 mask,“am,a,student” 對 “I” 的翻譯將會有一定的貢獻
    • 如果對 “I am a student” attention 計算做 mask,“am,a,student” 對 “I” 的翻譯將沒有貢獻
  • 測試階段:我們不知道 “我愛中國” 的翻譯結果爲 “I love China”,我們只能隨機初始化一個 Embedding 輸入到 Decoders 裏面,翻譯第一個詞 “I” 時:

    • 無論是否做 mask,“love,China” 對 “I” 的翻譯都不會產生貢獻
    • 但是翻譯了第一個詞 “I” 後,隨機初始化的 Embedding 有了 “I” 的 Embedding,也就是說在翻譯第二詞 “love” 的時候,“I” 的 Embedding 將有一定的貢獻,但是 “China” 對 “love” 的翻譯毫無貢獻,隨之翻譯的進行,已經翻譯的結果將會對下一個要翻譯的詞都會有一定的貢獻,這就和做了 mask 的訓練階段做到了一種匹配

總結下就是:Decoder 做 Mask,是爲了讓訓練階段和測試階段行爲一致,不會出現間隙,避免過擬合

11.2 爲什麼 Encoder 給予 Decoders 的是 K、V 矩陣

我們在講解 Attention 機制中曾提到,Query 的目的是藉助它從一堆信息中找到重要的信息。

現在 Encoder 提供了 \(K_e、V_e\) 矩陣,Decoder 提供了 \(Q_d\) 矩陣,通過 “我愛中國” 翻譯爲 “I love China” 這句話詳細解釋下。

當我們翻譯 “I” 的時候,由於 Decoder 提供了 \(Q_d\) 矩陣,通過與 \(K_e、V_e\) 矩陣的計算,它可以在 “我愛中國” 這四個字中找到對 “I” 翻譯最有用的單詞是哪幾個,並以此爲依據翻譯出 “I” 這個單詞,這就很好的體現了注意力機制想要達到的目的,把焦點放在對自己而言更爲重要的信息上。

  • 其實上述說的就是 Attention 裏的 soft attention機制,解決了曾經的 Encoder-Decoder 框架的一個問題,在這裏不多做敘述,有興趣的可以參考網上的一些資料。
    • 早期的 Encoder-Decoder 框架中的 Encoder 通過 LSTM 提取出源句(Source) “我愛中國” 的特徵信息 C,然後 Decoder 做翻譯的時候,目標句(Target)“I love China” 中的任何一個單詞的翻譯都來源於相同特徵信息 C,這種做法是極其不合理的,例如翻譯 “I” 時應該着眼於 “我”,翻譯 “China” 應該着眼於 “中國”,而早期的這種做法並沒有體現出,然而 Transformer 卻通過 Attention 的做法解決了這個問題。

十二、GPT 模型

12.1 GPT 模型的預訓練

在講解 ELMo 的時候,我們說到 ELMo 這一類預訓練的方法被稱爲 “Feature-based Pre-Training”。並且如果把 ELMo 這種預訓練方法和圖像領域的預訓練方法對比,發現兩者模式看上去還是有很大差異的。

除了以 ELMo 爲代表的這種基於特徵融合的預訓練方法外,NLP 裏還有一種典型做法,這種做法和圖像領域的方式就是看上去一致的了,一般將這種方法稱爲 “基於Fine-tuning的模式”,而 GPT 就是這一模式的典型開創者,下面先讓我們看看 GPT 的網絡結構。

GPT 是 “Generative Pre-Training” 的簡稱,從名字看其含義是指的生成式的預訓練。

GPT也採用兩階段過程:

  1. 第一個階段:利用語言模型進行預訓練;
  2. 第二個階段:通過 Fine-tuning 的模式解決下游任務。

上圖展示了 GPT 的預訓練過程,其實和 ELMo 是類似的,主要不同在於兩點:

  1. 首先,特徵抽取器用的不是 RNN,而是用的 Transformer,它的特徵抽取能力要強於RNN,這個選擇很明顯是很明智的;
  2. 其次,
    1. GPT 的預訓練雖然仍然是以語言模型作爲目標任務,但是採用的是單向的語言模型,所謂 “單向” 的含義是指:語言模型訓練的任務目標是根據 \(w_i\) 單詞的上下文去正確預測單詞 \(w_i\)\(w_i\) 之前的單詞序列Context-before稱爲上文,之後的單詞序列Context-after稱爲下文。
    2. ELMo 在做語言模型預訓練的時候,預測單詞 \(w_i\) 同時使用了上文和下文,而 GPT 則只採用 Context-before 這個單詞的上文來進行預測,而拋開了下文。
    3. GPT 這個選擇現在看不是個太好的選擇,原因很簡單,它沒有把單詞的下文融合進來,這限制了其在更多應用場景的效果,比如閱讀理解這種任務,在做任務的時候是可以允許同時看到上文和下文一起做決策的。如果預訓練時候不把單詞的下文嵌入到 Word Embedding 中,是很喫虧的,白白丟掉了很多信息。

12.2 GPT 模型的 Fine-tuning

上面講的是 GPT 如何進行第一階段的預訓練,那麼假設預訓練好了網絡模型,後面下游任務怎麼用?它有自己的個性,和 ELMO 的方式大有不同。

上圖展示了 GPT 在第二階段如何使用:

  1. 首先,對於不同的下游任務來說,本來你可以任意設計自己的網絡結構,現在不行了,你要向 GPT 的網絡結構看齊,把任務的網絡結構改造成和 GPT 一樣的網絡結構。

  2. 然後,在做下游任務的時候,利用第一步預訓練好的參數初始化 GPT 的網絡結構,這樣通過預訓練學到的語言學知識就被引入到你手頭的任務裏來了。

  3. 再次,你可以用手頭的任務去訓練這個網絡,對網絡參數進行 Fine-tuning,使得這個網絡更適合解決手頭的問題。就是這樣。

這有沒有讓你想起最開始提到的圖像領域如何做預訓練的過程,對,這跟那個預訓練的模式是一模一樣的。

對於 NLP 各種花樣的不同任務,怎麼改造才能靠近 GPT 的網絡結構呢?由於 GPT 對下游任務的改造過程和 BERT 對下游任務的改造極其類似,並且我們主要目的是爲了講解 BERT,所以這個問題將會在 BERT 那裏得到回答。

十三、BERT 模型

13.1 BERT:公認的里程碑

BERT 模型可以作爲公認的里程碑式的模型,但是它最大的優點不是創新,而是集大成者,並且這個集大成者有了各項突破,下面讓我們看看 BERT 是怎麼集大成者的。

  • BERT 的意義在於:從大量無標記數據集中訓練得到的深度模型,可以顯著提高各項自然語言處理任務的準確率。
  • 近年來優秀預訓練語言模型的集大成者:參考了 ELMO 模型的雙向編碼思想、借鑑了 GPT 用 Transformer 作爲特徵提取器的思路、採用了 word2vec 所使用的 CBOW 方法
  • BERT 和 GPT 之間的區別:
    • GPT:GPT 使用 Transformer Decoder 作爲特徵提取器、具有良好的文本生成能力,然而當前詞的語義只能由其前序詞決定,並且在語義理解上不足
    • BERT:使用了 Transformer Encoder 作爲特徵提取器,並使用了與其配套的掩碼訓練方法。雖然使用雙向編碼讓 BERT 不再具有文本生成能力,但是 BERT 的語義信息提取能力更強
  • 單向編碼和雙向編碼的差異,以該句話舉例 “今天天氣很{},我們不得不取消戶外運動”,分別從單向編碼和雙向編碼的角度去考慮 {} 中應該填什麼詞:
    • 單向編碼:單向編碼只會考慮 “今天天氣很”,以人類的經驗,大概率會從 “好”、“不錯”、“差”、“糟糕” 這幾個詞中選擇,這些詞可以被劃爲截然不同的兩類
    • 雙向編碼:雙向編碼會同時考慮上下文的信息,即除了會考慮 “今天天氣很” 這五個字,還會考慮 “我們不得不取消戶外運動” 來幫助模型判斷,則大概率會從 “差”、“糟糕” 這一類詞中選擇

13.2 BERT 的結構:強大的特徵提取能力

  • 如下圖所示,我們來看看 ELMo、GPT 和 BERT 三者的區別

    • ELMo 使用自左向右編碼和自右向左編碼的兩個 LSTM 網絡,分別以 \(P(w_i|w_1,\cdots,w_{i-1})\)\(P(w_i|w_{i+1},\cdots,w_n)\) 爲目標函數獨立訓練,將訓練得到的特徵向量以拼接的形式實現雙向編碼,本質上還是單向編碼,只不過是兩個方向上的單向編碼的拼接而成的雙向編碼
    • GPT 使用 Transformer Decoder 作爲 Transformer Block,以 \(P(w_i|w_1,\cdots,w_{i-1})\) 爲目標函數進行訓練,用 Transformer Block 取代 LSTM 作爲特徵提取器,實現了單向編碼,是一個標準的預訓練語言模型,即使用 Fine-Tuning 模式解決下游任務。
    • BERT 也是一個標準的預訓練語言模型,它以 \(P(w_i|w_1,\cdots,w_{i-1},w_{i+1},\cdots,w_n)\) 爲目標函數進行訓練,BERT 使用的編碼器屬於雙向編碼器
      • BERT 和 ELMo 的區別在於使用 Transformer Block 作爲特徵提取器,加強了語義特徵提取的能力;
      • BERT 和 GPT 的區別在於使用 Transformer Encoder 作爲 Transformer Block,並且將 GPT 的單向編碼改成雙向編碼,也就是說 BERT 捨棄了文本生成能力,換來了更強的語義理解能力。

BERT 的模型結構如下圖所示:

從上圖可以發現,BERT 的模型結構其實就是 Transformer Encoder 模塊的堆疊。在模型參數選擇上,論文給出了兩套大小不一致的模型。

\(BERT_{BASE}\) :L = 12,H = 768,A = 12,總參數量爲 1.1 億

\(BERT_{LARGE}\):L = 24,H = 1024,A = 16,總參數量爲 3.4 億

其中 L 代表 Transformer Block 的層數;H 代表特徵向量的維數(此處默認 Feed Forward 層中的中間隱層的維數爲 4H);A 表示 Self-Attention 的頭數,使用這三個參數基本可以定義 BERT的量級。

BERT 參數量級的計算公式:

\[\begin{align*} & 詞向量參數+ 12 * (Multi-Heads參數 + 全連接層參數 + layernorm參數)\\ & = (30522+512 + 2)* 768 + 768 * 2 \\ & + 12 * (768 * 768 / 12 * 3 * 12 + 768 * 768 + 768 * 3072 * 2 + 768 * 2 * 2) \\ & = 108808704.0 \\ & \approx 110M \end{align*} \]

訓練過程也是很花費計算資源和時間的,總之表示膜拜,普通人即便有 idea 沒有算力也只能跪着。

13.3 BERT 之無監督訓練

和 GPT 一樣,BERT 也採用二段式訓練方法:

  1. 第一階段:使用易獲取的大規模無標籤餘料,來訓練基礎語言模型;
  2. 第二階段:根據指定任務的少量帶標籤訓練數據進行微調訓練。

不同於 GPT 等標準語言模型使用 \(P(w_i|w_1,\cdots,w_{i-1})\) 爲目標函數進行訓練,能看到全局信息的 BERT 使用 \(P(w_i|w_1,\cdots,w_{i-1},w_{i+1},\cdots,w_n)\) 爲目標函數進行訓練。

並且 BERT 用語言掩碼模型(MLM)方法訓練詞的語義理解能力;用下句預測(NSP)方法訓練句子之間的理解能力,從而更好地支持下游任務。

13.4 BERT之語言掩碼模型(MLM)

BERT 作者認爲,使用自左向右編碼和自右向左編碼的單向編碼器拼接而成的雙向編碼器,在性能、參數規模和效率等方面,都不如直接使用深度雙向編碼器強大,這也是爲什麼 BERT 使用 Transformer Encoder 作爲特徵提取器,而不使用自左向右編碼和自右向左編碼的兩個 Transformer Decoder作爲特徵提取器的原因。

由於無法使用標準語言模型的訓練模式,BERT 借鑑完形填空任務和 CBOW 的思想,使用語言掩碼模型(MLM )方法訓練模型。

MLM 方法也就是隨機去掉句子中的部分 token(單詞),然後模型來預測被去掉的 token 是什麼。這樣實際上已經不是傳統的神經網絡語言模型(類似於生成模型)了,而是單純作爲分類問題,根據這個時刻的 hidden state 來預測這個時刻的 token 應該是什麼,而不是預測下一個時刻的詞的概率分佈了。

隨機去掉的 token 被稱作掩碼詞,在訓練中,掩碼詞將以 15% 的概率被替換成 [MASK],也就是說隨機 mask 語料中 15% 的 token,這個操作則稱爲掩碼操作。注意:在CBOW 模型中,每個詞都會被預測一遍。

但是這樣設計 MLM 的訓練方法會引入弊端:在模型微調訓練階段或模型推理(測試)階段,輸入的文本中將沒有 [MASK],進而導致產生由訓練和預測數據偏差導致的性能損失。

考慮到上述的弊端,BERT 並沒有總用 [MASK] 替換掩碼詞,而是按照一定比例選取替換詞。在選擇 15% 的詞作爲掩碼詞後這些掩碼詞有三類替換選項:

  • 80% 練樣本中:將選中的詞用 [MASK] 來代替,例如:
“地球是[MASK]八大行星之一”
  • 10% 的訓練樣本中:選中的詞不發生變化,該做法是爲了緩解訓練文本和預測文本的偏差帶來的性能損失,例如:
“地球是太陽系八大行星之一”
  • 10% 的訓練樣本中:將選中的詞用任意的詞來進行代替,該做法是爲了讓 BERT 學會根據上下文信息自動糾錯,例如:
“地球是蘋果八大行星之一”

作者在論文中提到這樣做的好處是,編碼器不知道哪些詞需要預測的,哪些詞是錯誤的,因此被迫需要學習每一個 token 的表示向量,另外作者也表示雙向編碼器比單項編碼器訓練要慢,進而導致BERT 的訓練效率低了很多,但是實驗也證明 MLM 訓練方法可以讓 BERT 獲得超出同期所有預訓練語言模型的語義理解能力,犧牲訓練效率是值得的。

13.5 BERT 之下句預測(NSP)

在很多自然語言處理的下游任務中,如問答和自然語言推斷,都基於兩個句子做邏輯推理,而語言模型並不具備直接捕獲句子之間的語義聯繫的能力,或者可以說成單詞預測粒度的訓練到不了句子關係這個層級,爲了學會捕捉句子之間的語義聯繫,BERT 採用了下句預測(NSP )作爲無監督預訓練的一部分。

NSP 的具體做法是,BERT 輸入的語句將由兩個句子構成,其中,50% 的概率將語義連貫的兩個連續句子作爲訓練文本(連續句對一般選自篇章級別的語料,以此確保前後語句的語義強相關),另外 50% 的概率將完全隨機抽取兩個句子作爲訓練文本。

連續句對:[CLS]今天天氣很糟糕[SEP]下午的體育課取消了[SEP]

隨機句對:[CLS]今天天氣很糟糕[SEP]魚快被烤焦啦[SEP]

其中 [SEP] 標籤表示分隔符。 [CLS] 表示標籤用於類別預測,結果爲 1,表示輸入爲連續句對;結果爲 0,表示輸入爲隨機句對。

通過訓練 [CLS] 編碼後的輸出標籤,BERT 可以學會捕捉兩個輸入句對的文本語義,在連續句對的預測任務中,BERT 的正確率可以達到 97%-98%。

13.6 BERT 之輸入表示

BERT 在預訓練階段使用了前文所述的兩種訓練方法,在真實訓練中一般是兩種方法混合使用

由於 BERT 通過 Transformer 模型堆疊而成,所以 BERT 的輸入需要兩套 Embedding 操作:

  1. 一套爲 One-hot 詞表映射編碼(對應下圖的 Token Embeddings);
  2. 另一套爲位置編碼(對應下圖的 Position Embeddings),不同於 Transformer 的位置編碼用三角函數表示,BERT 的位置編碼將在預訓練過程中訓練得到(訓練思想類似於Word Embedding 的 Q 矩陣)
  3. 由於在 MLM 的訓練過程中,存在單句輸入和雙句輸入的情況,因此 BERT 還需要一套區分輸入語句的分割編碼(對應下圖的 Segment Embeddings),BERT 的分割編碼也將在預訓練過程中訓練得到

對於分割編碼,Segment Embeddings 層只有兩種向量表示。前一個向量是把 0 賦給第一個句子中的各個 token,後一個向量是把 1 賦給第二個句子中的各個 token ;如果輸入僅僅只有一個句子,那麼它的 segment embedding 就是全 0,下面我們簡單舉個例子描述下:

[CLS]I like dogs[SEP]I like cats[SEP] 對應編碼 0 0 0 0 0 1 1 1 1

[SEP]I Iike dogs and cats[SEP] 對應編碼 0 0 0 0 0 0 0

十四、BERT 下游任務改造

BERT 根據自然語言處理下游任務的輸入和輸出的形式,將微調訓練支持的任務分爲四類,分別是句對分類、單句分類、文本問答和單句標註,接下來我們將簡要的介紹下 BERT 如何通過微調訓練適應這四類任務的要求。

14.1 句對分類

給定兩個句子,判斷它們的關係,稱爲句對分類,例如判斷句對是否相似、判斷後者是否爲前者的答案。

針對句對分類任務,BERT 在預訓練過程中就使用了 NSP 訓練方法獲得了直接捕獲句對語義關係的能力。

如下圖所示,句對用 [SEP] 分隔符拼接成文本序列,在句首加入標籤 [CLS],將句首標籤所對應的輸出值作爲分類標籤,計算預測分類標籤與真實分類標籤的交叉熵,將其作爲優化目標,在任務數據上進行微調訓練。

針對二分類任務,BERT 不需要對輸入數據和輸出數據的結構做任何改動,直接使用與 NSP 訓練方法一樣的輸入和輸出結構就行。

針對多分類任務,需要在句首標籤 [CLS] 的輸出特徵向量後接一個全連接層和 Softmax 層,保證輸出維數與類別數目一致,最後通過 arg max 操作(取最大值時對應的索引序號)得到相對應的類別結果。

下面給出句對分相似性任務的實例:

任務:判斷句子 “我很喜歡你” 和句子 “我很中意你” 是否相似

輸入改寫:“[CLS]我很喜歡你[SEP]我很中意你”

取 “[CLS]” 標籤對應輸出:[0.02, 0.98]

通過 arg max 操作得到相似類別爲 1(類別索引從 0 開始),即兩個句子相似

14.2 單句分類

給定一個句子,判斷該句子的類別,統稱爲單句分類,例如判斷情感類別、判斷是否爲語義連貫的句子。

針對單句二分類任務,也無須對 BERT 的輸入數據和輸出數據的結構做任何改動。

如下圖所示,單句分類在句首加入標籤 [CLS],將句首標籤所對應的輸出值作爲分類標籤,計算預測分類標籤與真實分類標籤的交叉熵,將其作爲優化目標,在任務數據上進行微調訓練。

同樣,針對多分類任務,需要在句首標籤 [CLS] 的輸出特徵向量後接一個全連接層和 Softmax 層,保證輸出維數與類別數目一致,最後通過 argmax 操作得到相對應的類別結果。

下面給出語義連貫性判斷任務的實例:

任務:判斷句子“海大球星飯茶喫” 是否爲一句話

輸入改寫:“[CLS]海大球星飯茶喫”

取 “[CLS]” 標籤對應輸出:[0.99, 0.01]

通過 arg max 操作得到相似類別爲 0,即這個句子不是一個語義連貫的句子

14.3 文本問答

給定一個問句和一個蘊含答案的句子,找出答案在後這種的位置,稱爲文本問答,例如給定一個問題(句子 A),在給定的段落(句子 B)中標註答案的其實位置和終止位置。

文本問答任何和前面講的其他任務有較大的差別,無論是在優化目標上,還是在輸入數據和輸出數據的形式上,都需要做一些特殊的處理。

爲了標註答案的起始位置和終止位置,BERT 引入兩個輔助向量 s(start,判斷答案的起始位置) 和 e(end,判斷答案的終止位置)。

如下圖所示,BERT 判斷句子 B 中答案位置的做法是,將句子 B 中的每一個次得到的最終特徵向量 \(T_i'\) 經過全連接層(利用全連接層將詞的抽象語義特徵轉化爲任務指向的特徵)後,分別與向量 s 和 e 求內積,對所有內積分別進行 softmax 操作,即可得到詞 Tok m(\(m\in [1,M]\))作爲答案其實位置和終止位置的概率。最後,去概率最大的片段作爲最終的答案

文本回答任務的微調訓練使用了兩個技巧:

  1. 用全連接層把 BERT 提取後的深層特徵向量轉化爲用於判斷答案位置的特徵向量
  2. 引入輔助向量 s 和 e 作爲答案其實位置和終止位置的基準向量,明確優化目標的方向和度量方法

下面給出文本問答任務的實例:

任務:給定問句 “今天的最高溫度是多少”,在文本 “天氣預報顯示今天最高溫度 37 攝氏度” 中標註答案的起始位置和終止位置

輸入改寫:“[CLS]今天的最高溫度是多少[SEP]天氣預報顯示今天最高溫度 37 攝氏度”

BERT Softmax 結果:

篇章文本 天氣 預報 顯示 今天 最高溫 37 攝氏度
起始位置概率 0.01 0.01 0.01 0.04 0.10 0.80 0.03
終止位置概率 0.01 0.01 0.01 0.03 0.04 0.10 0.80

對 Softmax 的結果取 arg max,得到答案的起始位置爲 6,終止位置爲 7,即答案爲 “37 攝氏度”

14.4 單句標註

給定一個句子,標註每個次的標籤,稱爲單句標註。例如給定一個句子,標註句子中的人名、地名和機構名。

單句標註任務和 BERT 預訓練任務具有較大差異,但與文本問答任務較爲相似。

如下圖所示,在進行單句標註任務時,需要在每個詞的最終語義特徵向量之後添加全連接層,將語義特徵轉化爲序列標註任務所需的特徵,單句標註任務需要對每個詞都做標註,因此不需要引入輔助向量,直接對經過全連接層後的結果做 Softmax 操作,即可得到各類標籤的概率分佈。

由於 BERT 需要對輸入文本進行分詞操作,獨立詞將會被分成若干子詞,因此 BERT 預測的結果將會是 5 類(細分爲 13 小類):

  • O(非人名地名機構名,O 表示 Other)
  • B-PER/LOC/ORG(人名/地名/機構名初始單詞,B 表示 Begin)
  • I-PER/LOC/ORG(人名/地名/機構名中間單詞,I 表示 Intermediate)
  • E-PER/LOC/ORG(人名/地名/機構名終止單詞,E 表示 End)
  • S-PER/LOC/ORG(人名/地名/機構名獨立單詞,S 表示 Single)

將 5 大類的首字母結合,可得 IOBES,這是序列標註最常用的標註方法。

下面給出命名實體識別(NER)任務的示例:

任務:給定句子 “愛因斯坦在柏林發表演講”,根據 IOBES 標註 NER 結果

輸入改寫:“[CLS]愛 因 斯坦 在 柏林 發表 演講”

BERT Softmax 結果:

BOBES 斯坦 柏林 發表 演講
O 0.01 0.01 0.01 0.90 0.01 0.90 0.90
B-PER 0.90 0.01 0.01 0.01 0.01 0.01 0.01
I-PER 0.01 0.90 0.01 0.01 0.01 0.01 0.01
E-PER 0.01 0.01 0.90 0.01 0.01 0.01 0.01
S-LOC 0.01 0.01 0.01 0.01 0.01 0.01 0.01

對 Softmax 的結果取 arg max,得到最終地 NER 標註結果爲:“愛因斯坦” 是人名;“柏林” 是地名

14.5 BERT效果展示

無論如何,從上述講解可以看出,NLP 四大類任務都可以比較方便地改造成 Bert 能夠接受的方式,總之不同類型的任務需要對模型做不同的修改,但是修改都是非常簡單的,最多加一層神經網絡即可。這其實是 Bert 的非常大的優點,這意味着它幾乎可以做任何NLP的下游任務,具備普適性,這是很強的。

但是講了這麼多,一個新模型好不好,效果纔是王道。那麼Bert 採用這種兩階段方式解決各種 NLP 任務效果如何?

在 11 個各種類型的 NLP 任務中達到目前最好的效果,某些任務性能有極大的提升。

十五、預訓練語言模型總結

到這裏我們可以再梳理下幾個模型之間的演進關係。

從上圖可見,Bert 其實和 ELMO 及 GPT 存在千絲萬縷的關係,比如如果我們把 GPT 預訓練階段換成雙向語言模型,那麼就得到了 Bert;而如果我們把 ELMO 的特徵抽取器換成 Transformer,那麼我們也會得到Bert。

所以你可以看出:Bert最關鍵兩點,一點是特徵抽取器採用 Transformer;第二點是預訓練的時候採用雙向語言模型。

那麼新問題來了:對於 Transformer 來說,怎麼才能在這個結構上做雙向語言模型任務呢?乍一看上去好像不太好搞。我覺得吧,其實有一種很直觀的思路,怎麼辦?看看 ELMO 的網絡結構圖,只需要把兩個 LSTM 替換成兩個 Transformer,一個負責正向,一個負責反向特徵提取,其實應該就可以。

當然這是我自己的改造,Bert 沒這麼做。那麼 Bert 是怎麼做的呢?我們前面不是提過 Word2Vec 嗎?我前面肯定不是漫無目的地提到它,提它是爲了在這裏引出那個 CBOW 訓練方法,所謂寫作時候埋伏筆的 “草蛇灰線,伏脈千里”,大概就是這個意思吧?

前面提到了 CBOW 方法,它的核心思想是:在做語言模型任務的時候,我把要預測的單詞摳掉,然後根據它的上文 Context-Before 和下文 Context-afte r去預測單詞。

其實 Bert 怎麼做的?Bert 就是這麼做的。從這裏可以看到方法間的繼承關係。當然 Bert 作者沒提 Word2Vec 及 CBOW 方法,這是我的判斷,Bert 作者說是受到完形填空任務的啓發,這也很可能,但是我覺得他們要是沒想到過 CBOW 估計是不太可能的。

從這裏可以看出,在文章開始我說過 Bert 在模型方面其實沒有太大創新,更像一個最近幾年 NLP 重要技術的集大成者,原因在於此,當然我不確定你怎麼看,是否認同這種看法,而且我也不關心你怎麼看。其實 Bert 本身的效果好和普適性強纔是最大的亮點。

最後,我講講我對Bert的評價和看法,我覺得 Bert 是 NLP 裏裏程碑式的工作,對於後面 NLP 的研究和工業應用會產生長久的影響,這點毫無疑問。但是從上文介紹也可以看出,從模型或者方法角度看,Bert 借鑑了 ELMO,GPT 及 CBOW,主要提出了 Masked 語言模型及 Next Sentence Prediction,但是這裏 Next Sentence Prediction 基本不影響大局,而 Masked LM 明顯借鑑了 CBOW 的思想。所以說 Bert 的模型沒什麼大的創新,更像最近幾年 NLP 重要進展的集大成者,這點如果你看懂了上文估計也沒有太大異議,如果你有大的異議,槓精這個大帽子我隨時準備戴給你。

如果歸納一下這些進展就是:首先是兩階段模型,第一階段雙向語言模型預訓練,這裏注意要用雙向而不是單向,第二階段採用具體任務 Fine-tuning 或者做特徵集成;第二是特徵抽取要用Transformer 作爲特徵提取器而不是 RNN 或者 CNN;第三,雙向語言模型可以採取 CBOW 的方法去做(當然我覺得這個是個細節問題,不算太關鍵,前兩個因素比較關鍵)。Bert 最大的亮點在於效果好及普適性強,幾乎所有 NLP 任務都可以套用 Bert 這種兩階段解決思路,而且效果應該會有明顯提升。可以預見的是,未來一段時間在 NLP 應用領域,Transformer 將佔據主導地位,而且這種兩階段預訓練方法也會主導各種應用。

另外,我們應該弄清楚預訓練這個過程本質上是在做什麼事情,本質上預訓練是通過設計好一個網絡結構來做語言模型任務,然後把大量甚至是無窮盡的無標註的自然語言文本利用起來,預訓練任務把大量語言學知識抽取出來編碼到網絡結構中,當手頭任務帶有標註信息的數據有限時,這些先驗的語言學特徵當然會對手頭任務有極大的特徵補充作用,因爲當數據有限的時候,很多語言學現象是覆蓋不到的,泛化能力就弱,集成儘量通用的語言學知識自然會加強模型的泛化能力。如何引入先驗的語言學知識其實一直是 NLP 尤其是深度學習場景下的 NLP 的主要目標之一,不過一直沒有太好的解決辦法,而 ELMO/GPT/Bert 的這種兩階段模式看起來無疑是解決這個問題自然又簡潔的方法,這也是這些方法的主要價值所在。

對於當前 NLP 的發展方向,我個人覺得有兩點非常重要:

  1. 一個是需要更強的特徵抽取器,目前看 Transformer 會逐漸擔當大任,但是肯定還是不夠強的,需要發展更強的特徵抽取器;
  2. 第二個就是如何優雅地引入大量無監督數據中包含的語言學知識,注意我這裏強調地是優雅,而不是引入,此前相當多的工作試圖做各種語言學知識的嫁接或者引入,但是很多方法看着讓人牙疼,就是我說的不優雅。

目前看預訓練這種兩階段方法還是很有效的,也非常簡潔,當然後面肯定還會有更好的模型出現。

完了,這就是預訓練語言模型的前世今生。

由於個人剛入門 NLP 方向,就不妄自總結,上述總結全部來自知乎文章:從Word Embedding到Bert模型—自然語言處理中的預訓練技術發展史-張俊林

十六、參考資料

我只是知識的搬運工,想詳細瞭解各個知識點的讀者可以自行選擇參考下列資料。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章