なにこれ?
巷にはびこる生成AI、特にChatGPT/ Gemini/ Claude といったLLM(大規模言語モデル)の中身について、わかったつもりになるよ。
LLMって、なんとなくはわかるけど、その中身って文脈とかベクトルとか言われても全然わからないよね。
初心者にもわかりやすく……はないよ。中級者向けだよ。
LLMの中身は超次元ウニだらけだよ。
どこまで話すの?
推論部分(inference)だけだよー。LLMはどうやってメッセージに応えてるの?って部分だけ。
ここだけでも十分複雑だからね......
学習部分(training)は扱わないよ。
レベル0:前提知識、ぼやっとした全体像
ここは駆け足でいくよ。LLMは大まかに次の流れでメッセージを返すよ。
LLM処理フロー
- ユーザがLLMにメッセージを投げる
- LLMはメッセージをトークン(単語みたいなもの)単位に分割する
- LLMはトークンの集まりから文脈を読み取る
- LLMは文脈から、続きとして良い感じのトークンを探して、ユーザに返す
- LLMはユーザのメッセージ+自分で吐いたトークンを入力として、また文脈づくり・トークン探しを繰り返す
さ、ここまではよく見る説明で、なんとなく理解できるけど、この先のレベルって急に数式とかよくわからない概念とか出てきてしんどくなるよね。
それじゃあ、この先をふんわりわかった気になるように説明していくよ。
本題
ずっと気になってたんだけど、ウニって何……
海にいるトゲトゲの高級食材だよ。
LLMの中では、ひとつのトークンを768次元とか巨大な多次元空間のベクトル群(hidden state)として扱うんだ。
うん、この時点でもう意味わからないよね。
だから、「ウニ」ってことにしよう。
ウニのトゲ一本一本がベクトルだよ。多次元のあっちこっちにトゲが生えてるウニ。超次元ウニ。
LLMの中身を考えるのに、この超次元ウニは常に中心にある考え方だよ。
レベル1:ウニモデル概要
超次元ウニを使って、初心者フローよりももうちょっと細かいフローにしてみよう
LLM処理フロー
- LLMは入力されたメッセージをトークンに分解する
- LLMは各トークンをそれぞれ超次元ウニに変換する(embedding)
- LLMは超次元ウニ達をお見合いさせたり引き伸ばしてまた縮めたりして、「今何の話してる?」の形(要点ウニ)を作る(Transformer処理)
- LLMは要点ウニをもとに、図鑑の中から次に来そうなウニがどれか探す(logits変換、softmax計算)
- LLMはこれだ!と思ったウニ図鑑のページをトークンに変換する(sampling)
- 変換したトークンを返す
さあ磯臭くなってまいりました。
ちょっと待て、なんでトークンをウニ(hidden state)にするの?
そのほうが都合がいいからだよ。
言葉の意味・雰囲気・つながり・文脈といった抽象的なモノは、機械的に加工したり比較できないんだよ。
LLMも所詮コンピューターだからね。ウニ(ベクトル群)って数字にしないと加工・比較ができないんだ。
まぁ、トークンは計算できないけど、ウニなら計算できる、と考えておいてくれればいいよ。
ウニ図鑑......?
大事だけどそんなに複雑じゃないからさらっと書くよ。
LLMはトークン(単語)を全部ウニ化(Embedding)した図鑑を持ってるんだ。
この図鑑があるおかげで、ウニ化・逆ウニ化ができるんだね。
専門用語ではembedding matrixというよ。この記事ではウニ図鑑で通すけどね。
レベル2-1:ウニのお見合い。Transformerでの文脈理解
さあここからは、難しくなってくるよー。
つぎは要点ウニの作り方に注目して、もう少し細かくしていこう。
この工程は、LLMの中でもTransformerという部分が担当しているよ。
LLM処理フロー
- TransformerのAttention層というところで、ウニ達のお見合いをする
- ウニは以下の3属性を持ってるよ
ここでは【美味しい】というトークンのウニで説明するね- 要求(Query):お相手への要求だよ。
「食べ物とマッチングしたい!解剖学とはマッチングしたくない!」 - 名札(Key):自己紹介だよ
「私は形容詞!私はポジティブ!」 - 本体(Value):ウニそのものだよ
「私は【美味しい】だよ!」
- 要求(Query):お相手への要求だよ。
- このウニ達を全員vs全員でお見合いさせて、要求と名札の一致度から加重率を算出して、ウニのトゲ(ベクトル)同士を加重平均するよ
- こうすることで「私は【99%美味しいリンゴ、1%美味しい脾臓】」という、ちょっと文脈感のある子ウニができるよ
- ウニは以下の3属性を持ってるよ
- Feedforward層では、子ウニを鍛えるよ
- まず、次元を上げる。イメージが難しいけど、今のトゲを消さずに別のトゲが生える余地を増やすような感じだよ
- 「短いトゲは切る」「トゲがマイナスになってメリ込んだところは戻す」といった操作をいろいろやる
- 最後に次元を戻す。余剰次元に存在したトゲは合成されて、子ウニはもっとボヤっとした「美味しいリンゴの"雰囲気"」に近づく
- AttentionとFeedforwardを合わせた1セットがTransformer層。Transformer層は層というだけあって、積み重なるように何度も同様の処理を繰り返す(数十~百層とか)。Transformer層を通過するごとに、だんだん個別の形は薄れて、抽象的な全体を表す形に変わっていくよ
- 最終的に入力されたウニを全部まとめた「今何の話してる?」の要点ウニが出来上がる
うん、一気に難しくなってきたけど、ウニのおかげで何とか理解できるね。
ここまでで、LLMはようやく今話していることを理解(数値化)することができたよ。
ね、LLMの中身はこの時点ですでに相当磯臭いね。
でも、この先もまだウニばっかりなんだ。
なんか……元のウニと全然別物になっちゃわない?(残差接続)
なりそうだね。元はウニだったのに、最終的にオパビニアになったら困っちゃうね。
そうならないように、残差接続という仕組みがあるよ。
2層目以降のAttention/ Feedforward層で子ウニを処理するとき、親ウニを一緒に放り込むんだ。
こうすることで、孫ウニも親ウニとかけ離れた姿にならずに済むよ。
美味しいリンゴ? リンゴが美味しい?(PositionEncoding)
そうだね。全員vs全員でお見合いするから、当然どっちがどっちかわからなくなるね。
「すもももももももものうち」なんて地獄だね。これはちょっとトークン切り出しの別問題もあるけど。
これを解消するために、PositionEncodingという仕組みがあるよ。
ウニに「このウニは何番目のトークンです」という次元の針を後付けする作業だよ。
要求(Query)/ 名札(Key)/ 本体(Value) って抽象的だな......
お、そろそろピンと来る頃かな? 「抽象」はLLMの世界において、全部ウニだよ。
当然、Query/Key/Valueもまたウニで表現されるよ。これらは元ウニを関数にかけた射影だよ。プロフィールシートみたいなものだね。
QueryもKeyもウニでできているから、内積を求めることで一致度を算出できるんだ。
なんかまだモヤっとする......
LLMは正直複雑すぎるからね。この記事では話を単純化するために意図的に以下の部分を除いてるよ。
- 学習がかかわる部分(ウニ図鑑/ QKV射影関数/ Feedforward なんかの作り方)
- 各サービスが持つモデル以外の層(記憶領域/ 安全フィルタ/ カスタム設定 などなど)
- 最新技術(MoE(Mixture of Experts)/ KVキャッシュ最適化 とか)
レベル2-2:ウニの大進化 線形層で探す次のウニ
いよいよここからLLMがお返事をしていくよ。
LLM処理フロー
- Transformer層で作られた要点ウニを線形層に入れてやると、ウニ図鑑のページ数次元の超々次元ウニが生まれる(Logits化)
- 超々次元ウニのトゲはウニ図鑑の各ページとどれだけマッチするかを表しているので、全ページ合わせて100%になるように、マッチぶりをパーセンテージを振る(Softmax計算)
- パーセンテージの上位いくつかの内から、ある程度テキトーに1ページを選ぶ(Sampling)
- 選んだページのトークンを返す(Decoding)
- 返したトークンも入力メッセージに追加して、またTransformer層から再処理を始める
- 以上を繰り返して、ここでメッセージが終わりだな、と思ったらやめる
やったね! LLMからようやく人間のわかるメッセージが出てきたよ!
これで磯臭い世界ともオサラバだよ!
超々次元ウニ……
「何言ってんだこいつ」って顔が目に浮かぶよ。
でもこれ、ウニ図鑑のページ数分のトゲを持つウニなんだ。数万から数十万本になるね。
一本のトゲは1つの次元をあらわすので、数十万次元を持つウニだね。ね? 超々次元ウニだよね。
線形層 is 何
要点ウニから超々ウニを生み出すよ。
どうやって?は……学習の成果だよ! 詳しい説明はここでは省くよ。
たくさんの学習の結果、「こういう流れのときはこういう返しをしておけばオッケー!」の塊だと思ってくれればいいよ
なんか回り道感がスゴい……
わかるよ! 超々ウニなんか作らなくても、768次元とかのウニ図鑑に載ってるウニと同じ次元数のウニを生み出して、単純に比較すればいいじゃんと思うよね。
実際それでもできるっちゃできるんだよ。
でも、一応下記の理由があって超々次元ウニを作っているんだよ。
- 768次元でのウニ比較演算は文脈理解の世界、数十万次元は言葉選びの世界、と分けることで学習が安定する
- 一つ一つ計算するよりもガっと一度に全ページのパーセンテージ算出する方がメモリ効率がいい
おわり
さー、だいぶ頭がウニになったね。
これでふんわり解説の推論編は終わりだよ。
まだここから、今度は学習編や詳細編、言語モデルの周辺システム編も控えてるよ!
LLMは地獄だね!
以上、おわり。