皆さんこんにちは、今日はラージ・ランゲージ・モデリング(LLM)における分詞のテクニックを探ります。残念ながら、曖昧性解消は現在のトップLLMではより複雑で厄介な部分ですが、その詳細を理解することは非常に必要です。なぜなら、多くの人がLLMの欠点のいくつかをニューラルネットワークやその他の一見謎めいた理由のせいにしていますが、実際にはこれらの問題の原因は曖昧性解消技術にあることが多いからです。
前回:文字ベースのセグメンテーション
では、サブテキストとは何か?実は、前回のビデオ [GPTをゼロから構築するで、分数ワードの話をしましたが、それは文字レベルの非常にシンプルで原始的な形に過ぎません。のビデオを見てください。グーグルコラボのページでは、トレーニング・データ([ ])を使用していることがわかります。シェイクスピア作品これはPythonでは非常に長い文字列に過ぎない:
第一市民:話を続ける前に聞いてください。全員:どうぞ、言ってください。ファースト・シチズン:皆さんは飢えるくらいなら死ぬと決めているのですか?全員:決意した。決定。第一市民:まず第一に、ガイアス・マルキウスが国民の一番の敵であることはご存じでしょう。全員:わかっている、わかっている。
しかし、どのようにして文字列を言語モデルに送り込むのだろうか?そのための最初のステップは、トレーニング・データセットを通して見つかるすべての異なる文字を含む語彙テーブルを構築することだ:
パイソン# 本文中に登場する唯一の文字である。chars = sorted(list(set(text)))vocab_size = len(chars)print('.join(chars))print(vocab_size)# !$&',-.3:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz# 65```
その直後に、上記の語彙に基づいて、個々の文字と整数の単語を変換するためのルックアップテーブルを作成します。このルックアップテーブルは実際にはPython辞書です:
パイソンstoi = { ch:i for i,ch in enumerate(chars) }.itos = { i:ch for i,ch in enumerate(chars) }.#エンコーダ:文字列を受け取り、対応する整数のリストを出力する。encode = lambda s: [stoi[c] for c in s].#デコーダー:整数のリストを受け取り、文字列に戻すdecode = lambda l: ''.join([itos[i] for i in l])print(encode("hii there"))print(decode(encode("hii there")))# [46, 47, 47, 1, 58, 46, 43, 56, 43]#さん、こんにちは```
配列を整数に変換すると、各整数は2次元の学習可能な埋め込み行列のインデックスとして使われることがわかる。語彙のサイズは `vocab_size=65` なので、この埋め込み行列も65行になる:
パイソンclass BigramLanguageModel(nn.Module).def __init__(self, vocab_size).super().__init__()self.token_embedding_table = nn.Embedding(vocab_size, n_embd)def forward(self, idx, targets=None).tok_emb = self.token_embedding_table(idx) # (B,T,C)```
ここで「整数」は、トークンを表すベクトルである埋め込みテーブルから行を抽出する。このベクトルは、対応する時間ステップの入力として変換器に供給される。
バイトペアエンコーディング(BPE)アルゴリズムを使用した「文字ブロック」のトークン化
これは初歩的な文字レベルの言語モデルとしては十分である。しかし実際には、最先端の言語モデルは、マークアップ・ボキャブラリーを構築するために、より複雑なスキームを使用している。これらのスキームは文字レベルではなく、文字ブロックレベルで機能する。このような文字ブロック・ボキャブラリーは、バイト・ペア・エンコーディング(BPE)のようなアルゴリズムを使って構築される。
このアプローチの歴史的発展に目を向けると、2019年に発表されたOpenAIのGPT-2論文「Language Models as Unsupervised Multitasking Learners(教師なしマルチタスク学習者としての言語モデル)」は、バイトレベルのBPEアルゴリズムを言語モデルのラベリングに普及させた。このアルゴリズムの説明と動機については、この論文のセクション2.2の「入力表現」をお読みください。このセクションの最後にも彼らのことが書かれている:
語彙は50,257に拡張された。また、コンテキストのサイズを512から1024トークンに増やし、バッチサイズも512と大きくした。
Transformerのアテンション層では、各トークンは前のシーケンスの有限個のトークンに対するアテンションであることを思い出してほしい。この論文では、GPT-2モデルの文脈長は1024トークンであり、GPT-1の512トークンより改善されていると述べている。言い換えれば、トークンは言語長期記憶(LLM)モデルの入力となる基本単位である。トークン化は、Pythonの生の文字列をトークンのリストに変換するプロセスであり、その逆も同様です。この抽象化のユビキタス性を示す他のよく使われる例を挙げると、[ラマ2論文]では、やはり "markers "で検索すると63件の言及がある。例えば、この論文では2兆個のトークンで訓練したなどと主張している。
実装の詳細を掘り下げる前に、トークン化プロセスを掘り下げる必要がある理由を簡単に探ってみよう。トークン化はLLMにおける多くの奇妙な問題の核心であり、軽視しないことをお勧めする。ニューラルネットワークの構造に関連しているように見える問題の多くは、実はトークン化に起因している。いくつか例を挙げよう:
- なぜLLMは単語のスペルを正しく書けないのか?
- なぜLLMは文字列反転のような単純な文字列処理ができないのか?
- なぜLLMは英語以外の言語(例えば日本語)を扱うと成績が悪くなるのか?
- なぜLLMは単純な算術演算が苦手なのか?
- GPT-2はなぜPythonでのプログラミングが難しいのですか?
- なぜLLMは""という文字列に遭遇すると突然動かなくなるのですか?
- 末尾にスペースがある」という奇妙な警告は何なのだろう?
- SolidGoldMagikarp "について尋ねると、なぜLLMはクラッシュするのですか?
- LLMとやりとりするのに、なぜJSONではなくYAMLを使う方がいいのですか?
- なぜLLMは真のエンド・ツー・エンドの言語モデルではないのか?
- 苦しみの根本原因はいったい何なのか?
これらのトピックについては、ビデオの最後で触れることにしよう。
次に、この[ ]をロードしてみよう。トークン化オンラインツール]このオンライン・ツールの利点は、トークン化のプロセスがウェブ・ブラウザ上でリアルタイムに行われることです。入力ボックスにテキスト文字列を簡単に入力し、トークン化の結果を右側ですぐに確認することができます。ページ上部には、現在使用している
gpt2
tokeniserを使うと、例の文字列が300個のトークンに分解されていることがわかる。これらのトークンは明らかに異なる色で表示されている:例えば、"Tokenisation "という文字列はトークン30642としてエンコードされ、その後にトークン1634が続く。スペースは文字列中に確かに存在し、他のすべての文字と一緒にトークン化されなければならないが、視覚的にわかりやすくするため、通常は省略されている。ツールの下部で、スペースの視覚化を切り替えることができる。同様に、トークン "at "は379、"the "は262などです。
次に、簡単な算数の例を見てみよう。ここでは、トークナイザーによって数値が一貫性のない方法で分解される場合があることがわかります。たとえば、127という数字は3文字からなる1つのトークンに分解されるのに対し、677という数字は" 6 "というトークン(ここでも先頭のスペースに注意!)と" 77 "という2つのトークンに分解される。とトークン「77」である。この恣意性を理解するために、我々は大規模な言語モデルに依存している。このモデルは、2つのトークン("6 "と "77")が実際に組み合わさって677を表すことを、パラメータと学習中に学習しなければならない。 同様に、LLMがこの足し算の結果が804になることを予測したい場合、2つのステップでそれを出力しなければならない:まず、トークン "8 "を発行し、次にトークン "04 "を発行する。これらの分解はすべて完全に任意である。下の例では、1275は "12 "と "75 "に分解され、6773は実際には "6 "と "773 "の2つのトークンであり、8041は "8 "と "041 "に分解されることがわかる。
続く(TODO:動画からこのコンテンツを自動的に生成する方法を見つけない限り、おそらくこれを続けるだろう)。