GPT
GPT全称为Generative Pre-trained Transformer,它运用了Transformer中的Decoder架构,并经过大规模的无监督预练习来提高模型的表现力。在预练习阶段,GPT经过处理很多的无标示文本数据,学习到了言语的统计规则和上下文信息。在实践应用时,GPT能够经过微调(fine-tuning)的方式,依据具体使命的需求,对预练习的模型进行细小的调整,从而习惯不同的文本生成、问答等使命。GPT在自然言语生成和处理使命上表现出色,在多个公开数据集上都取得了很好的成绩。如果对于Transformer架构不是很熟悉,[能够参阅我的这篇文章](Transformer导论之Transformer – ())。
无监督的预练习
GPT的无监督预练习便是让模型自己学习言语的规则和上下文信息,而无需人为标示数据。在预练习阶段,GPT运用了很多的无标示文本数据进行练习,例如维基百科、互联网新闻等大规模语料库。GPT将这些文本数据输入到模型中,经过不断地学习言语中的统计规则和上下文信息,提高模型的表现力。
在这个阶段中,GPT最早期运用的是一种基于自回归模型的言语模型,它经过最大化给定输入序列的下一个单词呈现的概率来预练习模型。
自回归模型的方针是最大化模型对无标示文本数据的似然性,即最大化模型在给定无标示文本数据下的对数似然函数。咱们期望练习出来的模型能够在当时输入文本序列的基础上,猜测下一个单词呈现的概率。而猜测概率的一个重要方针便是似然性,即当时模型猜测的结果与实践观测值之间的类似程度。
假定咱们有一个无标示文本数据集D=x1,x2,…,xND = {x_1, x_2, …, x_N},其间每个xix_i是一个长度为TiT_i的文本序列,而模型的参数为\theta。假定咱们的模型能够将xix_i中的每个单词表明为wi,1,wi,2,…,wi,Ti{w_{i,1}, w_{i,2}, …, w_{i,T_i}},那么模型对于xix_i的对数似然函数能够表明为:
logp(xi∣)=∑t=1Tilogp(wi,t∣wi,<t,)\log p(x_i|\theta)=\sum_{t=1}^{T_i}\log p(w_{i,t}|w_{i,<t},\theta)
其间,p(wi,t∣wi,<t,)p(w_{i,t}|w_{i, <t},\theta)表明给定上文wi,<tw_{i, <t}的情况下,模型对于wi,tw_{i,t}的条件概率散布。这种基于自回归的方法使得GPT 只需求一个 decoder,它就能够依据前面已经生成的单词来猜测下一个单词,生成整个言语模型。这一点和Bert便是不同的,Bert选用的是encoder架构。
在GPT2,GPT3中在预练习阶段还引入了掩码言语模型(MLM,Masked Language Model,和Bert中的相同)
MLM的方针是在输入序列中随机隐瞒一些单词,并让模型猜测这些被隐瞒的单词。
掩码言语模型(Masked Language Model,MLM)的似然函数表明为:
LMLM=∏i=1NP(wi∣w<i,w>i)L_{MLM}=\prod_{i=1}^{N}P(w_{i}|w_{<i},w_{>i})
其间,wiw_{i}表明第ii个位置的被遮盖的单词,通常在文本顶用一个特殊符号“[MASK]”符号,w<iw_{<i}表明第ii个位置之前的单词序列,w>iw_{>i}表明第ii个位置之后的单词序列,NN表明文本序列的长度。这些都是经过多层级联的Transformer的decoder完结的。经过梯度下降的练习方法,能够使得似然函数最大。
有监督的微调
GPT中的Supervised fine-tuning是指在完结了无监督的预练习后,运用有标示数据对模型进行有监督的微调,以习惯特定的下流使命。
假定咱们有一个已经预练习好的GPT模型,它的参数为\theta。现在,咱们想将这个模型应用于一个下流使命,例如文本分类使命。在文本分类使命中,咱们有一个由NN个样本组成的练习集,其间第ii个样本的输入为xix_i,对应的标签为yiy_i。
在进行Supervised fine-tuning时,咱们需求对GPT模型进行微调,以习惯特定的下流使命。咱们能够将GPT模型的输出层进行修改,例如增加一个全衔接层,并将其衔接到GPT模型的最终一个躲藏层。咱们能够将这个修改后的模型表明为GPTft(⋅;ft)GPT_{\text{ft}}(\cdot;\theta_{\text{ft}}),其间ft\theta_{\text{ft}}是微调后的参数。
对于文本分类使命,咱们能够界说一个丢失函数LclsL_{\text{cls}},cls代表输入的初步,丢失函数用于衡量模型在分类使命上的性能。常见的丢失函数包含穿插熵丢失和均方差错丢失等。咱们的方针是最小化丢失函数LclsL_{\text{cls}},以习惯特定的下流使命。咱们能够经过以下进程来完结Supervised fine-tuning:
- 将预练习好的GPT模型的输出层进行修改,得到修改后的模型GPTft(⋅;ft)GPT_{\text{ft}}(\cdot;\theta_{\text{ft}})。
- 在练习集上对修改后的模型进行练习,这儿和预练习的文本调集不同,Fine-Tuning运用的是带有标签的数据集,如情感分类、文本生成、问答等使命的标示数据集,而预练习的调集是无标签的。最小化丢失函数LclsL_{\text{cls}}。能够运用随机梯度下降等优化算法进行练习。
- 微调完结后,运用测验集对模型进行评价,并计算模型在下流使命上的性能方针,例如准确率、F1值等。
Supervised fine-tuning的数学表明能够如下表明:
minft1N∑i=1NLcls(GPTft(xi;ft),yi)\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{}
其间,Lcls(⋅,⋅)L_{\text{cls}}(\cdot, \cdot)表明分类使命的丢失函数,xix_i表明第ii个样本的输入,yiy_i表明第ii个样本的标签。咱们的方针是找到微调后的参数ft\theta_{\text{ft}},使得模型在练习集上的丢失函数最小。
在 Improving Language Understanding by Generative Pre-Training 这篇论文中,作者提出了一种自习惯的学习率战略,用于在 GPT 中进行练习。练习的进程中只用到了1212层的decoder网络。
GPT的pytorch完结
首要,需求导入需求用到的库和模块:
import torch
import torch.nn as nn
from torch.nn import functional as F
接下来,界说GPT模型的首要组成部分——Transformer Decoder。这儿咱们参阅GPT-2,运用12个Transformer Decoder来构建整个模型。在每个Transformer Decoder中,都包含一个多头自注意力机制(multi-head self-attention),一个前馈神经网络(feedforward neural network)和一个残差衔接(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串联起来,构成整个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
最终,咱们能够界说练习进程,包含丢失函数、优化器等:
model = 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