基于 transformer 的編碼器-解碼器模型是 表征學(xué)習(xí) 和 模型架構(gòu) 這兩個領(lǐng)域多年研究成果的結(jié)晶。本文簡要介紹了神經(jīng)編碼器-解碼器模型的歷史,更多背景知識,建議讀者閱讀由 Sebastion Ruder 撰寫的這篇精彩 博文。此外,建議讀者對 自注意力 (self-attention) 架構(gòu) 有一個基本了解,可以閱讀 Jay Alammar 的 這篇博文 復(fù)習(xí)一下原始 transformer 模型。
本文分 4 個部分:
- 背景 - 簡要回顧了神經(jīng)編碼器-解碼器模型的歷史,重點(diǎn)關(guān)注基于 RNN 的模型。
- 編碼器-解碼器 - 闡述基于 transformer 的編碼器-解碼器模型,并闡述如何使用該模型進(jìn)行推理。
- 編碼器 - 闡述模型的編碼器部分。
- 解碼器 - 闡述模型的解碼器部分。
每個部分都建立在前一部分的基礎(chǔ)上,但也可以單獨(dú)閱讀。這篇分享是最后一部分 解碼器。
解碼器
如 編碼器-解碼器 部分所述, 基于 transformer 的解碼器定義了給定上下文編碼序列條件下目標(biāo)序列的條件概率分布:
根據(jù)貝葉斯法則,在給定上下文編碼序列和每個目標(biāo)變量的所有前驅(qū)目標(biāo)向量的條件下,可將上述分布分解為每個目標(biāo)向量的條件分布的乘積:
我們首先了解一下基于 transformer 的解碼器如何定義概率分布?;?transformer 的解碼器由很多 解碼器模塊 堆疊而成,最后再加一個線性層 (即 “LM 頭”)。這些解碼器模塊的堆疊將上下文相關(guān)的編碼序列 \(\mathbf{\overline{X}}_{1:n}\) 和每個目標(biāo)向量的前驅(qū)輸入 \(\mathbf{Y}_{0:i-1}\) (這里 \(\mathbf{y}_0\) 為 BOS) 映射為目標(biāo)向量的編碼序列 \(\mathbf{\overline{Y} }_{0:i-1}\)。然后,“LM 頭”將目標(biāo)向量的編碼序列 \(\mathbf{\overline{Y}}_{0:i-1}\) 映射到 logit 向量序列 \(\mathbf {L}_{1:n} = \mathbf{l}_1, \ldots, \mathbf{l}_n\), 而每個 logit 向量\(\mathbf{l}_i\) 的維度即為詞表的詞匯量。這樣,對于每個 \(i \in {1, \ldots, n}\),其在整個詞匯表上的概率分布可以通過對 \(\mathbf{l}_i\) 取 softmax 獲得。公式如下:
“LM 頭” 即為詞嵌入矩陣的轉(zhuǎn)置, 即 \(\mathbf{W}_{\text{emb}}^{\intercal} = \left[\mathbf{ y}^1, \ldots, \mathbf{y}^{\text{vocab}}\right]^{??T}\) \({}^1\)。直觀上來講,這意味著對于所有 \(i \in {0, \ldots, n - 1}\) “LM 頭” 層會將 \(\mathbf{\overline{y }}_i\) 與詞匯表 \(\mathbf{y}^1, \ldots, \mathbf{y}^{\text{vocab}}\) 中的所有詞嵌入一一比較,輸出的 logit 向量 \(\mathbf{l}_{i+1}\) 即表示 \(\mathbf{\overline{y }}_i\) 與每個詞嵌入之間的相似度。Softmax 操作只是將相似度轉(zhuǎn)換為概率分布。對于每個 \(i \in {1, \ldots, n}\),以下等式成立:
總結(jié)一下,為了對目標(biāo)向量序列 \(\mathbf{Y}_{1: m}\) 的條件分布建模,先在目標(biāo)向量 \(\mathbf{Y}_{1: m-1}\) 前面加上特殊的 \(\text{BOS}\) 向量 ( 即 \(\mathbf{y}_0\)),并將其與上下文相關(guān)的編碼序列 \(\mathbf{\overline{X}}_{1:n}\) 一起映射到 logit 向量序列 \(\mathbf{L}_{1:m}\)。然后,使用 softmax 操作將每個 logit 目標(biāo)向量 \(\mathbf{l}_i\) 轉(zhuǎn)換為目標(biāo)向量 \(\mathbf{y}_i\) 的條件概率分布。最后,將所有目標(biāo)向量的條件概率 \(\mathbf{y}_1, \ldots, \mathbf{y}_m\) 相乘得到完整目標(biāo)向量序列的條件概率:
與基于 transformer 的編碼器不同,在基于 transformer 的解碼器中,其輸出向量 \(\mathbf{\overline{y}}_{i-1}\) 應(yīng)該能很好地表征 下一個 目標(biāo)向量 (即 \(\mathbf{y}_i\)),而不是輸入向量本身 (即 \(\mathbf{y}_{i-1}\))。此外,輸出向量 \(\mathbf{\overline{y}}_{i-1}\) 應(yīng)基于編碼器的整個輸出序列 \(\mathbf{\overline{X}}_{1:n}\)。為了滿足這些要求,每個解碼器塊都包含一個 單向自注意層,緊接著是一個 交叉注意層,最后是兩個前饋層\({}^2\)。單向自注意層將其每個輸入向量 \(\mathbf{y'}_j\) 僅與其前驅(qū)輸入向量 \(\mathbf{y'}_i\) (其中 \(i \le j\),且 \(j \in {1, \ldots, n}\)) 相關(guān)聯(lián),來模擬下一個目標(biāo)向量的概率分布。交叉注意層將其每個輸入向量 \(\mathbf{y''}_j\) 與編碼器輸出的所有向量 \(\mathbf{\overline{X}}_{1:n}\) 相關(guān)聯(lián),來根據(jù)編碼器輸入預(yù)測下一個目標(biāo)向量的概率分布。
好,我們?nèi)砸杂⒄Z到德語翻譯為例可視化一下 基于 transformer 的解碼器。
我們可以看到解碼器將 \(\mathbf{Y}_{0:5}\): “BOS”、“Ich”、“will”、“ein”、“Auto”、“kaufen” (圖中以淺紅色顯示) 和 “I”、“want”、“to”、“buy”、“a”、“car”、“EOS” ( 即 \(\mathbf{\overline{X}}_{1:7}\) (圖中以深綠色顯示)) 映射到 logit 向量 \(\mathbf{L}_{1:6}\) (圖中以深紅色顯示)。
因此,對每個 \(\mathbf{l}_1、\mathbf{l}_2、\ldots、\mathbf{l}_6\) 使用 softmax 操作可以定義下列條件概率分布:
\[p_{\theta_{dec}}(\mathbf{y} | \text{BOS Ich}, \mathbf{\overline{X}}_{1:7}), \]\[\ldots, \]\[p_{\theta_{dec}}(\mathbf{y} | \text{BOS Ich will ein Auto kaufen}, \mathbf{\overline{X}}_{1:7}) \]
總條件概率如下:
其可表示為以下乘積形式:
圖右側(cè)的紅框顯示了前三個目標(biāo)向量 \(\mathbf{y}_0\)、\(\mathbf{y}_1\)、 \(\mathbf{y}_2\) 在一個解碼器模塊中的行為。下半部分說明了單向自注意機(jī)制,中間說明了交叉注意機(jī)制。我們首先關(guān)注單向自注意力。
與雙向自注意一樣,在單向自注意中, query
向量 \(\mathbf{q}_0, \ldots, \mathbf{q}_{m-1}\) (如下圖紫色所示), key
向量 \(\mathbf{k}_0, \ldots, \mathbf{k}_{m-1}\) (如下圖橙色所示),和 value
向量 \(\mathbf{v }_0, \ldots, \mathbf{v}_{m-1}\) (如下圖藍(lán)色所示) 均由輸入向量 \(\mathbf{y'}_0, \ldots, \mathbf{ y'}_{m-1}\) (如下圖淺紅色所示) 映射而來。然而,在單向自注意力中,每個 query
向量 \(\mathbf{q}_i\) 僅 與當(dāng)前及之前的 key
向量進(jìn)行比較 (即 \(\mathbf{k}_0 , \ldots, \mathbf{k}_i\)) 并生成各自的 注意力權(quán)重 。這可以防止輸出向量 \(\mathbf{y''}_j\) (如下圖深紅色所示) 包含未來向量 (\(\mathbf{y}_i\),其中 \(i > j\) 且 \(j \in {0, \ldots, m - 1 }\)) 的任何信息 。與雙向自注意力的情況一樣,得到的注意力權(quán)重會乘以它們各自的 value
向量并加權(quán)求和。
我們將單向自注意力總結(jié)如下:
請注意, key
和 value
向量的索引范圍都是 \(0:i\) 而不是 \(0: m-1\),\(0: m-1\) 是雙向自注意力中 key
向量的索引范圍。
下圖顯示了上例中輸入向量 \(\mathbf{y'}_1\) 的單向自注意力。
可以看出 \(\mathbf{y''}_1\) 只依賴于 \(\mathbf{y'}_0\) 和 \(\mathbf{y'}_1\)。因此,單詞 “Ich” 的向量表征 ( 即 \(\mathbf{y'}_1\)) 僅與其自身及 “BOS” 目標(biāo)向量 ( 即 \(\mathbf{y'}_0\)) 相關(guān)聯(lián),而 不 與 “will” 的向量表征 ( 即 \(\mathbf{y'}_2\)) 相關(guān)聯(lián)。
那么,為什么解碼器使用單向自注意力而不是雙向自注意力這件事很重要呢?如前所述,基于 transformer 的解碼器定義了從輸入向量序列 \(\mathbf{Y}_{0: m-1}\) 到其 下一個 解碼器輸入的 logit 向量的映射,即 \(\mathbf{L}_{1:m}\)。舉個例子,輸入向量 \(\mathbf{y}_1\) = “Ich” 會映射到 logit 向量 \(\mathbf{l}_2\),并用于預(yù)測下一個輸入向量 \(\mathbf{y}_2\)。因此,如果 \(\mathbf{y'}_1\) 可以獲取后續(xù)輸入向量 \(\mathbf{Y'}_{2:5}\)的信息,解碼器將會簡單地復(fù)制向量 “will” 的向量表征 ( 即 \(\mathbf{y'}_2\)) 作為其輸出 \(\mathbf{y''}_1\),并就這樣一直傳播到最后一層,所以最終的輸出向量 \(\mathbf{\overline{y}}_1\) 基本上就只對應(yīng)于 \(\mathbf{y}_2\) 的向量表征,并沒有起到預(yù)測的作用。
這顯然是不對的,因?yàn)檫@樣的話,基于 transformer 的解碼器永遠(yuǎn)不會學(xué)到在給定所有前驅(qū)詞的情況下預(yù)測下一個詞,而只是對所有 \(i \in {1, \ldots, m }\),通過網(wǎng)絡(luò)將目標(biāo)向量 \(\mathbf{y}_i\) 復(fù)制到 \(\mathbf {\overline{y}}_{i-1}\)。以下一個目標(biāo)變量本身為條件去定義下一個目標(biāo)向量,即從 \(p(\mathbf{y} | \mathbf{Y}_{0:i}, \mathbf{\overline{ X}})\) 中預(yù)測 \(\mathbf{y}_i\), 顯然是不對的。因此,單向自注意力架構(gòu)允許我們定義一個 因果的 概率分布,這對有效建模下一個目標(biāo)向量的條件分布而言是必要的。
太棒了!現(xiàn)在我們可以轉(zhuǎn)到連接編碼器和解碼器的層 - 交叉注意力 機(jī)制!
交叉注意層將兩個向量序列作為輸入: 單向自注意層的輸出 \(\mathbf{Y''}_{0: m-1}\) 和編碼器的輸出 \(\mathbf{\overline{X}}_{1:n}\)。與自注意力層一樣, query
向量 \(\mathbf{q}_0, \ldots, \mathbf{q}_{m-1}\) 是上一層輸出向量 \(\mathbf{Y''}_{0: m-1}\) 的投影。而 key
和 value
向量 \(\mathbf{k}_0, \ldots, \mathbf{k}_{n-1}\)、\(\mathbf{v}_0, \ldots, \mathbf {v}_{n-1}\) 是編碼器輸出向量 \(\mathbf{\overline{X}}_{1:n}\) 的投影。定義完 key
、value
和 query
向量后,將 query
向量 \(\mathbf{q}_i\) 與 所有 key
向量進(jìn)行比較,并用各自的得分對相應(yīng)的 value
向量進(jìn)行加權(quán)求和。這個過程與 雙向 自注意力對所有 \(i \in {0, \ldots, m-1}\) 求 \(\mathbf{y'''}_i\) 是一樣的。交叉注意力可以概括如下:
注意,key
和 value
向量的索引范圍是 \(1:n\),對應(yīng)于編碼器輸入向量的數(shù)目。
我們用上例中輸入向量 \(\mathbf{y''}_1\) 來圖解一下交叉注意力機(jī)制。
我們可以看到 query
向量 \(\mathbf{q}_1\)(紫色)源自 \(\mathbf{y''}_1\)(紅色),因此其依賴于單詞 "Ich" 的向量表征。然后將 query
向量 \(\mathbf{q}_1\) 與對應(yīng)的 key
向量 \(\mathbf{k}_1, \ldots, \mathbf{k}_7\)(黃色)進(jìn)行比較,這里的 key
向量對應(yīng)于編碼器對其輸入 \(\mathbf{X}_{1:n}\) = "I want to buy a car EOS" 的上下文相關(guān)向量表征。這將 "Ich" 的向量表征與所有編碼器輸入向量直接關(guān)聯(lián)起來。最后,將注意力權(quán)重乘以 value
向量 \(\mathbf{v}_1, \ldots, \mathbf{v}_7\)(青綠色)并加上輸入向量 \(\mathbf{y''}_1\) 最終得到輸出向量 \(\mathbf{y'''}_1\)(深紅色)。
所以,直觀而言,到底發(fā)生了什么?每個輸出向量 \(\mathbf{y'''}_i\) 是由所有從編碼器來的 value
向量(\(\mathbf{v}_{1}, \ldots, \mathbf{v}_7\) )的加權(quán)和與輸入向量本身 \(\mathbf{y''}_i\) 相加而得(參見上圖所示的公式)。其關(guān)鍵思想是: 來自解碼器的 \(\mathbf{q}_i\) 的 query
投影與 來自編碼器的 \(\mathbf{k}_j\) 越相關(guān),其對應(yīng)的 \(\mathbf{v}_j\) 對輸出的影響越大。
酷!現(xiàn)在我們可以看到這種架構(gòu)的每個輸出向量 \(\mathbf{y'''}_i\) 取決于其來自編碼器的輸入向量 \(\mathbf{\overline{X}}_{1 :n}\) 及其自身的輸入向量 \(\mathbf{y''}_i\)。這里有一個重要的點(diǎn),在該架構(gòu)中,雖然輸出向量 \(\mathbf{y'''}_i\) 依賴來自編碼器的輸入向量 \(\mathbf{\overline{X}}_{1:n}\),但其完全獨(dú)立于該向量的數(shù)量 \(n\)。所有生成 key
向量 \(\mathbf{k}_1, \ldots, \mathbf{k}_n\) 和 value
向量 $\mathbf{v}_1, \ldots, \mathbf{v}_n $ 的投影矩陣 \(\mathbf{W}^{\text{cross}}_{k}\) 和 \(\mathbf{W}^{\text{cross}}_{v}\) 都是與 \(n\) 無關(guān)的,所有 \(n\) 共享同一個投影矩陣。且對每個 \(\mathbf{y'''}_i\),所有 value
向量 \(\mathbf{v}_1, \ldots, \mathbf{v}_n\) 被加權(quán)求和至一個向量。至此,關(guān)于為什么基于 transformer 的解碼器沒有遠(yuǎn)程依賴問題而基于 RNN 的解碼器有
這一問題的答案已經(jīng)很顯然了。因?yàn)槊總€解碼器 logit 向量 直接 依賴于每個編碼后的輸出向量,因此比較第一個編碼輸出向量和最后一個解碼器 logit 向量只需一次操作,而不像 RNN 需要很多次。
總而言之,單向自注意力層負(fù)責(zé)基于當(dāng)前及之前的所有解碼器輸入向量建模每個輸出向量,而交叉注意力層則負(fù)責(zé)進(jìn)一步基于編碼器的所有輸入向量建模每個輸出向量。
為了驗(yàn)證我們對該理論的理解,我們繼續(xù)上面編碼器部分的代碼,完成解碼器部分。
\({}^1\) 詞嵌入矩陣 \(\mathbf{W}_{\text{emb}}\) 為每個輸入詞提供唯一的 上下文無關(guān) 向量表示。這個矩陣通常也被用作 “LM 頭”,此時(shí) “LM 頭”可以很好地完成“編碼向量到 logit” 的映射。
\({}^2\) 與編碼器部分一樣,本文不會詳細(xì)解釋前饋層在基于 transformer 的模型中的作用。Yun 等 (2017) 的工作認(rèn)為前饋層對于將每個上下文相關(guān)向量 \(\mathbf{x'}_i\) 映射到所需的輸出空間至關(guān)重要,僅靠自注意力層無法完成。這里應(yīng)該注意,每個輸出詞元 \(\mathbf{x'}\) 對應(yīng)的前饋層是相同的。有關(guān)更多詳細(xì)信息,建議讀者閱讀論文。
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 token ids for encoder input
input_ids = tokenizer("I want to buy a car", return_tensors="pt").input_ids
# pass input token ids to encoder
encoder_output_vectors = model.base_model.encoder(input_ids, return_dict=True).last_hidden_state
# create token ids for decoder input
decoder_input_ids = tokenizer("<pad> Ich will ein", return_tensors="pt", add_special_tokens=False).input_ids
# pass decoder input ids and encoded input vectors to decoder
decoder_output_vectors = model.base_model.decoder(decoder_input_ids, encoder_hidden_states=encoder_output_vectors).last_hidden_state
# derive embeddings by multiplying decoder outputs with embedding weights
lm_logits = torch.nn.functional.linear(decoder_output_vectors, embeddings.weight, bias=model.final_logits_bias)
# change the decoder input slightly
decoder_input_ids_perturbed = tokenizer("<pad> Ich will das", return_tensors="pt", add_special_tokens=False).input_ids
decoder_output_vectors_perturbed = model.base_model.decoder(decoder_input_ids_perturbed, encoder_hidden_states=encoder_output_vectors).last_hidden_state
lm_logits_perturbed = torch.nn.functional.linear(decoder_output_vectors_perturbed, embeddings.weight, bias=model.final_logits_bias)
# compare shape and encoding of first vector
print(f"Shape of decoder input vectors {embeddings(decoder_input_ids).shape}. Shape of decoder logits {lm_logits.shape}")
# compare values of word embedding of "I" for input_ids and perturbed input_ids
print("Is encoding for `Ich` equal to its perturbed version?: ", torch.allclose(lm_logits[0, 0], lm_logits_perturbed[0, 0], atol=1e-3))
輸出:
Shape of decoder input vectors torch.Size([1, 5, 512]). Shape of decoder logits torch.Size([1, 5, 58101])
Is encoding for `Ich` equal to its perturbed version?: True
我們首先比較解碼器詞嵌入層的輸出維度 embeddings(decoder_input_ids)
(對應(yīng)于 \(\mathbf{Y}_{0: 4}\),這里 <pad>
對應(yīng)于 BOS 且 "Ich will das" 被分為 4 個詞) 和 lm_logits
(對應(yīng)于 \(\mathbf{L}_{1:5}\)) 的維度。此外,我們還通過解碼器將單詞序列 “<pad>
Ich will ein” 和其輕微改編版 “<pad>
Ich will das” 與 encoder_output_vectors
一起傳遞給解碼器,以檢查對應(yīng)于 “Ich” 的第二個 lm_logit 在僅改變輸入序列中的最后一個單詞 (“ein” -> “das”) 時(shí)是否會有所不同。
正如預(yù)期的那樣,解碼器輸入詞嵌入和 lm_logits 的輸出, 即 \(\mathbf{Y}_{0: 4}\) 和 \(\mathbf{L}_{ 1:5}\) 的最后一個維度不同。雖然序列長度相同 (=5),但解碼器輸入詞嵌入的維度對應(yīng)于 model.config.hidden_??size
,而 lm_logit
的維數(shù)對應(yīng)于詞匯表大小 model.config.vocab_size
。其次,可以注意到,當(dāng)將最后一個單詞從 “ein” 變?yōu)?“das”,\(\mathbf{l}_1 = \text{“Ich”}\) 的輸出向量的值不變。鑒于我們已經(jīng)理解了單向自注意力,這就不足為奇了。
最后一點(diǎn), 自回歸 模型,如 GPT2,與刪除了交叉注意力層的 基于 transformer 的解碼器模型架構(gòu)是相同的,因?yàn)榧冏曰貧w模型不依賴任何編碼器的輸出。因此,自回歸模型本質(zhì)上與 自編碼 模型相同,只是用單向注意力代替了雙向注意力。這些模型還可以在大量開放域文本數(shù)據(jù)上進(jìn)行預(yù)訓(xùn)練,以在自然語言生成 (NLG) 任務(wù)中表現(xiàn)出令人印象深刻的性能。在 Radford 等 (2019) 的工作中,作者表明預(yù)訓(xùn)練的 GPT2 模型無需太多微調(diào)即可在多種 NLG 任務(wù)上取得達(dá)到 SOTA 或接近 SOTA 的結(jié)果。你可以在 此處 獲取所有 ?? transformers 支持的 自回歸 模型的信息。
好了!至此,你應(yīng)該已經(jīng)很好地理解了 基于 transforemr 的編碼器-解碼器模型以及如何在 ?? transformers 庫中使用它們。
非常感謝 Victor Sanh、Sasha Rush、Sam Shleifer、Oliver ?strand、Ted Moskovitz 和 Kristian Kyvik 提供的寶貴反饋。
附錄
如上所述,以下代碼片段展示了如何為 基于 transformer 的編碼器-解碼器模型編寫一個簡單的生成方法。在這里,我們使用 torch.argmax
實(shí)現(xiàn)了一個簡單的 貪心 解碼法來對目標(biāo)向量進(jìn)行采樣。
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")
# create ids of encoded input vectors
input_ids = tokenizer("I want to buy a car", return_tensors="pt").input_ids
# create BOS token
decoder_input_ids = tokenizer("<pad>", add_special_tokens=False, return_tensors="pt").input_ids
assert decoder_input_ids[0, 0].item() == model.config.decoder_start_token_id, "`decoder_input_ids` should correspond to `model.config.decoder_start_token_id`"
# STEP 1
# pass input_ids to encoder and to decoder and pass BOS token to decoder to retrieve first logit
outputs = model(input_ids, decoder_input_ids=decoder_input_ids, return_dict=True)
# get encoded sequence
encoded_sequence = (outputs.encoder_last_hidden_state,)
# get logits
lm_logits = outputs.logits
# sample last token with highest prob
next_decoder_input_ids = torch.argmax(lm_logits[:, -1:], axis=-1)
# concat
decoder_input_ids = torch.cat([decoder_input_ids, next_decoder_input_ids], axis=-1)
# STEP 2
# reuse encoded_inputs and pass BOS + "Ich" to decoder to second logit
lm_logits = model(None, encoder_outputs=encoded_sequence, decoder_input_ids=decoder_input_ids, return_dict=True).logits
# sample last token with highest prob again
next_decoder_input_ids = torch.argmax(lm_logits[:, -1:], axis=-1)
# concat again
decoder_input_ids = torch.cat([decoder_input_ids, next_decoder_input_ids], axis=-1)
# STEP 3
lm_logits = model(None, encoder_outputs=encoded_sequence, decoder_input_ids=decoder_input_ids, return_dict=True).logits
next_decoder_input_ids = torch.argmax(lm_logits[:, -1:], axis=-1)
decoder_input_ids = torch.cat([decoder_input_ids, next_decoder_input_ids], axis=-1)
# let's see what we have generated so far!
print(f"Generated so far: {tokenizer.decode(decoder_input_ids[0], skip_special_tokens=True)}")
# This can be written in a loop as well.
輸出:
Generated so far: Ich will ein
在這個示例代碼中,我們準(zhǔn)確地展示了正文中描述的內(nèi)容。我們在輸入 “I want to buy a car” 前面加上 \(\text{BOS}\) ,然后一起傳給編碼器-解碼器模型,并對第一個 logit $\mathbf{l}_1 $ (對應(yīng)代碼中第一次出現(xiàn) lm_logits 的部分) 進(jìn)行采樣。這里,我們的采樣策略很簡單: 貪心地選擇概率最高的詞作為下一個解碼器輸入向量。然后,我們以自回歸方式將采樣得的解碼器輸入向量與先前的輸入一起傳遞給編碼器-解碼器模型并再次采樣。重復(fù) 3 次后,該模型生成了 “Ich will ein”。結(jié)果沒問題,開了個好頭。
在實(shí)踐中,我們會使用更復(fù)雜的解碼方法來采樣 lm_logits
。你可以參考 這篇博文 了解更多的解碼方法。
至此,《基于 Transformers 的編碼器-解碼器模型》的四個部分就全部分享完啦,歡迎大家閱讀其他分享 ??!
英文原文: 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)練推理。文章來源:http://www.zghlxwxcb.cn/news/detail-473785.html
審校/排版: zhongdongy (阿東)文章來源地址http://www.zghlxwxcb.cn/news/detail-473785.html
到了這里,關(guān)于解碼器 | 基于 Transformers 的編碼器-解碼器模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!