您误解了tol 参数。
这不是关于:|obj_i - obj_i-1|(基于标量的计算),而是关于:||grad_i||_p(基于向量的计算)。
后一种条件经常被使用,并且是大多数非线性优化器的一部分(尤其是当没有 KKT 条件或二阶信息可用时)。它也直接遵循理论:局部最优点的一阶必要最优性条件。
您可以查看来源:
here: tol becomes gtol:
if meth in ('bfgs', 'cg', 'l-bfgs-b', 'tnc', 'dogleg',
'trust-ncg', 'trust-exact', 'trust-krylov'):
options.setdefault('gtol', tol)
here: _minimize_trust_krylov is called:
elif meth == 'trust-krylov':
return _minimize_trust_krylov(fun, x0, args, jac, hess, hessp,
callback=callback, **options)
_trustregion_krylov talks about the oder conditions 并根据 exact / inexact 调用最终优化器:
if inexact:
return _minimize_trust_region(fun, x0, args=args, jac=jac,
hess=hess, hessp=hessp,
subproblem=get_trlib_quadratic_subproblem(
tol_rel_i=-2.0, tol_rel_b=-3.0,
disp=trust_region_options.get('disp', False)
),
**trust_region_options)
else:
return _minimize_trust_region(fun, x0, args=args, jac=jac,
hess=hess, hessp=hessp,
subproblem=get_trlib_quadratic_subproblem(
tol_rel_i=1e-8, tol_rel_b=1e-6,
disp=trust_region_options.get('disp', False)
),
**trust_region_options)
the optimizer used 包含以下几行:
gtol : float
Gradient norm must be less than `gtol`
before successful termination.
# check if the gradient is small enough to stop
if m.jac_mag < gtol:
warnflag = 0
break
# check if we have looked at enough iterations
if k >= maxiter:
warnflag = 1
break
here jac_mag is found:
@property
def jac_mag(self):
"""Magniture of jacobian of objective function at current iteration."""
if self._g_mag is None:
self._g_mag = scipy.linalg.norm(self.jac)
return self._g_mag
在这个答案的开头之后,并且使用了 euclidean-norm (p=2)!