TT Lab
はじめる
学ぶ 学習パス コース

MiniMind — 小さな言語モデルを最初から最後まで自分で学習する

MiniMind の学習ループで300ステップ事前学習し、損失曲線を読む

TT Labで続きを見る

目標

MiniMindのtrain_pretrain.pyの骨組み(AdamW・MiniMindのコサイン学習率・勾配クリッピング1.0)をCPUの大きさに縮小した学習ループを自分で書き、シードを固定して再現されるかを確認してから、300学習ステップを学習します。損失曲線を数字で読み、学習率が大きすぎると何が壊れるかを見ます。

なぜ重要なのか

学習ループの核心は2行ですが、結果を分けるのは、その周りの決定です。学習率とそのスケジュール、勾配クリッピング、シード、検証損失を測る間隔です。この決定が間違っていると、数時間回したあとでようやく気づきます。そのため、数分の学習で、曲線の形を先に確認する習慣が必要です。 損失曲線は、モデルが何を先に学ぶのかも見せてくれます。最初の数十学習ステップではトークンの頻度を、そのあとは文脈に応じた規則を学びます。文脈なしで頻度だけを知っているモデルの損失(ユニグラムエントロピー)と比べれば、曲線のどの部分が「文脈を使いはじめた」区間なのかがわかります。

ステップ

  1. スクリプト(/root/mm/pre/train.py)を書き(引数は--steps・--lr・--seed・--eval-every・--out・--log)、同じシードで20学習ステップを2回回して、記録を残してください(出力先: /root/mm/pre/log_a.csv・/root/mm/pre/log_b.csv)。
  2. 300学習ステップ(バッチ8・長さ128・lr 3e-3)を学習して、重みと記録を残してください(重み: /root/mm/pre/ckpt.pth、記録: /root/mm/pre/log.csv)。検証損失が1.6を下回る必要があります。
  3. log.csvから曲線の形を取り出して書いてください(出力先: /root/mm/pre/curve.json)。
  4. 学習配列のユニグラムエントロピーを書いてください(出力先: /root/mm/pre/unigram.json)。
  5. lr 0.05で50学習ステップ回して、記録を残してください(出力先: /root/mm/pre/log_high.csv)。
  6. ckpt.pthを使い、韓国語の文字列「ガラム村の」の後ろを、16トークンぶんグリーディ生成で書き続けさせて、保存してください(出力先: /root/mm/pre/sample.txt)。
  7. ## 손실 곡선 ## 학습률 ## 이어 쓰기の3つのセクションを書き、最後の検証損失とユニグラムエントロピーを数字で入れてください(出力先: /root/mm/pre/report.md)。韓国語の見出しは、順に「損失曲線」「学習率」「続きを書く」という意味です。

参考

同じシードなら同じ損失になる

スクリプト(/root/mm/pre/train.py)を書いてください。/opt/mm/ref/config.jsonでモデルを作り、/opt/mm/ref/train.npyから任意の位置の128トークンをバッチ8個ずつ取り出して学習し、学習ステップごとにstep,train_loss,val_loss,lrを、--logのパスのCSVに記録します。--steps 20で2回回して、2つの記録を作ってください(出力先: /root/mm/pre/log_a.csv・/root/mm/pre/log_b.csv)。

再現するには、2種類の乱数をどちらも固定する必要があります。重みの初期化(mmkit.seed_all(시드)を、モデルを作る前に)と、バッチの選択(torch.Generator().manual_seed(시드)をrandintに渡す)です(プレースホルダーは、どちらもシードです)。最初の学習ステップの損失は、ln 1024 ≈ 6.93の近くになる必要があります。

300学習ステップの事前学習

train.pyで300学習ステップ(バッチ8・長さ128・lr 3e-3・シード42、50学習ステップごとに検証)を学習してください(重み(model.state_dict())の出力先: /root/mm/pre/ckpt.pth、記録の出力先: /root/mm/pre/log.csv)。

学習率は、MiniMindのコサイン(mmkit.minimind_lr)で、最初の学習ステップに3e-3、最後に3e-4になる必要があります。採点ツールは、ckpt.pthを読み込んで検証損失を測り直し、1.6を下回っているか、そして記録の最後のval_lossと同じかを見ます。

曲線の形を数字で取り出す

log.csvから、最初の損失(first_loss)、学習損失が初めて3を下回った学習ステップ(step_below_3)、最後の学習損失(final_train)、最後の検証損失と最低の検証損失(final_val・best_val)を書いてください(出力先: /root/mm/pre/curve.json)。

急に下がる区間が何学習ステップで終わるかを見てください。そのあとは、同じ量だけ下げるのに、はるかに多くの学習ステップが必要です。

頻度だけを知るモデルの損失を計算する

/opt/mm/ref/train.npyのトークン頻度で、ユニグラムエントロピー(−Σ p·ln p、ナット)を計算し、unigram_entropyとして書いてください(出力先: /root/mm/pre/unigram.json)。

文脈をまったく見ず、いつも同じ分布(トークン頻度)を出すモデルのクロスエントロピーが、この値です。曲線がこの値より下に下がれば、モデルが前のトークンを見て、次を絞り込みはじめたという意味です。numpy.bincountが速いです。

学習率が大きすぎると何が起きるかを見る

train.pyを--lr 0.05 --steps 50で回して、記録を残してください(出力先: /root/mm/pre/log_high.csv)。同じシードなので、ステップ2の記録の41–50学習ステップと比べられます。

大きな学習率は、最初の数学習ステップは速く下がるように見えても、一度大きく跳ねたあと、ある値に張りついて下がってきません。勾配クリッピング(1.0)も、1学習ステップの大きさまでは止められません。1学習ステップの大きさは、lrが決めます。

学習したもので続きを書かせる

ckpt.pthを読み込み、[bos] + '가람 마을의'(韓国語で「ガラム村の」を意味する語です)の後ろを、16トークン、グリーディ(do_sample=False, top_k=0, top_p=1.0, eos_token_id=2)で書き続けさせ、bosを除いた全文を保存してください(出力先: /root/mm/pre/sample.txt)。

mmkit.load_model(경로)で読み込み(プレースホルダーはパスです)、MiniMindのmodel.generateを呼べばよいです。グリーディ生成は、同じ重みなら常に同じ文章を出すので、採点ツールが、作成したckpt.pthで再生成して比べます。事前学習だけをしたモデルは、質問に答えず、コーパスのように続きを書きます。

曲線を読んだ記録を書く

## 손실 곡선 ## 학습률 ## 이어 쓰기の3つのセクションを書き、ステップ3のfinal_valとステップ4のunigram_entropyを数字で入れてください(出力先: /root/mm/pre/report.md)。韓国語の見出しは、順に「損失曲線」「学習率」「続きを書く」という意味です。

曲線のどの区間が頻度を、どの区間が文脈を学んだものなのかを、ユニグラムエントロピーを基準に1行書いてください。学習率のセクションには、ステップ5で見たことを書きます。