1. はじめに
大学の課題でSymPyを使って数式微分を行う課題が出ました.そのとき,勾配ベクトルを求めることにつまづいたので,整理します.
2. SymPyによる勾配ベクトルの求め方
結論から言うと,sympy.tensor.array.derive_by_array()
関数で求めることができます.
例として,$\boldsymbol{a}=[a_1, a_2]^{\rm{T}}$,$\boldsymbol{b}=[b_1, b_2]^{\rm{T}}$のときの$f(\boldsymbol{a})=\boldsymbol{a}^{\rm{T}}\boldsymbol{b}$の勾配ベクトルを考えます.
- 手計算
まず,$f(\boldsymbol{a})$を展開します.
f(\boldsymbol{a})=
\left[
a_1\ a_2
\right]
\begin{bmatrix}
b_1 \\
b_2
\end{bmatrix}
=a_1b_1+a_2b_2
したがって,勾配ベクトル$\partial f(\boldsymbol{a}) / \partial \boldsymbol{a}$は以下のように求まります.
\dfrac{\partial f(\boldsymbol{a})}{\partial \boldsymbol{a}}
=
\begin{bmatrix}
\dfrac{\partial f(\boldsymbol{a})}{\partial a_1} \\
\dfrac{\partial f(\boldsymbol{a})}{\partial a_2}
\end{bmatrix}
=
\begin{bmatrix}
b_1 \\
b_2
\end{bmatrix}
- SymPyによる計算
calculate_gradient.py
import sympy as sp
sp.init_printing() # Jupyter NotebookにおいてLaTex形式で表示するおまじない
# 変数の定義
a1, a2, b1, b2 = sp.symbols("a1 a2 b1 b2")
# ベクトルa,bと関数f(a)の定義
a = sp.Matrix([[a1], [a2]])
b = sp.Matrix([[b1], [b2]])
f = a.T*b
f[0] # -> a_1*b_1+a_2*b_2
# 勾配ベクトルの計算
sp.tensor.array.derive_by_array(f[0], a)
3. まとめ
課題ではヤコビ行列も求めたのですが,関数1つで計算してくれて「技術の進歩って素晴らしいな」と思いました.また,SymPyは積分や行列計算もできるので,すごく便利だと思いました.