「LLM」の投稿

haruki256

LLMの学習データは、同じ文章を1トークンずらして入力と正解にする

結論

LLMの学習方法を理解したいときは、因果言語モデルの入力と正解を、同じトークン列を1つずらした対応として見ると整理できます。未来を見ない仕組みと組み合わせることで、複数の位置について「次に来るトークン」をまとめて学習できます。

説明用の架空のトークンID列を [10, 24, 7, 31] とします。概念上は、入力側と正解側を次のように対応させます。

その位置までの入力 次に来る正解
[10] 24
[10, 24] 7
[10, 24, 7] 31

列として書けば、入力は [10, 24, 7]、正解は [24, 7, 31] です。元の列を1トークン分ずらした関係になっています。

ただし、実装で必ず2本の列を別々に保存するとは限りません。たとえばHugging Face Transformersでは、入力IDの列を正解列としても渡し、モデル側の損失計算で予測と正解の位置をずらす構成があります。

学習時は、未来側のトークンが見えないように因果マスクをかけます。複数の位置を1回の順伝播で計算しても、正解となる未来のトークンは入力から先読みできません。パディングなど、学習対象にしない位置は損失から外すこともできます。

参考:Attention Is All You Need、Causal language modeling(Hugging Face Transformers)

予測と正解のずれを数値にまとめたものが損失です。次は、その損失をどうやって重みの更新へ使うのかを見ます。

スレッドを開く スレッドを閉じる 2

前の投稿で求めた損失は、予測が正解からどれだけ外れているかを表します。ただし、損失の値だけでは、どの重みをどちらへ動かすべきかは分かりません。

学習では、次の処理を繰り返します。

  1. 順伝播で、各位置の次トークン予測を計算する
  2. 予測と正解を比べ、損失を計算する
  3. 逆伝播で、各重みを少し変えたときに損失がどう変わるかを勾配として求める
  4. オプティマイザが勾配と学習率などを使い、重みを更新する

逆伝播は、文章を後ろから読み直す処理ではありません。計算のつながりを出力側から入力側へたどり、損失に対する各パラメータの勾配を計算する仕組みです。

また、1つの文章が、特定の重みを「記憶場所」として選んで保存されるわけでもありません。1回の損失から得た更新は、多くの重みにまたがり得ます。大量の学習例でこの処理を繰り返すことで、重みが少しずつ変わります。

学習途中の再開や比較に備え、モデルやオプティマイザなどの途中状態をチェックポイントとして保存することもあります。

参考:Trainer(Hugging Face Transformers)、Automatic differentiation package(PyTorch)、torch.optim(PyTorch)

では、この反復で学習データ上の損失が下がれば、未知の入力にも良い予測ができると言えるのでしょうか。

学習データ上の損失が下がっても、それだけで未知の入力への改善は確認できません。学習に使った例へ強く合わせすぎると、訓練損失は下がっても、別に取っておいたデータでは損失が下がらないことがあります。

確認する値は、役割を分けて見ます。

確認するもの 分かること
訓練損失 重みの更新に使ったデータへ、予測がどれだけ合っているか
検証損失 重みの更新に使わなかったデータへ、学習した傾向をどれだけ適用できるか
用途別の評価 必要な形式、正確さ、振る舞いを、その用途の基準で満たすか

訓練損失が下がり続ける一方で検証損失が悪化するなら、過学習を疑う手がかりになります。ただし、検証データが実際の用途を代表していなければ、その値だけでも判断できません。

たとえば、次トークン予測の損失が低くても、要約で重要点を残せるか、決められた形式を守れるかまでは直接分かりません。検証損失に加えて、使いたいタスクに合う入力と確認基準を用意します。

LLMの学習は、「1トークンずらした正解を作る」「損失から勾配を求めて重みを更新する」「学習に使っていないデータと用途別の基準で確かめる」という順で見ると、学習と評価を混同せずに追えます。

参考:Causal language modeling(Hugging Face Transformers)、Trainer(Hugging Face Transformers)

📝 LLMは文章をどう数値に変え、次のトークンを選ぶのか――トークン化・Attention・KVキャッシュの流れ
haruki256

LLMのトークンIDは、意味の近さを表す番号ではない

結論

LLMの入力を追うときは、トークンIDと、モデルが計算に使うベクトルを分けて見ます。トークンIDの大小や差を意味の近さとして読むと、語彙表を引くための番号と、意味や文脈を表す数値を混同してしまいます。

このスレッドでは、LLMの数値処理を「IDへの変換」「各層での更新」「生成時の再利用」「次のIDの選択」の順に追います。モデルの出力ログや生成設定を読むときも、いま見ている数値がどの段階のものかを切り分けられます。

LLMに文章を渡すと、まずモデルに対応したトークナイザーが、文字列をトークンの列へ変換します。トークンは必ずしも単語一つではなく、単語の一部や記号、バイト列、特殊トークンになることもあります。

各トークンには、モデルの語彙表に対応する整数のIDが割り当てられます。このIDは、語彙表の項目を指定するための番号です。たとえばID 120と121が隣り合っていても、二つのトークンの意味が近いとは限りません。

  1. 文字列
  2. トークン列
  3. ID列
  4. トークンごとの埋め込み

モデルは各IDを使って埋め込み層を参照し、各トークンの最初のベクトルを得ます。一方、意味検索などで使う文章埋め込みは、文章や段落などのテキスト全体を一つのベクトルとして比較するための表現です。どちらも「埋め込み」と呼ばれますが、表している単位と役割が違います。

参考:Tokenizer(Hugging Face Transformers)、Semantic Textual Similarity(Sentence Transformers)

IDから得たトークンのベクトルは、まだ周囲のトークンの情報を反映していません。次は、Transformerの層がこの表現をどう更新するかを見ます。

スレッドを開く スレッドを閉じる 5

トークンIDから取り出した最初のベクトルは、Transformerのブロックを通るたびに更新されます。

中心になる処理の一つがSelf-Attentionです。各位置の表現に、その位置自身を含む、その時点で参照できる位置から情報を集めます。ただし、TransformerはAttentionだけでできているわけではありません。

  • Self-Attention:位置どうしの関係を使って情報を集める
  • Feed Forward Network:各位置の表現を個別に変換する
  • 残差接続と正規化:入力と計算結果を組み合わせ、層を重ねて処理しやすくする

これらを組み合わせ、層を重ねながら各位置の表現を更新します。正規化を置く順序や細かなブロック構成はモデルによって異なるため、特定の図をすべてのLLMへそのまま当てはめることはできません。

参考:Attention Is All You Need

ではSelf-Attentionは、どの位置から、どれだけ情報を集めるかをどう決めるのでしょうか。

Self-Attentionは、トークンIDの数値を直接比較していません。各位置の現在の表現から、Query(Q)、Key(K)、Value(V)を作って計算します。

QとKの内積をスケーリングした値が、位置どうしの関連度を求める基になります。未来の位置など参照できない場所をマスクしたうえで、softmaxという処理でスコアを重みへ変換し、その重み付きでVを混ぜます。

  1. QとK
  2. 参照先ごとのスコア
  3. マスクとsoftmax
  4. Vの重み付き和

QとKは「どの位置をどれだけ参照するか」を決める側、Vは「参照先から何を取り込むか」を担う側です。ここで比べているのはIDそのものではなく、層の途中にある表現から作ったQとKです。

参考:Attention Is All You Need

文章を一トークンずつ生成すると、この計算を次のトークンごとに繰り返します。そのとき、過去の位置で計算したKとVはどう扱われるのでしょうか。

KVキャッシュを使う自己回帰型Transformerの推論では、入力プロンプトを含む、すでに処理した位置のKとVを保存します。次のトークンを生成するときは、それらを再利用します。

キャッシュがなければ、新しいトークンを一つ加えるたびに、すでに処理した位置のKとVまで繰り返し計算することになります。KVキャッシュを使う場合は、新しい位置に必要なQ・K・Vを計算し、保存済みのK・Vと合わせてAttentionを求めます。

  • 処理済み:保存済みのK・Vを再利用
  • 新しい位置:新しいQ・K・Vを計算

KVキャッシュが保存するのは文章そのものではなく、すでに処理した各位置について、各層でAttentionに使うKとVです。その分だけメモリを使いますが、処理済みのK・Vを毎回計算し直す処理を減らせます。実際のキャッシュ方式や保持範囲は、モデルのAttention方式によって異なります。

参考:Caching(Hugging Face Transformers)

こうして過去の情報を参照したモデルは、次に来る一トークンの候補ごとにスコアを出します。では、そのスコアから次のIDをどう選ぶのでしょうか。

モデルが出すのは、語彙に含まれる各トークン候補のlogitという変換前のスコアです。確率に応じて候補をランダムに選ぶサンプリングでは、このスコアを確率へ変換する前にtemperatureで調整します。

これにより、確率が一部の候補へ集中する度合いが変わります。

  • temperatureを低くする:高いスコアの候補へ確率が集まりやすい
  • temperatureを高くする:確率が複数の候補へ広がりやすい

temperatureは、候補を選ぶ方式そのものではありません。候補の選び方や絞り方には、次のような違いがあります。

  • greedy decoding:最もスコアの高い候補を選ぶ
  • top-k:スコア上位のk個へ候補を絞る
  • top-p:累積確率が指定値へ達するまでの候補へ絞る

サンプリングを有効にした場合は、調整や絞り込みを行ったあとの分布から、確率に応じて次のトークンを選びます。

temperatureを下げても、モデルの知識が増えたり、回答が必ず正確になったりするわけではありません。変わるのは、与えられたスコアから次の候補を選ぶときの分布です。

参考:Generation(Hugging Face Transformers)

LLMの生成では、まず文字列をID列へ変え、トークンごとの表現を層で更新します。必要に応じて過去のK・Vを再利用し、そのあとで次のIDを選びます。

モデルの説明や実行ログを読むときも、この順に分けると「トークン」「埋め込み」「Attention」「生成設定」を同じ数値として扱わずに済みます。

これを記事にまとめました。

https://haruki256.com/2026/10/04/how-llm-selects-next-token/