翻訳者|朱 仙中 レビュー | Chonglou 導入GPT などの言語モデルは最近非常に人気が高まっており、 ChatGPT やその他の会話型 AI システムなど、さまざまなテキスト生成タスクに適用されています。通常、これらの言語モデルはサイズが非常に大きく、数百億を超えるパラメータを使用することが多く、実行するには膨大な量のコンピューティング リソースと資金が必要です。 英語モデルの文脈では、これらの大規模なモデルは、英語をモデル化するだけでなく、モデルのパラメータを使用して世界の側面を記憶し学習するため、過剰にパラメータ化されています。言語とその構造を理解するだけのモデルを必要とするアプリケーションを開発する場合は、おそらくはるかに小さなモデルを使用することになります。 注:トレーニング済みモデルで推論を実行するための完全なソース コードは、この記事に付属のJupyter ノートブックにあります。 問題の説明携帯電話で次に入力する単語を予測するスライド キーボード システムを構築しているとします。スライディングモードによって追跡されたパターンに基づいて、ユーザーが望む単語には多くの可能性があります。ただし、これらの可能性のある単語の多くは英語の実際の単語ではないため、削除できます。この最初の整理と排除のステップを経た後でも、まだ多くの候補が残っており、そのうちの1 つをユーザーへの推奨として選択する必要があります。 この候補リストをさらに絞り込むには、提供されたコンテキストを調べてどの候補が文を完成させる可能性が最も高いかを教えてくれるディープラーニング ベースの言語モデルを使用できます。 たとえば、ユーザーが「これをスケジュールしました」という文を入力し、次のようにモーダルをスライドするとします。 ユーザーが求める可能性のある英語の単語は次のとおりです。 - めちゃくちゃ
- 会議
しかし、よく考えてみると、文の前半に「予定されている」という言葉があることから、ユーザーは「トラブルを起こす」という意味ではなく「会議をする」という意味を意図していた可能性が高いです。 これまでにわかっていることすべてを考慮すると、これをプログラムで調整するためのオプションは何でしょうか?以下のセクションでいくつかの解決策をブレインストーミングしてみましょう。 ブレインストーミングによる解決策アルゴリズムとデータ構造第一原理を使用して、データのコーパスから始めて、一緒になる単語のペアを見つけ、単語のペアが文に現れる確率を予測するようにマルコフモデルをトレーニングするのが合理的であると思われます。ただし、このアプローチには 2 つの重大な問題があることに気付くでしょう。 - スペースの利用: 英語には、増加し続ける膨大な数の固有名詞を除いても、250,000 から 1,000,000 語あります。したがって、単語のペアが一緒に出現する確率をモデル化する従来のソフトウェア ソリューションでは、 250k * 250k = 625 億の単語ペアを持つルックアップテーブルを維持する必要があり、これは明らかに過剰です。実際、多くの単語のペアは頻繁に出現しないようで、削除できる可能性があります。剪定後でも、考慮すべき単語のペアはまだたくさんあります。
- 完全性: 単語のペアの確率をエンコードするだけでは、当面の問題を十分に解決できません。たとえば、最新の単語のペアだけを見ると、前の文のコンテキストは完全に失われます。 「How is your day coming ? 」という文章で、「 coming 」の後の単語を調べると、「 coming 」で始まる一致が多数見つかります。これでは、単語の前の文全体の文脈が失われます。単語のトリプレットなどを使用することも考えられますが、これにより、前述のスペース利用の問題が悪化します。
次に、英語の本質を活用したソリューションに焦点を移し、それが役立つかどうかを見てみましょう。 自然言語処理歴史的に、NLP (自然言語処理) の分野は、文の品詞を理解し、この情報を使用してそのような剪定や予測の決定を行うことに重点を置いてきました。各単語に関連付けられたPOSタグを使用して、文中の次の単語が有効かどうかを判断する状況を想像することができます。 しかし、文の品詞を計算するプロセス自体は、 NLTK の品詞タグ付けページからもわかるように、言語の専門的な理解を必要とする複雑なプロセスです。 次に、より多くのラベル付きデータが必要でありながら、構築にそれほど多くの言語の専門知識を必要としない、ディープラーニング ベースのアプローチを見てみましょう。 ディープラーニング(ニューラルネットワーク)ディープラーニングの出現により、NLP 分野に革命が起こりました。 LSTM と Transformer ベースの言語モデルの発明により、解決策としては通常、モデルに高品質のデータを与え、次の単語を予測するようにトレーニングすることになります。 これが基本的に GPT モデルが行っていることです。 GPT モデルは常に、文の接頭辞が与えられた場合に次の単語 (トークン) を予測するようにトレーニングされます。 たとえば、文の接頭辞「It is so would a would」が与えられた場合、モデルは文中に続く単語に対して次のような高い確率の予測を提供する可能性が高くなります。 - 日
- 経験
- 世界
- 人生
次の単語も、文の接頭辞を完成させる可能性は低いかもしれません。 - 赤
- マウス
- ライン
Transformer モデル アーキテクチャ(machine_learning_model)は、ChatGPT のようなシステムの中心です。ただし、英語の意味を学習するというより制限されたアプリケーションシナリオでは、 LSTM (Long Short-Term Memory) モデルなどの実行コストが安いモデルアーキテクチャを使用できます。 LSTM モデル次に、単純な LSTM モデルを構築し、トークンのプレフィックスが与えられた場合に次のトークンを予測するようにトレーニングします。さて、タグとは何かと疑問に思うかもしれません。 トークン化通常、言語モデルの場合、トークンは次のものを表します。 - 1文字(または1バイト)
- 対象言語の単語全体
- 1 と 2 の間の単語はサブワードと呼ばれることが多いです。
単一の文字 (またはバイト) をトークンにマッピングすることは、トークンの発生場所に関する多くのコンテキストを保持するためにトークンをオーバーロードする必要があるため、非常に制限があります。たとえば、「c」という文字はさまざまな単語に出現し、「c」を見た後に次の文字を予測するには、その誘導となる文脈を注意深く観察する必要があるからです。 英語自体には 250,000 から 1,000,000 の単語があるため、単語をトークンにマッピングすることも問題になります。さらに、言語に新しい単語が追加されると何が起こるでしょうか?この新しい単語を考慮するために、モデル全体を再度トレーニングする必要がありますか? サブワードのトークン化は、 2023 年までに業界標準になると考えられています。頻繁に一緒に出現するバイトの部分文字列を一意のタグに割り当てます。通常、言語モデルには数千 (例: 4,000) から数万 (例: 60,000) の固有トークンが含まれます。トークンを構成するものを決定するアルゴリズムは、BPE (バイトペアエンコーディング)アルゴリズムによって決定されます。 語彙内の一意のトークンの数 (語彙サイズと呼ばれる) を選択するには、いくつかの点に留意する必要があります。 - 選択したトークンが少なすぎると、文字ごとに 1 つのトークンに戻り、モデルが有用な情報を学習することが難しくなります。
- トークンを多すぎる数選択すると、モデルの埋め込みテーブルがモデルの残りの重みを圧倒し、制約のある設定でモデルを展開することが困難になる状況に陥ります。埋め込みテーブルのサイズは、各トークンに使用する次元の数によって異なります。 256、512、786 などのサイズを使用することは珍しくありません。トークン埋め込み次元を512にし、トークンの数が 100k の場合、メモリで 200MiB を使用する埋め込みテーブルが作成されます。
したがって、語彙のサイズを選択する際にはバランスを取る必要があります。この例では、 6600 個のトークンを選択し、語彙サイズ 6600 でトークナイザーをトレーニングします。次に、モデル定義自体を見てみましょう。 PyTorch モデルモデル自体は非常にシンプルです。次のレイヤーを作成しました。 - トークン埋め込み(語彙サイズ = 6600、埋め込み次元= 512)、合計サイズは約 15 MiB です(埋め込みテーブルのデータ型が 4バイトfloat32型であると仮定)
- LSTM(レイヤー数 = 1、隠しサイズ = 786)、合計サイズは約16MiB
- 多層パーセプトロン(786 x 3144 x 6600 次元)、合計サイズ約 93 MiB
モデル全体には約 31M のトレーニング可能なパラメータがあり、合計サイズは約 120MiB です。 以下にモデルの PyTorch コードを示します。 class WordPredictionLSTMModel(nn.Module): def __init__(self, num_embed, embed_dim, pad_idx, lstm_hidden_dim, lstm_num_layers, output_dim, dropout): super().__init__() self.vocab_size = num_embed self.embed = nn.Embedding(num_embed, embed_dim, pad_idx) self.lstm = nn.LSTM(embed_dim, lstm_hidden_dim, lstm_num_layers, batch_first=True, dropout=dropout) self.fc = nn.Sequential( nn.Linear(lstm_hidden_dim, lstm_hidden_dim * 4), nn.LayerNorm(lstm_hidden_dim * 4), nn.LeakyReLU(), nn.Dropout(p=dropout), nn.Linear(lstm_hidden_dim * 4, output_dim), ) # def forward(self, x): x = self.embed(x) x, _ = self.lstm(x) x = self.fc(x) x = x.permute(0, 2, 1) return x # # 以下は、 torchinfoライブラリを使用して出力されたモデルの概要情報です。 LSTM モデルの概要 ================================================================= Layer (type:depth-idx) Param # ================================================================= WordPredictionLSTMModel - ├─Embedding: 1–1 3,379,200 ├─LSTM: 1–2 4,087,200 ├─Sequential: 1–3 - │ └─Linear: 2–1 2,474,328 │ └─LayerNorm: 2–2 6,288 │ └─LeakyReLU: 2–3 - │ └─Dropout: 2–4 - │ └─Linear: 2–5 20,757,000 ================================================================= Total params: 30,704,016 Trainable params: 30,704,016 Non-trainable params: 0 =================================================================
説明精度: P100 GPU で約 8 時間にわたって 1200 万の英語の文章でモデルをトレーニングした結果、損失値4.03 、トップ 1 精度 29%、トップ 5 精度 49% が得られました。これは、モデルが次のトークンを正しく予測できた時間が 29% であり、トレーニングセット内の次のトークンがモデルの上位 5 つの予測の 1 つであった時間が 49% であることを意味します。 では、成功の指標は何であるべきでしょうか?私たちのモデルのトップ 1 とトップ 5 の精度の数値は印象的ではありませんが、私たちの問題にとってそれほど重要ではありません。候補となる単語は、スライドパターンに適合する可能性のある単語の小さなセットです。私たちのモデルは、文法的にも意味的にも一貫性のある文を完成させるために理想的な候補を選択できるようにしたいと考えています。私たちのモデルはトレーニング データを通じて言語の特性を学習するため、一貫性のある文に高い確率を割り当てることが期待されます。たとえば、 「野球選手」という文と、可能な補完語(「ran」、「swim」、「hid」)がある場合、「ran」という単語は他の 2 つの単語よりも後続の使用に適しています。したがって、モデルが「ran」という単語を他の単語よりも高い確率で予測した場合、そのモデルはうまく機能していることになります。 損失値の解釈: 損失値が 4.03 の場合、予測の負の対数尤度は 4.03 です。つまり、次のトークンを正しく予測する確率は e^-4.03 = 0.0178、つまり 56 分の 1 です。ランダムに初期化されたモデルの損失値は通常約 8.8 で、これは -log_e(1/6600) です。これは、モデルがトークンの 1/6600 (6600 は語彙サイズ) をランダムに予測するためです。損失値4.03 は大きくないように思えるかもしれませんが、トレーニングされたモデルはトレーニングされていない (またはランダムに初期化された) モデルよりも約 120 倍優れていることを覚えておくことが重要です。 次に、このモデルを使用してスライドキーボードの候補を改善する方法を見てみましょう。 モデルプルーニングの無効な提案の使用実際の例を見てみましょう。 「私は思う」という部分的に完成した文章があり、ユーザーが以下の青色で示すように、文字「o」から始めて文字「c」と文字「v」の間を通り、文字「e」と文字「v」の間で終わるスライド パターンを作成したとします。 このスライドパターンで表現できる可能性のある単語には次のようなものがあります。 - 以上
- 10月(10月の略語)
- 氷
- 私は
これらの提案の中で、最も可能性が高いのはおそらく「I’ve」でしょう。これらの提案をモデルに入力して、どのような結果が生成されるかを見てみましょう。 [I think] [I've] = 0.00087 [I think] [over] = 0.00051 [I think] [ice] = 0.00001 [I think] [Oct] = 0.00000 = 記号の後の値は、その単語が文を完成させるための有効な接頭辞である確率です。この場合、「I have」という単語に最も高い確率が割り当てられていることがわかります。したがって、これは文頭辞「I think」の後に続く可能性が最も高い単語です。 次の質問は、次の単語の確率をどのように計算するかです。 次の単語の確率を計算する単語が文の接頭辞の有効な補完である確率を計算するには、モデルを eval (推論) モードで実行し、トークン化された文の接頭辞を入力します。また、単語に空白の接頭辞を追加した後、その単語をトークン化します。これを実行するのは、HuggingFace の事前トークナイザーが単語の先頭のスペースで単語を区切るため、入力が HuggingFace トークナイザーが使用するトークン化戦略と一致していることを確認するためです。 候補単語が 3 つのトークン T0、T1、T2 で構成されていると仮定します。 - まず、元のトークン化された文の接頭辞を使用してモデルを実行します。最後のトークンについては、予測トークンT0の確率を確認します。それを「問題」リストに追加します。
- 次に、プレフィックス +T0 の予測を行い、トークンT1 の確率を確認します。この確率を「probs」リストに追加します。
- 次に、プレフィックス +T0+T1 の予測を行い、トークンT2 の確率を確認します。この確率を「probs」リストに追加します。
「probs」リストには、タグT0、T1、T2 を順番に生成する個々の確率が含まれています。これらのトークンは候補語のトークン化に対応しているため、これらの確率を掛け合わせると、候補語が文の接頭辞を完成させる総合的な確率が得られます。 完了確率を計算するコードを以下に示します。 def get_completion_probability(self, input, completion, tok): self.model.eval() ids = tok.encode(input).ids ids = torch.tensor(ids, device=self.device).unsqueeze(0) completion_ids = torch.tensor(tok.encode(completion).ids, device=self.device).unsqueeze(0) probs = [] for i in range(completion_ids.size(1)): y = self.model(ids) y = y[0,:,-1].softmax(dim=0) #prob是完成的概率。 prob = y[completion_ids[0,i]] probs.append(prob) ids = torch.cat([ids, completion_ids[:,i:i+1]], dim=1) # return torch.tensor(probs) #
以下にさらに例を示します。 [That ice-cream looks] [really] = 0.00709 [That ice-cream looks] [delicious] = 0.00264 [That ice-cream looks] [absolutely] = 0.00122 [That ice-cream looks] [real] = 0.00031 [That ice-cream looks] [fish] = 0.00004 [That ice-cream looks] [paper] = 0.00001 [That ice-cream looks] [atrocious] = 0.00000 [Since we're heading] [toward] = 0.01052 [Since we're heading] [away] = 0.00344 [Since we're heading] [against] = 0.00035 [Since we're heading] [both] = 0.00009 [Since we're heading] [death] = 0.00000 [Since we're heading] [bubble] = 0.00000 [Since we're heading] [birth] = 0.00000 [Did I make] [a] = 0.22704 [Did I make] [the] = 0.06622 [Did I make] [good] = 0.00190 [Did I make] [food] = 0.00020 [Did I make] [color] = 0.00007 [Did I make] [house] = 0.00006 [Did I make] [colour] = 0.00002 [Did I make] [pencil] = 0.00001 [Did I make] [flower] = 0.00000 [We want a candidate] [with] = 0.03209 [We want a candidate] [that] = 0.02145 [We want a candidate] [experience] = 0.00097 [We want a candidate] [which] = 0.00094 [We want a candidate] [more] = 0.00010 [We want a candidate] [less] = 0.00007 [We want a candidate] [school] = 0.00003 [This is the definitive guide to the] [the] = 0.00089 [This is the definitive guide to the] [complete] = 0.00047 [This is the definitive guide to the] [sentence] = 0.00006 [This is the definitive guide to the] [rapper] = 0.00001 [This is the definitive guide to the] [illustrated] = 0.00001 [This is the definitive guide to the] [extravagant] = 0.00000 [This is the definitive guide to the] [wrapper] = 0.00000 [This is the definitive guide to the] [miniscule] = 0.00000 [Please can you] [check] = 0.00502 [Please can you] [confirm] = 0.00488 [Please can you] [cease] = 0.00002 [Please can you] [cradle] = 0.00000 [Please can you] [laptop] = 0.00000 [Please can you] [envelope] = 0.00000 [Please can you] [options] = 0.00000 [Please can you] [cordon] = 0.00000 [Please can you] [corolla] = 0.00000 [I think] [I've] = 0.00087 [I think] [over] = 0.00051 [I think] [ice] = 0.00001 [I think] [Oct] = 0.00000 [Please] [can] = 0.00428 [Please] [cab] = 0.00000 [I've scheduled this] [meeting] = 0.00077 [I've scheduled this] [messing] = 0.00000 これらの例は、単語が前の文を完成させる確率を示しています。候補となる単語は確率の降順で並べられます。 Transformer は、シーケンスベースのタスクで LSTM モデルと RNN モデルを徐々に置き換えつつあるため、同じ目的に対して Transformer モデルがどのようなものになるかを見てみましょう。 トランスフォーマーモデルトランスフォーマーベースのモデルは、文中の次の単語を予測する言語モデルをトレーニングするための非常に一般的なアーキテクチャです。私たちが使用する具体的な技術は因果的注意メカニズムです。 PyTorch のトランスフォーマー エンコーダー レイヤーをトレーニングするために、因果的注意を使用します。因果的注意とは、シーケンス内の各トークンが、その前にあったトークンのみを参照できるようにすることを意味します。これは、順方向のみのトレーニング時に単方向 LSTM レイヤーによって使用される情報に似ています。 ここで説明する Transformer モデルは、 PyTorchのnn.TransformerEncoderとnn.TransformerEncoderLayerを直接ベースにしています。 import math def generate_src_mask(sz, device): return torch.triu(torch.full((sz, sz), True, device=device), diagnotallow=1) # class PositionalEmbedding(nn.Module): def __init__(self, sequence_length, embed_dim): super().__init__() self.sqrt_embed_dim = math.sqrt(embed_dim) self.pos_embed = nn.Parameter(torch.empty((1, sequence_length, embed_dim))) nn.init.uniform_(self.pos_embed, -1.0, 1.0) # def forward(self, x): return x * self.sqrt_embed_dim + self.pos_embed[:,:x.size(1)] # # class WordPredictionTransformerModel(nn.Module): def __init__(self, sequence_length, num_embed, embed_dim, pad_idx, num_heads, num_layers, output_dim, dropout, norm_first, activation): super().__init__() self.vocab_size = num_embed self.sequence_length = sequence_length self.embed_dim = embed_dim self.sqrt_embed_dim = math.sqrt(embed_dim) self.embed = nn.Sequential( nn.Embedding(num_embed, embed_dim, pad_idx), PositionalEmbedding(sequence_length, embed_dim), nn.LayerNorm(embed_dim), nn.Dropout(p=0.1), ) encoder_layer = nn.TransformerEncoderLayer( d_model=embed_dim, nhead=num_heads, dropout=dropout, batch_first=True, norm_first=norm_first, activatinotallow=activation, ) self.encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers) self.fc = nn.Sequential( nn.Linear(embed_dim, embed_dim * 4), nn.LayerNorm(embed_dim * 4), nn.LeakyReLU(), nn.Dropout(p=dropout), nn.Linear(embed_dim * 4, output_dim), ) # def forward(self, x): src_attention_mask = generate_src_mask(x.size(1), x.device) x = self.embed(x) x = self.encoder(x, is_causal=True, mask=src_attention_mask) x = self.fc(x) x = x.permute(0, 2, 1) return x # # このモデルは API と互換性があるため、以前使用した LSTM モデルの代わりに使用できます。同じ量のトレーニング データの場合、このモデルのトレーニングにはより長い時間がかかりますが、パフォーマンスは同等です。 Transformer モデルは長いシーケンスに適しています。この場合、長さが 256 のシーケンスがあります。次の単語の補完を実行するために必要なコンテキストのほとんどはローカルである傾向があるため、ここでトランスフォーマーの力に頼る必要はほとんどありません。 結論はこの記事では、 LSTM (RNN) と Transformer モデルに基づくディープラーニング技術を使用して、非常に実用的な NLP 問題を解決する方法を学びました。すべての言語タスクに数十億のパラメータを持つモデルが必要なわけではありません。大量の情報を記憶することなく言語自体をモデル化する必要がある特殊なアプリケーションは、現在見られる大規模な言語モデルよりも簡単かつ効率的に展開できる小さなモデルを使用して処理できます。 注:この記事のすべての画像は著者によって作成されたものです。 翻訳者紹介Zhu Xianzhong 氏は、51CTO のコミュニティ エディターであり、51CTO の専門ブロガー兼講師であり、濰坊の大学のコンピューター教師であり、フリーランス プログラミング コミュニティのベテランです。 原題:文完成のための言語モデル、著者: Dhruv Matani
|