python隐函数求导,python求偏导函数
动机
作者fzdlz
因为最近求各种导数,所以想写一个自动求导数的算法。其实python的theano就有这个功能,但是仔细想想,想法也不难,就实现了一个。
本来想用C实现,但是用C写了各种问题,发现内存管理和运算符过载都不尽如人意。过了一段时间,我决定换个词。Java是第一个精通的语言,但是它不支持运算符重载。我该怎么办?于是转战python。
源代码
想法
# #功能显示
将函数表达式表示为表达式树。
这个表达式树是怎么构建的?你自己写语法分析吗?因为很麻烦,所以有一个比较简单的方法,就是用运算符重载来实现。
定义E类,重载其-*/* *(幂)运算,在重载的过程中建立二叉树。
节点类型
这个表达式树主要需要三种类型的节点。
第一,常数节点。例如,2、3
二是可变节点,如A、B、X、Y等。
第三,运营节点。如-、*、/、power等。
寻求指导
如果有公式组成的二叉树,接下来就是求指导了。
常数节点推导后,结果为0。
从可变节点寻求指导有两种情况。例如
$$f(a,b )=a^2) 3b$$
如果这个函数取$a$的偏导数,那么节点B被视为常数,取导数的结果为0。
对于保存的节点,导数结果为1。
寻求指导的方法是寻求这些指导的公式,例如:
$$(xy ) )=x y $$
上面的公式是一棵有根的二叉树,分别从左子树和右子树中导出,导出的结果加在一起。
那么,如何引导左边的树呢?递归调用这个引导方法就可以了。
电源节点很难处理。
首先,对左子树F和右子树g求导。
f的导数为0,表示指数函数,g的导数为0,表示幂函数。这些公式分别适用。
对于形式$ f (x) g) x) $来说,推导公式有点复杂,需要咨询数学上比较快的车。我还没做。
简化
推导不是最难的,最难的是简化。例如,根据上述算法推导出1/(1e (-) W * XB())),结果如下:
(0 *)1e^(-)w * XB))(-1e^)-(w * XB)))0 *(w * XB)-))1 * xw * 0)))1e)652
这需要简化。我意识到几个简化的想法:
1)将0 x和0 x-0的简化设置为X.0x x0 0/x降级为0。
上图中,左图C节点为0时,请做一个直接指向d的A,删除C和b节点。右图是1x。请将A直接指向d。
)2)直接简化为x1 1x x/1。
)3)运算两个常数,F F,F-F,F F,F/F都简化为单个节点。
4)更复杂的节点集成。
在上图中,右边的子树中有三个算法,左边的子树中有四个算法。
如果右边的子树是常数节点,请在左边的子树中找到与P节点符号相同的节点。在三个星号之后,我找到了4,然后是3*4 -12。然后,我们删除原P指向的节点,让P直接指向原左边的树。
$x*x=x^2元
(6)0-x美元=-1*x美元
)7) x^1=x
(8)日志e - 1
代码实现
这个项目
运行测试
以sigmoid函数为例,取导数。
导数函数
1/(1e^(-) w*xb))
推导之后,简化之前
(0 *)1e^(-)w * XB))(-1e^)-(w * XB)))0 *(w * XB)-))1 * xw * 0)))1e)652
简化后中间还有一个1。有什么问题?我发现的时候已经太晚了。结果是正确的。
e^(-) w*xb ) )1*x/) 1e^(-) w*xb ) ) 2
待办事项
分数简化
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。