我想为神经网络编写一些自定义CUDA内核以加速计算,但是如果有可以自动执行此操作的软件包,我不想花时间手动区分张量表达式。
是否有一个python包可以显示符号矩阵区分的表达式?
我知道sympy
可以为非矩阵表达式执行此操作:
def func(x):
return 1 / x
arg_symbols = sp.symbols(inspect.getfullargspec(func).args)
sym_func = func(*arg_symbols)
s = ''
for arg in arg_symbols:
s += '{}\n'.format(arg, sp.Lambda(arg_symbols, sym_func.diff(arg)))
# this is what I need:
print(s)
>>> Lambda(x, -1/x**2)
我知道autograd
包可以计算矩阵表达式的导数
评估函数后,autograd会列出所有操作 已执行的以及它们依赖的节点。这是 功能评估的计算图。计算 衍生物,我们只是将差异规则应用于每个节点 在图中。
但是有没有办法从它或类似的包中获得这种差异计算图?
答案 0 :(得分:1)
您引用的软件包之间存在一些严重差异。差异是您无法直接从自动差异库中获取(AFAIK)计算图形的原因,但您可以从基于符号的图形中获取它。
简而言之:
shmget
就足够了numpy
sympy
就是一个例子有三种差异化方法:
autograd
,其中Delta(f(x)) / Delta(x)
是一个小差异,代表Delta(x)
的变体,同时保留在x
的域中。这不是你需要的。你不需要一个包。 符号区分:基于构成表示函数符号应用的图形(我有一篇关于Ruby here中符号引擎实现的文章)。在这种情况下,区分是通过链推导规则的递归应用来执行的:
f
当此规则应用于整个符号图时,结果是具有导数的较新符号图。优点在于导数是精确的,但对于非常复杂的图,最终的导数图可能是不可处理的(超过内存限制或过深递归的堆栈限制)。 在python中f(g(x))' = f'(g(x)) * g'(x)
实现了这种派生。另一方面,如果您有衍生图表,您可以对其进行操作,例如简化或替换。
sympy
正如您可以看到它与from sympy import *
import numpy as np
x = symbol('x')
f = 1 / x
df = diff(f, x)
print(df)
# -1/x**2
ldf = lambdify((x), df)
# Now ldf is a lambda
x_ary = np.array([
[[1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3]]
])
y_ary = ldf(x_ary)
print(xn.shape)
# (2, 2, 3)
print(y_ary)
# array([[[-1. , -0.25 , -0.11111111],
# [-1. , -0.25 , -0.11111111]],
# [[-1. , -0.25 , -0.11111111],
# [-1. , -0.25 , -0.11111111]]])
一起使用,但它涵盖了一些基本示例而不是所有内容,实际上numpy
与sympy.matrix
一起应该用于特定图表(对于例如:我认为它不能直接处理sympy.symbol
。
export the graph as C
code也可以,但它有一些有限的功能,对于你的应用程序,你必须修改结果:
diff(x.T A x, x) = x.T A + A x)
打印出来:
from scipy.utilities.codegen import codegen
[(cf, cc), (hf, hc)] = codegen(("df", df), "C", "df")
print(hc, cc)
自动区分是通过/*****************************************************
* Code generated with sympy 1.1.1 *
* See http://www.sympy.org/ for more information. *
* This file is part of 'project' *
*****************************************************/
#ifndef PROJECT__DIFF__H
#define PROJECT__DIFF__H
double df(double x);
#endif
/*****************************************************
* Code generated with sympy 1.1.1 *
* See http://www.sympy.org/ for more information. *
* This file is part of 'project' *
*****************************************************/
#include "diff.h"
#include <math.h>
double df(double x) {
double df_result;
df_result = -1/pow(x, 2);
return df_result;
}
完成的工作。在这种情况下,两个世界的最好是团结一致。从一方面来说,没有必要明确地评估图形,另一方面,您不能对派生函数执行进一步操作,同时保持导数精确。这通常是通过使用附加字段(类似autograd
或更多字段)扩充float
定义来完成的,其中附加字段包含派生。例如,在自动差异化环境中,float[2]
函数可能会超载:
sin
但正如您可以通过这种方式理解的那样,没有可用的计算图,但您可以直接得到def sin(x):
return [sin(x[0]), x[1] * cos(x[0])]
的精确导数的值(所有函数都必须重载)。我有一个更完整的例子(在C语言中,只使用宏)here。 请注意,内部Tensorflow使用自动区分而不是符号,但建议用户直接提供&#34;显式版本&#34;处理数值不稳定的问题!。自动微分通常不会处理数值不稳定。