基于 transformer 的編碼器-解碼器模型是 表征學(xué)習(xí) 和 模型架構(gòu) 這兩個(gè)領(lǐng)域多年研究成果的結(jié)晶。本文簡(jiǎn)要介紹了神經(jīng)編碼器-解碼器模型的歷史,更多背景知識(shí),建議讀者閱讀由 Sebastion Ruder 撰寫的這篇精彩 博文。此外,建議讀者對(duì) 自注意力 (self-attention) 架構(gòu) 有一個(gè)基本了解,可以閱讀 Jay Alammar 的 這篇博文 復(fù)習(xí)一下原始 transformer 模型。
本文分 4 個(gè)部分:
- 背景 - 簡(jiǎn)要回顧了神經(jīng)編碼器-解碼器模型的歷史,重點(diǎn)關(guān)注基于 RNN 的模型。
- 編碼器-解碼器 - 闡述基于 transformer 的編碼器-解碼器模型,并闡述如何使用該模型進(jìn)行推理。
- 編碼器 - 闡述模型的編碼器部分。
- 解碼器 - 闡述模型的解碼器部分。
每個(gè)部分都建立在前一部分的基礎(chǔ)上,但也可以單獨(dú)閱讀。這篇分享是第三部分 編碼器。
編碼器
如前一節(jié)所述, 基于 transformer 的編碼器將輸入序列映射到上下文相關(guān)的編碼序列:
仔細(xì)觀察架構(gòu),基于 transformer 的編碼器由許多 殘差注意力模塊 堆疊而成。每個(gè)編碼器模塊都包含一個(gè) 雙向 自注意力層,其后跟著兩個(gè)前饋層。這里,為簡(jiǎn)單起見,我們忽略歸一化層 (normalization layer)。此外,我們不會(huì)深入討論兩個(gè)前饋層的作用,僅將其視為每個(gè)編碼器模塊 \({}^1\) 的輸出映射層。雙向自注意層將每個(gè)輸入向量 \(\mathbf{x'}_j, \forall j \in {1, \ldots, n}\) 與全部輸入向量 \(\mathbf{x'}_1, \ldots, \mathbf{x'}_n\) 相關(guān)聯(lián)并通過(guò)該機(jī)制將每個(gè)輸入向量 \(\mathbf{x'}_j\) 提煉為與其自身上下文相關(guān)的表征: \(\mathbf{x''}_j\)。因此,第一個(gè)編碼器塊將輸入序列 \(\mathbf{X}_{1:n}\) (如下圖淺綠色所示) 中的每個(gè)輸入向量從 上下文無(wú)關(guān) 的向量表征轉(zhuǎn)換為 上下文相關(guān) 的向量表征,后面每一個(gè)編碼器模塊都會(huì)進(jìn)一步細(xì)化這個(gè)上下文表征,直到最后一個(gè)編碼器模塊輸出最終的上下文相關(guān)編碼 \(\mathbf{\overline{X}}_{1:n}\) (如下圖深綠色所示)。
我們對(duì) 編碼器如何將輸入序列 "I want to buy a car EOS" 變換為上下文編碼序列
這一過(guò)程進(jìn)行一下可視化。與基于 RNN 的編碼器類似,基于 transformer 的編碼器也在輸入序列最后添加了一個(gè) EOS,以提示模型輸入向量序列已結(jié)束 \({}^2\)。
上圖中的 基于 transformer 的編碼器由三個(gè)編碼器模塊組成。我們?cè)谟覀?cè)的紅框中詳細(xì)列出了第二個(gè)編碼器模塊的前三個(gè)輸入向量: \(\mathbf{x}_1\),\(\mathbf {x}_2\) 及 \(\mathbf{x}_3\)。紅框下部的全連接圖描述了雙向自注意力機(jī)制,上面是兩個(gè)前饋層。如前所述,我們主要關(guān)注雙向自注意力機(jī)制。
可以看出,自注意力層的每個(gè)輸出向量 \(\mathbf{x''}_i, \forall i \in {1, \ldots, 7}\) 都 直接 依賴于 所有 輸入向量 \(\mathbf{x'}_1, \ldots, \mathbf{x'}_7\)。這意味著,單詞 “want” 的輸入向量表示 \(\mathbf{x'}_2\) 與單詞 “buy” (即 \(\mathbf{x'}_4\)) 和單詞 “I” (即 \(\mathbf{x'}_1\)) 直接相關(guān)。 因此,“want” 的輸出向量表征, 即 \(\mathbf{x''}_2\),是一個(gè)融合了其上下文信息的更精細(xì)的表征。
我們更深入了解一下雙向自注意力的工作原理。編碼器模塊的輸入序列 \(\mathbf{X'}_{1:n}\) 中的每個(gè)輸入向量 \(\mathbf{x'}_i\) 通過(guò)三個(gè)可訓(xùn)練的權(quán)重矩陣 \(\mathbf{W}_q\),\(\mathbf{W}_v\),\(\mathbf{W}_k\) 分別投影至 key
向量 \(\mathbf{k}_i\)、value
向量 \(\mathbf{v}_i\) 和 query
向量 \(\mathbf{q}_i\) (下圖分別以橙色、藍(lán)色和紫色表示):
請(qǐng)注意,對(duì)每個(gè)輸入向量 \(\mathbf{x}_i (\forall i \in {i, \ldots, n}\)) 而言,其所使用的權(quán)重矩陣都是 相同 的。將每個(gè)輸入向量 \(\mathbf{x}_i\) 投影到 query
、 key
和 value
向量后,將每個(gè) query
向量 \(\mathbf{q}_j (\forall j \in {1, \ldots, n}\)) 與所有 key
向量 \(\mathbf{k}_1, \ldots, \mathbf{k}_n\) 進(jìn)行比較。哪個(gè) key
向量與 query
向量 \(\mathbf{q}_j\) 越相似,其對(duì)應(yīng)的 value
向量 \(\mathbf{v}_j\) 對(duì)輸出向量 \(\mathbf{x''}_j\) 的影響就越重要。更具體地說(shuō),輸出向量 \(\mathbf{x''}_j\) 被定義為所有 value
向量的加權(quán)和 \(\mathbf{v}_1, \ldots, \mathbf{v}_n\) 加上輸入向量 \(\mathbf{x'}_j\)。而各 value
向量的權(quán)重與 \(\mathbf{q}_j\) 和各個(gè) key
向量 \(\mathbf{k}_1, \ldots, \mathbf{k}_n\) 之間的余弦相似度成正比,其數(shù)學(xué)公式為 \(\textbf{Softmax}(\mathbf{K}_{1:n}^\intercal \mathbf{q}_j)\),如下文的公式所示。關(guān)于自注意力層的完整描述,建議讀者閱讀 這篇 博文或 原始論文。
好吧,又復(fù)雜起來(lái)了。我們以上例中的一個(gè) query
向量為例圖解一下雙向自注意層。為簡(jiǎn)單起見,本例中假設(shè)我們的 基于 transformer 的解碼器只有一個(gè)注意力頭 config.num_heads = 1
并且沒(méi)有歸一化層。
圖左顯示了上個(gè)例子中的第二個(gè)編碼器模塊,右邊詳細(xì)可視化了第二個(gè)輸入向量 \(\mathbf{x'}_2\) 的雙向自注意機(jī)制,其對(duì)應(yīng)輸入詞為 “want”。首先將所有輸入向量 \(\mathbf{x'}_1, \ldots, \mathbf{x'}_7\) 投影到它們各自的 query
向量 \(\mathbf{q}_1, \ldots, \mathbf{q}_7\) (上圖中僅以紫色顯示前三個(gè) query
向量), value
向量 \(\mathbf{v}_1, \ldots, \mathbf{v}_7\) (藍(lán)色) 和 key
向量 \(\mathbf{k}_1, \ldots, \mathbf{k}_7\) (橙色)。然后,將 query
向量 \(\mathbf{q}_2\) 與所有 key
向量的轉(zhuǎn)置 ( 即 \(\mathbf{K}_{1:7}^{\intercal}\)) 相乘,隨后進(jìn)行 softmax 操作以產(chǎn)生 自注意力權(quán)重 。 自注意力權(quán)重最終與各自的 value
向量相乘,并加上輸入向量 \(\mathbf{x'}_2\),最終輸出單詞 “want” 的上下文相關(guān)表征, 即 \(\mathbf{x''}_2\) (圖右深綠色表示)。整個(gè)等式顯示在圖右框的上部。 \(\mathbf{K}_{1:7}^{\intercal}\) 和 \(\mathbf{q}_2\) 的相乘使得將 “want” 的向量表征與所有其他輸入 (“I”,“to”,“buy”,“a”,“car”,“EOS”) 的向量表征相比較成為可能,因此自注意力權(quán)重反映出每個(gè)輸入向量 \(\mathbf{x'}_j\) 對(duì) “want” 一詞的最終表征 \(\mathbf{x''}_2\) 的重要程度。
為了進(jìn)一步理解雙向自注意力層的含義,我們假設(shè)以下句子: “ 房子很漂亮且位于市中心,因此那兒公共交通很方便 ”。 “那兒”這個(gè)詞指的是“房子”,這兩個(gè)詞相隔 12 個(gè)字。在基于 transformer 的編碼器中,雙向自注意力層運(yùn)算一次,即可將“房子”的輸入向量與“那兒”的輸入向量相關(guān)聯(lián)。相比之下,在基于 RNN 的編碼器中,相距 12 個(gè)字的詞將需要至少 12 個(gè)時(shí)間步的運(yùn)算,這意味著在基于 RNN 的編碼器中所需數(shù)學(xué)運(yùn)算與距離呈線性關(guān)系。這使得基于 RNN 的編碼器更難對(duì)長(zhǎng)程上下文表征進(jìn)行建模。此外,很明顯,基于 transformer 的編碼器比基于 RNN 的編碼器-解碼器模型更不容易丟失重要信息,因?yàn)榫幋a的序列長(zhǎng)度相對(duì)輸入序列長(zhǎng)度保持不變, 即 \(\textbf{len }(\mathbf{X}_{1:n}) = \textbf{len}(\mathbf{\overline{X}}_{1:n}) = n\),而 RNN 則會(huì)將 \(\textbf{len}((\mathbf{X}_{1:n}) = n\) 壓縮到 \(\textbf{len}(\mathbf{c}) = 1\),這使得 RNN 很難有效地對(duì)輸入詞之間的長(zhǎng)程依賴關(guān)系進(jìn)行編碼。
除了更容易學(xué)到長(zhǎng)程依賴外,我們還可以看到 transformer 架構(gòu)能夠并行處理文本。從數(shù)學(xué)上講,這是通過(guò)將自注意力機(jī)制表示為 query
、 key
和 value
的矩陣乘來(lái)完成的:
輸出 \(\mathbf{X''}_{1:n} = \mathbf{x''}_1, \ldots, \mathbf{x''}_n\) 是由一系列矩陣乘計(jì)算和 softmax 操作算得,因此可以有效地并行化。請(qǐng)注意,在基于 RNN 的編碼器模型中,隱含狀態(tài) \(\mathbf{c}\) 的計(jì)算必須按順序進(jìn)行: 先計(jì)算第一個(gè)輸入向量的隱含狀態(tài) \(\mathbf{x}_1\); 然后計(jì)算第二個(gè)輸入向量的隱含狀態(tài),其取決于第一個(gè)隱含向量的狀態(tài),依此類推。RNN 的順序性阻礙了有效的并行化,并使其在現(xiàn)代 GPU 硬件上比基于 transformer 的編碼器模型的效率低得多。
太好了,現(xiàn)在我們應(yīng)該對(duì):
a) 基于 transformer 的編碼器模型如何有效地建模長(zhǎng)程上下文表征,以及
b) 它們?nèi)绾斡行У靥幚黹L(zhǎng)序列向量輸入這兩個(gè)方面有了比較好的理解了。
現(xiàn)在,我們寫一個(gè) MarianMT
編碼器-解碼器模型的編碼器部分的小例子,以驗(yàn)證這些理論在實(shí)踐中行不行得通。
\({}^1\) 關(guān)于前饋層在基于 transformer 的模型中所扮演的角色的詳細(xì)解釋超出了本文的范疇。Yun 等人 (2017) 的工作認(rèn)為前饋層對(duì)于將每個(gè)上下文向量 \(\mathbf{x'}_i\) 映射到目標(biāo)輸出空間至關(guān)重要,而單靠 自注意力 層無(wú)法達(dá)成這一目的。這里請(qǐng)注意,每個(gè)輸出詞元 \(\mathbf{x'}\) 都經(jīng)由相同的前饋層處理。更多詳細(xì)信息,建議讀者閱讀論文。
\({}^2\) 我們無(wú)須將 EOS 附加到輸入序列,雖然有工作表明,在很多情況下加入它可以提高性能。相反地,基于 transformer 的解碼器必須把 \(\text{BOS}\) 作為第 0 個(gè)目標(biāo)向量,并以之為條件預(yù)測(cè)第 1 個(gè)目標(biāo)向量。
from transformers import MarianMTModel, MarianTokenizer
import torch
tokenizer = MarianTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-de")
model = MarianMTModel.from_pretrained("Helsinki-NLP/opus-mt-en-de")
embeddings = model.get_input_embeddings()
# create ids of encoded input vectors
input_ids = tokenizer("I want to buy a car", return_tensors="pt").input_ids
# pass input_ids to encoder
encoder_hidden_states = model.base_model.encoder(input_ids, return_dict=True).last_hidden_state
# change the input slightly and pass to encoder
input_ids_perturbed = tokenizer("I want to buy a house", return_tensors="pt").input_ids
encoder_hidden_states_perturbed = model.base_model.encoder(input_ids_perturbed, return_dict=True).last_hidden_state
# compare shape and encoding of first vector
print(f"Length of input embeddings {embeddings(input_ids).shape[1]}. Length of encoder_hidden_states {encoder_hidden_states.shape[1]}")
# compare values of word embedding of "I" for input_ids and perturbed input_ids
print("Is encoding for `I` equal to its perturbed version?: ", torch.allclose(encoder_hidden_states[0, 0], encoder_hidden_states_perturbed[0, 0], atol=1e-3))
輸出:
Length of input embeddings 7. Length of encoder_hidden_states 7
Is encoding for `I` equal to its perturbed version?: False
我們比較一下輸入詞嵌入的序列長(zhǎng)度 ( 即 embeddings(input_ids)
,對(duì)應(yīng)于 \(\mathbf{X}_{1:n}\)) 和 encoder_hidden_??states
的長(zhǎng)度 (對(duì)應(yīng)于\(\mathbf{\overline{X}}_{1:n}\))。同時(shí),我們讓編碼器對(duì)單詞序列 “I want to buy a car” 及其輕微改動(dòng)版 “I want to buy a house” 分別執(zhí)行前向操作,以檢查第一個(gè)詞 “I” 的輸出編碼在更改輸入序列的最后一個(gè)單詞后是否會(huì)有所不同。
不出意外,輸入詞嵌入和編碼器輸出編碼的長(zhǎng)度, 即 \(\textbf{len}(\mathbf{X}_{1:n})\) 和 \(\textbf{len }(\mathbf{\overline{X}}_{1:n})\),是相等的。同時(shí),可以注意到當(dāng)最后一個(gè)單詞從 “car” 改成 “house” 后,\(\mathbf{\overline{x}}_1 = \text{“I”}\) 的編碼輸出向量的值也改變了。因?yàn)槲覀儸F(xiàn)在已經(jīng)理解了雙向自注意力機(jī)制,這就不足為奇了。
順帶一提, 自編碼 模型 (如 BERT) 的架構(gòu)與 基于 transformer 的編碼器模型是完全一樣的。 自編碼 模型利用這種架構(gòu)對(duì)開放域文本數(shù)據(jù)進(jìn)行大規(guī)模自監(jiān)督預(yù)訓(xùn)練,以便它們可以將任何單詞序列映射到深度雙向表征。在 Devlin 等 (2018) 的工作中,作者展示了一個(gè)預(yù)訓(xùn)練 BERT 模型,其頂部有一個(gè)任務(wù)相關(guān)的分類層,可以在 11 個(gè) NLP 任務(wù)上獲得 SOTA 結(jié)果。你可以從 此處 找到 ?? transformers 支持的所有 自編碼 模型。
敬請(qǐng)關(guān)注其余部分的文章。
英文原文:
https://hf.co/blog/encoder-decoder 原文作者: Patrick von Platen
譯者: Matrix Yao (姚偉峰),英特爾深度學(xué)習(xí)工程師,工作方向?yàn)?transformer-family 模型在各模態(tài)數(shù)據(jù)上的應(yīng)用及大規(guī)模模型的訓(xùn)練推理。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-472403.html
審校/排版: zhongdongy (阿東)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-472403.html
到了這里,關(guān)于編碼器 | 基于 Transformers 的編碼器-解碼器模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!