在 Python 中将函数的导数设置为 0
Set derivatives of a function to 0 in Python
我正在尝试同时求解一个方程组。方程本身是通过计算具有某些变量的函数的梯度来找到的。我正在使用 sympy,这里是代码:
from sympy import *
m = Matrix(symbols('a b c', positive = True))
y = 4*log(m[0]) + 4*log(m[1]) + 4*log(m[2]) - 2*log(m[1] + m[2]) \
- 2*log(m[0] + m[2]) - 2*log(m[0] + m[1]) - 6*log(m[0] + m[1] + m[2])
s = [diff(y, i) for i in m]
solve(s,m)
但是我收到以下错误:"raise NotImplementedError('could not solve %s' % eq2)"
有人可以帮我解决这个问题吗?还是有其他方法可以计算一堆梯度,然后求解得到的方程组?我很乐意获得数值近似值,如果存在多个解决方案,即使一个解决方案也足够了。
编辑
我知道我在上面显示的代码中的 objective 将具有对称梯度。所以在这里我正在寻找像(1,1,1)或(2,2,2)这样的解决方案。但在实际实现中,我的 objective 函数将具有不对称的梯度。所以在某种程度上我需要知道它们之间的比例。
ln(x)
的导数是1/x
,商法则是f(x)/g(x)
有导数(g(x)f'(x) - g'(x)f(x))/(g(x)^2)
。
这导致 log(base, x)
(= ln(x)/ln(base)
) 的导数为 (ln(base)/x - 0)/(ln(base)^2) = 1/xln(base)
。因此 alog(base, x)
有导数 a/xln(base)
.
你的公式是对称的,所以我计算一个导数来知道所有的公式:
d/da 4loga + 4logb + 4logc - 2log(b+c) - 2log(a+c) - 2log(a+b) - 6log(a+b+c) = 4/aln(10) + 0 + 0 - 0 - 2/(a+c)ln(10) - 2/(a+b)ln(10) - 6/(a+b+c)ln(10)
= 2/ln(10)*(2/a - 1/(a+c) - 1/(a+b) - 3/(a+b+c))
-> 2/ln(10)*(2/a - 1/(a+c) - 1/(a+b) - 3/(a+b+c)) = 2/ln(10)*(2/b - 1/(b+c) - 1/(a+b) - 3/(a+b+c)) = 2/ln(10)*(2/c - 1/(b+c) - 1/(a+c) - 3/(a+b+c)) | *ln(10)/2; - 3/(a+b+c)
2/a - 1/(a+c) - 1/(a+b) = 2/b - 1/(b+c) - 1/(a+b) = 2/c - 1/(b+c) - 1/(a+c) | - 1/(a+c) - 1/(a+b) - 1/(b+c)
2/a + 1/(b+c) = 2/b + 1/(a+c) = 2/c + 1/(a+b)
-> (2(b+c) + a)/a(b+c) = (2(a+c) + b)/b(a+c) = (2(a+b) + c)/c(a+b)
我不知道如何继续。我只知道 a = b = c
总是会产生一个解决方案(一开始就很清楚),但我不知道如何找到其他解决方案(如果有的话)。 (我猜你想要的不是 a = b = c
解决方案)
import sympy as sp
# define a vector of variables
vm = sp.var('m0:3', real = True)
y = 4*sp.log(vm[0]) + 4*sp.log(vm[1]) + 4*sp.log(vm[2]) - 2*sp.log(vm[1] + vm[2]) \
- 2*sp.log(vm[0] + vm[2]) - 2*sp.log(vm[0] + vm[1]) - 6*sp.log(vm[0] + vm[1] + vm[2])
梯度w.r.t。到 vm
可以得到
grad = [sp.diff(y, i) for i in vm]
然而,结果是一组复杂的有理多项式,sp.solve(grad, vm)
无法处理。我们可以通过对方程进行一些预处理来帮助 solve
,即因式分解并仅考虑分子:
grad_numerators = [sp.numer(sp.diff(y, i).together()).factor() for i in vm]
现在打电话给
sp.solve(grad_numerators,vm)
给出了一组可能的解决方案。
[{m1: -m2, m0: 0},
{m0: -m1, m2: 0},
{m1: m2, m0: -4*m2/3},
{m1: 0, m0: -m2},
{m1: -3*m2/4, m0: -3*m2/4},
{m1: -4*m2/3, m0: m2}]
请注意,其中一些可能无效,因为它们可能对应于(某些)grad
元素的零分母,这些元素在此推导中被忽略。
我正在尝试同时求解一个方程组。方程本身是通过计算具有某些变量的函数的梯度来找到的。我正在使用 sympy,这里是代码:
from sympy import *
m = Matrix(symbols('a b c', positive = True))
y = 4*log(m[0]) + 4*log(m[1]) + 4*log(m[2]) - 2*log(m[1] + m[2]) \
- 2*log(m[0] + m[2]) - 2*log(m[0] + m[1]) - 6*log(m[0] + m[1] + m[2])
s = [diff(y, i) for i in m]
solve(s,m)
但是我收到以下错误:"raise NotImplementedError('could not solve %s' % eq2)"
有人可以帮我解决这个问题吗?还是有其他方法可以计算一堆梯度,然后求解得到的方程组?我很乐意获得数值近似值,如果存在多个解决方案,即使一个解决方案也足够了。
编辑 我知道我在上面显示的代码中的 objective 将具有对称梯度。所以在这里我正在寻找像(1,1,1)或(2,2,2)这样的解决方案。但在实际实现中,我的 objective 函数将具有不对称的梯度。所以在某种程度上我需要知道它们之间的比例。
ln(x)
的导数是1/x
,商法则是f(x)/g(x)
有导数(g(x)f'(x) - g'(x)f(x))/(g(x)^2)
。
这导致 log(base, x)
(= ln(x)/ln(base)
) 的导数为 (ln(base)/x - 0)/(ln(base)^2) = 1/xln(base)
。因此 alog(base, x)
有导数 a/xln(base)
.
你的公式是对称的,所以我计算一个导数来知道所有的公式:
d/da 4loga + 4logb + 4logc - 2log(b+c) - 2log(a+c) - 2log(a+b) - 6log(a+b+c) = 4/aln(10) + 0 + 0 - 0 - 2/(a+c)ln(10) - 2/(a+b)ln(10) - 6/(a+b+c)ln(10)
= 2/ln(10)*(2/a - 1/(a+c) - 1/(a+b) - 3/(a+b+c))
-> 2/ln(10)*(2/a - 1/(a+c) - 1/(a+b) - 3/(a+b+c)) = 2/ln(10)*(2/b - 1/(b+c) - 1/(a+b) - 3/(a+b+c)) = 2/ln(10)*(2/c - 1/(b+c) - 1/(a+c) - 3/(a+b+c)) | *ln(10)/2; - 3/(a+b+c)
2/a - 1/(a+c) - 1/(a+b) = 2/b - 1/(b+c) - 1/(a+b) = 2/c - 1/(b+c) - 1/(a+c) | - 1/(a+c) - 1/(a+b) - 1/(b+c)
2/a + 1/(b+c) = 2/b + 1/(a+c) = 2/c + 1/(a+b)
-> (2(b+c) + a)/a(b+c) = (2(a+c) + b)/b(a+c) = (2(a+b) + c)/c(a+b)
我不知道如何继续。我只知道 a = b = c
总是会产生一个解决方案(一开始就很清楚),但我不知道如何找到其他解决方案(如果有的话)。 (我猜你想要的不是 a = b = c
解决方案)
import sympy as sp
# define a vector of variables
vm = sp.var('m0:3', real = True)
y = 4*sp.log(vm[0]) + 4*sp.log(vm[1]) + 4*sp.log(vm[2]) - 2*sp.log(vm[1] + vm[2]) \
- 2*sp.log(vm[0] + vm[2]) - 2*sp.log(vm[0] + vm[1]) - 6*sp.log(vm[0] + vm[1] + vm[2])
梯度w.r.t。到 vm
可以得到
grad = [sp.diff(y, i) for i in vm]
然而,结果是一组复杂的有理多项式,sp.solve(grad, vm)
无法处理。我们可以通过对方程进行一些预处理来帮助 solve
,即因式分解并仅考虑分子:
grad_numerators = [sp.numer(sp.diff(y, i).together()).factor() for i in vm]
现在打电话给
sp.solve(grad_numerators,vm)
给出了一组可能的解决方案。
[{m1: -m2, m0: 0}, {m0: -m1, m2: 0}, {m1: m2, m0: -4*m2/3}, {m1: 0, m0: -m2}, {m1: -3*m2/4, m0: -3*m2/4}, {m1: -4*m2/3, m0: m2}]
请注意,其中一些可能无效,因为它们可能对应于(某些)grad
元素的零分母,这些元素在此推导中被忽略。