Trasnformer導(dǎo)論之——GPT

GPT

GPT全稱為Generative Pre-trained Transformer,它使用了Transformer中的Decoder架構(gòu),并通過大規(guī)模的無監(jiān)督預(yù)訓(xùn)練來提高模型的表現(xiàn)力。在預(yù)訓(xùn)練階段,GPT通過處理大量的無標(biāo)注文本數(shù)據(jù),學(xué)習(xí)到了語言的統(tǒng)計(jì)規(guī)律和上下文信息。在實(shí)際應(yīng)用時(shí),GPT可以通過微調(diào)(fine-tuning)的方式,根據(jù)具體任務(wù)的需求,對(duì)預(yù)訓(xùn)練的模型進(jìn)行微小的調(diào)整,從而適應(yīng)不同的文本生成、問答等任務(wù)。GPT在自然語言生成和處理任務(wù)上表現(xiàn)出色,在多個(gè)公開數(shù)據(jù)集上都取得了很好的成績(jī)。

無監(jiān)督的預(yù)訓(xùn)練

GPT的無監(jiān)督預(yù)訓(xùn)練就是讓模型自己學(xué)習(xí)語言的規(guī)律和上下文信息,而無需人為標(biāo)注數(shù)據(jù)。在預(yù)訓(xùn)練階段,GPT使用了大量的無標(biāo)注文本數(shù)據(jù)進(jìn)行訓(xùn)練,例如維基百科、互聯(lián)網(wǎng)新聞等大規(guī)模語料庫。GPT將這些文本數(shù)據(jù)輸入到模型中,通過不斷地學(xué)習(xí)語言中的統(tǒng)計(jì)規(guī)律和上下文信息,提高模型的表現(xiàn)力。

在這個(gè)階段中,GPT最早期使用的是一種基于自回歸模型的語言模型,它通過最大化給定輸入序列的下一個(gè)單詞出現(xiàn)的概率來預(yù)訓(xùn)練模型。

自回歸模型的目標(biāo)是最大化模型對(duì)無標(biāo)注文本數(shù)據(jù)的似然性,即最大化模型在給定無標(biāo)注文本數(shù)據(jù)下的對(duì)數(shù)似然函數(shù)。我們希望訓(xùn)練出來的模型可以在當(dāng)前輸入文本序列的基礎(chǔ)上,預(yù)測(cè)下一個(gè)單詞出現(xiàn)的概率。而預(yù)測(cè)概率的一個(gè)重要指標(biāo)就是似然性,即當(dāng)前模型預(yù)測(cè)的結(jié)果與實(shí)際觀測(cè)值之間的相似程度。假設(shè)我們有一個(gè)無標(biāo)注文本數(shù)據(jù)集D = {x_1, x_2, ..., x_N},其中每個(gè)x_i是一個(gè)長(zhǎng)度為T_i的文本序列,而模型的參數(shù)為\theta。假設(shè)我們的模型能夠?qū)_i中的每個(gè)單詞表示為{w_{i,1}, w_{i,2}, ..., w_{i,T_i}},那么模型對(duì)于x_i的對(duì)數(shù)似然函數(shù)可以表示為:

\log p(x_i|\theta)=\sum_{t=1}^{T_i}\log p(w_{i,t}|w_{i,<t},\theta)

其中,p(w_{i,t}|w_{i, <t},\theta)表示給定上文w_{i, <t}的情況下,模型對(duì)于w_{i,t}的條件概率分布。

在GPT2,GPT3中在預(yù)訓(xùn)練階段還引入了掩碼語言模型(MLM,Masked Language Model,和Bert中的一樣)

MLM的目標(biāo)是在輸入序列中隨機(jī)遮蓋一些單詞,并讓模型預(yù)測(cè)這些被遮蓋的單詞。

掩碼語言模型(Masked Language Model,MLM)的似然函數(shù)表示為:

L_{MLM}=\prod_{i=1}^{N}P(w_{i}|w_{<i},w_{>i})

其中,w_{i}表示第i個(gè)位置的被遮蔽的單詞,通常在文本中用一個(gè)特殊符號(hào)“[MASK]”標(biāo)記,w_{<i}表示第i個(gè)位置之前的單詞序列,w_{>i}表示第i個(gè)位置之后的單詞序列,N表示文本序列的長(zhǎng)度。這些都是通過多層級(jí)聯(lián)的Transformer的decoder實(shí)現(xiàn)的。通過梯度下降的訓(xùn)練方法,可以使得似然函數(shù)最大。
language_understanding_paper_2.jpg

有監(jiān)督的微調(diào)

GPT中的Supervised fine-tuning是指在完成了無監(jiān)督的預(yù)訓(xùn)練后,使用有標(biāo)注數(shù)據(jù)對(duì)模型進(jìn)行有監(jiān)督的微調(diào),以適應(yīng)特定的下游任務(wù)。

language_understanding_paper_21.jpg

假設(shè)我們有一個(gè)已經(jīng)預(yù)訓(xùn)練好的GPT模型,它的參數(shù)為\theta?,F(xiàn)在,我們想將這個(gè)模型應(yīng)用于一個(gè)下游任務(wù),例如文本分類任務(wù)。在文本分類任務(wù)中,我們有一個(gè)由N個(gè)樣本組成的訓(xùn)練集,其中第i個(gè)樣本的輸入為x_i,對(duì)應(yīng)的標(biāo)簽為y_i。

在進(jìn)行Supervised fine-tuning時(shí),我們需要對(duì)GPT模型進(jìn)行微調(diào),以適應(yīng)特定的下游任務(wù)。我們可以將GPT模型的輸出層進(jìn)行修改,例如添加一個(gè)全連接層,并將其連接到GPT模型的最后一個(gè)隱藏層。我們可以將這個(gè)修改后的模型表示為GPT_{\text{ft}}(\cdot;\theta_{\text{ft}}),其中\(zhòng)theta_{\text{ft}}是微調(diào)后的參數(shù)。

對(duì)于文本分類任務(wù),我們可以定義一個(gè)損失函數(shù)L_{\text{cls}},cls代表輸入的開端,損失函數(shù)用于衡量模型在分類任務(wù)上的性能。常見的損失函數(shù)包括交叉熵?fù)p失和均方誤差損失等。我們的目標(biāo)是最小化損失函數(shù)L_{\text{cls}},以適應(yīng)特定的下游任務(wù)。我們可以通過以下步驟來實(shí)現(xiàn)Supervised fine-tuning:

  1. 將預(yù)訓(xùn)練好的GPT模型的輸出層進(jìn)行修改,得到修改后的模型GPT_{\text{ft}}(\cdot;\theta_{\text{ft}})。

  2. 在訓(xùn)練集上對(duì)修改后的模型進(jìn)行訓(xùn)練,這里和預(yù)訓(xùn)練的文本集合不同,F(xiàn)ine-Tuning使用的是帶有標(biāo)簽的數(shù)據(jù)集,如情感分類、文本生成、問答等任務(wù)的標(biāo)注數(shù)據(jù)集,而預(yù)訓(xùn)練的集合是無標(biāo)簽的。最小化損失函數(shù)L_{\text{cls}}??梢允褂秒S機(jī)梯度下降等優(yōu)化算法進(jìn)行訓(xùn)練。

  3. 微調(diào)完成后,使用測(cè)試集對(duì)模型進(jìn)行評(píng)估,并計(jì)算模型在下游任務(wù)上的性能指標(biāo),例如準(zhǔn)確率、F1值等。

Supervised fine-tuning的數(shù)學(xué)表示可以如下表示:

\min_{\theta_{\mathrm{ft}}}\frac{1}{N}\sum_{i=1}^N L_{\mathrm{cls}}(GPT_{\mathrm{ft}}(x_i;\theta_{\mathrm{ft}}),y_i)\quad\quad\text{}

其中,L_{\text{cls}}(\cdot, \cdot)表示分類任務(wù)的損失函數(shù),x_i表示第i個(gè)樣本的輸入,y_i表示第i個(gè)樣本的標(biāo)簽。我們的目標(biāo)是找到微調(diào)后的參數(shù)\theta_{\text{ft}},使得模型在訓(xùn)練集上的損失函數(shù)最小。

在 Improving Language Understanding by Generative Pre-Training 這篇論文中,作者提出了一種自適應(yīng)的學(xué)習(xí)率策略,用于在 GPT 中進(jìn)行訓(xùn)練。訓(xùn)練的過程中只用到了12層的decoder網(wǎng)絡(luò)。

GPT的pytorch實(shí)現(xiàn)

首先,需要導(dǎo)入需要用到的庫和模塊:

<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="python" cid="n33" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">import torch
import torch.nn as nn
from torch.nn import functional as F
</pre>

接下來,定義GPT模型的主要組成部分——Transformer Decoder。這里我們參考GPT-2,使用12個(gè)Transformer Decoder來構(gòu)建整個(gè)模型。在每個(gè)Transformer Decoder中,都包含一個(gè)多頭自注意力機(jī)制(multi-head self-attention),一個(gè)前饋神經(jīng)網(wǎng)絡(luò)(feedforward neural network)和一個(gè)殘差連接(residual connection):

class TransformerDecoder(nn.Module):
 def __init__(self, hidden_dim, num_heads, ff_dim, dropout):
 super().__init__()

 self.multihead_attn = nn.MultiheadAttention(hidden_dim, num_heads)
 self.dropout1 = nn.Dropout(dropout)
 self.layer_norm1 = nn.LayerNorm(hidden_dim)

 self.ff = nn.Sequential(
 nn.Linear(hidden_dim, ff_dim),
 nn.ReLU(),
 nn.Dropout(dropout),
 nn.Linear(ff_dim, hidden_dim),
 )
 self.dropout2 = nn.Dropout(dropout)
 self.layer_norm2 = nn.LayerNorm(hidden_dim)

 def forward(self, x, mask):
 # Multi-head self-attention
 attn_out, _ = self.multihead_attn(x, x, x, attn_mask=mask)
 attn_out = self.dropout1(attn_out)
 x = self.layer_norm1(x + attn_out)

 # Feedforward neural network
 ff_out = self.ff(x)
 ff_out = self.dropout2(ff_out)
 x = self.layer_norm2(x + ff_out)

 return x

接下來,我們將這些Transformer Decoder串聯(lián)起來,形成整個(gè)GPT模型:

class GPT(nn.Module):
 def __init__(self, num_tokens, hidden_dim, num_heads, num_layers, seq_len, dropout):
 super().__init__()

 self.token_emb = nn.Embedding(num_tokens, hidden_dim)
 self.pos_emb = nn.Parameter(torch.zeros(1, seq_len, hidden_dim))
 self.dropout = nn.Dropout(dropout)

 self.decoders = nn.ModuleList([
 TransformerDecoder(hidden_dim, num_heads, hidden_dim * 4, dropout)
 for _ in range(num_layers)
 ])

 self.output_layer = nn.Linear(hidden_dim, num_tokens)
 self.softmax = nn.Softmax(dim=-1)

 def forward(self, x):
 # Token embeddings
 x = self.token_emb(x)

 # Add position embeddings
 x += self.pos_emb[:, :x.shape[1]]

 # Transformer Decoder layers
 mask = torch.triu(torch.ones(x.shape[1], x.shape[1]), diagonal=1).bool().to(x.device)
 for decoder in self.decoders:
 x = decoder(x, mask)

 # Output layer
 x = self.output_layer(x)
 x = self.softmax(x)

 return x

最后,我們可以定義訓(xùn)練過程,包括損失函數(shù)、優(yōu)化器等:

 GPT(num_tokens, hidden_dim, num_heads, num_layers, seq_len, dropout)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

for epoch in range(num_epochs):
 for inputs, labels in dat
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容