皆さんこんにちは、今日はラージ・ランゲージ・モデリング(LLM)における分詞のテクニックを探ります。残念ながら、曖昧性解消は現在のトップLLMではより複雑で厄介な部分ですが、その詳細を理解することは非常に必要です。なぜなら、多くの人がLLMの欠点のいくつかをニューラルネットワークやその他の一見謎めいた理由のせいにしていますが、実際にはこれらの問題の原因は曖昧性解消技術にあることが多いからです。
原文ママhttps://github.com/karpathy/minbpe
前回:文字ベースのセグメンテーション
では、サブテキストとは何か?実は、前回のビデオ [GPTをゼロから構築するで、分数ワードの話をしましたが、それは文字レベルの非常にシンプルで原始的な形に過ぎません。のビデオを見てください。グーグルコラボのページでは、トレーニング・データ([ ])を使用していることがわかります。シェイクスピア作品これはPythonでは非常に長い文字列に過ぎない:
第一市民:話を続ける前に聞いてください。
全員:どうぞ、言ってください。
ファースト・シチズン:皆さんは飢えるくらいなら死ぬと決めているのですか?
全員:決意した。決定。
第一市民:まず第一に、ガイアス・マルキウスが国民の一番の敵であることはご存じでしょう。
全員:わかっている、わかっている。
しかし、どのようにして文字列を言語モデルに送り込むのだろうか?そのための最初のステップは、トレーニング・データセットを通して見つかるすべての異なる文字を含む語彙テーブルを構築することだ:
"`python#これはテキストに現れる唯一の文字である chars = sorted(list(set(text)))vocab_size = len(chars)print(".join(chars))print(vocabサイズ)
# !$&',-.3:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz# 65"`.
その直後に、上記の語彙に基づいて、個々の文字と整数の単語を変換するためのルックアップテーブルを作成します。このルックアップテーブルは実際にはPython辞書です:
"`pythonstoi = { ch:i for i,ch in enumerate(chars) }itos = { i:ch for i,ch in enumerate(chars) }# Encoder: 文字列を受け取り、対応する整数のリストを出力 encode =lambda s: [stoi[c] for c in s]# Decoder: 整数のリストを受け取り、文字列に戻す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]# hii there"`.
配列を整数に変換すると、各整数は2次元の学習可能な埋め込み行列のインデックスとして使われることがわかる。語彙のサイズは `vocab_size=65` なので、この埋め込み行列も65行になる:
"`pythonclass BigramLanguageModel(nn.Module).
def __init__(self, vocab_size):super().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が続きます。トークン "is "のインデックス(ここには3つの文字があることに注意してください。)トークンのインデックスは318です。スペースは文字列中に確かに存在し、他のすべての文字と一緒にトークン化されなければならないので注意してください。ツールの下部で、スペースの視覚化を切り替えることができる。同様に、トークン "at "は379、"the "は262などです。
次に、簡単な算数の例を見てみよう。ここでは、トークナイザーによって数値が一貫性のない方法で分解される場合があることがわかります。例えば、127という数字は3文字からなる1つのトークンに分解されますが、677という数字は2つのトークンに分解されます。とトークン "77″に分解される。この恣意性を理解するためには、大規模な言語モデルに頼らざるを得ない。このモデルは、2つのトークン("6″と "77″)が組み合わさって677という数字を表すことを、パラメータと学習中に学習しなければなりません。 同様に、LLMがこの足し算の結果の数字が804であることを予測したい場合、2つのステップで出力しなければなりません。次にトークン "04″を出力する。これらの分解はすべて完全に任意である。下の例では、1275は "12″と "75″に分解され、6773は実際には "6″と "773″の2つのトークンであり、8041は "8″と"041″.
(続く...)(TODO:動画からこのコンテンツを自動的に生成する方法を見つけない限り、おそらくこれを続けるだろう)。