行列微分入門
高次元最適化への扉
なぜ行列微分が必要なのか
現代の科学・工学では、複雑なシステムを数式でモデル化し、コンピュータで最適化する場面が急増している。 その中心にあるのが「行列微分」である。 ここで行列微分とは、スカラー、ベクトル、行列を変数とする関数の微分を総称する概念である。 具体的には、スカラー関数のベクトル微分(勾配ベクトル)、ベクトル値関数のベクトル微分(Jacobi行列)、スカラー関数の行列微分などが含まれる。
例えば、ニューラルネットワークの学習を考えてみる。 数百万〜数十億個のパラメータを持つモデルに対して、損失関数 $$ L(\boldsymbol{W}_1, \boldsymbol{W}_2, \ldots, \boldsymbol{W}_n) \tag{1} $$ を最小化する。各 $\boldsymbol{W}_i$ は行列であり、これらすべてのパラメータに関する勾配を計算する必要がある。 1つずつ偏微分を手計算する場合、実用的な時間では終わらない。
行列微分の理論を使えば、このような高次元の最適化問題を体系的に扱える。 具体的には:
- 機械学習: ニューラルネットワークのバックプロパゲーション、損失関数の勾配計算
- 統計学: 最尤推定、混合Gaussモデル(GMM)のパラメータ更新、Fisher情報行列の計算
- 制御工学: 非線形システムの線形化、カルマンフィルタの導出
- ロボット工学: ヤコビ行列を用いた順運動学・逆運動学
- 物理シミュレーション: エネルギー最小化、変形勾配テンソルの計算
- 計算化学: 分子構造の最適化、量子化学計算における勾配法
これらの分野では、スカラー関数をベクトルや行列で微分したり、ベクトル値関数をベクトルで微分したりする操作が日常的に必要になる。
行列微分をマスターするメリット
行列微分を身につけると、以下のような強力な能力が得られる:
1. 高次元最適化を効率的に解ける
1変数関数の最小化では、微分がゼロになる点 $\displaystyle\frac{df}{dx} = 0$ を探せばよい。 しかし、10,000次元のパラメータを持つ関数ではどうであろうか。 ベクトル微分を使えば、勾配ベクトル $$ \nabla f = \frac{\partial f}{\partial \boldsymbol{x}} \tag{2} $$ を一度に計算でき、勾配降下法などのアルゴリズムで効率的に最適化できる。
2. 複雑な式を簡潔に表現できる
例えば、$n$ 次元ベクトル $\boldsymbol{x}$ に対する二次形式 $$ f(\boldsymbol{x}) = \boldsymbol{x}^\top \boldsymbol{A} \boldsymbol{x} \tag{3} $$ の勾配は、行列微分の公式を使えば一瞬で $$ \frac{\partial f}{\partial \boldsymbol{x}} = (\boldsymbol{A} + \boldsymbol{A}^\top) \boldsymbol{x} \tag{4} $$ と求まる。成分ごとに $\displaystyle\frac{\partial f}{\partial x_i}$ を計算する必要はない。
3. 連鎖律が使える
多層ニューラルネットワークのように、複数の関数が合成された複雑なシステムでは、連鎖律が不可欠である。 行列微分では、合成関数 $\boldsymbol{z} = \boldsymbol{f}(\boldsymbol{g}(\boldsymbol{x}))$ の微分を(分母レイアウトで) $$ \frac{\partial \boldsymbol{z}}{\partial \boldsymbol{x}} = \frac{\partial \boldsymbol{g}}{\partial \boldsymbol{x}} \cdot \frac{\partial \boldsymbol{f}}{\partial \boldsymbol{g}} \tag{5} $$ のように、中間層のJacobi行列の積として計算できる。これにより、深い計算グラフの勾配を層ごとに順次計算できる。
4. 自動微分の仕組みが理解できる
PyTorch、TensorFlow、JAXなどの機械学習フレームワークは「自動微分」を提供している。 これは連鎖律を行列微分の形で自動的に適用する技術である。 行列微分を理解していれば、フレームワークが裏で何をしているのか、なぜそのような計算グラフになるのかが明確にわかる。
5. 最先端の論文や教科書が読める
機械学習・統計学・制御工学の論文では、行列微分の記法が当然のように使われる。 例えば、Transformerの論文ではAttention機構の勾配を行列形式で導出し、Adam optimizerの論文では2次モーメント行列の更新式を記述し、Kalman filterの論文では状態推定の誤差共分散行列を導出する。 これらの数式を理解できなければ、アルゴリズムの本質的な理解や改良は不可能である。
6. 新しいモデルの勾配を自分で導出できる
既存のフレームワークに実装されていない損失関数やモデルを設計したとき、行列微分を知っていれば勾配を自力で導出できる。 例えば、カスタム正則化項 $$ R(\boldsymbol{W}) = \mathrm{tr}(\boldsymbol{W}^\top \boldsymbol{L} \boldsymbol{W}) \tag{6} $$ を追加したい場合、$\displaystyle\frac{\partial R}{\partial \boldsymbol{W}} = (\boldsymbol{L} + \boldsymbol{L}^\top)\boldsymbol{W}$ とすぐに求められる。 研究や実務で独自のアルゴリズムを開発する際に不可欠なスキルである。
基本的な考え方
1変数関数 $f(x)$ の微分 $\displaystyle\frac{df}{dx}$ はスカラーである。 一方、多変数関数 $f(x_0, x_1, \ldots, x_{n-1})$ をベクトル $\boldsymbol{x}$ で微分すると何になるのであろうか。
直感的には、各成分に関する偏微分 $$ \frac{\partial f}{\partial x_0}, \quad \frac{\partial f}{\partial x_1}, \quad \ldots, \quad \frac{\partial f}{\partial x_{n-1}} \tag{7} $$ を並べたベクトルになる。これが「勾配ベクトル」$\nabla f$ である。
ここで問題が生じる。このベクトルを列ベクトルにするか、行ベクトルにするかという問題である。 数学・物理・工学の各分野で異なる慣習が使われており、それぞれ「分子レイアウト」「分母レイアウト」と呼ばれる。
- 分母レイアウト: 勾配を列ベクトルとして表す。最適化・統計学で主流。勾配降下法の更新式 $\boldsymbol{x} \leftarrow \boldsymbol{x} - \alpha \nabla f$ がそのまま書ける。
- 分子レイアウト: 勾配を行ベクトルとして表す。制御工学・ロボット工学で主流。Jacobi行列の連鎖律が自然な形になる。
困ったことに、多くの文献ではどちらの表記を採用しているか明記されていない。 そのため、複数の文献を見比べると同じ式なのに結果が転置の関係になっていて混乱することが少なくない。 さらに、行列の積は可換ではないため、確認せずに異なる表記で書かれた複数文献から式を引用すると、計算結果が間違ってしまう。
分野ごとの主流表記
分野によって主流の表記が異なる傾向がある。一般的には:
- 分母レイアウト: 最適化、統計学、機械学習、化学など、勾配降下法やエネルギー最適化を多用する分野で主流
- 分子レイアウト: 制御工学、ロボット工学、天文学、地球科学など、Jacobi行列の連鎖律を多用する分野で主流
- テンソル添字表記: 相対論、微分幾何学、材料工学など、共変・反変の区別が重要な分野で使用
情報科学、物理学、工学、経済学、生命科学など、約60の細分野についてレイアウトの傾向を詳しくまとめた一覧表は、 以下の参考ページを参照のこと。
分野ごとの行列微分レイアウト一覧(準備中) - 各分野で典型的に使われるレイアウト(分母・分子・混在)を網羅的に整理。
どちらの記法を選ぶべきか
前述のように、どちらのレイアウトも広く使われている。 それぞれに利点があり、どちらが「正しい」わけではない。 重要なのは、使う文脈に合わせて一貫した記法を選ぶことである。
分母レイアウトが適している場面
- 最適化問題: 勾配が列ベクトルになり、更新式 $\boldsymbol{x} \leftarrow \boldsymbol{x} - \alpha \nabla f$ がそのまま書ける
- 統計学・機械学習: パラメータベクトル $\boldsymbol{\theta}$ に関する勾配 $\nabla_{\boldsymbol{\theta}} L$ が列ベクトルとして自然に扱える
- Hesse行列の計算: 2階微分が対称行列として直感的に表現できる
分子レイアウトが適している場面
- Jacobi行列の連鎖律: 合成関数の微分が $\displaystyle\frac{\partial \boldsymbol{z}}{\partial \boldsymbol{x}} = \displaystyle\frac{\partial \boldsymbol{z}}{\partial \boldsymbol{y}} \displaystyle\frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}}$ の形で自然に表現できる
- 制御工学・ロボット工学: 状態空間表現や運動学で頻繁に使われる
- 座標変換: 変形勾配テンソル、速度勾配テンソルなどが自然な形になる
実践的なアドバイス
自分でコードや論文を書く場合:
- 参照する文献・フレームワークの記法を確認する(PyTorchやNumPyは分母レイアウトに近い)
- どちらのレイアウトを使うか文書の冒頭で明記する
- 途中でレイアウトを変えない(混在させると計算ミスの原因になる)
- 他の文献から式を引用する際は、必ずレイアウトを確認し、必要なら転置を入れる
各レイアウトにおける微分結果の正確な定義(行列の形状、添字の対応など)は 行列微分の公式集の「1. 記法と定義」および「付録A. 分子レイアウトとの対応」で詳しく解説している。
本シリーズの方針:分母レイアウトで統一
スカラー・ベクトル・行列を対象とする微分では、両レイアウトの違いは転置だけであり、どちらを選んでも大きな差はない。 しかし、行列から行列への写像のように、微分結果が4階以上のテンソルになる場合は事情が異なる。
分子レイアウトでは、連鎖律を適用する際に添字の並べ替え(転置の一般化である置換操作)が必要になる。 一方、分母レイアウトでは隣接する添字がそのまま縮約でき、式が自然に書ける。 詳細は後述の「連鎖律での違い」を参照のこと。
分野ごとの傾向を見ると、分母レイアウトと分子レイアウトは拮抗しており、どちらが主流とも言い難い。 そこで本シリーズでは、テンソル微分との整合性を重視し、分母レイアウトで統一する。
この選択には以下の利点もある:
- 深層学習フレームワーク(PyTorch、JAX、TensorFlow)が実質的に採用しているレイアウトと一致する
- 逆方向自動微分(VJP)の操作と整合する
- 高階テンソルを扱う際に式が複雑になりにくい
分子レイアウトで書かれた文献を参照する際の変換方法は、 行列微分の公式集の「付録A. 分子レイアウトとの対応」で解説している。
レイアウトの違いが問題になる場面
ベクトルやスカラーの微分では、分母レイアウトと分子レイアウトの違いは転置の有無だけであり、比較的対処しやすい。 しかし、行列を変数とする微分や、合成関数の連鎖律を適用する場面では、両者の違いが顕著になる。
例1: ベクトルの勾配
スカラー関数 $f: \mathbb{R}^n \to \mathbb{R}$ の勾配を考える。
- 分母レイアウト: $\displaystyle\frac{\partial f}{\partial \boldsymbol{x}} = \begin{pmatrix} \frac{\partial f}{\partial x_1} \\ \vdots \\ \frac{\partial f}{\partial x_n} \end{pmatrix} \in \mathbb{R}^{n \times 1}$(列ベクトル)
- 分子レイアウト: $\displaystyle\frac{\partial f}{\partial \boldsymbol{x}} = \begin{pmatrix} \frac{\partial f}{\partial x_1} & \cdots & \frac{\partial f}{\partial x_n} \end{pmatrix} \in \mathbb{R}^{1 \times n}$(行ベクトル)
この場合、両者は単純な転置の関係にある。勾配降下法の更新式 $\boldsymbol{x} \leftarrow \boldsymbol{x} - \alpha \nabla f$ を書くとき、分母レイアウトでは $\nabla f$ がそのまま列ベクトルとして使えるが、 分子レイアウトでは転置が必要になる。
例2: Jacobi行列と連鎖律
ベクトル値関数 $\boldsymbol{f}: \mathbb{R}^n \to \mathbb{R}^m$ のJacobi行列を考える。 成分で書くと $\displaystyle\frac{\partial f_i}{\partial x_j}$ である。
- 分母レイアウト: $\displaystyle\frac{\partial \boldsymbol{f}}{\partial \boldsymbol{x}} = \begin{pmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_m}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_n} \end{pmatrix} \in \mathbb{R}^{m \times n}$
- 分子レイアウト: $\displaystyle\frac{\partial \boldsymbol{f}}{\partial \boldsymbol{x}} = \begin{pmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_1} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_1}{\partial x_n} & \cdots & \frac{\partial f_m}{\partial x_n} \end{pmatrix} \in \mathbb{R}^{n \times m}$
合成関数 $\boldsymbol{z} = \boldsymbol{g}(\boldsymbol{f}(\boldsymbol{x}))$ の連鎖律は、レイアウトによって積の順序が変わる。
- 分母レイアウト: $\displaystyle\frac{\partial \boldsymbol{z}}{\partial \boldsymbol{x}} = \frac{\partial \boldsymbol{f}}{\partial \boldsymbol{x}} \cdot \frac{\partial \boldsymbol{g}}{\partial \boldsymbol{f}}$(右から左へ伝播)
- 分子レイアウト: $\displaystyle\frac{\partial \boldsymbol{z}}{\partial \boldsymbol{x}} = \frac{\partial \boldsymbol{g}}{\partial \boldsymbol{f}} \cdot \frac{\partial \boldsymbol{f}}{\partial \boldsymbol{x}}$(左から右へ伝播)
例3: 行列から行列への写像(4階テンソル)
行列 $\boldsymbol{Y} \in \mathbb{R}^{p \times q}$ が行列 $\boldsymbol{X} \in \mathbb{R}^{m \times n}$ の関数であるとき、 微分 $\displaystyle\frac{\partial Y_{ij}}{\partial X_{kl}}$ は4つの添字を持つ。 これを並べると4階テンソルになる。
- 分母レイアウト: 添字の並びは $(i, j, k, l)$、つまり $\mathbb{R}^{p \times q \times m \times n}$(出力添字 → 入力添字)
- 分子レイアウト: 添字の並びは $(k, l, i, j)$、つまり $\mathbb{R}^{m \times n \times p \times q}$(入力添字 → 出力添字)
具体例として、$\boldsymbol{Y} = \boldsymbol{A}\boldsymbol{X}$($\boldsymbol{A} \in \mathbb{R}^{p \times m}$)を考える。 成分で書くと $Y_{ij} = \sum_k A_{ik} X_{kj}$ なので、 $$ \frac{\partial Y_{ij}}{\partial X_{kl}} = A_{ik} \delta_{jl} $$ となる。ここで $\delta_{jl}$ はクロネッカーのデルタである。
例4: 連鎖律での縮約
合成関数 $\boldsymbol{X} \to \boldsymbol{Y} \to z$($z$ はスカラー)を考える。 連鎖律により、 $$ \frac{\partial z}{\partial X_{kl}} = \sum_{i,j} \frac{\partial z}{\partial Y_{ij}} \frac{\partial Y_{ij}}{\partial X_{kl}} $$ となる。この和(縮約)は、$\boldsymbol{Y}$ の添字 $(i, j)$ について取る。
分母レイアウトでは、$\displaystyle\frac{\partial z}{\partial \boldsymbol{Y}}$ の添字が $(i, j)$、 $\displaystyle\frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}}$ の先頭の添字も $(i, j)$ なので、 行列積のように自然に縮約できる。
分子レイアウトでの縮約
分子レイアウトでは、添字の並びが分母レイアウトと異なるため、縮約の前に添字の並べ替えが必要になる。 これを具体的に見てみよう。
分子レイアウトの定義では、出力の添字が先、入力の添字が後に来る:
$$ \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分子}}_{ijkl} = \frac{\partial Y_{ij}}{\partial X_{kl}} $$
一方、分母レイアウトでは入力の添字が先に来る:
$$ \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分母}}_{klij} = \frac{\partial Y_{ij}}{\partial X_{kl}} $$
両者の関係は、添字の置換 $(i,j,k,l) \to (k,l,i,j)$ で結ばれている:
$$ \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分母}}_{klij} = \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分子}}_{ijkl} $$
連鎖律での違い
$z = f(\boldsymbol{Y})$、$\boldsymbol{Y} = g(\boldsymbol{X})$ という合成の場合、連鎖律を適用する。
分母レイアウトの場合:
$$ \left( \frac{\partial z}{\partial \boldsymbol{X}} \right)^{\text{分母}}_{kl} = \sum_{i,j} \left( \frac{\partial z}{\partial \boldsymbol{Y}} \right)^{\text{分母}}_{ij} \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分母}}_{ijkl} $$
ここで $\displaystyle\left( \frac{\partial z}{\partial \boldsymbol{Y}} \right)^{\text{分母}}_{ij}$ の添字 $(i,j)$ と $\displaystyle\left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分母}}_{ijkl}$ の先頭の添字 $(i,j)$ が一致しているので、 そのまま縮約できる。
分子レイアウトの場合:
$$ \left( \frac{\partial z}{\partial \boldsymbol{Y}} \right)^{\text{分子}}_{ij} = \frac{\partial z}{\partial Y_{ij}} $$
$$ \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分子}}_{ijkl} = \frac{\partial Y_{ij}}{\partial X_{kl}} $$
連鎖律を適用すると:
$$ \left( \frac{\partial z}{\partial \boldsymbol{X}} \right)^{\text{分子}}_{kl} = \sum_{i,j} \frac{\partial z}{\partial Y_{ij}} \frac{\partial Y_{ij}}{\partial X_{kl}} = \sum_{i,j} \left( \frac{\partial z}{\partial \boldsymbol{Y}} \right)^{\text{分子}}_{ij} \left( \frac{\partial \boldsymbol{Y}}{\partial \boldsymbol{X}} \right)^{\text{分子}}_{ijkl} $$
一見同じ形に見えるが、分子レイアウトでは $(i,j)$ が「出力側の添字」として配置されているため、 縮約を行うには添字の対応を明示的に意識する必要がある。
行列の場合との比較
2階テンソル(行列)の場合、この添字の並べ替えは単なる転置で済む。 例えば、ベクトル $\boldsymbol{y} = f(\boldsymbol{x})$ の連鎖律では:
分母レイアウト: $$ \frac{\partial z}{\partial \boldsymbol{x}} = \frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}} \frac{\partial z}{\partial \boldsymbol{y}} $$ (ヤコビ行列 × 縦ベクトル)
分子レイアウト: $$ \frac{\partial z}{\partial \boldsymbol{x}} = \frac{\partial z}{\partial \boldsymbol{y}} \frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}} $$ (横ベクトル × ヤコビ行列)
行列の場合は積の順序を入れ替えて転置を取れば両者を相互変換できる。
しかし、4階以上のテンソルでは「転置」という単純な操作では不十分で、 添字の一般的な置換操作が必要となる。 例えば上記の4階テンソルでは $(i,j,k,l) \to (k,l,i,j)$ という置換であり、 これは単純な転置(2つの添字の入れ替え)ではなく、4つの添字のうち前半と後半を入れ替える操作である。
より高階のテンソル(例えば6階)になると、置換のパターンはさらに複雑になり、 式の見通しが悪くなりやすい。このため、高階テンソルを扱う際には分母レイアウトが好まれることが多い。
深層学習フレームワークとの関係
PyTorch、JAX、TensorFlowなどの深層学習フレームワークでは、
.backward() や grad() が返す勾配は常に入力と同じ形状になる。
これは分母レイアウトの考え方と一致している。
例えば、入力が $(3, 4)$ 行列で出力がスカラーの関数を微分すると、 勾配も $(3, 4)$ 行列として返される。 これは「スカラーを行列で微分すると、入力と同じ形状の行列になる」という分母レイアウトの定義そのものである。
行列微分をテンソルの観点から一般化した解説は テンソル微分入門(準備中)を参照のこと。 また、自動微分との関係については 自動微分と最適化(準備中)で詳しく扱っている。
参考文献・関連記事
- Matrix calculus - Wikipedia
- The Matrix Cookbook - Petersen & Pedersen (2012)
- 混合Gaussモデル(GMM)とEM法