自動微分というアルゴリズムによって関数の微分値を求める例を記載します。本ページでは、一階微分を対象としており、高階微分は考えません。また簡単のため、関数の出力は一つのテンソルであり、入力となる一つ以上のテンソルおよび出力となる一つのテンソルの階数は零である例を考えます。
更に、関数は、微分可能な関数からなる合成関数であることを仮定します。これは自動微分の応用先の一つである、ディープラーニングにおけるニューラルネットワークの性質の一つです: Chainer Tutorial / ニューラルネットワークの基礎 / 誤差逆伝播法(バックプロパゲーション)
PyTorch による例
PyTorch はテンソル (多次元配列) を扱うことができるライブラリで、ディープラーニングなどに用いられます。スカラは零階のテンソル、ベクトルは一階のテンソル、行列は二階のテンソルです。
以下のようにインストールできます。
NVIDIA GPU が利用できる環境であれば以下の値が True になります。
PyTorch には自動微分が実装されており、以下のように利用できます。入力となる二つのテンソル $x$
と $y$
の階数は零です。出力となる一つのテンソル $z$
の階数も零です。
数式微分を考えても $x^2 + y^2$
の $x$
および $y$
に関する偏微分はどちらも 2 となるため、上記結果は正しいことが分かります。必要に応じて数値微分で自動微分の結果を検証することもできます。
自動微分のアルゴリズム
『ゼロから作るDeep Learning ❸』のソースコードはこちらで公開されており、内容を確認すると、自動微分のアルゴリズムは以下のようになっていることが分かります。
main.py
autograd/__init__.py
Python パッケージのために必要な空ファイルです。
autograd/variable.py
__repr__
や __len__
は Python の特殊メソッドです。同様に __add__
や __mul__
も特殊メソッドで、これらは Python における演算子オーバーロードのために用いられます。
autograd/function.py
弱参照 weakref によって、循環参照によるメモリリークを回避しています。
実行例
確かに PyTorch の出力結果と一致することが分かります。
ヤコビ行列について
$(y_1, ..., y_m)$
それぞれが $(x_1, ..., x_l)$
の関数であり、$y_j$
は $x_i$
で偏微分可能である場合について、以下の行列をヤコビ行列とよびます。ヤコビ行列の行列式をヤコビアンとよびます。
ヤコビ行列は例えば関数の一次近似を扱う場合に利用できます。具体例として、ロボットアームのマニピュレータの位置姿勢 $x_1, x_2, x_3, \phi_1, \phi_2, \phi_3$
は関節値 $\theta_1, ..., \theta_l$
の関数です。マニピュレータの位置姿勢はヤコビ行列を用いて以下のように近似できます。
連鎖律 (Chain Rule) について
さらに $(z_1, ..., z_n)$
それぞれが $(y_1, ..., y_m)$
の関数であり、$z_k$
は $y_j$
で偏微分可能である場合について、ヤコビ行列を $J_{yz}$
とします。
このとき、$(z_1, ..., z_n)$
の $(x_1, ..., x_l)$
を用いた一次近似は以下のようになります。
$J_{xz} = J_{yz} J_{xy}$
の部分は連鎖律 (Chain Rule) とよばれています。
さきほどの自動微分のサンプルプログラムにおけるバックプロパゲーションのアルゴリズムでは、この Chain Rule が利用されています。例えば、乗算 class Mul
の Backward
関数は以下のようになっています。
一般性を失うことなく $k$
が 1 の場合を考えます。例えば以下のような合成関数 $z_1(x_1, x_2)$
の $y_2(x_1, x_2)$
が $x_1$
と $x_2$
の乗算である場合、
連鎖律は以下のようになります。
$\frac{\partial z_1}{\partial y_2} x_2$
および $\frac{\partial z_1}{\partial y_2} x_1$
の部分が def Backward
の実装内容です。
記事の執筆者にステッカーを贈る
有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。
さらに詳しく →Feedbacks
ログインするとコメントを投稿できます。
関連記事
- Python コードスニペット (条件分岐)if-elif-else sample.py #!/usr/bin/python # -*- coding: utf-8 -*- # コメント内であっても、ASCII外の文字が含まれる場合はエンコーディング情報が必須 x = 1 # 一行スタイル if x==0: print 'a' # 参考: and,or,notが使用可能 (&&,||はエラー) elif x==1: p...
- Python コードスニペット (リスト、タプル、ディクショナリ)リスト range 「0から10まで」といった範囲をリスト形式で生成します。 sample.py print range(10) # for(int i=0; i<10; ++i) ← C言語などのfor文と比較 print range(5,10) # for(int i=5; i<10; ++i) print range(5,10,2) # for(int i=5; i<10;...
- ZeroMQ (zmq) の Python サンプルコードZeroMQ を Python から利用する場合のサンプルコードを記載します。 Fixing the World To fix the world, we needed to do two things. One, to solve the general problem of "how to connect any code to any code, anywhere". Two, to wra...
- Matplotlib/SciPy/pandas/NumPy サンプルコードPython で数学的なことを試すときに利用される Matplotlib/SciPy/pandas/NumPy についてサンプルコードを記載します。 Matplotlib SciPy pandas [NumPy](https://www.numpy
- pytest の基本的な使い方pytest の基本的な使い方を記載します。 適宜参照するための公式ドキュメントページ Full pytest documentation API Reference インストール 適当なパッケージ