文の補完のための言語モデル
言語モデルの文の補完
英語の文を単語一つ追加して拡張する最も可能性の高い候補単語を選ぶ言語モデルの実用的な応用
Naresh Singhとの共著。
目次
はじめに問題の説明解決策の考案
- アルゴリズムとデータ構造
- NLP(自然言語処理)
- ディープラーニング(ニューラルネットワーク)
LSTMモデル
- トークナイゼーション
- PyTorchモデル
- モデルを使用して無効な提案を絞り込む
- 次の単語の確率を計算する
Transformerモデル
結論
はじめに
GPTなどの言語モデルは最近非常に人気があり、ChatGPTや他の対話型AIシステムなど、さまざまなテキスト生成タスクで使用されています。これらの言語モデルは非常に大きく、数百億のパラメーターを超えることがあり、実行には多くの計算リソースとお金が必要です。
英語の言語モデルの文脈では、これらの巨大なモデルは、英語の言語モデルだけをモデリングするのではなく、モデルのパラメーターを使用して私たちの世界の側面を記憶し学習するため、過剰にパラメーター化されています。言語とその構造だけを理解するモデルが必要なアプリケーションがあれば、はるかに小さなモデルを使用できる可能性があります。
トレーニング済みモデルで推論を実行するための完全なコードは、このノートブックにあります。
問題の説明
次に打つ単語を予測しようとするスワイプキーボードシステムを構築していると想像してみましょう。スワイプパターンによって形成されるパターンに基づいて、ユーザーが意図した単語は多くの可能性があります。しかし、これらの可能性のある単語の多くは実際の英語の単語ではなく、除外することができます。この初期の絞り込みと除外のステップを経ても、多くの候補が残り、ユーザーに提案するために1つを選ばなければなりません。
この候補リストをさらに絞り込むために、提供された文脈を見て、文を完成させるために最も可能性の高い候補を教えてくれるディープラーニングベースの言語モデルを使用することができます。
たとえば、ユーザーが「I’ve scheduled this」という文を入力し、次に以下のようなパターンをスワイプした場合
その場合、ユーザーが意味したかもしれない可能性のある英語の単語は次の通りです。
- messing
- meeting
しかし、考えてみると、おそらくユーザーが「meeting」を意味しており、「messing」ではない可能性が高いです。なぜなら、文の前半部分に「scheduled」という言葉があるからです。
これまでのところ、プログラムでこの絞り込みを行うためのオプションは何でしょうか?以下のセクションでいくつかの解決策を考えてみましょう。
解決策の考案
アルゴリズムとデータ構造
第一原理を使用すると、データのコーパスを使って一緒に現れる単語のペアを見つけ、文の中でそのペアが発生する確率を予測するマルコフモデルをトレーニングすることが合理的なアプローチのように思えます。このアプローチには2つの重要な問題があります。
- スペース利用:英語には25万から100万語の単語があり、増え続けている数多くの固有名詞を含んでいません。したがって、単語のペアが一緒に現れる確率をモデリングする従来のソフトウェアソリューションは、6250億の単語ペアを保持するルックアップテーブルを維持する必要があり、やや過剰です。多くのペアはあまり頻繁に発生しない可能性が高く、絞り込むことができるでしょう。絞り込んだ後でも、心配すべきペアがたくさんあります。
- 完全性:単語のペアの確率をエンコードするだけでは、手元の問題を十分に解決することができません。たとえば、最新の単語のペアだけを見ている場合、以前の文脈は完全に失われてしまいます。文「How is your day coming」の「coming」の後の単語をチェックしたい場合、多くの「coming」で始まるペアがあります。これにより、その単語の前の文脈が見逃されます。単語のトリプレットなどを使用することを想像することができますが、これは上記のスペース利用の問題をさらに悪化させます。
ここでは、英語の言語の特性を活用した解決策に焦点を当てて、それがどのように助けになるかを見てみましょう。
NLP (自然言語処理)
歴史的には、NLP(自然言語処理)の領域では、文の品詞(POS)を理解し、その情報を使って剪定や予測の決定を行ってきました。文中の次の単語が有効かどうかを判断するために、各単語に関連付けられたPOSタグを使用することを想像することができます。
ただし、文の品詞を計算するプロセス自体が複雑であり、言語の専門的な理解が必要とされます。このページのNLTKの品詞タグ付けに示されているように。
次に、大量のタグ付きデータを必要とするが、言語の専門知識はそれほど必要としない深層学習ベースのアプローチを見てみましょう。
ディープラーニング(ニューラルネットワーク)
NLPの領域は、ディープラーニングの登場によって一変しました。LSTMやTransformerをベースとした言語モデルの発明により、解決策はほとんどの場合、高品質のデータをモデルに投入し、次の単語を予測するためにモデルを訓練することを含みます。
基本的に、これがGPTモデルが行っていることです。GPT(Generative Pre-Trained Transformer)モデルは、文の接頭辞に対して次の単語(トークン)を予測するように訓練されます。
「素晴らしい」という文の接頭辞が与えられた場合、モデルが次の単語に対して高確率の予測として以下を提供する可能性があります。
- day
- experience
- world
- life
また、以下の単語は文の接頭辞を補完するための低い確率を持つ可能性があります。
- red
- mouse
- line
Transformerモデルのアーキテクチャは、ChatGPTなどのシステムの中心です。ただし、英語の言語の意味を学習するというよりも制限された用途では、LSTM(長短期記憶)モデルなどの実行コストの低いモデルアーキテクチャを使用できます。
LSTMモデル
簡単なLSTMモデルを構築し、トークンの接頭辞が与えられた場合に次のトークンを予測するように訓練しましょう。さて、トークンとは何でしょうか。
トークン化
通常、言語モデルでは、トークンとは以下のいずれかの意味を持ちます。
- 1つの文字(または1バイト)
- 対象言語の単語全体
- 1と2の間の何か。これは通常、サブワードと呼ばれます
1つの文字(またはバイト)をトークンにマッピングするのは非常に制限的です。なぜなら、例えば文字”c”は多くの異なる単語に現れるため、文字”c”の次の文字を予測するためには、先行する文脈をよく見る必要があるからです。
1つの単語をトークンにマッピングすることも問題があります。なぜなら、英語自体には25万から100万の単語があります。さらに、新しい単語が言語に追加された場合、この新しい単語を考慮するためにモデル全体を再トレーニングする必要があるでしょうか?
サブワードトークン化は、2023年の業界標準とされています。頻繁に一緒に現れるバイトの部分文字列に一意のトークンを割り当てます。通常、言語モデルには数千(4,000とします)から数万(60,000とします)の一意のトークンがあります。トークンとは何を構成するかを決定するアルゴリズムは、BPE(Byte pair encoding)アルゴリズムによって決定されます。
語彙の一意のトークンの数(語彙サイズと呼ばれる)を選択する場合、いくつかのことに注意する必要があります。
- トークンが少なすぎると、文字ごとのトークンの領域に戻り、モデルが有用な情報を学習するのが難しくなります。
- トークンが多すぎると、モデルの埋め込みテーブルがモデルの他の重みを圧倒し、制約のある環境でモデルを展開するのが難しくなります。埋め込みテーブルのサイズは、各トークンに使用する次元の数に依存します。通常、サイズが256、512、786などのトークン埋め込み次元を使用し、10万個のトークンがある場合、メモリ上で200MiBを使用する埋め込みテーブルが生成されます。
したがって、語彙サイズを選ぶ際にはバランスを取る必要があります。この例では、6600トークンを選び、語彙サイズを6600に設定してトークナイザをトレーニングします。次に、モデルの定義を見てみましょう。
PyTorchモデル
モデル自体は非常にシンプルです。以下のレイヤーがあります。
- トークン埋め込み(語彙サイズ=6600、埋め込み次元=512)、合計サイズはおよそ15MiB(埋め込みテーブルのデータ型として4バイトのfloat32を仮定)
- LSTM(レイヤー数=1、隠れ次元=786)、合計サイズはおよそ16MiB
- マルチレイヤーパーセプトロン(786から3144から6600次元)、合計サイズはおよそ93MiB
完全なモデルは、トレーニング可能なパラメータが約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モデルのサマリー
=================================================================レイヤー(タイプ:深さ)パラメータ数=================================================================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=================================================================合計パラメータ数:30,704,016トレーニング可能なパラメータ数:30,704,016トレーニング不可のパラメータ数:0=================================================================
正確さの解釈:このモデルをP100 GPU上で約8時間、12Mの英語の文章でトレーニングした結果、損失は4.03、トップ1の正確さは29%、トップ5の正確さは49%でした。これはモデルが次のトークンを正しく予測できた割合が29%であり、トレーニングセットの次のトークンがモデルによるトップ5の予測のいずれかである割合が49%であることを意味します。
成功指標は何であるべきか? モデルのトップ1およびトップ5の正確さは印象的ではありませんが、私たちの問題にとっては重要ではありません。候補単語はスワイプパターンに合致する可能性のある少数の単語のセットです。私たちのモデルに求めるのは、文法的にも意味的にも整合性のある完全な文を選択する能力です。モデルはトレーニングデータを通じて言語の性質を学習するため、連続する文に対してより高い確率を割り当てることが期待されます。例えば、文が「The baseball player」であり、可能な完成候補が(「ran」、「swam」、「hid」)である場合、単語「ran」は他の2つよりも優れた次の単語です。したがって、モデルが「ran」という単語を他の単語よりも高い確率で予測する場合、私たちにとってはうまく機能しています。
損失の解釈:4.03の損失は、予測の負の対数尤度が4.03であることを意味し、次のトークンを正しく予測する確率がe^-4.03 = 0.0178または1/56であることを意味します。ランダムに初期化されたモデルは通常、損失が約8.8であり、これは-log_e(1/6600)です。なぜなら、モデルはランダムに1/6600のトークンを予測するからです(6600は語彙サイズです)。4.03の損失は素晴らしいとは言えないかもしれませんが、トレーニングされたモデルは未訓練の(またはランダムに初期化された)モデルよりも約120倍優れていることを覚えておくことが重要です。
次に、このモデルを使用してスワイプキーボードの提案を改善する方法を見てみましょう。
モデルを使用して無効な提案を削除する
実際の例を見てみましょう。部分的な文「I think」があるとします。ユーザーが下の青色で示されたスワイプパターンを作成し、「o」から始まり、「c」と「v」の間を通り、「e」と「v」の間で終わるとします。
このスワイプパターンで表される可能性のある単語は次のとおりです。
- Over
- Oct(Octoberの略)
- Ice
- I’ve(省略形のアポストロフィを含む)
これらの提案の中で、最も可能性が高いのはおそらく「I’ve」です。これらの提案をモデルに入れて結果を見てみましょう。
[I think] [I've] = 0.00087[I think] [over] = 0.00051[I think] [ice] = 0.00001[I think] [Oct] = 0.00000
「=」の後の値は、単語が文の接頭辞の有効な補完である確率です。この場合、単語「I’ve」には最も高い確率が割り当てられています。したがって、「I think」という文の後に続く最も可能性の高い単語です。
次の質問は、次の単語の確率をどのように計算できるかということです。具体的に見てみましょう。
次の単語の確率を計算する
文の接頭辞が有効な補完である単語の確率を計算するには、モデルを推論モードで実行し、トークン化された文の接頭辞を入力します。また、単語の前に空白の接頭辞を追加してトークン化します。これは、HuggingFaceのプリトークナイザーが単語の先頭にスペースを持つ単語を分割するため、入力がHuggingFace Tokenizersで使用されるトークン化戦略と一致することを確認するためです。
候補単語が3つのトークンT0、T1、およびT2で構成されていると仮定しましょう。
- 最初に、元のトークン化された文の接頭辞でモデルを実行します。最後のトークンでは、トークンT0の予測確率をチェックします。これを「probs」リストに追加します。
- 次に、接頭辞+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 is the probability of this completion. 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モデルについて見てみましょう。
Transformerモデル
Transformerベースのモデルは、次の単語を予測する言語モデルのトレーニングにおいて非常に人気のあるアーキテクチャです。ここで使用する具体的な技術は、因果的な注意機構です。PyTorchを使用してTransformerのエンコーダーレイヤーのみをトレーニングします。因果的な注意は、シーケンス内の各トークンが、それより前のトークンのみを参照できることを意味します。これは、一方向のLSTMレイヤーが前向きの方向だけでトレーニングされた場合の情報に似ています。
ここで見るTransformerモデルは、PyTorchのnn.TransformerEncoderとnn.TransformerEncoderLayerに直接基づいています。
import mathdef generate_src_mask(sz, device): return torch.triu(torch.full((sz, sz), True, device=device), diagonal=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, activation=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です。次の単語の補完に必要なコンテキストのほとんどはローカルであるため、ここではTransformerのパワーは実際には必要ありません。
結論
LSTM(RNN)およびTransformerモデルに基づいたディープラーニング技術を使用して、非常に実践的な自然言語処理の問題を解決する方法を見ました。すべての言語タスクには数十億のパラメータを持つモデルが必要とされるわけではありません。大量の情報を記憶するのではなく、言語自体をモデリングすることが必要な特定のアプリケーションは、より小さなモデルを使用して簡単に展開でき、効率的に処理できます。
最初の画像以外のすべての画像は、著者によって作成されました。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles
- このAI論文は、自律言語エージェントのためのオープンソースのPythonフレームワークである「Agents」を紹介しています
- 「vLLMに会ってください:高速LLM推論とサービスのためのオープンソース機械学習ライブラリ」
- 「Würstchenをご紹介します:高速かつ効率的な拡散モデルで、テキスト条件付きコンポーネントは画像の高圧縮潜在空間で動作します」
- AutoMLのジレンマ
- 「CodiumAIに会ってください:開発者のための究極のAIベースのテストアシスタント」
- スタビリティAIが安定したオーディオを導入:テキストプロンプトからオーディオクリップを生成できる新しい人工知能モデル
- 「リソース制約のあるアプリケーションにおいて、スパースなモバイルビジョンMoEsが密な対応物よりも効率的なビジョンTransformerの活用を解き放つ方法」