【AI理論学習】言語モデル:BERTモデルとGPTモデルをマスターする


ELMo モデルは、コンテキストに応じて単語の特徴表現を更新し、静的な単語ベクトルから動的な単語ベクトルへの変換を実現します。ただし、ELMo は双方向言語モデルのアーキテクチャに依存しているため、そのトレーニングは小規模なコーパスにのみ適用でき、計算効率は高くありません。これらの問題を解決するために、Transformer フレームワークに基づく BERT モデルと GPT モデルが提案されました。

BERTモデル

BERTの基本原理

BERT の正式名は、Transformers の Bidirectional Encoder Representation で、事前トレーニングされた言語表現モデルです。これは、従来の一方向言語モデルや、事前トレーニング用に 2 つの一方向言語モデルを浅く結合する方法ではなく、新しいマスク言語モデル (MLM)であるため、深い双方向言語表現を生成できることを強調しています。 BERTの論文が発表されたとき、11のNLP(自然言語処理、自然言語処理)タスクで新たな最先端の結果が得られたと記載され、度肝を抜かれました。

このモデルには次の主な利点があります。
1) MLM を使用して双方向トランスフォーマーを事前トレーニングし、深い双方向言語表現を生成します
2) 事前トレーニング後は、出力レイヤーを追加して微調整するだけで、さまざまなダウンストリーム タスクで最先端のパフォーマンスを実現できますこのプロセスでは、タスク固有の BERT の構造変更は必要ありません。

BERT の全体的なアーキテクチャ

BERT は事前トレーニングに MLM を使用し、深い双方向の Transformer コンポーネントを使用します (一方向の Transformer は一般に と呼ばれ、Transformer decoderその各トークン (シンボル) は現在左側に移動しているトークンにのみ参加します。 Transformer が呼び出される方法ではTransformer encoder、その各トークンがすべてのトークンに対応してモデル全体を構築し、最終的に左右のコンテキスト情報を融合できる深い双方向言語表現を生成します全体的なアーキテクチャを以下に示します。
バート
図 1. 事前トレーニングされたモデルのアーキテクチャの違い。Trm は、Transformer の Encoder モジュールを指します。BERT は双方向トランスを使用します。OpenAI GPT は、左から右に Transformers を使用します。ELMo は、独立してトレーニングされた左から右および右から左の LSTM の連結を使用して、下流タスクの特徴を生成します。3 つのうち、BERT 表現のみがすべてのレイヤーの左と右の両方のコンテキストに条件付けされますアーキテクチャの違いに加えて、BERT と OpenAI GPT は微調整方式であるのに対し、ELMo は機能ベースの方式です

TransformerBlock コードは次のとおりです。

class TransformerBlock(nn.Module):
	def __init__(self, k, heads):
		super().__init__()
		self.attention = SelfAttention(k, heads = heads)
		self.norm1 = nn.LayerNorm(k)
		self.norm2 = nn.LayerNorm(k)

		self.mlp = nn.Sequential(
			nn.Linear(k, 4*k)
			nn.ReLU()
			nn.Linear(4*k, k)
		)
	def forward(self, x):
		attended = self.attention(x)
		x = self.norm1(attended + x)
		feedforward = self.mlp(x)
		return self.norm2(feedforward + x)

BERT には単純なモデルと複雑なモデルの 2 つのモデルが用意されており、対応するハイパーパラメータは次のとおりです。

  • BERT BASE \text{BERT}_{BASE}バートベース_ _: L=12、H=768、A=12、パラメータの合計量は 110MB です。
  • バート ラージ \text{バート}_{ラージ}バート_ _: L=24、H=1024、A=16、パラメータの合計量は 340MB です。

BERT は、大規模なコーパスに基づいて自己教師あり学習を実行します (いわゆる自己教師あり学習とは、手動でラベル付けされていないデータセットに対して実行される教師あり学習を指します)。下流の NLP タスクでは、BERT の特徴表現を下流タスクの単語埋め込み特徴として直接使用できます。したがって、BERT は、下流タスクの移行学習用のモデルを提供し、下流タスクに応じて微調整または修正した後、特徴抽出器として使用できます。

BERTへの入力

BERT の入力エンコード ベクトル (d_model=512) は、3 つの埋め込み特徴の単位合計ですこれを次の図に示します。
入力表現
図 2. BERT 入力の表現。入力エンベディングは、トークン エンベディング、セグメンテーション エンベディング、位置エンベディングの合計です。図のピンクのブロックはトークン、黄色のブロックはトークンの対応する表現であり、単語辞書は WordPiece アルゴリズムを使用して構築されています。特定の分類タスクを完了するために、単語のトークンに加えて、作成者各入力シーケンスの先頭に特定の分類トークン ([CLS]) を挿入し、それに対応する最後の Transformer 層の出力も挿入します。分類トークンが使用され、シーケンス表現情報全体を集約する役割を果たします。

BERT は事前トレーニングされたモデルであるため、さまざまな自然言語タスクに適応する必要があります。そのため、モデルの入力シーケンスには 1 つの文 (テキスト感情分類、シーケンスのラベル付けタスク) または 2 つ以上の文 (テキスト) を含めることができる必要があります。要約、自然言語推論、質問応答タスク)。どの範囲が文 A に属し、どの範囲が文 B に属するかを区別できるモデルを作成するにはどうすればよいでしょうか? BERT はこれを解決するために 2 つの方法を使用します。 1)
シーケンス トークン内の各文にセグメンテーション トークン ([SEP]) を挿入して、異なる文トークンを分離します。
2) 各トークン表現に学習可能なセグメンテーション埋め込みを追加して、それが文 A に属するか文 B に属するかを示します。

したがって、最終モデルの入力系列トークンは次のようになります(入力系列が 1 文のみの場合、[SEP] 以降のトークンは存在しません): 前述したように、BERT の入力は各トークンに対応する表現になります
モデルの入力シーケンス
。実際、表現は 3 つの部分、つまり対応するトークン、セグメンテーション、および位置の埋め込みで構成されます。

  1. Token Embeddings
    英語コーパスは通常、単語部分埋め込み (WordPiece Embedding) を採用しています。つまり、単語は限られた共通のサブワード単位のセットに分割され、単語の有効性と文字の柔軟性のバランスを取ることができます。たとえば、「playing」を「play」と「ing」に分割します。中国語コーパスの場合は単語レベルに設定します。
  2. 位置埋め込み
    位置埋め込みとは、単語の位置情報を特徴ベクトルにエンコードすることを指します。これは、単語の位置関係をモデルに導入する際の重要な部分です。ここでの位置の埋め込みは、前回の記事のTransformerの位置の埋め込みとは異なり、三角関数ではなく学習させたものになります。
  3. セグメント埋め込みは
    、B が A の文脈 (会話シーン、質疑応答シーンなど) であるかどうかなど、2 つの文を区別するために使用されます。文ペアの場合、最初の文の特徴値は 0、2 番目の文の特徴値は 1 になります。

BERT の出力

Transformer の特性は、次の図に示すように、入力の数だけ対応する出力があることです
BERT の出力
。 C は分类token、最後の Transformer の出力、T i T_iに対応する ([CLS]) です。T私はこれは、他のトークンが最後の Transformer の出力に対応することを意味します。一部のトークンレベルのタスク (シーケンスのラベル付けや質問応答タスクなど) の場合は、T i T_iと入力します。T私は予測のために追加の出力層に入力します。一部の文レベルのタスク (自然言語推論や感情分類タスクなど) では、C が追加の出力層に入力されます。これにより、特定の分類トークンが各トークン シーケンスの前に挿入される理由が説明されます。

BERT の事前トレーニング

実際、事前トレーニングの概念は CV (Computer Vision、コンピュータ ビジョン) ではすでに非常に成熟しており、広く使用されています。CV で使用される事前トレーニング タスクは通常、ImageNet 画像分類タスクです。画像分類タスクを完了するための前提条件は、優れた画像特徴を抽出できることです。同時に、ImageNet データ セットには大規模で、かつ大規模であるという利点があります。高品質なので、多くの場合、良好な画像特徴を得ることが可能です。

NLP 分野には ImageNet のような人間がラベル付けした高品質のデータはありませんが、大規模なテキスト データの自己教師ありの性質を利用して、事前トレーニング タスクを構築できますしたがって、BERT は 2 つの事前トレーニング タスク、つまりマスクされた言語モデル次の文の予測を構築しました。

マスクされた言語モデル

マスクされた言語モデル (Masked Language Model、MLM) は真の双方向メソッドであるため、BERT は一方向言語モデルによって制限されません前の記事で説明した ELMo モデルは、左から右と右から左を別々にトレーニングするだけです。2 つのモデルの違いは、目的関数から明確にわかります。

  • ELMo以P ( tk ∣ t 1 , . . , tk − 1 ) , P ( tk ∣ tk + 1 ) , . . . . . . . . , tn P(t_k|t_1,...,t_{k-1}), P(t_k|t_{k+1}),...,t_nP ( t∣t _1... tk 1P ( t∣t _k + 1... t目的関数として独立してトレーニングし、最後に結果をつなぎ合わせます。
  • BERT とP ( tk ∣ t 1 , . . . , tk − 1 ) , tk + 1 , . . , tn P(t_k|t_1,...,t_{k-1}),t_{k+1},...,t_nP ( t∣t _1... tk 1tk + 1... tこのようにして学習された単語ベクトルは目的関数として、左右の単語の情報に同時に注目することができます。

簡単に言うと、各トレーニング シーケンス内のトークンを 15% の確率でランダムにマスク トークン ([MASK]) に置き換え、[MASK] の位置にある元の単語を予測しますただし、下流タスクの微調整ステージには [MASK] が表示されないため、事前トレーニング ステージと微調整ステージの間に不一致が生じます (ここでよく説明されています。つまり、事前トレーニング ターゲットは生成された言語表現は [MASK] には敏感ですが、他のトークンには敏感ではありません)。したがって、BERT はこの問題を解決するための小さなトリックを採用しています。つまり、マスクする単語を決定した後、80% が [MASK] に直接置換され、10% が他の単語に置換され、10% がマスクされた単語を保持します。元の識別子。具体的な戦略は以下のとおりです。

まず、特定のトークン位置が各トレーニング シーケンスで 15% の確率で予測用にランダムに選択されます。i 番目のトークンが選択された場合、次の 3 つのトークンのいずれかに置き換えられます。

  1. 80%の確率で[MASK]です。たとえば、私の犬は毛深いです——>私の犬は[マスク]です
  2. 10% の確率で、それはランダムな他のトークンです。たとえば、私の犬は毛深いです—>私の犬はリンゴです
  3. 10% の確率で、それは元のトークンです (変更されないまま、つまり、ポイント 2 に対応するネガティブ クラスとして維持されます)。たとえば、私の犬は毛深いです——>私の犬は毛深いです

次に、位置に対応するT i T_iを使用します。T私は元のトークンを予測するには (完全な接続に入力し、次にソフトマックスを使用して各トークンの確率を出力し、最後にクロス エントロピーを使用して損失を計算します)。

MLM トレーニング プロセス全体を以下の図に示します。
BERT の MLM トレーニング プロセス
図 3 BERT の MLM トレーニング プロセス

次の文を予測する

質問応答や自然言語推論などの一部のタスクでは 2 つの文間の関係を理解する必要がありますが、MLM タスクではトークン レベルの表現を抽出する傾向があるため、文レベルの表現を直接取得することはできません。モデルが文間の関係を理解できるようにするために、BERT は事前トレーニングに次文予測 (NSP) タスクを使用します。これは、単に 2 つの文が互いに接続されているかどうかを予測することを意味します

具体的な方法は次のとおりです。トレーニング例ごとに、コーパス内の文 A と文 B を選択して形成します。50% の確率で文 B が文 A の次の文 (IsNext としてマーク) となり、残りの 50% が文 A の次の文になります。 time 文 B は、コーパスからのランダムな文 (NotNext というラベルが付けられている) です。次に、トレーニング サンプルを BERT モデルに入力し、[CLS] に対応する C 情報を使用して 2 つの分類を予測します。

具体的なトレーニング プロセスを次の図に示します。
BERT の NSP 事前トレーニング プロセス
図 4 BERT の NSP 事前トレーニング プロセス

最終的なトレーニングの例は次のようになります。

Input1=[CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
Label1=IsNext

Input2=[CLS] the man [MASK] to the store [SEP] penguin [MASK] are flight ##less birds [SEP]
Label2=NotNext

各トレーニング サンプルを BERT に入力して 2 つのタスクの対応する損失を取得し、これら 2 つの損失を加算して全体のトレーニング前損失を形成します (つまり、2 つのタスクが同時にトレーニングされます)。

これら 2 つのタスクに必要なデータは、実際にはラベルのないテキスト データ (自己教師ありの性質) から構築できることが明確にわかります。

BERT トレーニング プロセスには MLM と NSP が含まれており、損失関数の具体的な定義については、Hugging Face 公式 Web サイトの対応するコードを参照してください。https://huggingface.co/docs/transformers/main/en/model_doc/bert

BERTの微調整

Transformer のセルフアテンション メカニズムにより、BERT は適切な入力と出力を交換することで、多くの下流タスク (単一のテキストまたはテキストのペアに関係する) をモデル化できるため、微調整が簡単です。テキスト ペアを含むアプリケーションの一般的なパターンは、双方向クロス アテンションを適用する前にテキスト ペアを個別にエンコードすることです。
代わりに、BERT はセルフ アテンション メカニズムを使用して 2 つのステージを統合します。セルフ アテンションは連結されたテキスト ペアをエンコードするために使用され、2 つの文間の双方向のクロス アテンションが効果的に含まれるためです。

BERT の下流分類タスクを完了する場合、BERT に基づいて出力層を追加するだけで、特定のタスクの微調整が完了します分類問題の場合、最初の識別子 (トークン) の最終出力 (つまり、最終隠れ状態、最終隠れ状態) を直接取得できますC ∈ RHC\in R^HCRH、ウェイトの層を追加しますWWWの後、Softmax を使用してラベルの確率を予測します。P = ソフトマックス ( CWT ) P= ソフトマックス(CW^T)P=ソフトマックス( CW ) _ _ _ _

他のダウンストリーム タスクについては、以下の図に示すように、いくつかの調整が必要です。
BERT 事前トレーニング モデルを微調整して、対応する下流タスクを完了します。
図 5 は、対応するダウンストリーム タスクを完了するために BERT 事前トレーニング モデルを微調整しています。Tok は異なるトークンを意味し、E は埋め込みベクトルを意味し、T i T_iT私はiiを示しますiトークンが BERT によって処理された後に得られる特徴ベクトル

以下は、いくつかの下流タスクと微調整が必​​要なコンテンツの簡単な紹介です。
1) 文ペアベースの分類タスク。たとえば、MNLL は前提が与えられると、その前提に従って仮説と前提の関係を推測し、MRPC は 2 つの文が同等であるかどうかを判断します。
2) 単一の文に基づいてタスクを分類します。SST-2、映画評価の感情分析、CoLA、文章意味判断、許容範囲など。
3) 質問に答えるタスク。たとえば、SQuAD v1.1: 文 (通常は質問) と説明テキストが与えられると、読解の短答問題と同様に、この質問に対する回答が出力されます。
4) 固有表現の認識。CoNLL-2023 NER など: 文内の単語が人 (person)、組織 (Organization)、場所 (Location)、またはその他の実体であるかどうかを判断します。

BERT の特徴抽出

これまでに提示されたすべての BERT 結果では、事前トレーニングされたモデルに単純な分類層が追加され、下流のタスクですべてのパラメーターが共同で微調整される微調整アプローチが使用されています。ただし、事前トレーニングされたモデルから固定特徴を抽出する特徴ベースの方法には、特定の利点がありますまず、すべてのタスクを Transformer-encoder アーキテクチャで簡単に表現できるわけではないため、タスク固有のモデル アーキテクチャを追加する必要があります。第 2 に、トレーニング データの高価な表現を 1 回事前計算し、その後、この表現に基づいて安価なモデルを使用して多くの実験を実行することには、計算上の大きな利点があります。
BERTによる特徴抽出
したがって、事前トレーニングされた BERT モデルを使用してコンテキストに応じた単語の埋め込みを作成し、それらの単語を既存のモデルに埋め込みます。例は次のとおりです。上の図から、入力文内の各単語の文脈上の埋め込みがBERT ベース BERT_{base}
特徴抽出法を用いたBERTの模式図
によって行われていることがわかります。BERT _ベース_生成されたモデル。BERT ベース BERT_{base}以降BERT _ベース_モデルは 12 の Transformer エンコーダーで構成されているため、各エンコーダー層は各単語のコンテキスト埋め込みを生成し、それが上位の Transformer エンコーダーに渡されます。したがって、12 個の Transformer エンコーダーによって生成される、文脈に応じた単語の埋め込みの 12 個の選択肢があります。

どのベクトルがコンテキスト埋め込みとして最適に機能しますか? 個人的にはタスクによると思います。このペーパーでは、6 つのオプションを検討します (96.4 のスコアを達成した微調整モデルと比較)。
BERT のさまざまな層の出力が下流タスクに及ぼす影響

PyTorch を使用した BERT の実装

BERT を試す最良の方法は、 Google Colab でホストされているCloud TPU ノートブックを使用して BERT を微調整することです。BERT コードは TPU、CPU、GPU でも動作するため、これまでに Cloud TPU を使用したことがない場合にも、ここから始めるのに適しています。

BERT 公式コード ウェアハウス: https://github.com/google-research/bert、PyTorch に基づいて Hugging face によって実装された BERT バージョン: https://github.com/huggingface/transformers も参照できます。AllenNLP ライブラリは、この実装を使用して、任意のモデルで BERT 埋め込みを使用できるようにします。

ここで使用されている PyTorch バージョン コードは から取得されていますhttps://github.com/codertimo/BERT-pytorchPyTorchを使用してBERTを実装するコアモジュールは主に2つあり、1つはBERT入力を生成するBERT Embeddingクラス、もう1つはTransformerBlockクラスであり、これら2つのモジュールを組み合わせたものがBERTモデルのモジュールbert.pyです。これらのモジュール間の関係は次のとおりです:
BERTモデルのモジュールクラス図
まず、BERT-pytorch のメイン ファイル (main) を解釈します:__main__.py
主なパラメータ
ここでtrain_dataset、 と は、test_dataset選択したタスクのトレーニング データとテスト データを指し、一般にcorpus(コーパス) と呼ばれます。 GLUE データ 集中型 MRPC タスクのトレーニング セットとテスト セット。vocab_path考えられるvocabularyすべての単語を記録した大きな辞書に相当するライブラリ(語彙ライブラリ)のことで、後でコーパス内の単語を変換する際には、idこの大きな辞書で調べる必要があります。

次にロードするのは vocab のコードです:
語彙をロードする
このコードは、後続の処理のために単語リストを txt 形式から対応する Python オブジェクトに変換します。具体的なプロセスは次のとおりです: 次に、
loca_vocab
データ オブジェクトをロードします。ここではトレーニング データ セットのみを確認します。
列車データセットの読み込み
次に、BERTDataset にジャンプします (この種のローダーは、__getitem__ メソッドを呼び出すことによって実装されます)。
時限式
データ処理コードのこの部分では、コーパスの各行が 2 つの文で構成され、'\t' で区切られるようにデフォルト設定されています。
get_corpus_line
その処理手順は次のとおりです。
(1) 一行の 2 つの文を取り出し、通常 50% の確率で 2 つの文を返します。ラベルは 1 を返します (2 つの文がつながっていることを意味します。そうでない場合はランダムに別の文をまとめて選択します)。 (
ランダム送信
2) これら 2 つの文の各単語を推測し、その単語を [MASK] に変更します。他の文の元の単語のID単語 (id は、大きな辞書にあるこの単語のシリアル番号を指します。コンピューターは単語を読み取るときに番号を読み取ろうとするためです)。
ランダムな単語
(3) 2 つの文のトークンに先頭の CLS と末尾の SEP を追加し、その 2 つの対応するラベルも 0 になります。
(4) セグメント ID と補完用のパディング ID

上記は、それぞれ NSP タスクと MLM タスクのデータ処理、CLS と SEP、対応するセグメント ID の追加などのいくつかの操作を含む、データの前処理部分です。次に、全体的なフレームワークの構築を正式に開始します。バート。
バートモデルを構築する
BERT を構築するためのコア コードは次のとおりです。

import torch.nn as nn

from .transformer import TransformerBlock
from .embedding import BERTEmbedding


class BERT(nn.Module):
    """
    BERT model : Bidirectional Encoder Representations from Transformers.
    """

    def __init__(self, vocab_size, hidden=768, n_layers=12, attn_heads=12, dropout=0.1):
        super().__init__()
        self.hidden = hidden  # 最后一层的维度 hidden size
        self.n_layers = n_layers  # Transformer的block数目,即层数
        self.attn_heads = attn_heads  # 多头注意力机制的注意力头数目 = hidden size / 每个头的维度
        # 在bert中,hidden size = 768 时,头数为12,每个头维度是64

        # paper noted they used 4*hidden_size for ff_network_hidden_size
        self.feed_forward_hidden = hidden * 4
        # transformer的每个block为多头-残差块-feedforward-残差块 这里是feedforward的维度
        
        # embedding for BERT, sum of positional, segment, token embeddings
        self.embedding = BERTEmbedding(vocab_size=vocab_size, embed_size=hidden)

        # multi-layers transformer blocks, deep network
        self.transformer_blocks = nn.ModuleList(
            [TransformerBlock(hidden, attn_heads, hidden * 4, dropout) for _ in range(n_layers)])

    def forward(self, x, segment_info):
        # attention masking for padded token
        # torch.ByteTensor([batch_size, 1, seq_len, seq_len)
        mask = (x > 0).unsqueeze(1).repeat(1, x.size(1), 1).unsqueeze(1)

        # embedding the indexed sequence to sequence of vectors
        x = self.embedding(x, segment_info)

        # running over multiple transformer blocks
        for transformer in self.transformer_blocks:
            x = transformer.forward(x, mask)

        return x

1 つ目は BERT モデルの初期化です。BERT が Transformer のエンコーダ部分であることがわかっているため、初期化部分は主に Transformer 構造 (Transformer ブロックとヘッドの数、隠しサイズのサイズを含む) を構築することです。 、レイヤーの数、上記の注記)。

次に、forward 関数から、最初にマスクを構築し、パディングされていないデータ内の場所を見つけ、値 1 を割り当てて対応する次元に拡張し、次に BERTEmbedding を使用して単語をエンコードし、最後にTransformer ブロックを 1 つずつ経由して出力します。以下は BERTEmbeding クラスと TransformerBlock クラスのコードです。

import torch.nn as nn
from .token import TokenEmbedding
from .position import PositionalEmbedding
from .segment import SegmentEmbedding


class BERTEmbedding(nn.Module):
    """
    BERT Embedding which is consisted with under features
        1. TokenEmbedding : normal embedding matrix 正则嵌入矩阵
        2. PositionalEmbedding : adding positional information using sin, cos
        2. SegmentEmbedding : adding sentence segment info, (sent_A:1, sent_B:2)

        sum of all these features are output of BERTEmbedding
    """

    def __init__(self, vocab_size, embed_size, dropout=0.1):
        """
        :param vocab_size: total vocab size  总词汇量的大小
        :param embed_size: embedding size of token embedding  标记嵌入的嵌入大小
        :param dropout: dropout rate
        """
        super().__init__()
        self.token = TokenEmbedding(vocab_size=vocab_size, embed_size=embed_size)
        self.position = PositionalEmbedding(d_model=self.token.embedding_dim)
        self.segment = SegmentEmbedding(embed_size=self.token.embedding_dim)
        self.dropout = nn.Dropout(p=dropout)
        self.embed_size = embed_size

    def forward(self, sequence, segment_label):
        x = self.token(sequence) + self.position(sequence) + self.segment(segment_label)
        return self.dropout(x)
import torch.nn as nn

from .attention import MultiHeadedAttention
from .utils import SublayerConnection, PositionwiseFeedForward


class TransformerBlock(nn.Module):
    """
    Bidirectional Encoder = Transformer (self-attention)
    Transformer = MultiHead_Attention + Feed_Forward with sublayer connection
    """

    def __init__(self, hidden, attn_heads, feed_forward_hidden, dropout):
        """
        :param hidden: hidden size of transformer
        :param attn_heads: head sizes of multi-head attention
        :param feed_forward_hidden: feed_forward_hidden, usually 4*hidden_size
        :param dropout: dropout rate
        """

        super().__init__()
        self.attention = MultiHeadedAttention(h=attn_heads, d_model=hidden)
        # attention会返回QKV计算后的结果,QKV都是可学习的Linear层
        self.feed_forward = PositionwiseFeedForward(d_model=hidden, d_ff=feed_forward_hidden, dropout=dropout)
        # Position这个好像就是两个Linear中间加一个激活层
        self.input_sublayer = SublayerConnection(size=hidden, dropout=dropout)
        self.output_sublayer = SublayerConnection(size=hidden, dropout=dropout)
        # Multi-head+残差块,配上FeedForward+残差块,共同组成了一个Transformer
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, x, mask):
        x = self.input_sublayer(x, lambda _x: self.attention.forward(_x, _x, _x, mask=mask))
        x = self.output_sublayer(x, self.feed_forward)
        return self.dropout(x)

最後に、これは PyTorch トレーニング ネットワークの通常のプロセスであり、データと対応するラベルを入力し、損失と逆伝播を計算します。
トレーニングプロセス

GPTモデル

2018 年 6 月、OpenAI は独自の言語モデル GPT を紹介する論文を発表しました。GPT は「Generative Pre-Training」の略です。Transformerアーキテクチャに基づいています。教師ありデータセットで特定のタスクを微調整する方法は数多くあります最初に一般的なモデルをトレーニングし、次にそれをタスクごとに調整するこの種の、個々のタスクに依存しないモデル設計手法により、複数のタスクで同時に優れたパフォーマンスを達成できます。

Transformer の Encoder 部分を使用する BERT 事前トレーニング モデルとは異なり、GPT シリーズは Transformer の Decoder 部分を使用します。GPT モデルは従来の言語モデルを使用してトレーニングされるため、つまり上記の単語を使用して単語を予測するため、GPT は自然言語生成タスク (NLG) の処理に優れ、BERT は自然言語理解タスク (NLU) の処理に優れています。

GPT モデルの全体的なアーキテクチャ

GPT フレームワークは、言語理解タスクを完了するために半教師あり学習手法を使用しており、トレーニング プロセスは、教師なしの事前トレーニング教師ありの微調整の2 つの段階に分かれています。事前トレーニング段階では、一方向の Transformer を使用して言語モデルを学習し、文に対して教師なし Embedding を実行し、微調整段階では、特定のタスクに応じて Transformer のパラメーターを微調整します。わずかな変更を加えることで、さまざまな種類のタスクに適応できる一般的な表現方法を学習します全体的なアーキテクチャを次の図に示します。
gpt1.0
ここで、Trm はデコーダ モジュールを表し、同じ水平線上の Trm は同じユニット、E i E_iを表します。E私は単語の埋め込みを表し、それらの複雑な接続は単語と単語の間の依存関係を表します。明らかに、GPT によって予測される単語は上記のみに依存します。

GPT-2 には、図に示すように、そのサイズに応じておよそ 4 つのバージョンがあります。
GPT-2 の 4 つのバージョン

GPTのモデル構造

GPT は Transformer の Decoder 構造を使用し、Transformer Decoder にいくつかの変更を加えます。元の Decoder には 2 つの Multi-Head Attender 構造が含まれており、GPT は Mask Multi-Head Attender のみを保持します以下に示すように:
GPTのモデル構造

GPT-2のマルチヘッドとBERTのマルチヘッドの違い

重要なのは、自己注意 (BERT で使用) とマスクされた自己注意 (GPT-2 で使用) の区別が明確であることです。通常のセルフ アテンション モジュールでは、位置がその右側の部分に集中することができますが、マスクされたセルフ アテンションはこれが起こらないようにします。つまり、BERT は単語の左側と右側に同時に注意を払うことができますが、GPT-2 は単語の右側にしか注意を払うことができません。
BERTとGPT-2のマルチヘッドの違い

デコーダ専用モジュール

オリジナルの Transformer 論文が出版された後、Generating Wikipedia by Summarizing Long Sequences では、言語モデリングが可能な Transformer モジュールの別のレイアウトが提案されました。このモデルは、Transformer の Encoder を破棄しますしたがって、このモデルを と呼ぶことができますTransformer-Decoderこの初期の Transformer ベースの言語モデルは、6 つの Decoder モジュールで構成されています。
トランスデコーダ
これらの Decoder モジュールは同じです。上の図では最初の Decoder が展開されているため、Self-Attender レイヤーがマスクされていることがわかります。このモデルは最大 4000 トークンを処理できるようになりました。これは、元の論文の 512 トークンから大幅にアップグレードされました。

これらのモジュールは、2 番目のセルフ アテンション レイヤーが削除されていることを除いて、元の Decoder モジュールと非常に似ています。同様の構造が、より深い自己注意を伴う文字レベルの言語モデリングで使用され、一度に 1 文字ずつ言語モデルを作成します。

OpenAI の GPT-2 は、これらの Decoder モジュールを使用します

GPT-2 モデルを理解する

まず、トレーニングされた GPT-2 がどのように機能するかを見てみましょう。
GPT-2 は 1024 個のトークンを処理できます
GPT-2 は 1024 個のトークンを処理できます。各トークンは、独自のパスに沿ってすべての Decoder モジュールを通過します。

トレーニングされた GPT-2 モデルを実行する最も簡単な方法は、テキスト自体を生成させることです (これを技術的には無条件サンプルの生成と呼びます)。あるいは、トピックについて話すように促すプロンプトを与えることもできます (つまり、対話型の条件付きサンプルを生成します)。とりとめのないケースでは、単純に初期トークンを与えて単語の生成を開始させることができます (訓練されたモデルは<|endoftext|>初期トークンとして使用します。これを と呼びます<s>)。
インタラクティブな条件付きサンプルの生成
モデルには入力トークンが 1 つだけあるため、アクティブなパスも 1 つだけあります。トークンはすべてのレイヤーで順次処理され、そのパスに沿ってベクトルが生成されますこのベクトルを使用して、モデルの語彙に基づいてスコアを計算できます(モデルはすべての単語を知っています。これは GPT-2 では 5000 単語です)。この例では、最も高い確率で を選択しました。ただし、状況を混同することもあります。キーボード アプリで候補の単語を選択し続けると、繰り返しループに陥ることがあり、2 番目または 3 番目の候補の単語をタップするしか方法がありません。ここでも同じことが起こります。GPT -2 には top-k パラメーターがあり、このパラメーターを使用してモデルに最初の単語 (top-k=1) 以外の単語を考慮させることができます

次に、最初のステップの出力を入力シーケンスに追加し、モデルに次の予測を行わせます。
GPT-2 の 2 番目の予測
この計算では 2 番目のパスが唯一のアクティブなパスであることに注意してください。GPT-2 の各層は、最初のトークンの独自の解釈を保持し、2 番目のトークンを処理するときにそれを使用します。GPT-2 は、2 番目のトークンに基づいて最初のトークンを再計算しません

GPT-2の詳細を深く理解する

GPT-2への入力

これまでに説明した他の NLP モデルと同様に、GPT-2 は埋め込み行列内の入力単語の埋め込みを検索します。これは、トレーニングされたモデルから取得するコンポーネントの 1 つです。
トークンの埋め込み
各行は単語を埋め込んでいます。これは、単語を表し、何らかの意味を捉えることができる数値のリストです。このリストのサイズは、GPT-2 モデルによって異なります。最小モデルで使用される埋め込みサイズは 768 です

したがって、最初に、埋め込み行列の最初のトークンの埋め込みを検索します<s>この埋め込みをモデルの最初のモジュールに渡す前に、シーケンス内の単語の順序を示すことができる位置エンコーディングを組み込む必要があります。トレーニングされたモデルの一部は行列であり、これには 1024 個の位置のそれぞれに対する位置エンコード ベクトルが含まれます。
位置エンコーディングここでは、入力単語が最初の Transformer モジュールに渡される前にどのように処理されるかについて説明します。また、トレーニングされた GPT-2 には 2 つの重み行列が含まれていることもわかっています: 1 つはすべての単語または識別子を記録する埋め込み行列 (Token Embedding) で、行列の形状は model_vocabulary_size × Embedding_size であり、もう 1 つは位置コードを表す位置コードですコンテキスト マトリックス (位置エンコーディング) 内の単語、マトリックスの形状は context_size × Embedding_size です。ここで、Embedding_size は GPT-2 モデルのサイズによって決まります。Small モデルは 768、Medium モデルは 1024、およびすぐ。

GPT-2 モデルを入力する前に、以下の図に示すように、対応する位置コードをロゴの埋め込みに追加する必要があります。Transformer
GPT-2の入力データ
の最初のモジュールに単語を入力するということは、単語の埋め込みを検索し、最初のモジュールを追加することを意味します。位置 位置エンコーディング ベクトル。各マークの位置コードは各レイヤのデコーダ内で不変であり、位置コードは学習ベクトルではない。

層を上に流れていく

最初のモジュールは、最初にセルフアテンション層を介して、次にニューラル ネットワーク層を介してトークンを処理できるようになりました。Transformer の最初のモジュールがトークンを処理すると、結果ベクトルが取得され、処理のためにスタック内の次のモジュールに送信されます。各モジュールの処理は同じですが、各モジュールには独自のセルフアテンション層とニューラル ネットワーク層があります。
スタックを上る旅


自己注意を見直す

言語は文脈に大きく依存します。たとえば、以下の第 2 法則を見てください。

ロボット工学の第 2 法則
ロボットは、人間が与えた命令に従わなければなりません。ただし、その命令が第 1 法則と矛盾する場合を除きます。

他の単語を参照するために単語が使用されている文内の 3 つの部分を強調表示します。これらの単語は、それが参照する文脈がなければ理解したり処理したりすることはできません。モデルがこの文を処理するとき、次のことを知ることができなければなりません。

  • それはロボットのことを指します
  • 命令とは、この法律の前の部分、つまり人によって与えられた命令を指します。
  • 第一法則とはロボット工学の第一法則を指します。

Self-Attention が行うことは、単語を処理する前に、単語の関連単語と関連単語に関するモデルの理解を組み合わせて (そしてそれをニューラル ネットワークに入力して) 行うことです。これは、文セグメント内の各単語の関連性をスコアリングし、これらの単語の重み付けされた表現ベクトルを合計することによって機能します。たとえば、下図の最上位モジュールの Self-Attendance レイヤーは、ロボットという単語を処理するときにロボットに注意を払います。ニューラル ネットワークに渡されるベクトルは、3 つの単語の乗算と加算、およびそれぞれのスコアの合計です。
自己注目層の例


自己注意のプロセス

Self-Attention は文内の各トークンのパスに沿って処理され、主なコンポーネントには 3 つのベクトルが含まれます。

  • Query : Query ベクトルは現在の単語の表現であり、他のすべての単語をスコアリングするために使用されます (それらの単語のキー ベクトルを使用)。現在処理されているトークンのクエリ ベクトルのみに焦点を当てます。
  • Key : Key ベクトルは、文内のすべての単語のラベルのようなものです。これらは、私たちが単語を検索するときに探しているものです。
  • : 値ベクトルは実際の単語表現です。各単語の関連性をスコア付けしたら、現在の単語を表すためにこれらのベクトルの重み付き合計を実行する必要があります。

ファイルキャビネットの中を探している
大まかに例えると、ファイリング キャビネット内を検索することと考えることができます。クエリ ベクトルは研究しているトピックを記載した付箋であり、キー ベクトルはキャビネット内のフォルダーのラベルのようなものです。メモとタグを照合すると、一致するフォルダーの内容 (値ベクトル) が取得されます。ただし、1 つの値ベクトルを探しているだけではなく、一連のフォルダー内の一連の値ベクトルを探していることになります

値ベクトルと各フォルダーのキー ベクトルを乗算すると、各フォルダーのスコアが得られます (技術的には、ソフトマックスが後に続く単なるドット積)。
クエリ ベクトルと各キー ベクトルを乗算すると、各フォルダーのスコアが生成されます。
各値ベクトルに対応するスコアを乗算し、合計してセルフ アテンションの出力を取得します。
セルフアテンション出力
これらの重み付けされた値ベクトルにより、単語 robot に 50%、単語 a に 30%、単語 it に 19% の注意が集中するベクトルが生成されます。以下では、セルフ アテンションについてさらに詳しく説明しますが、ここではまず、モデルの出力までモデルを進めていきます。

GPT-2の出力

モデルの最上部にあるモジュールが出力ベクトルを生成すると (このベクトルはセルフ アテンション層とニューラル ネットワーク層を通じて取得されます)、モデルはこのベクトルに埋め込み行列を乗算します
モデルはそのベクトルに埋め込み行列を乗算します。
埋め込み行列の各行がモデルの語彙内の単語に対応していることを思い出してください。この乗算の結果は、モデルの語彙内の各単語のスコアとして解釈されます
出力トークンの確率
最も高いスコアを持つトークンを選択できます (top_k=1)。しかし、モデルが他の単語も考慮できれば、より良い結果が得られる可能性があります。したがって、より良い戦略は、スコアを単語の確率として使用し、リスト全体から単語を選択することです(スコアの高い単語が選択される可能性が高くなります)。妥協案は、top_k を 40 に設定し、モデルに上位 40 個の単語を考慮させることです。
その単語が選択される確率としてのスコア
なお、図中のDecoder #12とPosition #1は、それぞれ第12層Decoderの位置と最初の識別子の位置を表している。

このようにして、モデルは反復を完了し、単語を出力します。モデルは、すべてのコンテキストが生成されるまで (1024 個のトークン)、または文の終わりを表すトークンが出力されるまで反復を続けます。

GPT と GPT-2 の類似点と相違点


GPT と GPT-2 はアーキテクチャに大きな変更はありませんが、規模やデータ量が若干異なり、以下の点で共通点と相違点が現れています。Transformer の Decoder を使用します。
2) 違いは次のとおりです。
- GPT-2 の方が規模が大きく、階層が多い
- GPT-2 の方がデータ量が多く、データの種類が多いため、モデルの汎用性が向上し、モデルの品質が向上します。データのフィルタリングと制御
- GPT は、さまざまなダウンストリーム タスクに教師あり学習を使用し、入力形式を変更し、完全に接続された層を追加します。GPT-2 は、さまざまなダウンストリーム タスクのパラメーターやモデルを変更することなく、ダウンストリーム タスクに教師なし学習方法を使用します (いわゆるゼロショット設定)。以下の図に示すように:
ダウンストリームタスクの GPT の違い
図 (左) Transformer のアーキテクチャとトレーニングの目標、図 (右) さまざまなタスクを微調整するための入力変換。

では、GPT は下流のタスクをどのように変換するのでしょうか? 微調整する場合、さまざまなダウンストリーム タスクに合わせて、主に GPT の入力形式を変更し、まずデータを通じてさまざまなタスクを結合し、Transformer モデルに代入してから、モデルの出力データの後に全結合層 (Linear) を追加して適応させます。ラベル付きデータのフォーマットの詳細は以下の通りです:
1) 分類問題の場合、変更が少ない場合は開始記号と終了記号を追加するだけで済みます;
2) 含意などの文の関係性判断問題の場合は、単に追加する必要があります。 2 つの文の間に区切り文字を追加します;
3) テキストの類似性の判断の問題では、2 つの文の順序を逆にして 2 つの入力を作成します。これは、文の順序が重要ではないことをモデルに伝えるためです。オプションは連結できます
。入力として。

GPT と ELMo の類似点と相違点

  1. モデル アーキテクチャは異なります。ELMo は浅い双方向 RNN、GPT は多層の Transformer エンコーダです。
  2. 下流のタスクは別の方法で処理されます。ELMo は追加機能として特定のタスクに単語埋め込みを追加しますが、GPT はすべてのタスクに対して同じ基本モデルを微調整します。

GPT と BERT の類似点と相違点

  1. 事前トレーニング: GPT 事前トレーニング メソッドは従来の言語モデルと同じで、上記のテキストを通じて次の単語を予測します。GPT 事前トレーニング メソッドは、コンテキストとコンテキストの両方を通じて単語を予測できるマスク LM を使用します。 。たとえば、文u 1 、u 2 、...、u_1、u_2、...、u_n があるとします。あなた1あなた2... あなた、GPT はui u_iという単語を予測しています。あなた私は的时候只会利用 u 1 , u 2 , . . . , u i − 1 u_1,u_2,...,u_{i-1} あなた1あなた2... あなたi 1的信息。而BERT会同时利用 u 1 , u 2 , . . . , u i − 1 , u i + 1 , . . . , u n u_1,u_2,...,u_{i-1},u_{i+1},...,u_n あなた1あなた2... あなたi 1あなた+ 1... あなた情報。
  2. モデル効果: GPT は従来の言語モデルを使用するため、自然言語生成タスク (NLG) により適しています。これらのタスクは通常、現在の情報に基づいて次の瞬間に情報を生成するからです。また、BERT は自然言語理解タスク (NLU) により適しています。
  3. モデル構造: モデル構造: GPT は Transformer の Decoder を使用し、BERT は Transformer の Encoder を使用します。GPTは、u 1 、u 2 、...、ui − 1 u_1,u_2,...,u_{i-1} を使用して、Decoder でマスク マルチヘッド アテンション構造を使用します。あなた1あなた2... あなたi 1単語ui u_iを予測しますあなた私はいつ、ういう_いあなた私はマスクオフという言葉の後に。

参考文献

  1. BERT: 言語理解のための深い双方向トランスフォーマーの事前トレーニング
  2. ハグ顔バート
  3. バートとは何ですか?
  4. https://ekbanaml.github.io/nlp/BERT/
  5. 図解された BERT、ELMo など (NLP が転移学習をどのように解読したか)
  6. BERT アーキテクチャを理解する
  7. グラフィカル BERT モデル: BERT をゼロから構築する
  8. BERT コードの行ごとの詳細バージョン
  9. 図解 GPT-2

おすすめ

転載: blog.csdn.net/ARPOSPF/article/details/132653539