Избегайте оценки функции с одним и тем же вводом несколько раз
Я пытаюсь использовать scipy.optimise.fsolve для решения функции. Я заметил, что функция оценивается с одним и тем же значением несколько раз в начале и в конце шагов итерации. Например, когда оценивается следующий код:
from scipy.optimize import fsolve
def yy(x):
print(x)
return x**2+9*x+20
y = fsolve(yy,22.)
print(y)
Получен следующий вывод:
[ 22.]
[ 22.]
[ 22.]
[ 22.00000033]
[ 8.75471707]
[ 4.34171812]
[ 0.81508685]
[-1.16277103]
[-2.42105811]
[-3.17288066]
[-3.61657372]
[-3.85653348]
[-3.96397335]
[-3.99561793]
[-3.99984826]
[-3.99999934]
[-4.]
[-4.]
[-4.]
Поэтому функция оценивается с 22. три раза, что не нужно.
Это особенно раздражает, когда функция требует значительного времени оценки. Может ли кто-нибудь объяснить это и предложить, как избежать этой проблемы?
2 ответа
Первая оценка выполняется только для проверки формы и типа данных выходных данных функции. В частности, fsolve
звонки _root_hybr
который содержит строку
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
Естественно, _check_func
вызывает функцию:
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
Поскольку из этой оценки сохраняются только форма и тип данных, решатель будет вызывать функцию со значением x0
снова, когда начинается фактический процесс поиска корня.
Вышеуказанный счет для одного постороннего вызова (из двух). Я не отслеживал другой, но вполне возможно, что код FORTRAN выполняет какую-то предварительную проверку самостоятельно. Такого рода вещи случаются, когда алгоритмы, написанные давным-давно, переносятся снова и снова.
Если вы действительно хотите сохранить эти две оценки дорогой функции yy, один из способов - вычислить значение yy(x0) отдельно и сохранить его. Например:
def yy(x):
if x == x0 and y0 is not None:
return y0
print(x)
return x**2+9*x+20
x0 = 22.
y0 = None
y0 = yy(x0)
y = fsolve(yy, x0)
Я понял, что важной причиной этой проблемы является то, что fsolve не предназначен для такой проблемы: решатели должны выбираться с умом:)
multivariate: fmin, fmin_powell, fmin_cg, fmin_bfgs, fmin_ncg
nonlinear: leastsq
constrained: fmin_l_bfgs_b, fmin_tnc, fmin_cobyla
global: basinhopping, brute, differential_evolution
local: fminbound, brent, golden, bracket
n-dimensional: fsolve
one-dimensional: brenth, ridder, bisect, newton
scalar: fixed_point