0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

運用・可視化編:Wandbで学習をコントロールする

0
Last updated at Posted at 2026-04-28

はじめに

この記事では、ミニマルな GPT 実装(microGPT)を題材に、

  • ひらがな名前データでの学習
  • Weights & Biases(W&B)による学習曲線の可視化
  • 学習済みモデルを使った名前生成

までを一通り回し、その実行結果から見えてきたことをまとめます。

コードは、以下の 2 本を前提にしています。

  • 学習用:microgpt_train.py
  • 生成用:microgpt_generate.py

どちらも外部フレームワーク(PyTorch 等)には依存せず、標準ライブラリと W&B だけで動く「自作 Transformer」です。

※また 2WINS では隔週で社内勉強会を開催しており、本稿は第15回勉強会「TransformerとGPTの仕組み」で扱った内容をベースに、GPT の内部構造理解を目的として microgpt を題材に学習した内容を発展させたものです。


1.1 実行方法のおさらい

まずは、このリポジトリでよく使う実行コマンドを整理します。

# 学習(デフォルト設定でモデルを学習)
uv run microgpt_train.py

# ハイパーパラメータを変えて学習
# 埋め込み次元とヘッド数を増やして、少し大きめのモデルを試す
uv run microgpt_train.py --n_embd 64 --n_head 8

# 学習ステップ数と学習率を変えて、収束の仕方の違いを観察する
uv run microgpt_train.py --num_steps 2000 --lr 0.005

# 生成(学習済みの最新の重みからランダムに名前を生成)
uv run microgpt_generate.py

# 「あ」から始まる名前だけに絞って 10 個生成する
uv run microgpt_generate.py --start-n 10

# temperature を上げて、より多様でランダム性の高い名前を生成する
uv run microgpt_generate.py --temperature 0.8

この記事では、この 3 パターンの学習条件と、対応する生成結果を見ながら考察していきます。また、ここでmicrogpt_train.py,microgpt_generate.pyを掲示しておきます。

1.2 環境構築

W&B 公式だと、まずはこのあたりを見るのがおすすめです。

W&B クイックスタート(インストール〜最初の実行)
https://docs.wandb.ai/ja/models/quickstart
→ pip install wandb、wandb login、wandb.init() の基本的な使い方がまとまっています。

ガイド一覧ページ(導入ガイドへの入口)
https://docs.wandb.ai/ja/guides
→ 「W&B のインストール方法と W&B をコードに追加する方法を学ぶために、quickstart を試してみてください」と案内されているページです。
もし APIキーを環境変数で持たせたい / サーバ環境で使いたい 場合は、以下も公式ドキュメントです。

環境変数の設定(W&B SDK 用)
https://docs.wandb.ai/ja/models/track/environment-variables
→ WANDB_API_KEY などの環境変数一覧と設定方法が載っています。

2. 学習条件と W&B の設定

デフォルト設定

学習スクリプトのデフォルト値は次のとおりです。

  • 層数:n_layer = 1
  • 埋め込み次元:n_embd = 48
  • ヘッド数:n_head = 4
  • 最大コンテキスト長:block_size = 16
  • 学習ステップ数:num_steps = 1000
  • 学習率:lr = 0.01
  • データセット:ひらがな名前(約 220 件)

W&B には、以下のように run を記録しています。

  • project 名:workshop-microgpt
  • run 名:jp-names_L{n_layer}_E{n_embd}_H{n_head}
  • config:
    • n_layer, n_embd, n_head, head_dim
    • block_size, vocab_size
    • learning_rate, num_steps
    • dataset, num_docs など

学習ループ内では、各 step ごとに次の指標をログしています。

  • train/loss:クロスエントロピー損失
  • train/perplexityexp(loss) として計算したパープレキシティ
  • lr:線形減衰させた学習率

3. W&B 上の学習曲線(3 条件比較)

今回は次の 3 条件で学習を回し、それぞれの train/losstrain/perplexity の曲線を比較しました。

  1. デフォルト設定

    • uv run microgpt_train.py
    • n_layer=1, n_embd=48, n_head=4, num_steps=1000, lr=0.01
  2. モデルを大きくした設定

    • uv run microgpt_train.py --n_embd 64 --n_head 8
    • n_layer=1, n_embd=64, n_head=8, num_steps=1000, lr=0.01
  3. step 数と学習率を変えた設定

    • uv run microgpt_train.py --num_steps 2000 --lr 0.005
    • n_layer=1, n_embd=48, n_head=4, num_steps=2000, lr=0.005

W&B 上では、それぞれ色を変えてプロットしました(ここでは便宜上、以下のように呼びます)。

  • 緑:ステップ数 2000、学習率 0.005
  • 赤:埋め込み次元 64 / ヘッド数 8
  • 青:デフォルト設定(48 次元 / 4 ヘッド)

スクリーンショット 2026-04-18 225851.png

スクリーンショット 2026-04-18 225840.png

スクリーンショット 2026-04-18 225828.png

3.1 共通して言えること

観察 原因
train/loss は全体的に右下がり 学習が進行している
ステップごとにギザギザしている データが 1 件ずつの小規模セットであり、シャッフルにより「簡単/難しい」サンプルが偏ってくるため

これらより、学習自体はうまく進んでいると言えます。

一方で、グラフはどれもかなりギザギザしています。 これは、

  • データが名前 1 件ずつの小規模セット
  • 各 step で 1 サンプル単位の loss をそのまま記録
  • docs をシャッフルしながら学習

しているため、step ごとに「たまたま難しいサンプル」「簡単なサンプル」が混ざりやすく、そのノイズが loss / perplexity に強く乗っているためです。ここでの「簡単/難しい」は、理論的な定義ではなく、今回の名前データに対して loss が下がりやすいかどうか、という実験的な感覚に基づいた分類です。少し補足説明しておきます。

分類 特徴 具体例 loss への影響
簡単 頻出パターン。次トークンがほぼ 1 通りに絞れる あや→か, しょう→す/た 小さくなりやすい
難しい 希少・分散パターン。次候補が多いか長さが外れ値 あ→きこ/や/い, 6〜7文字の名前 跳ね上がりやすい

こういう名前は、モデルから見ると「次の文字を当てづらい」ので、その step の loss が跳ね上がりやすくなります。下図をイメージすると分かりやすいかもしれません。

正規分布図.png

3.2 モデルを大きくした場合(赤)

--n_embd 64 --n_head 8 でモデルを少し大きくした run は、デフォルトと比べて loss / perplexity の曲線の形が大きく変わる、ということはありませんでした。

条件 学習曲線の特徴 示唆
赤:モデル拡大 デフォルトと大差なし。最終 loss/perplexity も同等 小規模データ+短い学習では、わずかな容量増加だけでは決定的な差が出にくい
緑:長め+低 LR 1000 step 以降も継続的に低下し、最終値が最も低い モデル容量よりも「学習率+ステップ数」の調整が、小規模設定では効きやすい

つまり今回の規模(データ 220 件・step 数 1000)では、

「モデルを少し大きくする」こと自体は、短い学習予算の範囲では決定的な差にはならなかった

と言えそうです。

もちろん、もっと長く回したり、別の初期値・シードを使ったりすれば差が出る可能性はありますが、「手軽に 1 回ずつ回した程度」の比較では、モデルサイズ増加のインパクトはあまり見られませんでした。

3.3 step 数と学習率を変えた場合(緑)

--num_steps 2000 --lr 0.005 の run は、

  • num_steps を倍(1000 → 2000)
  • lr を半分(0.01 → 0.005)

にした条件です。

この run の学習曲線をみると:

  • 初期のスパイクはあるものの、1000 step 以降も loss / perplexity がさらに下がり続ける
  • 最終的な loss / perplexity は、他の 2 条件よりも明らかに低い位置に落ち着く

という挙動を示しました。

ここから分かることは、

今回の microGPT 設定では、「学習率をやや抑えつつ、step 数を増やして長めに回す」方が、短時間で大きなモデルを試すよりも収束の改善がはっきり見えた

ということです。

この結果は、特に小規模データ+シンプルなモデルでは、

  • モデル容量をむやみに増やすより、
  • optimizer 側(lr やスケジュール)と学習時間の調整の方が効きやすい

という、典型的な傾向とも一致しています。


4. 名前生成の結果

学習済みの重み L1_E48_H4_S2000.pkl(1 層・48 次元・4 ヘッド・2000 step 学習)を使って、実際に名前を生成してみました。

4.1 「あ」から始まる名前を 10 個生成

uv run microgpt_generate.py --start-n 10

出力:

重み: L1_E48_H4_S2000.pkl (vocab=60, embd=48, head=4)
--- 「あ」から始まる名前を 10 個生成 ---
   1: あお
   2: あきこ
   3: あみ
   4: あや
   5: あきら
   6: あいな
   7: あきこ
   8: あおり
   9: あきと
  10: あみ
  • 「あきこ」「あきら」「あきと」「あや」「あみ」など、日本語として自然な名前が多数生成されています。
  • 「あお」「あおり」など、既存の名前としても見かける形が出ている一方で、完全には見慣れない形も混じるあたりが、いい意味でのランダム性です。
  • 同じ名前(例:あきこ, あみ)が複数回出ているのは、学習データ中の頻度や、モデルが覚えたパターンの「確率の高さ」を反映していると考えられます。

4.2 完全ランダムに 20 個生成

uv run microgpt_generate.py

出力:

重み: L1_E48_H4_S2000.pkl (vocab=60, embd=48, head=4)
--- ランダムに名前を 20 個生成 ---
   1: あおり
   2: あい
   3: けんと
   4: あきと
   5: みどり
   6: ゆうた
   7: まさひろ
   8: かずき
   9: えみ
  10: あやか
  11: あみ
  12: まさこ
  13: まさひろ
  14: しずひ
  15: ゆづき
  16: しょうすけ
  17: あお
  18: ゆうか
  19: そうすけ
  20: えい

ここでも、

  • 「けんと」「ゆうた」「かずき」「あやか」「ゆづき」「しょうすけ」「そうすけ」など、よくある名前が多く出力されている
  • 「しずひ」「えい」など、若干不思議な形も混ざっている

という結果になりました。

「完全にデタラメ」というよりも、「聞いたことのある名前と、ギリギリ名前っぽいものの中間」に収まっているのが分かります。
これは、モデルが「ひらがな列としてのパターン」を学習していることの良い証拠です。

4.3 temperature を 0.8 に上げて 20 個生成

uv run microgpt_generate.py --temperature 0.8

出力:

重み: L1_E48_H4_S2000.pkl (vocab=60, embd=48, head=4)
--- ランダムに名前を 20 個生成 ---
   1: しのぶ
   2: あやか
   3: しんじ
   4: なつき
   5: かなで
   6: えな
   7: まゆ
   8: ゆめ
   9: さちこ
  10: たくみ
  11: ゆめ
  12: かずお
  13: いつき
  14: くみ
  15: まなみ
  16: なおゆき
  17: あい
  18: たくみ
  19: さちこ
  20: ゆうせい

ちなみに、ここで使っている temperatureとは、ChatGPT や各種 API で見かけるものと同じで、「確率分布をどれだけ尖らせる/広げるか」のパラメータです。このパラメータを出力のランダム性と多様性を調整する際に使います。0~1か2の範囲で指定でき、temperatureの値が高くなればなるほどランダム性の高い表現が生成され、低いほどより正確な解答が返ってきます。下図でイメージすると分かりやすいかもしれません。

temperature_sampling-1.png

引用:https://www.mdrk.io/temperature-samplig-in-ai/ Temperature Sampling and Scaling in AI and LLMs

この図では、LLM が次のトークンを選ぶ状況を、アイスクリームのフレーバー選択に見立てて可視化しています。「Vanilla」「Strawberry」などの各フレーバーが 1つのトークン候補 に対応しており、縦軸の値はそのトークンが次に選ばれる確率を表しています。実際の LLM では語彙数が数万〜数十万に及びますが、ここでは概念の理解を優先し、候補を少数に絞った簡略モデルを用いています。

話を戻して、temperature を 0.8 にすると

  • 「しのぶ」「しんじ」「なつき」「かなで」「ゆめ」「さちこ」「たくみ」「いつき」「まなみ」「なおゆき」「ゆうせい」など、現実にありそうな名前のバリエーションが一気に増えました。
  • 一方で、破綻した文字列(明らかに名前になっていないもの)はほとんど出ていません。

今回の例の範囲では、

  • temperature = 0.5(デフォルト)
    → わりと「安定寄り」で、よく見る名前に寄りがち
  • temperature = 0.8
    → 少しランダム性が増しつつ、まだ「名前として十分読める」範囲に収まっている

という印象を受けました。


5. 学習曲線と生成結果から分かること

今回の 3 条件の学習と生成結果から、ざっくり次のようなことが言えます。

  1. microGPT でも、ひらがな名前のパターンはしっかり学習できる

    • loss / perplexity は右下がりで、学習が進んでいる
    • 生成される名前も、人間が読んで「名前だ」と感じるレベルになっている
  2. モデルを少し大きくしても、短い学習では劇的な差は出なかった

    • n_embd=64, n_head=8 の run は、n_embd=48, n_head=4 と比べて学習曲線が大きく改善したとは言いにくい
    • 小規模データ+短い学習では、「モデルを大きくするだけ」では性能差が出にくいケースを確認できた
  3. 学習率と step 数の調整は効きやすい

    • num_steps=2000, lr=0.005 の run は、他の条件より最終 loss / perplexity が低くなった
    • 生成結果も自然さ・多様性ともに良好で、「学習を少し長めに回し、学習率を抑える」ことの効果が見て取れた
  4. temperature で「名前の攻め方」をコントロールできる

    • 低め(0.5)では無難でよくある名前が多く、高め(0.8)ではやや攻めた名前が増える
    • どちらも破綻しない範囲なので、好みや用途に応じて変えられる

6. おわりに

microGPT のような小さな実装でも、W&B を使って loss / perplexity を可視化し、ハイパーパラメータ(モデルサイズ・学習率・step 数)を変え、生成結果を見ながら手触りを確認するという一連の「実験サイクル」を回すことで、「モデルをどういじると学習と生成がどう変わるか」 をかなり感覚的に掴むことができます。

本番用の巨大モデルとはスケールが違いますが、

  • 自動微分
  • Transformer ブロック
  • 次トークン予測
  • 学習率スケジュール
  • temperature によるサンプリング制御

といった、LLM の核になる要素はすべて同じです。

大きなモデルを触る前に、こういったミニマル実装で「学習と推論のフロー」を体験しておくと、後からフレームワークのコードを読んだときにも理解がスムーズになるはずです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?