一文まとめ: モデルがどれほど巨大で、トレーニングにいくらかかったとしても、LLMは2つのものとして理解できます。パラメータが詰まったファイルと、インファレンスを実行するプログラムです。
2.1 GPTはどうやって答えるのか?
第1章では、GPTがどこから来たのかを見てきました。次は、もっと根本的な問いを立てましょう。
GPTはどうやって、1トークンずつ答えを生成しているのか?
2.1.1 列車の前に線路を敷く
私は、列車が自分の進む先に線路を敷きながら走っていく、というイメージが好きです。
列車は終着駅まで一気にジャンプすることはできません。小さな動作を繰り返すことで前に進んでいきます。
- 線路を1本敷く
- その線路の上に進む
- 次の線路を敷く
- また進む
GPTもほとんど同じやり方でテキストを生成します。
- 列車 = モデル
- 線路 = 生成済みのトークン
- 線路を敷く = 次のトークンを予測する
モデルは通常、答え全体を一度に出すことはありません。次のトークンを予測し、それをコンテキストに追加し、また予測する、を繰り返します。
チャットUIでテキストが少しずつ現れるのは、このためです。演出のためのアニメーションではありません。モデルは実際にステップごとに生成しているのです。
2.1.2 なぜ次のトークン予測なのか?
「答え全体を一度に出力すればよいのでは?」と思うかもしれません。
しかし、言語には可能な続きの組み合わせが多すぎます。1つの質問にも妥当な答えはたくさんありますし、それぞれの答えにもさまざまな表現があります。段落をまるごと一度に予測しようとすると、巨大な組み合わせ空間から選ばなければなりません。
次のトークン予測は、この問題を扱いやすくしてくれます。
ここまでの内容を踏まえて、次に来るべきトークンは何か?
専門用語では、これを自己回帰生成 (autoregressive generation) と呼びます。「自己」とは、モデルが自分の出力を次のステップの入力に戻すことを意味します。答えは、自分自身の前置きをコンテキストとして使いながら伸びていくのです。
2.2 テキストの頻度に隠れたシグナル
GPTが次のトークンを予測するなら、何が起きやすいかをどうやって知っているのでしょうか?
2.2.1 シンプルな思考実験
次のような前置きを見たとします。
The agent opened a pull ...
次に来るのは何でしょうか?
ほとんどの英語話者は、こう続けるはずです。
request
これは魔法ではなく、統計的なパターンです。現代のエンジニアリング文書では、「opened a pull request」が「opened a pull quote」や「opened a pull tab」よりもはるかに多く現れます。
言語モデルは、こうしたパターンを巨大なスケールで学習します。
- 「opened a pull」のあとには「request」が来やすい
- 「the build turned」のあとには「green」が来やすい
- 「vibe-coded a」のあとには、文脈次第で「prototype」や「demo」が来やすい
GPTは単純な頻度表ではありませんが、頻度は直感の出発点です。
2.2.2 統計からニューラルネットワークへ
生の頻度表をそのまま保存することは現実的に不可能です。あらゆる文脈に対してエントリを持たなければならないからです。
モデルはこの問題を、統計的なパターンをニューラルネットワークに圧縮することで解決しています。
処理の流れはこうなります。
- 入力: 「The agent opened a pull」のようなコンテキスト
- ニューラルネットワーク: 学習済みの大量のパラメータ
- 出力: 次に来るトークンの確率分布
たとえば、こんな具合です。
| 候補トークン | 確率 |
|---|---|
request | 54% |
tab | 12% |
quote | 8% |
| その他のトークン | 残りの確率 |
モデルは最も確率の高いトークンを選ぶことも、分布からサンプリングすることも、確信度と多様性のバランスをとるデコーディング戦略を使うこともできます。
パラメータはモデルが学習した記憶です。数十億のパラメータを持つモデルは、テキストから学んだパターンをエンコードした数十億の数値を保持しています。
2.3 自己回帰生成をステップごとに見る
それでは、ループの様子を観察してみましょう。
2.3.1 シンプル版
プロンプトがこう始まったとします。
The agent
モデルのループはこんな出力をするかもしれません。
- 入力
The agent-> 出力opened - 入力
The agent opened-> 出力a - 入力
The agent opened a-> 出力pull - 入力
The agent opened a pull-> 出力request - 入力
The agent opened a pull request-> 出力.
各ステップで、モデルは前置き全体、つまりユーザーのプロンプトとそれまでに生成したトークンすべてを使います。
2.3.2 詳細版
繰り返されるパターンはこうです。
コンテキスト -> モデル -> 次のトークン -> 追加 -> 新しいコンテキスト
これは、いずれかの停止条件が満たされるまで続きます。
- モデルが終端トークン (end-of-text) を出力する
- システムが最大トークン数に達する
- ユーザーまたはアプリケーションが生成を止める
2.3.3 なぜ遅く感じるのか
新たに100トークンを生成するということは、モデルを100回走らせるということです。各ステップは前のコンテキストを必要とします。後の章では、KVキャッシュを使って毎回ゼロから再計算することを避ける方法を紹介しますが、大枠の考え方は変わりません。
テキスト生成は単発ではなく、ループである。
2.4 トレーニングには何が必要か?
インファレンスを理解したら、次の問いはトレーニングです。
大規模モデルをトレーニングするには、次のものが必要です。
大量のデータ + 大量の計算 + 大量のエンジニアリング労力
2.4.1 データ
トレーニングデータには次のようなものが含まれます。
- ウェブページ
- 書籍
- 論文
- コード
- 指示データ
- 人間の選好データ
データはクリーニング、フィルタリング、重複除去、そして慎重な配合が必要です。モデルが大きくなったからといって、悪いデータが消えてくれるわけではありません。Garbage in, garbage out の法則は依然として有効です。
2.4.2 計算
70Bクラスのモデルでは、ハイエンドGPUを数千台、数日間動かす必要があります。覚えやすいオーダーの目安としては、整備済みテキスト約10TB、NVIDIA A100 GPU 約6,000台、トレーニング期間約12日、浮動小数点演算数約10^21、といったところです。
具体的な数値は、トレーニングのレシピやハードウェア、データの配合、実装効率によって変わるので、これらは普遍的な請求書ではなくスケール感の直感として受け取ってください。ただし、方向性は安定しています。
- ハードウェアは高い
- 電気代は高い
- 分散処理の障害コストは高い
- 熟練エンジニアの時間は高い
これが、最先端モデルのトレーニングに数百万ドルかかると言われる理由です。大規模なランの目安として「およそ200万ドル」というのは便利なアンカーですが、ハードウェアの所有コスト、人件費、失敗したラン、データ整備、サービング基盤などを思い出すと、実際の総コストはずっと高くなり得ます。(GPT-4 のような最先端モデルは、トレーニングコストがさらに2桁高いとされています。)
2.4.3 MoE: すべてを動かさずに巨大化する
モデルの容量を増やす1つの方法が、Mixture of Experts、すなわちMoEです。
すべてのトークンに対して全パラメータを動かすのではなく、ルーターを使って少数のエキスパートネットワークを選びます。これによって、パラメータ数を非常に大きく保ちつつ、トークンあたりの計算量を扱いやすい範囲に抑えることができます。
イメージはこうです。
1つの巨大な密モデル -> 多数のエキスパート、トークンごとにごく一部だけがアクティブ
MoEについては後の章で改めて取り上げます。
2.5 ユーザーが見ているのはチャットボックス
これだけの仕掛けがあっても、ユーザーが目にするものはとてもシンプルです。
ユーザーの視点では、
- メッセージを入力する
- 答えを受け取る
- 会話を続ける
- ターンをまたいだコンテキストに頼る
このシンプルなインターフェースの裏側では、
- ニューラルネットワークがコンテキストをロジットに変換する
- ロジットが確率になる
- 確率がトークンになる
- トークンがテキストになる
- ループが繰り返される
このインターフェースとメカニズムのギャップを理解することが、LLMをエンジニアリングシステムとして理解するための第一歩です。
2.6 中心となる発想: 大規模モデルは2つのファイル
ここで、本章で最も重要な考え方にたどり着きます。
Andrej Karpathy は、こんなフレーミングをしています。
大規模言語モデルとは、2つのファイルのことだ。
これはどういう意味でしょうか?
2.6.1 ファイル1: パラメータ
パラメータファイルには、学習された数値が格納されています。
大規模モデルの場合、このファイルは数十GBから数百GBに及びます。fp16で保存された70Bモデルなら、パラメータだけで約140GBになります。中身はラベルでもルールでも手書きの事実でもありません。トレーニング中に学習された浮動小数点の数値です。
パラメータファイルはこう捉えてください。
データから学んだ統計的構造を圧縮したもの
2.6.2 ファイル2: インファレンスコード
インファレンスコードはパラメータをロードし、フォワードパスを実行します。
- 入力をトークナイズする
- 埋め込みを引く
- Transformerブロックを通す
- ロジットを計算する
- 次のトークンをサンプリングする
- 繰り返す
Karpathyの llama2.c はこれを見事に示しました。LLaMA系モデルのコアなインファレンスロジックは、約500行のCで書けるのです。
コードは自明ではありませんが、神秘的なものでもありません。
2.6.3 このフレーミングがなぜ重要か
「2つのファイル」という発想は、後で出てくるいくつかの概念を理解するのに役立ちます。
- デプロイ: パラメータをロードし、インファレンスコードを実行する。
- 量子化: パラメータファイルを圧縮する。
- ファインチューニング: 新しいデータをもとに一部のパラメータを調整する。
- LoRA: 全部を書き換えるのではなく、小さなパラメータの差分を保存する。
- サービング: インファレンスループを高速化し、バッチ化し、キャッシュし、観測可能にする。
魔法のような感覚は薄れていきます。残るのは数学とエンジニアリングです。
2.7 章のまとめ
2.7.1 重要な概念
| 概念 | 意味 |
|---|---|
| 自己回帰生成 | 1度に1トークンずつ生成し、前の出力を新しいコンテキストとして使う |
| 次のトークン予測 | コンテキストを与えると、次のトークンの確率分布を出力する |
| パラメータ | トレーニングデータから得られたパターンをエンコードする学習済み数値 |
| 2つのファイル | パラメータとインファレンスコード |
2.7.2 覚えておきたい数値
| 項目 | おおまかな直感 |
|---|---|
| トークン生成 | 新しいトークン1つにつきモデルを1回実行 |
| パラメータ | 数十億の学習済み数値 |
| トレーニングデータ | クリーニング・配合済みのテキスト/コード/指示データ |
| 70Bパラメータファイル | fp16で約140GB |
| LLaMA-2-70Bのトレーニング | A100 GPU 約6,000台、約12日、重み約140GB |
| トレーニングコスト | 数百万ドル。約200万ドルは目安アンカーであって固定価格ではない |
| インファレンス | フォワードパスを繰り返し実行する |
2.7.3 結論
LLMは機械の中の幽霊ではない。次のトークンを繰り返し予測する、パラメータファイルとコードである。
章のチェックリスト
この章を読んだあとは、次のことができるようになっているはずです。
- 自己回帰生成をシンプルなアナロジーで説明できる。
- 次のトークン予測がなぜ実用的なトレーニングターゲットなのかを説明できる。
- 生成がなぜ繰り返しのループになるのかを説明できる。
- 「2つのファイル」というフレーミングを説明できる。
- パラメータ、インファレンスコード、量子化、ファインチューニングをつなげて説明できる。
- 70Bモデルのトレーニングに必要なGPU数、ドル、トークン数の桁感をおおよそ言える。
次章でまた
ここまでで本章はおしまいです。大事なのはすべての数値を暗記することではなく、モデルを「幽霊」として扱うのをやめることです。
モデルがパラメータとインファレンスコードの組であるとわかったので、次はそのインファレンスコードが実際に何をしているのかを描いた地図が必要になります。
第3章では、その地図を示します。入力テキストから出力確率までの、Transformerの全体フローです。