Sympyで勾配ベクトルを計算したい!


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は積分や行列計算もできるので,すごく便利だと思いました.

参考リンク