在 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 元素的零分母,这些元素在此推导中被忽略。