コンテンツにスキップ

5. 次のトークンを選ぶ

モデルの最後の出力は、語彙(ボキャブラリ)トークナイザが知っているトークンの一覧。LLM は、この一覧のどれか 1 つを次のトークンとして選ぶ。語彙の数を語彙サイズという。用語集でくわしく →のすべてのトークンに対するスコア(ロジット(logits)モデルが最後に出す、語彙のトークン 1 つ 1 つに対するスコア。大きいほど「次に来そう」という意味だが、まだ確率ではなく、負の値もとる。用語集でくわしく →)です。ここから次の 1 トークンを選びます。

この回の入力と出力
  • 入力: logits(語彙数ぶんの実数。GPT-2 なら 50,257 個)。例:「猫が魚を食べた。それは新鮮だった」の次として、「。」に 9.1、「ね」に 7.4、「が」に 6.2、…(数値は下のデモ用の仮の値。前の回の小さな計算例 [2, 1, 0] とは別)
  • 途中で作るもの: 確率(語彙数ぶん。すべて 0 以上で、合計 1)
  • 出力: 次のトークン 1 個(例:「。」)
  • その後: 選んだトークンの ID を ID の列の末尾に足して 11 個にし、埋め込みからもう一度計算する

logits はただの実数で、負の値もあります。これを softmax(ソフトマックス)数値の並びを、すべて 0 以上で合計がちょうど 1 になる「確率の並び」に変える関数。元の値が大きいものほど大きな確率になる。用語集でくわしく → で確率分布起こりうる結果のそれぞれに、どれくらいの確率で起こるかを割り当てたもの。確率はすべて 0 以上で、合計は 1。用語集でくわしく →に変えます。ziz_i を ii 番目のトークンの logit とすると、

pi=ezi∑jezjp_i = \frac{e^{z_i}}{\sum_j e^{z_j}}

pip_i は ii 番目のトークンの確率、ee は約 2.718 の定数(ネイピア数)、分母の ∑j\sum_j は語彙のすべてのトークンについての合計です。指数関数をかけてから合計で割るので、すべて正の値になり、合計は 1 になります。

例:前の回の出力層の小さな例(候補は「。」「ね」「が」の 3 つで、logits は [2, 1, 0])なら、e2≈7.39e^2 \approx 7.39、e1≈2.72e^1 \approx 2.72、e0=1e^0 = 1 で、合計は約 11.1。それぞれを合計で割ると、確率は約 [0.67, 0.24, 0.09] になります。

ez+1/ez=ee^{z+1} / e^{z} = e なので、logit が 1 違うと、確率は約 2.7 倍違います。差が 2 なら約 7.4 倍、差が 3 なら約 20 倍と、logits の差が少し増えるだけで、確率の比は急に大きくなります。

  • 貪欲法(greedy): 常に一番確率の高いトークンを選ぶ。同じ入力なら毎回同じ文章になり(実際のサービスでは、計算の細かな誤差でわずかに変わることもある)、同じ言い回しを繰り返しやすい。
  • サンプリング: 確率に従ってサイコロを振る。自然で多様な文章になるが、まれに変なトークンも選ばれる。

その中間を調整するのが、次の 3 つのつまみです。

  • temperature TT:logits を TT で割ってから softmax にかける。T<1T<1 で一番手に集中し、T>1T>1 で平らになる。T→0T \to 0 で貪欲法と同じ(一番大きい logit が 1 つだけなら)。
  • top-k:確率の高い上位 kk 個だけを残す。確率の低い候補を切り捨てて、選ぶ範囲を絞る(候補の数は分布によらず kk 個)。
  • top-p(nucleus):上位から確率を足していき、合計が pp に達するまでを残す。自信があるときは候補が少なく、迷っているときは多くなる。

残した候補だけで確率を割り直してから(合計が 1 になるように)、サンプリングします。

top-p の例:確率が [0.67, 0.24, 0.09] で p=0.9p = 0.9 なら、上から足して 0.67 → 0.91 で 0.9 に達するので、2 個が残ります(割り直すと約 [0.74, 0.26])。迷っている分布 [0.40, 0.35, 0.25] なら、0.40 → 0.75 → 1.00 で、3 個とも残ります。

temperature が効く理由:logits [2, 1, 0] を T=0.5T = 0.5 で割ると [4, 2, 0] になり、差が 2 倍に開きます。softmax にかけると約 [0.87, 0.12, 0.02] で、一番手に集中します。TT を 0 に近づけるほど差は限りなく開き、一番手の確率が 1 に近づく(貪欲法と同じになる)のです。ただし、一番大きい logit が同点で複数あるときは、その候補どうしで確率を分け合います。

次のトークンを選んでみる
「猫が魚を食べた。それは新鮮だった」の次に来る確率(点線 = 調整前の確率、灰色 = 候補から除外)
。
75.2%
ね
13.7%
が
4.1%
よ
2.8%
!
2.1%
けど
1.1%
わ
0.5%
、
0.3%
から
0.2%
猫
<0.1%

temperature を下げると一番手に集中し、上げると平らになります。top-k は上位 k 個、top-p は累積確率が p に達するまでの上位だけを残して、確率を割り直します。

  • 例文「…それは新鮮だった」で 1 回サンプリングする: 上の IOBox の logits(「。」9.1、「ね」7.4、「が」6.2、…)から確率を作り、多くの場合「。」が選ばれます。これで例文が 1 トークン伸びます。

  • 「吾輩は…」で temperature を 0.1 まで下げる: ほぼ確実に「猫」になります。上げていくと「人間」や「犬」も出始めます。

  • top-p だけを効かせて、迷い具合で候補数が変わるのを見る:

    1. 「設定を初期値に戻す」を押す(temperature 1、top-k 10。このデモでは候補を 1 つも切らない設定)
    2. 「好きな食べ物は…」を選び、top-p を 0.5 にする → 候補が拮抗しているので、3 個残ります
    3. 「吾輩は…」に切り替える → 「猫」だけが残ります

    top-p は「モデルの迷い具合」に合わせて候補数が変わるのが特徴です。

  • 100 回サンプリングする: 「好きな食べ物は…」を選び、「設定を初期値に戻す」を押してから試します。各候補が選ばれた回数を 100 で割ると、棒グラフの確率に近い値になることを確かめましょう。

選んだトークンの ID を入力の末尾に足し、もう一度モデル全体を計算して、次のトークンを選ぶ。LLM の文章生成は、これを「終わり」を表す特別なトークン(終了トークン)が出るか、決めた長さに達するまで繰り返しているだけです(自己回帰生成)。

同じ質問をしても毎回違う答えが返ってくるのは、主にこのサンプリングに乱数が使われているからです。