GPT1 の先駆的な研究: 生成的な事前トレーニングによる言語理解の向上
この論文では、最初にラベルのないデータを使用してモデルをトレーニングし、モデル学習が各タスクの一般的な表現に適応できるようにする gpt1 を提案します。次に、タスク認識データのごく一部を使用してモデルを微調整します。各タスク機能でさらに強力になります。
デザインフレームワーク
これは、トランスフォーマー モデルのデコーダー部分を使用して、事前トレーニングと微調整の 2 つの部分に分かれています。
第 1 段階: 教師なしの事前トレーニング
k 個の連続する単語の次の単語の確率を予測する本質は最尤推定です。そのため、モデルの次の出力単語の最大確率の出力は実際のサンプルの次の単語の ui u_i になります。あなた私は。次の要素は調べられず、最初の k 要素だけが調べられます。これは、トランスフォーマーのデコーダと非常によく似ています。
第 2 段階: 監視付き微調整
下流タスクをトレーニングするためのデータ セットは、次の形式のデータを持ちます: 各文に m 個の単語があると仮定すると、入力シーケンス{ x 1 , x 2 , . . . , xm } \{x^1,x^2 ,.. .,x^m\}{
×1、バツ2、... 、バツm }とラベルyyy (下流タスクの決定)。
この段階で、作成者は 2 つの最適化関数を定義します。L1 は文の一貫性を保証し、L2 は下流のタスクの精度を保証します。
下流のタスク
さまざまな下流タスクに対してさまざまなトレーニング プログラムが開発されており、その完全な内部フレームワーク構造は次のとおりです。
再現コード
非常に単純な再現:
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
import copy
import torch.nn.functional as F
# accepts input in [ batch x channels x shape ] format
class Attention(nn.Module):
def __init__(self, in_channels, heads, dropout=None):
assert in_channels % heads == 0
super().__init__()
self.in_channels = in_channels
self.heads = heads
self.dropout = dropout
def forward(self, queries, keys, values, mask=None):
attention = torch.bmm(queries, keys.permute(0,2,1)) / self.in_channels**0.5
if mask is not None:
attention = attention.masked_fill(mask, -1e9)
attention = F.softmax(attention, dim=-1)
if self.dropout is not None:
attention = F.dropout(attention, self.dropout)
output = torch.bmm(attention, values)
return output
# adds positional encodings
class PositionalEncoding(nn.Module):
def forward(self, input_):
_, channels, length = input_.shape
numerator = torch.arange(length, dtype=torch.float)
denominator = 1e-4 ** (2 * torch.arange(channels, dtype=torch.float) / channels)
positional_encodings = torch.sin(torch.ger(denominator, numerator))
return input_ + positional_encodings
class EncoderLayer(nn.Module):
def __init__(self, in_channels, heads, dropout=None):
super().__init__()
self.in_channels = in_channels
self.heads = heads
self.produce_qkv = nn.Linear(in_channels, 3*in_channels)
self.attention = Attention(in_channels, heads, dropout)
self.linear = nn.Linear(in_channels, in_channels)
def forward(self, inputs):
qkv = self.produce_qkv(inputs)
queries, keys, values = qkv.split(self.in_channels, -1)
attention = self.attention(queries, keys, values)
outputs = F.layer_norm(attention + inputs, (self.in_channels,))
outputs = F.layer_norm(self.linear(outputs) + outputs, (self.in_channels,))
return outputs
class DecoderLayer(nn.Module):
def __init__(self, in_channels, heads, dropout=None):
super().__init__()
self.in_channels = in_channels
self.heads = heads
self.produce_qkv = nn.Linear(in_channels, 3*in_channels)
self.produce_kv = nn.Linear(in_channels, 2*in_channels)
self.masked_attention = Attention(in_channels, heads, dropout)
self.attention = Attention(in_channels, heads, dropout)
self.linear = nn.Linear(in_channels, in_channels)
def forward(self, inputs, outputs):
qkv = self.produce_qkv(outputs)
queries, keys, values = qkv.split(self.in_channels, -1)
n = inputs.shape[1]
mask = torch.tril(torch.ones((n, n), dtype=torch.uint8))
attention = self.masked_attention(queries, keys, values, mask)
outputs = F.layer_norm(attention + outputs, (self.in_channels,))
kv = self.produce_kv(inputs)
keys, values = kv.split(self.in_channels, -1)
attention = self.attention(outputs, keys, values)
outputs = F.layer_norm(attention + outputs, (self.in_channels,))
outputs = F.layer_norm(self.linear(outputs) + outputs, (self.in_channels,))
return outputs
if __name__ == '__main__':
print("Running...")
test_in = torch.rand([3,4,5])
encoder = EncoderLayer(5, 1)
test_out = encoder(test_in) # torch.Size([3, 4, 5])
assert test_out.shape == (3, 4, 5)
print("encoder passed")
decoder = DecoderLayer(5, 1) # 这就是gpt模型
test_mask = torch.tril(torch.ones((4, 4), dtype=torch.uint8))
test_out = decoder(test_in, test_in)
assert test_out.shape == (3, 4, 5) # torch.Size([3, 4, 5])
print("decoder passed")
GPT2:言語モデルは教師なしマルチタスク学習者である
gpt1 の作業を継続して、この論文では、元の gpt よりも大きな構造を使用し、ゼロショット タスク転送を実現できる gpt2 を提案します。つまり、下流のタスクを指定されたデータ セットで微調整する必要がありません。
どのようにプロンプトを出しますか?
gpt1 では、下流のタスクを微調整するときにセパレーターなどの記号が導入されますが、ゼロショット シナリオでは導入できないため、このパターンをモデルにどのように学習させるかが新たな問題となっています。では、この記事ではどのように解決するのでしょうか? モデルに自然言語のプロンプトを通じて指定されたコマンドを実行させます。
トレーニングデータ
前任者が使用したデータセットとは異なり、この論文ではインターネット クローラーの大規模なデータセットを使用します。