Numpy退場?!Sympyで行列を偏微分


更新履歴

2020.4.28.加筆:スカラー関数をベクトルで微分

はじめに

こんばんは,老技術者です。
私の時代はまだまだ終わりませんよ。
でも,行列演算といったらNumpyでしょという時代は終わったようです。
その名もSympy(まさか新pyじゃないと思う)!

Sympyで行列を偏微分とかいろいろ

とりあえずこんなことできる。

#%%
import sympy as sym
from IPython.display import Math, display

# 変数を定義
(x, y, p, q) = sym.symbols("x y p q")
# 行列を定義
A = sym.Matrix([
    [x,2*x,3*x],
    [4*x,5*x,6*x]
])
display((Math(f"A={sym.latex(A)}")))
B = sym.Matrix([
    [y,y],
    [4*y,5*y],
    [7*y,y]
])
display((Math(f"B={sym.latex(B)}")))
# ベクトル関数を定義
xy = sym.Matrix([
    [x,y]
])
display((Math(f"xy={sym.latex(xy)}")))
pq = sym.Matrix([
    [3*x*y,2*x+y]
])
display((Math(f"pq={sym.latex(pq)}")))
# スカラー関数を定義
f = x**2

#行列同士の掛け算
C = A * B
display((Math(f"C=AB={sym.latex(C)}")))

#行列のx,yに数値を代入
C1 = C.subs({x:10, y: 20})
display((Math(f"C(10,20)={sym.latex(C1)}")))

#行列をxで偏微分
dCdx = sym.diff(C, x)
display((Math(r"\frac{\partial C}{\partial x}"f"={sym.latex(dCdx)}")))
#行列をyで偏微分
dCdy = sym.diff(C, y)
display((Math(r"\frac{\partial C}{\partial y}"f"={sym.latex(dCdy)}")))

#スカラー関数をベクトルで微分
dfdxy = sym.diff(f, xy)
display((Math(r"\frac{df}{dxy}"f"={sym.latex(dfdxy)}")))
#ベクトル関数をベクトルで微分
dpqdxy = sym.diff(pq, xy.T)
display((Math(r"\frac{dpq}{dxy}"f"={sym.latex(dpqdxy)}")))
#スカラー関数を行列で微分(エラーが出ます)
# dfdA = sym.diff(f, A)
# display((Math(r"\frac{df}{dA}"f"={sym.latex(dfdA)}")))

Visual Studio Codeで1行目の#%%からコピペなり写経なりしてみてほしい。
1行目の#%%はVS CodeがJupyter notebookに変わるおまじないだ。
普通に実行なんてやっちゃだめですよ。
下図にあるRun Cellってのをつついてください。

すると,こんなのが出てくるんですよ!

行列の要素は数字でももちろん良いのですが,上の例のように文字でも良いし
演算も文字込みでやってくれる。
さらにこの文字(変数)に数値を代入できるし,数式を入れる田中さんのような
変態もいる…
ベクトルで微分も可能なので,バックプロパゲーションの連鎖律を教えるときに
使えそう。
ということで昼飯食ってきます。