GPT2 モデルの構造とそのトレーニング プロセスの詳細な理解 - GPT シリーズのトレーニングと展開

        この記事はブロガーのオリジナル記事ですので、ブロガーの許可なく転載することはできません。

        この記事はコラム「Python AIGC 大規模モデルのトレーニングとゼロからの推論」のシリーズ記事で、アドレスは「https://blog.csdn.net/suiyingy/article/details/130169592」です。

        GPT2 モデル環境のセットアップとデバッグについては、ブログ投稿「GPT シリーズのトレーニングとデプロイメント - GPT2 環境の構成とモデル トレーニング」および「ColossalAI GPT2 分散トレーニングとデバッグ構成 - GPT シリーズのトレーニングとデプロイメント」を参照してください。アドレスは次のとおりです。 「https://blog.csdn.net/suiyingy/article/details/128711444」および「https://blog.csdn.net/suiyingy/article/details/128806531」。このセクションでは、主に GPT2 モデルの構造原理とそのトレーニングとデバッグのプロセスを詳しく紹介します。

        なお、このコラムの具体的な更新情報については、記事下の公式アカウントをフォローしていただくか、本コラムをフォローしていただくことが可能です。関連記事はすべて「ゼロから始める Python AIGC 大規模モデルのトレーニングと推論」で更新されます。アドレスは「https://blog.csdn.net/suiyingy/article/details/130169592」です。AIGC に似たすべてのモデル展開のエクスペリエンス効果は、RdFast アプレットで同期的に起動されます。

1 変圧器の主構造

        Transformer モデルは、2017 年に Google 研究者によって提案され、論文「Attending is All you need」で発表された NLP 用のニューラル ネットワーク モデルです。モデルの中核はセルフ アテンション メカニズム (セルフ アテンション) です。これにより、長いシーケンスを処理する際の RNN の勾配消失問題を回避でき、シーケンス内の要素間の関係をより適切に捉えることもできます。Transformer モデルは、自然言語処理の分野で目覚ましい成果を上げ、この分野の重要な基盤となった革新的なニューラル ネットワーク アーキテクチャです。

        Transformer モデルの全体的な構造は次の図に示されています。これは典型的なエンコード / デコード構造に属しており、左側がエンコード構造、右側がデコード構造です。

図1 変圧器モデルの構造

1.1 セルフアテンションのメカニズム(セルフアテンション)

        自己注意メカニズムは、特徴抽出を実行するときにモデルが自身のデータ間の相関関係に注意を払うことを意味します。注意とは、データの重みに注目することを意味します。A、B、C、D で構成されるシーケンスのセットがあると仮定すると、A、B、C、D の影響を受ける A のサイズは、注目のサイズ、つまり A、B、C に相当します。 、および D は、A がサイズの程度を特徴とする場合に注目されます。

        Transformer は、このアテンション値を測定するために QKV (Query、Key、Value) エンコード モデルを提案しています。Q、K、V は、新しい空間での元のデータの表現と同等です。入力シーケンスの特徴次元が (N_seq, C_embedding)、N_seq が入力シーケンスの長さ、C_embedding がシーケンス内の各要素の特徴次元であると仮定します。全結合層 Linear(C_embedding, C_qkv) の後、出力は特徴の次元は (N_seq, C_qkv) です。Transformer は、このような全結合演算の 3 セットを使用して、元のシーケンスを Q、K、V に変換します。次元は (N_seq、C_qkv) です。

 図2 QKVプロセスの模式図

        これは、Q、K、V 空間を使用して元のデータを表すものとして理解できます。Q は、元のシーケンス内の要素の位置と比較できる、元のデータのクエリ インデックスを定義することに相当します。(K, V) はデータの値を表します。この Key-Value メソッドを使用してデータを表す利点は、アテンション サイズの計算時に値が影響を受けないこと、つまり、値がアテンション サイズから切り離されることです。

        注意の大きさはQとKの相関関係で表され、相関が大きいほど注意の重みが大きくなります。下図に示すように、相関関係は行列乗算(ベクトル乗算)、つまり Q × KT で計算され、乗算後の出力次元は (N_seq, N_seq) となります。各行は、現在の要素とすべての完全な要素の相関関係を表します。出力データの分布特性を維持するには、乗算されたデータを sqrt(dk) で除算する必要があります。dk は上記の C_qkv です。明らかに、sqrt(dk) で除算してもアテンションの相対的なサイズは変わりませんが、全体的な大きさが調整されます。

 図3 アテンションの計算

        注意の重みの合計が 1 であり、各重みの値が割合に等しいことを望みます。次に、出力乗算データは Softmax を通過して、この重み変換を完了する必要があります。入力シーケンスの長さが 3 (x1, x2, x3) であると仮定すると、Softmax 後の出力は exp(x1)/(exp(x1)+exp(x2)+exp(x3))、exp(x2)/( exp(x1)+exp(x2)+exp(x3)) および exp(x1)/(exp(x3)+exp(x2)+exp(x3))。

図 4 ソフトマックス

        注目の重みに V を乗算する、つまり加重和を出力した結果が得られ、その次元は (N, C_qkv) となります。これにより、入力データの次元が (N_seq, C_embedding) から (N, C_qkv) に変換されます。これは、新しいシーケンスを使用して元のシーケンスを表すのと同等であり、新しいシーケンスでは要素間の相関が考慮されます。

1.2 自己注意メカニズムと畳み込みニューラル ネットワーク (CNN)

        一般に、畳み込みニューラル ネットワークが特徴抽出のために全結合されると、V が得られることになります。ネットワーク モデルのトレーニングが完了すると、全結合層のすべてのパラメーターが固定されます。すべての入力は、同じ完全に接続されたパラメータを使用して変換されます。注意メカニズムは、QK を通じて V に重み付けを行うことです。QK によって取得されるアテンションの重みは、入力条件が異なると異なります。これは、入力が異なる場合の全結合層のパラメーターの変化に相当します。したがって、セルフアテンションメカニズムを使用した後は、入力特徴抽出方法がより多様になり、より豊富で効果的な特徴を抽出できるようになります。もちろんパラメータの数もそれに応じて増加します。

        コンピューター ビジョンの分野では、研究者は PAConv や Deformable Conv など、入力の影響を受ける多くの畳み込み演算も設計しました。

1.3 マルチヘッドアテンション

        マルチヘッド アテンション メカニズムは、セルフ アテンション メカニズムを複数回使用して元の特徴を抽出し、スプライシングと融合を実行することと同等です。上記のセルフ アテンション プロセスを畳み込みプロセスと比較することもでき、マルチヘッド アテンション メカニズムは出力チャネルの数を変更することに相当します。単一のセルフ アテンション メカニズム モジュールの出力次元を (N, C_qkv)、アテンション メカニズム モジュールの数を MA (つまり、ヘッド、マルチヘッドの数) とすると、出力次元は MA x となります。 N×C_qkv。スプライシング後の出力フィーチャの次元は N x (MA x C_qkv) であり、これはフィーチャの融合に相当します。畳み込みニューラル ネットワークでは、結合された特徴に対して、通常、畳み込みまたは完全接続の層がさらに使用され、結合された特徴を全体として融合します。Transformer もこの構造、フィードフォワード ネットワークを使用します。さらに、Transformer は入力特徴を融合するために残差構造を何度も使用します。

        アテンション特徴量と入力特徴量の一貫性を保つために、MA x C_qkv は C_embedding と一貫性がある必要があります。C_embedding が 512、C_qkv が 64 であると仮定すると、ロング ポジション MA の数は 8 になるはずです。C_embedding が 768、C_qkv が 64 であると仮定すると、ロング ポジションの数 MA は 12 になるはずです。

1.4 多層積層

        注目モジュールの出力次元が入力次元と一致する場合、モジュールを複数の層にスタックできます。つまり、前のモジュールの出力 (N_seq、C_embedding) が次のモジュール (N_seq) の入力として使用されます。 、C_embedding)、以下に紹介する GPT2 モデル構造と同様です。GPT2 構造の共通層は次のとおりです。

表 1 GPT2 レイヤーとパラメーター

パラメータ層番号ベクトル長

117M 12 768

345M 24 1024

762M 36 1280

1542M 48 1600

2 GPT2モデルの構造

        GPT シリーズ モデルはトランスフォーマーのエンコード構造のみを使用し、多層スタッキング方式で実装されます。以下の図は、12 層 GPT2 構造の模式図です。各層はアテンションメカニズムモジュールです。

図 5 12 層 GPT2

3 GPT2トレーニング手順

        次に紹介する GPT2 プログラムは Colossal-AI フレームワークからのもので、アドレスは「https://github.com/hpcaitech/ColossalAI-Examples/tree/main/ language/gpt」です。環境構築やデバッグ方法については、本コラムの過去記事で詳しく解説しています。

3.1 入力データと単語の分割

3.1.1 入力データ

        テストで使用するデータは OpenWebText で、ダウンロードと前処理のプロセスについては、「GPT シリーズのトレーニングとデプロイメント - GPT2 環境の構成とモデルのトレーニング」を参照してください (アドレスは「https://blog.csdn.net/suiyingy/article/」)詳細/128711444 」。処理後の元データは train.json に保存され、そのデータ構造は以下に示すように {'text': text, 'url': unique_url} になります。

{"text": "The space station looks like an airplane or a very bright star moving across the sky, except it doesn't have flashing lights or change direction. It will also be moving considerably faster than a typical airplane (airplanes generally fly at about 600 miles per hour; the space station flies at 17,500 miles per hour).\n\nBelow is a time-lapse photo of the space station moving across the sky.\n\nThe International Space Station is seen in this 30 second exposure as it flies over Elkton, VA early in the morning, Saturday, August 1, 2015. Photo Credit: NASA/Bill Ingalls\n\nVisit the NASA Johnson Flickr Photostream", "url": "http://spotthestation.nasa.gov/sightings/view.cfm?country=United_States®ion=Arizona&city=Phoenix#.UvPTWWSwLpM"}

        モデルの入力データはテキスト内のテキストであり、テキストで許可される最大単語分割長は 1024、つまり GPT2 モデルで入力される系列長 N_seq は 1024 に設定されます。

3.1.2 単語の分割

        自然言語処理における単語の分割とは、テキストを単語に分割するプロセスを指します。単語の分割は、自然言語処理の分野における重要な基本タスクであり、その主な目的は、連続した自然言語テキストを特定の意味論的な意味を持つ語彙シーケンスに分割して、さらに意味論的な分析を行うことです。

        中国語などの言語では、英語のように単語がスペースで区切られておらず、単語の分割によって識別および抽出する必要があります。単語のセグメンテーションは、機械翻訳、情報検索、感情分析などの分野にとって非常に重要です。単一の文字や文字では完全な意味を表現することはできず、それらを適切な単語に組み合わせることによってのみ、自然言語テキストをよりよく理解して処理できるからです。

        単語の分割操作中に、すべての単語とそのシリアル番号を記録する辞書が作成されます。たとえば、ここでの辞書は、合計 50257 語を含む GPT2Tokenizer です。このうち、「<|endoftext|>」は最後の単語であり、unk トークンです。最後の単語のインデックス番号は 50256 です。「tokenizer = GPT2Tokenizer.from_pretrained('gpt2')」は辞書全体を読み込みます。単語に基づいてシリアル番号をクエリするための辞書は tokenizer.encoder (tokenizer.encoder['bot'] など) であり、シリアル番号に基づいて単語をクエリするための辞書は tokenizer.decoder (tokenizer.decoder[13645] など) です。この辞書には中国語が含まれていないことに注意してください。したがって、異なる自然言語処理タスクで使用される単語分割辞書も異なる場合があります。

        単語の分割は、最終的にはテキストの一部を対応する一連のインデックス番号、つまりプログラム内の input_id に変換することです。入力シーケンスの最大長 N_seq は 1024 に設定されているため、テキスト分割後のシーケンスの実際の長さが 1024 より大きい場合、最初の 1024 個の分割は保持され、残りの分割は削除されます。テキスト分割後のシーケンスの実際の長さが 1024 未満の場合は、1024 分割まで埋める必要があります。プログラムでは <|endoftext|> で埋めているので、input_ids の長さが 1024 未満の場合は 50256 で埋められます。

        プログラム内の単語分割出力のもう 1 つの部分は、attention_mask です。これは主に、有効な単語分割を識別するために使用されます。有効な単語の分割に属する位置は値 1 をとり、埋められて完了した位置は値 0 をとります。

        GPT2 単語分割プロセスの主要なプログラムを以下に示します。プログラムは ColossalAI-Examples/labguage/gpt/dataset/webtext.py にあります。ユーザーは、プログラムのデバッグのためにファイルの関連する位置にブレークポイントを設定できます。

tokenizer = GPT2Tokenizer.from_pretrained('gpt2')#50257个词
tokenizer.pad_token = tokenizer.unk_token#'<|endoftext|>'
encoded_data = tokenizer(raw_data, padding=True, truncation=True, max_length=seq_len, return_tensors='pt')
self.data = encoded_data['input_ids']#长度大于1024时将保留前1024个分词,并删除剩余分词;长度不足1024时用50256进行填充。
self.attention_mask = encoded_data['attention_mask']#属于有效分词的位置取值为1,填充补齐的位置取值为0。
torch.save((seq_len, self.data, self.attention_mask), encoded_data_cache_path)#第一次运行时将结果保存,后续可直接加载。

3.2 主な構造

        以下の GPT2 モデル トレーニング プログラムの導入中、トレーニングのバッチ サイズは 1 に設定されています。入力は、長さ 1024 の単語セグメンテーション シーケンス input_id とそのattention_mask で、次元は両方とも 1x1024 です。1 はバッチ サイズを示します。プログラムは「titans/layer/block/gpt_block.py」にあり、デバッグ用に対応する場所にブレークポイントを設定できます。

#计算输入有效程度
torch.where(input_ids!=50256)[0].size()
#计算attention_mask长度,与输入有效长度相等
attention_mask.sum()
x = self.embed(input_ids)
#attention_mask取值为1的地方转换为0,取值为0的地方转为-10000。较大的负数在通过Softmax求解自注意力权重时取值接近于0。
if attention_mask is not None:
    batch_size = input_ids.shape[0]
    attention_mask = attention_mask.view(batch_size, -1)
    attention_mask = col_nn.partition_batch(attention_mask)
    attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
    attention_mask = attention_mask.to(dtype=x.dtype)    # fp16 compatibility
    attention_mask = (1.0 - attention_mask) * -10000.0
for block in self.blocks:#最小配置 12层,隐藏变量维度为768
x, attention_mask = block(x, attention_mask)
x = self.head(self.norm(x))#1x1024x50304

3.2.1 ワードベクトル

        上記のデータ処理により、入力テキストは長さ 1024 のシーケンスに変換されました。単語ベクトルはさらに特徴ベクトルを使用して各単語を表し、特徴ベクトルの長さは隠し変数 (HIDDEN_SIZE) の長さになります。ワードベクトル処理関数のエントリは「x = self.embed(input_ids)」、入力シーケンスの次元は BATCH_SIZE x SEQ_LEN (1x1024)、出力シーケンスの次元は BATCH_SIZE x SEQ_LEN x HIDDEN_SIZE です。

        ワードベクトル処理には多くの方法があり、この方向に特化した研究も行われる予定です。最も簡単な方法は、単語ベクトルの辞書を準備することです。プログラムの辞書内の単語の数は 50304 で、各単語は 768 (HIDDEN_SIZE) 次元ベクトルで表されます。この辞書はランダム生成によって得られ、各単語ベクトルは正規化されており、正規化後の平均値は 0、分散は 1 です。最後に、1024 個の単語セグメントのインデックス番号に従って、辞書クエリを実行して、対応する番号の単語ベクトルを取得します。

        シーケンスにはシーケンスが存在するため、その位置コードもシリアル番号で表すことができ、位置ベクトルのセットを使用してこのシーケンスを表すこともできます。最大シーケンス長が 1024 に設定されているため、位置インデックスのベクトル辞書次元は 1024x768 です。総単語ベクトルは単語ベクトルと位置ベクトルを加算することで得られ、その次元は 1024x768 です。

        ワードベクトル処理のキープログラムは次のとおりです。プログラムは「titans/layer/embedding/gpt_embedding.py」にあり、デバッグ用に対応する位置にブレークポイントを設定できます。出力サイズは 1x1024x768 です。

seq_length = input_ids.size(1)
if position_ids is None:
    bs = input_ids.size(0)
    position_ids = torch.arange(seq_length, dtype=torch.long, device=get_current_device()).unsqueeze(0)
    position_ids = position_ids.repeat(bs, 1)
# the size of input_ids is (BATCH_SIZE, SEQ_LEN)
# the size of x after word_embeddings is (BATCH_SIZE, SEQ_LEN, HIDDEN_SIZE)
x = self.word_embeddings(input_ids) + self.position_embeddings(position_ids)#词向量与位置向量,1x1024x768
if self.tokentype_embeddings is not None and tokentype_ids is not None:
    x = x + self.tokentype_embeddings(tokentype_ids)
x = self.dropout(x)#增加轻微扰动
return x

3.2.2 アテンションモジュール

        前の説明によると、GPT2 プログラムは同じアテンション モジュールの 12 層を使用します。各モジュールは 2 つの残差モジュール、つまりセルフ アテンション モジュールとフィード フォワード モジュールで構成され、入力は最初に正規化されます。正規化後の平均は 0、分散は 1 です。12 層アテンション モジュールの最終出力は 1x1024x768 です。

        (a) セルフアテンションモジュール

        最初の残差モジュールは次の図に示されており、その特徴抽出ではマルチヘッド セルフ アテンション メカニズムが使用されます。このうち、ブルの数は 12 で、QKV フィーチャーの次元は 64 であるため、スプライシング後の最終出力フィーチャーの次元は依然として 768、つまり 12x64 です。

図 6 最初の残りのモジュール

        対応するプログラムは次のとおりです。プログラムは「titans/layer/block/gpt_block.py」にあり、デバッグ用に対応する位置にブレークポイントを設定できます。出力サイズは 1x1024x768 です。注意マスクの値が1の箇所は0に変換され、値が0の箇所は-10000に変換されます。Softmax を通じてセルフ アテンション ウェイトを解く場合、大きな負の数は 0 に近くなります。

if not self.apply_post_layernorm:
    residual = x
x = self.norm1(x)#dropout操作之后数据不再是归一化的,需重新归一化,特征维度上均值为0,方差为1
residual = x #1x024x768
x = residual + self.attn(x, attention_mask)#1x1024x768

        プログラムの重要な部分は、自己注意機能の抽出、つまり self.attn(x,attention_mask) です。特定のプログラムは「titans/layer/attention/gpt_attention.py」にあり、デバッグ用に対応する位置にブレークポイントを設定できます。出力サイズは 1x1024x768 です。主な手順は次のとおりです。

        1) QKV を計算します。入力次元は 1x1024x768 です。QKV は 768 次元で変換され、それぞれを 64 次元に変換する必要があり、合計 64*3 の出力になります。Long の数が 12 であるため、変換されたフィーチャの合計次元は 64*3*12、つまり 2304 になります。したがって、1x1024x2304 次元の出力は、完全に接続された層 VanillaLinear (768、2304) を通じて計算されます。次元変換後、プログラムは Q、K、V 成分をそれぞれ抽出し、次元はすべて 1x12x1024x64 になります。

        2) 自己注意重みスコア行列を計算します。Q に K を乗算し、sqrt(64) で除算して、1x12x1024x1024 の仮の重み行列を取得します。次の単語の予測結果は前の内容にのみ関連するため、プログラムは現在の単語の後の重みを絶対値が大きい負の数にそれぞれ設定します。一方、attention_mask に重み行列を追加すると、無効な位置の重みが大きい方の絶対値の負の値に設定されます。Softmax 演算後、各単語の注意の重みの合計は 1 になり、絶対値が大きい前の負の数の対応する位置の重みは 0 に近づきます。出力の寸法は 1x12x1024x1024 です。

        3) 加重加算。加重加算後も V は 1x12x1024x64 のままです。

        4) マルチヘッドフィーチャースプライシング。1x12x1024x64 次元の特徴が連結されて、1x1024x768 次元の新しい特徴が得られます。

        5) フィーチャーのスプライシングと融合。1x1024x768 次元のフィーチャが結合された後、完全に接続された層 VanillaLinear (768、768) を介して再度融合され、ドロップアウト障害が追加されます。最終的な出力サイズは 1x1024x768 です。

        自己注意特徴抽出の主要なプログラム分析は次のとおりです。

# the size of x is (BATCH_SIZE, SEQ_LEN, HIDDEN_SIZE)
# the size of qkv is (BATCH_SIZE, SEQ_LEN, HIDDEN_SIZE*3)
qkv = self.query_key_value(x)#计算QKV,1x1024x2304
all_head_size = qkv.shape[-1] // 3#多头隐藏变量维度,768
num_attention_heads = divide(all_head_size, self.attention_head_size)#计算头的数量,每个头的基本隐藏变量数量为64,那么768/64=12
new_qkv_shape = qkv.shape[:-1] + (num_attention_heads, 3 * self.attention_head_size)#1x1024x12x192,q、k、v的特征维度各为64
qkv = qkv.view(new_qkv_shape)#1x1024x12x192
qkv = qkv.permute((0, 2, 1, 3))#1x12x1024x192
# the size of q is (BATCH_SZIE, NUM_HEADS, SEQ_LEN, HIDDEN_SIZE//NUM_HEADS)
q, k, v = torch.chunk(qkv, 3, dim=-1)#q、k、v分量,1x12x1024x64, 1x12x1024x64, 1x12x1024x64
# the size of x after matmul is (BATCH_SIZE, NUM_HEADS, SEQ_LEN, SEQ_LEN)
x = torch.matmul(q, k.transpose(-1, -2))#自注意力机制权重得分矩阵,1x12x1024x1024
x = x / math.sqrt(self.attention_head_size)# x / sqrt(64),1x12x1024x1024
q_len, k_len = q.size(-2), k.size(-2)#1024, 1024
causal_mask = torch.tril(torch.ones((q_len, k_len), dtype=torch.uint8, device=get_current_device())).view(1, 1, q_len, k_len).bool()#下三角矩阵,当前词仅与之前词相关,每一行代表一组权重,1x1x1024x1024
x = torch.where(causal_mask, x, torch.tensor(-1e4, dtype=x.dtype, device=get_current_device()))#True为x,False为-1e4,1x12x1024x1024
x = x + attention_mask#无效处全部置为较大负值,从而在softmax操作后权重得分基本为0,1x12x1024x1024。
x = self.softmax(x)#转换为权重概率得分,1x12x1024x1024
x = self.attention_dropout(x)#对数据增加扰动,1x12x1024x1024
# the size of x after matmul is (BATCH_SZIE, NUM_HEADS, SEQ_LEN, HIDDEN_SIZE//NUM_HEADS)
x = torch.matmul(x, v)#对v进行加权求和,1x12x1024x64
x = x.transpose(1, 2)#1x1024x12x64
new_context_layer_shape = x.size()[:-2] + (all_head_size,)#1x1024x768
# the size of x after reshape is (BATCH_SZIE, SEQ_LEN, HIDDEN_SIZE)
x = x.reshape(new_context_layer_shape)#多头拼接,1x1024x768
# the size of x after dense is (BATCH_SZIE, SEQ_LEN, HIDDEN_SIZE)
x = self.dense(x)#Linear(768, 768),相当于再次进行一次特征融合,1x1024x768
x = self.dropout(x)#对数据增加扰动,1x1024x768
return x#1x1024x768

(b) Feed Forwardフィードフォワードモジュール

        2 番目の残りのモジュールを下の図に示します。

 図 7 2 番目の残りのモジュール

        対応するプログラムは次のとおりです。プログラムは「titans/layer/block/gpt_block.py」にあり、デバッグ用に対応する位置にブレークポイントを設定できます。出力サイズは 1x1024x768 です。フィードフォワード プロセスは主に、完全に接続された 2 つの層 VanillaLinear(768, 3072) と VanillaLinear(3072, 768) によって完了し、最終出力寸法は依然として 1x1024x768 です。

residual = x
x = self.norm2(x)#dropout操作之后数据不再是归一化的,需重新归一化,特征维度上均值为0,方差为1
x = residual + self.mlp(x)#VanillaLinear(768, 3072)、VanillaLinear(3072, 768)、dropout,再次特征融合

        注目モジュールの最終出力はすべて 1x1024x768 です。

2 )ヘッド

        Head の役割は、問題の解決策に対応する空間に特徴をマップし直すことです。関数エントリは「x = self.head(self.norm(x))」です。アテンションモジュールの後にプログラムによって抽出される特徴次元は 1x1024x768 です。768 次元のそれぞれの特徴に基づいて、それがどの分詞に属するかを計算する、つまり特徴を分類する必要があります。単語ベクトル辞書には合計 50304 のカテゴリがあります。

        GPT2 ヘッドは、LayerNorm 正規化層と完全接続層 (768、50304) で構成され、出力サイズは 1x1024x50304 です。

3.3損失関数

        GPT2 モデルのトレーニングは教師なし手法を採用しており、現在のシーケンスを使用して次の単語セグメントを 1 つずつ予測します。したがって、そのラベルは入力単語分割インデックスのシリアル番号でもあります。N番目の単語分割から抽出された特徴は1~Nの単語分割に関連付けられており、その特徴はN+1番目の単語分割のインデックス番号を予測するために使用されます。入力された単語切り出し順序により、N+1番目の単語切り出しの順序番号が分かる。

        対応するプログラムは次のとおりです。プログラムは「tians/loss/lm_loss/gpt_lmloss.py」にあり、デバッグ用に対応する場所にブレークポイントを設定できます。出力サイズは 1x1024x768 です。損失関数は交差損失商関数 (CrossEntropyLoss) であり、最も一般的に使用される分類損失関数でもあります。損失関数の予測入力特徴の次元は 1023x50304、ラベルの次元は 1023 です。

class GPTLMLoss(nn.Module):
    def __init__(self):
        super().__init__()
        self.loss = col_nn.CrossEntropyLoss()
    def forward(self, logits, labels):
        shift_logits = logits[..., :-1, :].contiguous()#预测结果
        shift_labels = labels[..., 1:].contiguous()#下一个取值为预测值对应的标签
        # Flatten the tokens
# shift_logits.view(-1, shift_logits.size(-1)).shape,1023x50304
# shift_labels.view(-1).shape,1023
        return self.loss(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))

4 トレーニングコマンドと結果

        GPT2 モデル環境のセットアップとデバッグについては、ブログ投稿「GPT シリーズのトレーニングとデプロイメント - GPT2 環境の構成とモデル トレーニング」および「ColossalAI GPT2 分散トレーニングとデバッグ構成 - GPT シリーズのトレーニングとデプロイメント」を参照してください。アドレスは次のとおりです。 「https://blog.csdn.net/suiyingy/article/details/128711444」および「https://blog.csdn.net/suiyingy/article/details/128806531」。

        ColossalAI-Examples の GPT トレーニング コマンドは、「colossalai run --nproc_per_node=2 train_gpt.py --config=gpt2_configs/gpt2_vanilla.py --from_torch」です。実行結果を下図に示します。

 図8 学習結果の模式図

5 モデルの保存とロード

5.1 モデルの保存

        ColossalAI-Examples/ language/gpt/train_gpt.py ファイルで、hook_list 内の hooks.SaveCheckpointHook(checkpoint_dir='./ckpt') のコメントを解除して、トレーニング モデルを保存します。デフォルトでは、トレーニング モデルは現在のディレクトリの ckpt に保存されます。デバッグ モードで実行している場合、トレーニング モデルはユーザーのホーム ディレクトリに保存され、コマンド「find ~ -name ckpt」で検索できます。

5.2 モデルトレーニングのロード

        ColossalAI-Examples/ language/gpt/train_gpt.py ファイルには、デフォルトで事前トレーニング済みモデルをロードするためのインターフェイスがないため、以下に示すように、自分でエントリ プログラムを記述する必要があります。新しいプログラムは、114 行目「logger.info('Build optimizer', Ranks=[0])」の後に追加されます。これは 115 行目です。

if os.path.exists('ckpt'):
    logger.info('Loading pretrained model from ckpt', ranks=[0])
    from collections import OrderedDict
    new_state_dict = OrderedDict()
    state_dict = torch.load('ckpt')
    for k, v in state_dict['model'].items():
        name = k[6:]  # remove `module.`
        new_state_dict[name] = v
    model.load_state_dict(new_state_dict)

        この記事はブロガーのオリジナル記事ですので、ブロガーの許可なく転載することはできません。

        この記事はコラム「Python AIGC 大規模モデルのトレーニングとゼロからの推論」のシリーズ記事で、アドレスは「https://blog.csdn.net/suiyingy/article/details/130169592」です。

        なお、このコラムの具体的な更新情報については、記事下の公式アカウントをフォローしていただくか、本コラムをフォローしていただくことが可能です。関連記事はすべて「ゼロから始める Python AIGC 大規模モデルのトレーニングと推論」で更新されます。アドレスは「https://blog.csdn.net/suiyingy/article/details/130169592」です。AIGC に似たすべてのモデル展開のエクスペリエンス効果は、RdFast アプレットで同期的に起動されます。

おすすめ

転載: blog.csdn.net/suiyingy/article/details/130937792