簡單介紹下python的幾個自動求導工具,tangent、autograd、sympy;
在各種機器學習、深度學習框架中都包含了自動微分,微分主要有這么四種:手動微分法、數值微分法、符號微分法、自動微分法,這里分別簡單走馬觀花(hello world式)的介紹下下面幾種微分框架;
sympy 強大的科學計算庫,使用的是符號微分,通過生成符號表達式進行求導;求得的導數不一定為最簡的,當函數較為復雜時所生成的表達式樹異常復雜;
autograd自動微分先將符號微分用於基本的算子,帶入數值並保存中間結果,后應用於整個函數;自動微分本質上就是圖計算,容易做很多優化所以廣泛應用於各種機器學習深度學習框架中;
tangent 為源到源(source-to-source)的自動微分框架,在計算函數f微分時他通過生成新函數f_grad來計算該函數的微分,與目前所存在的所有自動微分框架都有所不同;由於它是通過生成全新的函數來計算微分所以具有非常搞的可讀性、可調式性這也是官方所說的與當前自動微分框架的重大不同;
sympy 求導
def grad():
# 定義表達式的變量名稱
x, y = symbols('x y')
# 定義表達式
z = x**2 +y**2
# 計算z關於y對應的偏導數
return diff(z, y)
func = grad()
輸出結果表達式z的導函數z‘=2*y
print(func)
把y 等於6 帶入計算 結果 為12
print(func.evalf(subs ={'y':3}))
Autograd求偏導
import autograd.numpy as np
from autograd import grad
#表達式 f(x,y)=x^2+3xy+y^2
#df/dx = 2x+3y
#df/dy = 3x+2y
#x=1,y=2
#df/dx=8
#df/dy=7
def fun(x, y):
z=x**2+3*x*y+y**2
return z
fun_grad = grad(fun)
fun_grad(2.,1.)
輸出:7.0
tangent求導
import tangent
def fun(x, y):
z=x**2+3*x*y+y**2
return z
默認為求z關於x的偏導數
dy_dx = tangent.grad(fun)
輸出偏導數值為 8 ,z’ = 2 * x,此處x傳任何值都是一樣的
df(4, y=1)
可通過使用wrt參數指定求關於某個參數的偏導數,下面為求z關於y的偏導數
df = tangent.grad(funs, wrt=([1]))
輸出值為10 ,z’ = 2 *y,此處x傳任何值都是一樣的
df(x=0, y=5)
上面說了那么多也沒體現出tangent的核心:源到源(source-to-source)
在生成導函數的時候加入verbose=1參數,即可看到tangent為我們生成的用於計算導數的函數,默認情況下該值為0所以我們沒感覺到tangent的求導與別的自動微分框架有什么區別;
def df(x):
z = x**2
return z
df = tangent.grad(df, verbose=1)
df(x=2)
在執行完上述代碼后,我們看到了tangent為我們所生成用於求導數的函數:
def ddfdx(x, bz=1.0):
z = x ** 2
assert tangent.shapes_match(z, bz), 'Shape mismatch between return value (%s) and seed derivative (%s)' % (numpy.shape(z), numpy.shape(bz))
# Grad of: z = x ** 2
_bx = 2 * x * bz
bx = _bx
return bx
ddfdx函數就是所生成的函數,從中我們也可以看到表達式z的導函數z’=2 * x,tangent就是通過執行該函數用於求得導數的;
sympy 中的自動微分只是它強大的功能之一,autograd 從名字也可知它就是為了自動微分而生的,tangent初出茅廬2017年底Google才發布的自動微分方法也比較新穎,從17年發v0.1.8版本后也沒見發版,源碼更新也不夠活躍;sympy、autograd比較成熟,tangent還有待觀察;