線形代数 入門

Transformer を読むための線形代数を、たった 1 枚の絵の上に組み上げる:格子の載った平面と、手で動かせる矢印。ベクトル、変換としての行列、ドット積、射影、固有ベクトル、そして SVD —— このページのすべての数値は隣の図が計算しているので、どこまで動かしても主張は崩れない。

01

ベクトルとは位置のこと

順序のある 2 つの数。それをリストではなく座標として読む —— この一手の上に、この分野のすべてが載っている。

住所、RGB の色、GPS の座標 —— どれも順序が意味を担うリストだ。(255, 0, 0) は赤、(0, 255, 0) は緑。(37.78, −122.42) はサンフランシスコだが、入れ替えれば南極沖の海の上になる。ベクトルはこの発想にもう一手加えたもの:数を座標として読むと、リストは位置になる。矢印の先端をドラッグして、 2 つの数がついてくるのを見てほしい:

v = [3.0, 4.0]
v = [3.0, 4.0]

二重に持っているものは何もない。矢印そのものが、描かれた数の組だ。慣例で尾は原点に固定されるので、先端と読み出しは同じ事実の 2 つの見え方にすぎない。1 つ目の枠は水平方向の歩幅、 2 つ目は垂直方向の歩幅 —— 入れ替えれば、まったく別の場所になる。

この絵は長さをただでくれる。ピタゴラスの定理はすでに格子の中に描かれている:2 つの成分が直角三角形の 2 辺で、矢印がその斜辺だ。高さを上げて ‖v‖ が伸びるのを見てほしい:

‖v‖ = 5.00

2 辺は足す前に二乗されるので、いちばん長い成分が支配する:初期の高さでは、縦の辺が合計 25 のうち 16 を担い、矢印はちょうど 5 になる。 までつぶせば、残るのは水平の辺だけだ。これが ‖v‖ = √(Σ vᵢ²) —— ユークリッドノルム、あるいは L2 ノルム —— で、成分がいくつになっても記号は 1 つも変わらない。

長さと向きはきれいに分離できる。ベクトルを自分の長さで割ると、同じ半直線の上に単位ベクトルが残る:大きさを捨てて向きだけにしたものだ。角度を回して、v と v̂ が原点を通る 1 本の直線から出ないことを確かめてほしい:

53°

回しながら読み出しを見てほしい:v̂ の 2 成分はちょうど角度のコサインとサインで、どちらも [−1, 1] から出ない。正規化はほとんどの検索パイプラインの 1 行目にある。長さが 10 倍違う 2 つの文書を比較可能にするのが、まさにこれだからだ。

1 つの数 —— スカラー —— を掛けると、矢印はその半直線上を滑るだけで、決してそこから出ない。スカラーをゼロより下に押すと、矢印は原点を突き抜けて反対側に出る:

s = 1.0

ゼロでない 1 本のベクトルのすべての倍数は同じ直線に乗る。つまり 1 本のベクトルが 1 次元の空間を張る。s = 0 で矢印は消える:ゼロベクトルは長さを持つが向きを持たない。長さで割るすべての式が、長さゼロの場合に答えを用意しなければならない理由がこれだ。

足し算は歩くことだ。v の尾を w の先端に置く。たどり着いた場所が2 つの和になる。v をドラッグして、平行四辺形が閉じるのを見てほしい:

v = [−1.0, 2.0]
v = [−1.0, 2.0]

この平行四辺形が「順序は関係ない」ことの証明になっている:w を歩いてから v を歩いても、逆の順でも、同じ向かいの角に着く。成分ごとに見れば [3, 1] + [−1, 2] = [2, 3] にすぎない —— そしてこの絵こそ、それが 768 次元でも当たり前でいられる理由だ。

実際にベクトルが暮らしているのは、その高次元のほうだ。GPT-2 のトークンは 768 成分、 Llama 3 70B は 8192 成分。高次元は「同じものが増えるだけ」ではない:そこで無作為に 2 つの向きを引くと、ほぼ必ず直交に近い。次元を上げて、対ごとのなす角の雲全体が 90° につぶれていくのを見てほしい:

2 次元 · 中央値 88°

d = 2 では角度は全域に散っているが、 では直交から数度の範囲に収まり、その幅は 1/√d で縮む。これが測度の集中で、コサイン類似度がそもそも信号として使える理由でもある:「既定の関係が 90°、つまり無関係」である空間では、30° と測れた対は本当に何かを言っている。

02

行列が格子にすること

4 つの数で、平面のすべての点が同時に動く。4 つが言うのは 2 本の矢印の着地点だけで、あとはすべて連れていかれる。

行列とは平面全体を動かす関数で、その動かし方はただ 1 通り —— 格子線をまっすぐ・平行・等間隔に保つ動かし方だ。この制約はきつく、着地点を言う必要があるのは 2 本の矢印だけになる: (1, 0) を指す î と、(0, 1) を指す ĵ。î をドラッグして、格子がついてくるのを見てほしい:

1 列目 = [1.0, 0.0]
1 列目 = [1.0, 0.0]

いま実際にドラッグしているものに注目してほしい:行列の1 列目だ。括弧の中の 4 つの数は、2 つの着地点を横に並べて書いただけ —— 1 列目は î の行き先、2 列目は ĵ の行き先で、それ以外はどこにも保存されていない。

列が決まれば、すべての点が決まる。どんなベクトルも v₁î + v₂ĵ なので、その像は必ず v₁(新しい î) + v₂(新しい ĵ) になる —— 展開すればまさにあの「行かける列」の計算だが、暗記ではなく絵から出てきたものだ。スライダーを引いて、v が曲がる格子に乗っていくのを見てほしい:

0% 適用

v が自分のマスから一度も出ないことに注目してほしい。出発時は古い基底に沿って 1 歩ずつ、到着時は新しい基底に沿って 1 歩ずつ:Mv = [2·1 + 1·1, 0.5·1 + 1.5·1] = [3, 2]、変換を入れたとき、読み出しに出ている組と同じだ。計算と絵は同じ主張をしている。

「まっすぐ・平行・等間隔」には名前がある:線形性、記号で書けば M(u + w) = Mu + Mw と M(su) = s(Mu)。ほとんどの関数はこれを壊す —— 二乗も壊すし、しきい値処理も壊す。変換を適用して、平行四辺形が生き延びるのを見てほしい:

0% 適用

足し算が生き延びるので、変換してから足しても、足してから変換しても、同じ点に着く。 1 つの重み行列をトークンベクトルのバッチ全体に一度で適用できるのは、この性質のおかげだ。そしてバイアスを行列の外で足さなければならない理由でもある:定数の平行移動は格子全体を原点から動かすことになり、線形写像にできない唯一のことだからだ。

4 つの数のうち 2 つ分の情報があれば、変換が面積をどれだけ作るか壊すかが言える。単位正方形は平行四辺形になり、その符号つき面積が行列式だ。スライダーを右へ押して、面積をゼロまで持っていってほしい:

det = 1.00

で行列式はゼロになり、平面は直線につぶれる: 2 列目がちょうど 1 列目の 2 倍になり、2 本の矢印は何も張らなくなって、入力の 1 方向まるごとが 1 点に写る。さらに進めると行列式は負になる —— 変換が平面を裏返したのであって、ĵ は î の反時計回り側から時計回り側へ移る。負の行列式は向きの反転であって、エラーではない。

向きだけを変え、ほかは何も変えない一族がある。回転は1 列目と2 列目を単位円の上に、4 分の 1 回転だけ離して置く:[cos θ, sin θ] と [−sin θ, cos θ]。回してみて、行列式が 1 から動かないことを見てほしい:

0°

2 つの列がどちらも単位長で、しかも直交したままなので、すべての長さとすべての角度がそのまま生き残る。それが直交行列で、QᵀQ = I は同じ文の記号版だ。直交行列は千回掛けても何も膨らまず何も縮まない行列で、数値安定性が問題になる場所に必ず顔を出す。

変換は掛け算で合成され、順序は答えの一部だ。AB は先に B を適用するという意味 —— 記法は右から左に読み、誰もがここで足をすくわれる。 2 歩とも歩いてから順序を入れ替えて、着地点が逆の順序の着地点から離れていくのを見てほしい:

0% 適用

行列の掛け算は可換ではなく、絵がその理由を言っている:回転させた正方形をせん断した形と、せん断した正方形を回転させた形は違う。これはモデルのコードでもっともよくある沈黙のバグだ —— 行列が正方なら x @ W も W @ x も型検査を通り、どちらも有限の数を出し、文句を言うのは損失曲線だけになる —— 2 つの答えの違いは、あとの逆の順序との違いと同じものだ。

何もつぶさなかった変換は、元に戻せる。M⁻¹ はすべての点を戻す変換なので、M⁻¹M = I になる。 M を適用してから元に戻す、という 2 手を 1 つずつ確かめてほしい:

変換前

格子はぴたりと戻る。それが可能なのは det(M) ≠ 0 だからで、出ていく途中で何も失われていない。行列式がゼロなら逆行列は存在しない: 2 つの異なる入力がすでに同じ出力に着いており、 1 つの点を 2 か所へ送り返せる関数はないからだ。「特異行列に逆行列はない」と「平面がつぶれた」は同じ文である。

03

ドット積が測るのは「そろい具合」

2 本のベクトルが入って、1 つの数が出る。その数が気にしているのは大きさではなく、 2 本がどれだけ同じ方向を向いているかだ。

定義は暗算でできる算術だ:対応する枠どうしを掛けて全部足す、v · w = v₁w₁ + v₂w₂ + …。そしてこの定義は、唯一重要な性質をちょうど隠している。v を w のまわりでドラッグして、数を見てほしい:

v = [1.2, 2.4]
v = [1.2, 2.4]

符号がどこでひっくり返るかに注目してほしい。v が w と同じ側に傾いているあいだは正、ちょうど直角でゼロ、反対側へ倒れると負になる。測っているのはそろい具合で、それに両者の長さが掛かっている。

幾何的な読み方は影だ。v の先端から w の直線に垂線を下ろすと、足は ‖v‖ cos θ の位置に落ち、ドット積はその長さに ‖w‖ を掛けたものになる。角を閉じて影が伸びるのを見てほしい:

30°

v · w = ‖v‖ ‖w‖ cos θ なので、計算に使う定義と頭に描く定義は同じ数だ。両者を縫い合わせているのがあの影で、枠ごとの形はハードウェアが走らせるほう、コサインの形はあなたが考えるときに使うほう。どちらも他方の近似ではない。

ほかのどの角より重要な角が 1 つある。v を 直角の向こうまで振って、数が途中でゼロを横切るのを見てほしい:

20°

ちょうど では、2 本の長さがいくつであってもドット積はゼロになる。それが直交の定義であり、続く 2 節が寄りかかっている検査でもある: 2 つの向きが独立な情報を運ぶのは、ドット積が消えるとき、そのときだけだ。

ベクトルを自分自身とドットすると角はゼロ、コサインは 1、残るのは長さの二乗だけになる。v をドラッグして、その上に建つ正方形を見てほしい:

‖v‖² = 13.00
‖v‖² = 13.00

つまり ‖v‖ = √(v · v) であり、ノルムは別の概念だったことなど一度もない:引数を 2 つとも同じにしたドット積 —— いまドラッグしたあの正方形そのものだ。L2 が機械学習の既定のノルムなのはこれが理由で、内積がただでくれるノルムであり、微分が 2v ときれいになるノルムでもある。

両方の長さを割り落とすと、残るのは純粋なそろい具合だ:cos θ = v·w / (‖v‖‖w‖)。ベクトルがどれだけ大きくても [−1, 1] の中に収まる。短いほうの矢印 をドラッグして、コサインが長さをまったく気にしないことを見てほしい:

[1.2, 0.4]
[1.2, 0.4]

単位円の上の2 つの点を見てほしい。長さを割り落としたあとに矢印が着地する場所で、コサインはそれ以外を何も知らない。検索システムが生のドット積ではなくコサインで順位を付けるのはこのためだ:割らなければ、長い文書というだけで本当に関連する文書を追い抜いてしまう。

この演算がいたるところにある理由はコストだ:d 回の掛け算と d − 1 回の足し算、1 パス、分岐なし、完全にベクトル化できる。幅を上げて、曲線から回数を読み取ってほしい:

2 次元

では、アテンションスコア 1 つが 1,535 FLOP —— 単体では何でもない。ところがアテンションはトークンの順序対すべてについて 1 つずつ計算するので、1,024 トークンの文脈では 1 層 1 ヘッドあたり 1,048,576 回のドット積になる。誰もが文句を言うあの二乗は、この図をその回数だけ走らせた結果だ。

04

行列積はドット積の積み重ね

積のセル 1 つがドット積 1 回。現代のモデルで高価なものはすべて、セルがいくつあるかから出てくる。

行列積は新しいものを何も持ち込まない:AB のセル (i, j) は、A の第 i 行と B の第 j 列のドット積そのものだ。だからこそ形は真ん中で出会わなければならない。内側の次元を 4 から滑らせて、積が存在しなくなるのを見てほしい:

B の行数 = 4

これが形の失敗であって数値の失敗ではないことに注目してほしい: では積のブロックに入れるべき答えが存在しないので、どのフレームワークもごみを出さずにここで例外を投げる。スタック全体でいちばん親切なエラーであり、(3×4)(4×2) → 3×2 を「内側の対が打ち消し合う」と覚える理由でもある。

形が合えば、積はセルを 1 つずつ埋めていく。6 つのセルを 1 歩ずつ進めて、それぞれがA のどの行と B のどの列を食べるのかを見てほしい:

6 個中 1 個目

セル 1 つに掛け算 4 回と足し算 3 回、それが 6 セル:3×4 と 4×2 の積でちょうど 42 演算。一般に M×K と K×N の積はちょうど MN(2K − 1) で、実際の幅では欠けている MN が隣に比べて消えてしまうので、誰もが 2MNK に丸める。この回数は値にまったく依存しない —— 行列積には速い経路も早期脱出もなく、だからこそ専用のハードウェアを作れる。

実際の処理が 1 行ずつ流すことはない。N 本のトークンベクトルを 1 つの行列に積めば、1 回の積が同じ重みに対してすべてを片づける。バッチを増やして、入力と出力のブロックだけが伸びるのを見てほしい:

1 トークン

重みは 1 回読まれて N 回使われるので、取ってきた重み 1 バイトあたりの仕事量が N とともに増える —— バッチ処理がアクセラレータを速くする理由はこれだけだ。N = 1 では 768² 個の重み(bf16 で 1.2 MB)を運んで 120 万回の積和をする:1 バイトあたり 1 FLOP で、演算器はメモリ待ちで遊んでいる。 なら同じバイト数が 32 倍の仕事をする。

もう一方の軸はもっと悪い。モデルを widen すると重みブロックの 2 辺が同時に伸びるからだ。下のブロックは縮尺どおりに描いてある —— 幅を広げて、重みが二乗で育ち、トークン数はその場に留まるのを見てほしい:

幅 64

から は幅で 10.7 倍、演算量で 114 倍: 2,048 トークンに対するその 1 回の射影は 2.4 GFLOP から 275 GFLOP になり、 H100 の稠密 BF16 989 TFLOP/s では 0.28 ミリ秒だ(NVIDIA データシート、2023 年)。そしてこの射影は 1 層のアテンションブロックあたり 4 つあり、そのあとフィードフォワードが請求額をもう一度倍にする。

すべてのアテンション実装に出てくる動きがもう 1 つある:転置だ。Aᵀ は添字を入れ替えた同じ数の集まりだが、下にあるバイトは 1 つも動いていない。ひっくり返して、読み出し順に何が起きるかを見てほしい:

0% 入れ替え

配列は行のあとに行が並んで格納されるので、列を下へ読むと 1 要素ではなく行 1 本分の幅を一度に飛ぶ。1 行が 768 個の浮動小数点数である実際の行列では、その飛び幅は 3,072 バイト。したがって各要素はそれぞれ別の 64 バイトのキャッシュラインに載り、取ってきた 16 個のうち 15 個は捨てられる。演算は同一でも実時間は同一ではない —— ライブラリが転置を実体化せず乗算に融合するのはそのためだ。

05

射影とは、合う分だけ残すこと

ベクトルを、ある向きに沿う成分とそうでない成分に分ける。最小二乗も、アテンションも、PCA も、この一手だ。

モデルがベクトルに対してすることは、ほぼこう要約できる:ある向きに沿う成分だけ残し、あとは捨てる。v をドラッグして、直線に沿う成分と直交する成分に割れるのを見てほしい:

v = [1.0, 2.6]
v = [1.0, 2.6]

2 つの断片が必ず v に戻ること、そして直交するほうが必ず直角で直線に出会うことに注目してほしい。記号で書けば p = (v·a / a·a) a —— ドット積が量を選び、向きが残りを供給する。初期位置では p = [1.84, 0.92]、r = [−0.84, 1.68] になる。

足は直線上のある点ではなく、いちばん近い点だ —— そしてそれは受け入れるのではなく確かめられる主張だ。点を直線上で滑らせて、v までの距離を見てほしい:

t = 0.00

底を通り過ぎるときに右の数を見てほしい。(v − q) · a は距離が最小のところでちょうどゼロになり、ほかではならない:二乗距離を最小化することと、残差を直交させることは同じ条件だ。この同値性が、微積分の問題を線形代数の問題に変えている。

最小二乗はこの絵に行を足しただけだ。7 点、1 本の直線、7 本の残差 —— 最良の直線とは、残差ベクトルがその直線の届く範囲すべてと直交する直線のこと。傾きを動かして合計を見てほしい:

傾き = 0.00

水平な直線は Σr² = 7.046 を残す。最小二乗の傾きは 0.575 で、スライダーが届く最寄りの は 0.837 を残す。論証はいま手で動かしたものそのままだ:AᵀA x̂ = Aᵀb は「残差が A のどの列とも直交する」と言っているにすぎず、正規方程式が手品に見えなくなるのはそのためだ。

誤差は各パラメータについて二次なので、作る曲面には底が 1 つだけあり、ほかにはない。直線を上下させて、放物線が最小値を通るのを見てほしい:

切片 = −1.20

底は にある。曲線が放物線だからこそ、その上の勾配降下は行き詰まらず、直接解法も存在しうる。これは二乗誤差に固有の性質だ:絶対値誤差に換えれば底は微分できない折れ目になり、 L1 回帰に必要なのが別の定数ではなく別のアルゴリズムである理由がそこにある。

射影に唯一できないことは、覚えておくことだ。その向きに直交する直線の上のどのベクトルも同じ足に落ちるので、この写像は逆向きに戻せない。ベクトルをその直線に沿って滑らせて、左の数がまったく動かないのを見てほしい:

ずれ = 0.0

このベクトルの集まりが零空間で、その存在こそランク落ちの手触りだ。計画行列に互いの定数倍である列が 2 本あると、当てはめには同じくらい良い解が直線 1 本ぶん存在し、AᵀA は特異になり、ソルバーは例外を投げるか —— もっと悪いことに、浮動小数点の雑音がたまたま好んだ 1 つを黙って返す。

06

行列がそのままにしておく向き

ほとんどのベクトルは行列を通ると別の方角を指す。指したままの数少ない向きこそ、その行列が本当にしていることだ。

前の 2 節の変換を持ってきて、ベクトルを 1 本通してみる。たいていの場合、Av は v とは違う方角を指す。向きを振って、2 本の矢印が重なる角度を探してほしい:

70°
70°

ちょうど 2 つある。 と で、そこでは読み出しが λ を渡してくる:2.50 と 1.00 だ。固有ベクトルとは行列が拡大縮小だけをする向きのことで、その固有値が倍率になる —— Av = λv、行列 1 つがその直線の上では 1 つの数につぶれている。

格子から見ると、その 2 つの向きは曲げがどうしても動かせない 2 本の直線だ。変換を適用して、固有直線が角度を保ったまま、そのあいだのすべてが振られるのを見てほしい:

0% 適用

A = PDP⁻¹ が言っているのはそれだ:任意のベクトルを固有ベクトルの基底で書き直せば、行列は互いに干渉しない 2 つの数の掛け算になる。見返りはそれがすべてで、Aᵏ が k 回の行列積ではなく固有値ごとの 1 回のべき乗で済む理由でもある。

繰り返し適用したときに何が起きるかも予言する。どんな初期ベクトルでも A を何度も掛ければ、最大の固有値に沿う成分が指数的にほかを追い抜く。 8 回の適用を 1 歩ずつたどって、向きが落ち着くのを見てほしい:

0 回適用

主固有ベクトルから 80.5° 離れた出発点が、8 歩で 0.075° になる:誤差は毎回 λ₂/λ₁ = 0.4 ずつ縮む。これがべき乗法 —— PageRank が実際に計算されていた方法 —— であり、λ₁ > 1 の再帰ネットワークが発散し、λ₁ < 1 のそれが忘れるのも、同じ算術だ。

すべての行列にそんな向きがあるわけではない。回転はどのベクトルも同じ角だけ動かすので、生き残る向きは 1 つもない。円を一周させて、数がゼロに届かないままであることを見てほしい:

0° · 一度も並ばない

角はどこでも 40.0° のままだ。実の固有ベクトルとは回転が固定する向きのことで、そんな向きが存在しないからだ。固有値は複素数になり、この 2 つの言明は同じ 1 つの言明にすぎない。つまり「すべての行列は対角化できるか」への答えは、実数の上では否 —— そして [[1,1],[0,1]] のような欠損行列は複素数の上でも対角化できない。

1 つだけ、いつでも行儀のよい一族がある。A = Aᵀ なら、成分が何であれ固有ベクトルは実で、しかも互いに直交することが保証される。非対角成分をどこへ押しても、直角が生き残るのを見てほしい:

b = c = 0.60

あの直角がスペクトル定理で、共分散行列も、グラム行列も、AᵀA も —— どれも構成からして対称だ —— あらゆるアルゴリズムが手を伸ばす行列である理由でもある。そして次節への橋でもある:A が正方でなくても AᵀA は対称だからだ。

07

どんな行列も、回転と伸縮と回転

特異値分解は固有値の絵が課していた 2 つの前提をどちらも捨て、見返りはほとんどそのまま残す。

固有ベクトルには正方行列が必要で、しかも存在する保証がない。SVD はどちらも要らず、その絵は一文で済む:どんな行列も単位円を楕円に送る。変換を適用して、円が開いていくのを見てほしい:

0% 適用

2 本の半軸が特異値だ。σ₁ = 2.558 と σ₂ = 0.977 —— この行列が何かを伸ばせる最大と最小の倍率になる。任意の v について ‖Mv‖ ≤ σ₁‖v‖、等号は長軸に沿うときだけ —— だから σ₁ は作用素ノルムそのものであって、その比喩ではない。

逆向きに読むと、楕円が分解を教えてくれる:円は 3 手でここまで来た —— 入力の座標系の回転、軸に沿った拡大縮小、そして結果の回転。1 手ずつたどってほしい:

円

つまり M = UΣVᵀ。U と V は直交、Σ は対角で非負 —— そしてどんな行列にもこれがある。長方形でも、特異でも、ランク落ちでも。2 本の矢印に注目してほしい:円の上で直交して出発し、どの手のあとでも直交している。長さを変えるのは Σ だけで、しかもそれは自分の軸に沿って変えるからだ。

Σ は並べ替えてあるので、小さいほうの端は捨てられる。最初の k 個の特異方向だけ残せば、それが存在しうる最良のランク k 近似になる。k を上げて、形が戻ってくるのを見てほしい:

ランク 0

では楕円は線分につぶれ、行列の 35.7% が失われている。ランク 2 では厳密だ。この「最良」は Eckart–Young の定理であって経験則ではない:フロベニウスノルムでも作用素ノルムでも、これより近いランク 1 行列は存在しない。 PCA も、潜在意味解析も、あらゆる低ランクアダプタも、この圧縮論法の上にある。

2 本の軸の比には名前があり、請求書もある。短軸をゼロへ絞って、条件数が暴走するのを見てほしい:

σ₂ = 1.000

κ = σ₁/σ₂ は、入力の相対誤差が出力に届くまでに何倍されうるかを表す。 solve が信用できるかを決めるのはこの数であって、det ≠ 0 は何も教えてくれない。σ₂ を まで追い込めば κ は 160 に届く。行列式が 1 で条件数が 10⁸ ということがありうるからだ。

代価は桁で測る。κ が 10 倍になるたびに答えの有効数字が 1 桁食われ、形式が持っている桁数には限りがある。条件数を上げて、桁が消えていくのを見てほしい:

κ = 10^0

float32 の十進有効桁はおよそ 7.2 桁なので、 では 1.2 桁しか残らず、答えは小数点のついた雑音になる。float64 の 16.0 桁は同じ solve を 10.0 桁の余裕をもって切り抜ける。線形ソルバーが条件数の推定値を報告する理由であり、「例外が出なかった」が答えに意味がある証拠にならない理由でもある。

同じ打ち切りの議論をモデル規模で走らせたものが、低ランク微調整が効く理由だ。 4,096 四方の重み行列は 1,680 万パラメータ。ランク r の更新は薄い板 2 枚にすぎない。ランクを上げて、その割合を読み取ってほしい:

ランク 1

なら更新は 65,536 パラメータ —— その層の 0.39% —— であり、8 番目より後ろの特異値が小さいような変化なら何でも表せる。これは更新の大きさではなく形についての賭けで、 LoRA が張っているのはまさにその賭けだ。

同じ定理を最後にもう一度読む。中心化したデータ行列の特異方向は、データが実際に広がっている方向 —— つまり PCA だ。直線を振って、射影された点の広がりを見てほしい:

0°
0°

広がりを見てほしい:32° で 2.089 が最大で、合計は 2.280 —— 1 つの向きが分散の 91.6% を担っているので、この雲はほとんど 1 次元だ。共分散の上位の軸を残せば広がりは残る。それが一文で言う PCA であり、上のランク打ち切りが服を着替えたものでもある。

08

黙って失敗する 4 つ

形の誤りは例外を投げる。この 4 つは投げない。

順序。正方なら x @ W も W @ x も型検査を通る。条件数。行列式は κ について何も言わない。正規化。生のドット積は長いほうを好む。メモリ順序。転置は添字では無料、キャッシュでは高い。