智能重写 sympy 中的表达式

Smart rewriting of expressions in sympy

我发现这很难解释,但我会通过一个例子尽力而为。

考虑下面grad变量赋值的表达式

 from sympy import *

 a, x, b = symbols("a x b")    
 y_pred = a * x    
 loss = log(1 + exp(- b * y_pred))
 grad = diff(loss, x, 1)

grad 具有以下表达式:

-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))

现在我想以两种方式操纵grad

1) 我希望 sympy 尝试重写表达式 grad,使其 none 项看起来像

exp(-a*b*x)/(1 + exp(-a*b*x))

2) 我还希望它尝试重写表达式,使其至少有一个看起来像这样的术语 1./(1 + exp(a*b*x)).

所以最后,grad 变成:

-a*b/(1 + exp(a*b*x)

请注意,1./(1 + exp(a*b*x)) 等同于 exp(-a*b*x)/(1 + exp(-a*b*x)),但我不想明确地向 sympy 提及这一点 :)。

我完全不确定这是否可行,但知道是否可以在某种程度上做到这一点会很有趣。

您只是在寻找 simplify 吗?

>>> grad
-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))
>>> simplify(grad)
-a*b/(exp(a*b*x) + 1)

cancel 这样做

In [16]: cancel(grad)
Out[16]:
  -a⋅b
──────────
 a⋅b⋅x
ℯ      + 1

这是可行的,因为它将表达式视为 -a*b*(1/A)/(1 + 1/A),其中 A = exp(a*b*x),并且 cancel 将有理函数重写为已取消的 p/q(请参阅 cancel 在 SymPy 教程中获取更多信息)。

请注意,这只有效,因为它使用 A = exp(a*b*x) 而不是 A = exp(-a*b*x)。因此,例如,cancel 不会在此处进行类似的简化

In [17]: cancel(-a*b*exp(a*b*x)/(1 + exp(a*b*x)))
Out[17]:
      a⋅b⋅x
-a⋅b⋅ℯ
────────────
  a⋅b⋅x
 ℯ      + 1