機械学習
MachineLearning
数学
行列
テンソル
0

機械学習で使うベクトルや行列の微分を使った公式の導出

はじめに

機械学習の勉強をしていると,次のようなベクトルや行列を使った公式達を使わなければならない場面が出てくると思います.機械学習の本の巻末に書いてあることが多いと思います.(これらはPattern Recognition and Machine Learning (Bishop著, 2006)の巻末に載っている公式です)

x(xTa)=aATr(AB)=BTATr(ABAT)=A(B+BT)

単純な公式はちょっと考えたら分かるけれど,複雑な公式になってくると理解するのに時間がかかります.とにかく沢山公式が出てきて,まあ覚えなくてもいいやと思っていると,いざ自力で式変形していった時に,あれ,こんな時どの公式使えばいいんだっけ?となって躓いてしまいます.これは,"行列表記"のままではとても式変形しづらく,"テンソル表記"に変換して計算してから"行列表記"に戻すことでほとんどの公式は覚えなくて良いことに気付くと簡単に解決できます.
基本的なことのような気もするのですが,案外きちんとまとまってる記事がなくて少し苦労したのでまとめてみました.また,微分の定義に複数の流儀があることも分かりました.
この記事で,行列やベクトルの公式に苦しめられてきた人達が私の経験したような苦労を回避できれば嬉しいです.

※結果だけ知りたい人は公式の導出まとめを読んでください.

こんな人向け

基本的な行列,ベクトル,微分に関することは知っているが,冒頭のことで困っている人.

表記

太字でない小文字と大文字(例えば a, A)はスカラー,太字の小文字(例えば a)はベクトル,太字の大文字(例えば A)は行列として書いています.

ベクトルは縦ベクトルで表記することが多いので,ここでもそうします.こんな風に書かれていることが多いと思います.

a=t[a1,a2,...,an]=[a1,a2,...,an]T

また,行列Aの第ij成分をAijまたは(A)ijと書きます.

積を各成分で表すための"しりとり"に慣れる

行列Aと行列Bの積の第ij成分は,

(AB)ij=kAikBkj

になります.この形を見てもらったら分かると思うのですが,右辺をkについて"しりとり"して,"しりとり"できなかった添え字を両端にそのまま残すと左辺になります.この考え方はとても役に立ちます.積をとる添え字の数が増えても同じです.

(ABC)ij=k,lAikBklClj

(※分かる人だけ 「アインシュタインの縮約を使えば和の記号を書かなくていいじゃないか」という声が聞こえてきそうですが,機械学習の式変形ではアインシュタインの縮約を使うとかえってややこしくなる場合が多い気がしているので,あえて用いていません.)

この"しりとり"はベクトルが入ってきた時に少しややこしくなりますが,ベクトルは縦ベクトルで表す,ということを思い出すと,ベクトルaの第i成分aiを,あたかも行列Aの第i1成分Ai1であるかのように扱うと行列と同じことになります.

(Ab)i=jAijbj

と書く時は,慣れるまでは心の中では

(Ab)i1=jAijbj1

という気持ちで書きます.しりとりできなかったi1がそのまま両端に残っているのが見てとれると思います.
最終的に縦ベクトルにする時は,iのようにしりとりできなかった添え字を左端に残すことを意識すると使いやすいです.

転置記号が入ってきた時には,次のように考えます.

(ATB)ij=k(AT)ikBkj=kAkiBkj

ベクトルの時も同じです.

bTAc=i,jbiAijcj

も,慣れるまでは心の中では

bTAc=i,j(bT)1iAijcj1=i,jbi1Aijcj1

という気持ちで書きます.

(定義) 行列,ベクトルによる微分

公式の導出に行く前に,行列,ベクトルによる微分の定義を確認しておきましょう.

英語版Wikipediaのページ(Matrix calculus)によれば,大きく分けてNumerator-layout notation(分子に従う流儀)と,Denominator-layout notation(分母に従う流儀)という2つの流儀があり,どちらが良いということも無く,文献によっては混合して使われることもあるそうです.また,このページには行列やベクトルによる微分の公式が両方の流儀で大量にまとめられています
ここではPattern Recognition and Machine Learningの流儀に従いましょう.

スカラーのベクトルによる微分は,第i成分が次で与えられる縦ベクトルとします.(Denominator-layout notation)

(xa)i=xai

ベクトルのベクトルによる微分は,第ij成分が次で与えられる行列とします.(Numerator-layout notation)

(ab)ij=aibj

スカラーの行列による微分は第ij成分が次で与えられる行列とします.(Denominator-layout notation)

(xA)ij=xAij

公式を導出する手順

行列やベクトルの公式を導出するには,以下のステップを踏みます.

  1. "行列表記"から"テンソル表記"に変換する
  2. "テンソル表記"で微分等の計算を行う
  3. "テンソル表記"から"行列表記"に変換する

公式

ATr(AB)=BT

を導出する流れを追っていきましょう.もっと複雑な公式の場合も手順は同じです.

"行列表記"から"テンソル表記"に変換する

適切な言葉が見つからないのですが(既にあったら誰か教えてください),ここでは

ATr(AB)

のような表記を”行列表記”と呼びます.スカラーの行列による微分なので行列ですが,これを先程の"しりとり"を使って各成分ごとについて考えて,トレースも和の記号で表すと,この行列の第ij成分は,

Aijk,lAlkBkl

となります.このような,行列やベクトルの各成分を用いて行列やベクトルの各成分を表した表式をここでは”テンソル表記”と呼びます."テンソル表記"のメリットは,各成分で表しているので,順番を自由に入れ替えて良いという点です.行列では一般にABBAですが,例えば上の式でk,lAlkBkl=k,lBklAlkという入れ替えが可能です.これによって計算の自由度が高くなります.また,登場するのも全部スカラーなので,覚えにくいベクトルや行列による微分の公式を覚えなくて良いです.

"テンソル表記"で微分等の計算を行う

この"テンソル表記"で微分の計算を行いましょう.

Aijk,lAlkBkl

を計算すると,

k,lδilδjkBkl

となります.ここでδijはクロネッカーのデルタ記号で,

δij={1(i=j)0(ij)

です.Aij=Alkの時だけ,AlkAij=1で,それ以外は0ということを示しています.k,lについて和をとると結局,

Bji

となります.これ以上変形できないので"テンソル表記"での計算は終了です.

"テンソル表記"から"行列表記"に変換する

ij成分がBji(=(BT)ij)となりました.この"テンソル表記"を"行列表記"に戻すと,

BT

となります.目的の公式が得られました.

公式の導出まとめ

まとめると次のようになります.

(ATr(AB))ij=Aijk,lAlkBkl=k,lδilδjkBkl=Bji=(BT)ij

より,

ATr(AB)=BT

です.

オンライン計算機

英語版Wikipediaのページ(Matrix calculus)にはなんと,オンラインで行列の微分を計算できるページへのリンクが張られていました.

http://www.matrixcalculus.org/

2018年8月22日現在,スカラーの行列による微分の時はDenominator-layout notationで出力され,それ以外はNumerator-layout notationで出力されるそうです(作者の方にお聞きしました).

LaTeX形式でもPython形式でも出力できるようです.

これでもう怖いもの無しですね.