python中⼏种⾃动微分库
简单介绍下python的⼏个⾃动求导⼯具,tangent、autograd、sympy;
  在各种机器学习、深度学习框架中都包含了⾃动微分,微分主要有这么四种:⼿动微分法、数值微分法、符号微分法、⾃动微分法,这⾥分别简单⾛马观花(hello world式)的介绍下下⾯⼏种微分框架;
sympy 强⼤的科学计算库,使⽤的是符号微分,通过⽣成符号表达式进⾏求导;求得的导数不⼀定为最简的,当函数较为复杂时所⽣成的表达式树异常复杂;
autograd⾃动微分先将符号微分⽤于基本的算⼦,带⼊数值并保存中间结果,后应⽤于整个函数;⾃动微分本质上就是图计算,容易做很多优化所以⼴泛应⽤于各种机器学习深度学习框架中;
tangent 为源到源(source-to-source)的⾃动微分框架,在计算函数f微分时他通过⽣成新函数f_grad来计算该函数的微分,与⽬前所存在的所有⾃动微分框架都有所不同;由于它是通过⽣成全新的函数来计算微分所以具有⾮常搞的可读性、可调式性这也是官⽅所说的与当前⾃动微分框架的重⼤不同;
sympy 求导
def grad():
# 定义表达式的变量名称
x, y = symbols('x y')
# 定义表达式
numpy库不具有的功能有
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 = ad(fun)
输出偏导数值为 8 ,z’ = 2 * x,此处x传任何值都是⼀样的
df(4, y=1)
可通过使⽤wrt参数指定求关于某个参数的偏导数,下⾯为求z关于y的偏导数
df = ad(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 = ad(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还有待观察;