ChatGPTなどLLMの仕組みを説明してみる(Pythonで超原始版ChatGPTを作成する)


## 1. テキストがモデルに届くまで ― 「前処理」

| ステップ         | 何をやっている？                                          | 例                                                     |
| ------------ | ------------------------------------------------- | ----------------------------------------------------- |
| **① トークン化**  | 文章を「トークン（細切れ）」に分割。<br>文字単位・サブワード単位・単語単位など方式はいろいろ。 | *「ChatGPT はすごい」 → \["Chat", "G", "PT", "▁は", "▁すごい"]* |
| **② ID へ変換** | 各トークンを辞書（語彙表）の番号に置き換える。                           | Chat → 1345, G → 97 …                                 |

> 🔍 **ポイント**
> LLM が “単語” を理解しているわけではありません。あくまで「ID の並び」として学習・推論します。

---

## 2. モデルの中身 ― 「Transformer」のざっくり図解
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125746/0c958b15-0645-4351-a0be-f6e0909cb4d2.png)


1. **埋め込み層 (Embedding)**

   * トークン ID → 高次元ベクトルへマッピング。
2. **多層 Transformer**

   * **自己注意 (Self-Attention)**: 一つのトークンが「系列中の他トークンをどれくらい見るか」を計算。
   * **FFN**: 全結合ニューラルネットで非線形変換。
   * これを何十層も重ねることで、文脈を深く表現できる。
3. **出力線形層 + Softmax**

   * 各語彙 ID ごとに「次トークンになる確率」を出力。
4. **生成 (Sampling)**

   * 温度付きサンプリング、Top-k / Top-p などで 1 語決定。
   * 新しいトークンを入力列の末尾に付け、再び 1-4 をループ → 文章が伸びる。

---

## 3. どう学習する？ ― 「自己教師あり」予測

* 大量のテキストを使い、
  **「直前までを見て、次のトークンを当てる」** というタスクでパラメータを調整。
* 誤差関数: 交差エントロピー (cross-entropy)。
* 最適化: AdamW など。
* こうして “テキストの統計的なクセ” を内部に蓄えます。

---

## 4. 超ミニ実装：ビッグラム（2 語連鎖）モデル

以下のスクリプトは **「直前の 1 語 → 次の 1 語」** という極めて原始的なモデルです。
Transformer とは桁違いに単純ですが、

1. **コーパスからペア (w₁, w₂) を数える**
2. **条件付き確率 P(w₂｜w₁) を求める**
3. **確率に従って次語をサンプリングし、文章を伸ばす**

という “言語モデル” の基本骨格を体験できます。
```python
import random
from collections import defaultdict, Counter

# --- 1. データ準備（とても小さなサンプル） ---
text = (
    "ChatGPT is a large language model. "
    "It predicts the next word based on the context of previous words. "
    "Language models learn patterns in text by seeing lots of examples."
)

# --- 2. 単語に分割（トークン化） ---
tokens = text.lower().split()

# --- 3. ビグラム（2語連鎖）を数え上げ ---
bigrams = defaultdict(Counter)
for w1, w2 in zip(tokens[:-1], tokens[1:]):
    bigrams[w1][w2] += 1

# --- 4. 次の単語をサンプリングする関数 ---
def sample_next(current_word):
    counts = bigrams.get(current_word, None)
    if not counts:                    # 未知語ならランダムにリセット
        return random.choice(tokens)
    total = sum(counts.values())
    r = random.randint(1, total)
    cum = 0
    for word, cnt in counts.items():
        cum += cnt
        if r <= cum:
            return word

# --- 5. テキスト生成 ---
def generate(seed="chatgpt", length=15):
    words = [seed]
    for _ in range(length):
        next_word = sample_next(words[-1])
        words.append(next_word)
    return " ".join(words)

if __name__ == "__main__":
    print(generate())

```

▶️ 実行結果：

```text
chatgpt is a large language model. it predicts the context of examples. previous words. language model.
```

> 実際は 30 億〜数兆語の学習データと **数十〜数百億パラメータの Transformer** を使いますが、やっていることの根っこは「過去を見て次を予測する」だけ、というのがポイントです。

---


## まとめ ― “魔法” ではなく大規模な統計予測

1. **入力をトークン化 → 数値化**
2. **埋め込み + Transformer で文脈ベクトルを計算**
3. **Softmax で「次のトークン分布」を出す**
4. **サンプリングして文章を生成**
5. **学習は「次トークン当てクイズ」をひたすら解く**

この 5 ステップさえ押さえれば、「ChatGPT の中で何が起きているか」の大枠をイメージできます。あとは **モデル規模・計算資源・最適化テクニック** をどこまで大きく／巧みにできるかが、精度と賢さを左右しているわけです。