24. microgpt の推論ループ
24.1. この章で学ぶこと
temperature、確率サンプリング、終了条件18 章 B7 に対応する生成フェーズ
24.2. 推論(生成)
学習ループとの主な差分:
観点 |
学習ループ(B6) |
推論ループ(B7) |
|---|---|---|
重みの更新 |
Adam で更新あり |
更新なし(固定) |
logits の扱い |
|
|
次トークン |
ラベルと比較して損失 |
|
まず 推論(生成)ブロック全体(microgpt.py L238〜L251)を引用します。続けて ブロック図と各ブロックの一行概要を置き、そのあと行ごとの意味を列挙します。
238temperature = 0.5 # (0,1]の範囲。低いほど確定的、高いほど多様な出力
239print("\n--- inference (new, hallucinated names) ---")
240for sample_idx in range(20):
241 keys, values = [[] for _ in range(n_layer)], [[] for _ in range(n_layer)]
242 token_id = BOS # BOSから開始
243 sample = []
244 for pos_id in range(block_size):
245 logits = gpt(token_id, pos_id, keys, values)
246 probs = softmax([l / temperature for l in logits]) # temperatureで分布を調整
247 token_id = random.choices(range(vocab_size), weights=[p.data for p in probs])[0] # 確率的サンプリング
248 if token_id == BOS:
249 break # BOSが来たら終端
250 sample.append(uchars[token_id])
251 print(f"sample {sample_idx+1:2d}: {''.join(sample)}")
24.3. 推論ループ内のブロック図と概要
次の図は、上記ソースの制御の流れを (1)~(7) の項番号に対応させたものです。外側は 20 本の独立したサンプル、内側は pos_id による 1 文字ずつの伸長です。
図-1: 推論ループのブロック
行ごとの意味
L238
temperature— logits を割ってからsoftmaxする際の鋭さ(小さいほど上位に集中、大きいほど分散)。L239 推論開始の見出しを表示。
L240 20 通りのサンプルをループ(毎回キャッシュを空にして新系列)。
L241 層ごとの K/V リストを初期化。
L242 最初のトークンは
BOS。L243 生成した文字を溜めるリスト。
L244–L250 位置ごとに
gpt→温度付きsoftmax→random.choicesで 1 トークンサンプル。BOSが出たら系列終了、それ以外はucharsから文字を復元してsampleに追加。L251 生成文字列を表示。
BOS から始めて、次の文字を 1 文字ずつ選んでいきます。temperature は低いと無難に、高いと少し冒険しやすくなります。つまり、このコードだけで学習と生成の両方が見えます。
図-2: 生成フェーズ(学習時よりシンプルな往復)。上のブロック図は制御の流れ、この図はデータの往復の補足です。