我用这段代码得到一个非线性函数的零点。
当然,函数应该有1或3个零

import numpy as np
import matplotlib.pylab as plt
from scipy.optimize import fsolve

[a, b, c] = [5, 10, 0]

def func(x):
    return -(x+a) + b / (1 + np.exp(-(x + c)))

x = np.linspace(-10, 10, 1000)

print(fsolve(func, [-10, 0,  10]))
plt.plot(x, func(x))
plt.show()

在这种情况下,代码给出了3个期望根,没有任何问题。
但是,使用c=-1.5代码会丢失一个根,使用c=-3代码会发现一个不存在的根。
我想计算许多不同参数组合的根,所以手动更改种子不是一个实际的解决方案。
我很感激任何解决方案、技巧或建议。

最佳答案

在两个固定点(即df/dx=0)之间,有一个或零个根。在您的情况下,可以通过分析计算两个固定点:

[-c + log(1/(b - sqrt(b*(b - 4)) - 2)) + log(2),
 -c + log(1/(b + sqrt(b*(b - 4)) - 2)) + log(2)]

所以你有三个间隔,你需要找到一个零。使用sympy可以避免手工计算。它的sy.nsolve()允许在一个区间内可靠地找到一个零:
import sympy as sy

a, b, c, x = sy.symbols("a, b, c, x", real=True)

# The function:
f = -(x+a) + b / (1 + sy.exp(-(x + c)))
df = f.diff(x)  # calculate f' = df/dx
xxs = sy.solve(df, x)  # Solving for f' = 0 gives two solutions

# numerical values:
pp = {a: 5, b: 10, c: .5}  # values for a, b, c
fpp = f.subs(pp)
xxs_pp = [xpr.subs(pp).evalf() for xpr in xxs]  # numerical stationary points
xxs_pp.sort()  # in ascending order

# resulting intervals:
xx_low = [-1e9,      xxs_pp[0], xxs_pp[1]]
xx_hig = [xxs_pp[0], xxs_pp[1],       1e9]

# calculate roots for each interval:
xx0 = []
for xl_, xh_ in zip(xx_low, xx_hig):
    try:
        x0 = sy.nsolve(fpp, (xl_, xh_), solver="bisect")  # calculate zero
    except ValueError:  # no solution found
        continue
    xx0.append(x0)

print("The zeros are:")
print(xx0)

sy.plot(fpp)  # plot function

08-24 20:47