我对scipy的牛顿方法有疑问。当我使用带有导数的牛顿时出现错误(参见下面的错误输出)。
我正在尝试计算x ** 2的根,其起始值为x0 = 2.0:
def test_newtonRaphson():
def f(x):
resf = x**2
return resf
assert(derivative(f, 1.0)) == 2.0
assert(round(newton(f, 0.0), 10)) == 0.0
dfx0 = derivative(f, 2.0)
assert(round(newton(f, 2.0, dfx0), 10)) == 0.0
整个错误ouptut如下:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
func = <function f at 0x04049EF0>, x0 = 2.0, fprime = 4.0, args = ()
tol = 1.48e-08, maxiter = 50, fprime2 = None
def newton(func, x0, fprime=None, args=(), tol=1.48e-8, maxiter=50,
fprime2=None):
"""
Find a zero using the Newton-Raphson or secant method.
Find a zero of the function `func` given a nearby starting point `x0`.
The Newton-Raphson method is used if the derivative `fprime` of `func`
is provided, otherwise the secant method is used. If the second order
derivate `fprime2` of `func` is provided, parabolic Halley's method
is used.
Parameters
----------
func : function
The function whose zero is wanted. It must be a function of a
single variable of the form f(x,a,b,c...), where a,b,c... are extra
arguments that can be passed in the `args` parameter.
x0 : float
An initial estimate of the zero that should be somewhere near the
actual zero.
fprime : function, optional
The derivative of the function when available and convenient. If it
is None (default), then the secant method is used.
args : tuple, optional
Extra arguments to be used in the function call.
tol : float, optional
The allowable error of the zero value.
maxiter : int, optional
Maximum number of iterations.
fprime2 : function, optional
The second order derivative of the function when available and
convenient. If it is None (default), then the normal Newton-Raphson
or the secant method is used. If it is given, parabolic Halley's
method is used.
Returns
-------
zero : float
Estimated location where function is zero.
See Also
--------
brentq, brenth, ridder, bisect
fsolve : find zeroes in n dimensions.
Notes
-----
The convergence rate of the Newton-Raphson method is quadratic,
the Halley method is cubic, and the secant method is
sub-quadratic. This means that if the function is well behaved
the actual error in the estimated zero is approximately the square
(cube for Halley) of the requested tolerance up to roundoff
error. However, the stopping criterion used here is the step size
and there is no guarantee that a zero has been found. Consequently
the result should be verified. Safer algorithms are brentq,
brenth, ridder, and bisect, but they all require that the root
first be bracketed in an interval where the function changes
sign. The brentq algorithm is recommended for general use in one
dimensional problems when such an interval has been found.
"""
if tol <= 0:
raise ValueError("tol too small (%g <= 0)" % tol)
if fprime is not None:
# Newton-Rapheson method
# Multiply by 1.0 to convert to floating point. We don't use float(x0)
# so it still works if x0 is complex.
p0 = 1.0 * x0
fder2 = 0
for iter in range(maxiter):
myargs = (p0,) + args
fder = fprime(*myargs)
E TypeError:'numpy.float64'对象不可调用
File "C:\Anaconda\lib\site-packages\scipy\optimize\zeros.py", line 116
TypeError
答案 0 :(得分:3)
您可以使用SymPy来评估派生,然后使用lambdify
将该表达式转换为可与scipy一起使用的函数。请注意,默认情况下lambdify
目前还不了解SciPy,因此您必须手动为scipy特殊功能添加翻译词典:
In [23]: expr = gamma(1+3/x)/gamma(1+1/x)**3
In [24]: print(expr.diff(x))
3*gamma(1 + 3/x)*polygamma(0, 1 + 1/x)/(x**2*gamma(1 + 1/x)**3) - 3*gamma(1 + 3/x)*polygamma(0, 1 + 3/x)/(x**2*gamma(1 + 1/x)**3)
In [25]: f = lambdify(x, expr.diff(x), ['numpy', {'gamma': scipy.special.gamma, 'polygamma': scipy.special.polygamma}])
此时,我无法使用newton
函数找到此表达式的任何根。根据{{3}}的原始图表,我没有看到衍生物为0的任何明显点,所以如果没有真正的根,我不会感到惊讶。
答案 1 :(得分:2)
我认为发生的事情是你传递衍生物的价值,而不是代表衍生物的函数。你需要一些可以调用的东西&#34;并且值(更具体地,值dfx0 = derivative(f, 2.0)
)无法被称为&#34;&#34;像一个功能。
仅供参考:如果您还没有,那么查看these examples可能是个好主意。