Simple loss

Simple loss#

A simple loss provides an easy way to minimize an arbitrary function where more than simply the function is known, such as when the gradient or hessian is known. It does not require a model or data, but can be used with them.

import numpy as np
import zfit

zfit.run.experimental_disable_param_update(True)
<zfit.util.temporary.TemporarilySet at 0x7b205931f7d0>

Let’s start with a simple example of a function to be minimized. The function is a simple quadratic function with a minimum at (1, 2, 3).

def optimizefn(x):
    return (x[0] - 1) ** 2 + (x[1] - 2) ** 2 + (x[2] - 3) ** 2


def optimizefn2(x):
    return (x[0] - 1) ** 2 + (x[1] - 2) ** 2 + (x[2] - 3) ** 2
minimizer = zfit.minimize.Minuit()

Simply minimizing this function fails because an errordef attribute is needed; the order of magnitude of the uncertainty.

minimizer.minimize(optimizefn, params=[2.0, 2.2, 2.4])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 1
----> 1 minimizer.minimize(optimizefn, params=[2.0, 2.2, 2.4])

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/zfit/minimizers/baseminimizer.py:532, in BaseMinimizer.minimize(self, loss, params, init)
    438 def minimize(
    439     self,
    440     loss: ZfitLoss | Callable,
    441     params: ztyping.ParamsTypeOpt | None = None,
    442     init: ZfitResult | None = None,
    443 ) -> FitResult:
    444     """Fully minimize the `loss` with respect to `params`, optionally using information from `init`.
    445 
    446     The minimizer changes the parameter values in order to minimize the loss function until the convergence
   (...)    529             result = minimizer.minimize(func, param)
    530     """
--> 532     loss, params, init = self._check_convert_input(loss=loss, params=params, init=init, floating=True)
    533     with self._make_stateful(loss=loss, params=params, init=init):
    534         return self._call_minimize(loss=loss, params=params, init=init)

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/zfit/minimizers/baseminimizer.py:358, in BaseMinimizer._check_convert_input(self, loss, params, init, floating)
    355 if not isinstance(loss, ZfitLoss):
    356     from zfit.loss import SimpleLoss  # noqa: PLC0415
--> 358     loss = SimpleLoss.from_any(loss, params=params)
    360 if isinstance(params, tuple | list) and not any(isinstance(p, ZfitParameter) for p in params):
    361     loss_params = loss.get_params()

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/zfit/core/loss.py:1524, in SimpleLoss.from_any(cls, func, params, **kwargs)
   1521 @classmethod
   1522 def from_any(cls, func, params=None, **kwargs):
   1523     for conv in cls._convertable_funcs:
-> 1524         if (loss := conv["constructor"](func, params=params, **kwargs)) is not False:
   1525             break
   1526     else:

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/zfit/core/loss.py:1632, in _simple_loss_constructor(func, **kwargs)
   1630 def _simple_loss_constructor(func, **kwargs):
   1631     try:
-> 1632         return SimpleLoss(func=func, **kwargs)
   1633     except TypeError as error:
   1634         if "got an unexpected keyword argument" in str(error):

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/tensorflow/python/util/deprecation.py:588, in deprecated_args.<locals>.deprecated_wrapper.<locals>.new_func(*args, **kwargs)
    580         _PRINTED_WARNING[(func, arg_name)] = True
    581       _log_deprecation(
    582           'From %s: calling %s (from %s) with %s is deprecated and will '
    583           'be removed %s.\nInstructions for updating:\n%s',
   (...)    586           'in a future version' if date is None else ('after %s' % date),
    587           instructions)
--> 588 return func(*args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/zfit-tutorials/envs/latest/lib/python3.12/site-packages/zfit/core/loss.py:1459, in SimpleLoss.__init__(self, func, params, errordef, gradient, hessian, jit, deps, dependents)
   1454 if errordef is None:
   1455     msg = (
   1456         f"{self} cannot minimize {func} as `errordef` is missing: "
   1457         f"it has to be set as an attribute. Typically 1 (chi2) or 0.5 (NLL)."
   1458     )
-> 1459     raise ValueError(msg)
   1461 self._do_jit = jit
   1462 self._simple_func = func

ValueError: <SimpleLoss model=[] data=[] constraints=[]> cannot minimize <function optimizefn at 0x7b1fc93f4ea0> as `errordef` is missing: it has to be set as an attribute. Typically 1 (chi2) or 0.5 (NLL).
optimizefn.errordef = 1  # 1 for a chi2, 0.5 for a likelihood typically
result = minimizer.minimize(optimizefn, params=[2.0, 2.2, 2.4])
print(result)
FitResult
 of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  
True
   │    True
     │      False
       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛
Parameters
name           value  (rounded)    at limit
-----------  ------------------  ----------
autoparam_0                   1       False
autoparam_1                   2       False
autoparam_2                   3       False

Extending the loss#

To add more knowledge to the loss, we can extend it with a gradient and hessian using the SimpleLoss class.

def gradientfn(x):
    print(f"gradientfn called with x={x}")
    return 2 * (x[0] - 1), 2 * (x[1] - 2), 2 * (x[2] - 3)


def hessianfn(x):
    print(f"hessianfn called with x={x}")
    return np.array([[2., 0, 0], [0, 2., 0], [0, 0, 2.]])


params = [zfit.Parameter(f"param_{i}", 2.0 + i * 0.2) for i in range(3)]
loss = zfit.loss.SimpleLoss(func=optimizefn, gradient=gradientfn, params=params, hessian=hessianfn)
loss.gradient()
gradientfn called with x=(<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2.2>, <zfit.Parameter 'param_2' floating=True value=2.4>)

(<tf.Tensor: shape=(), dtype=float64, numpy=2.0>,
 <tf.Tensor: shape=(), dtype=float64, numpy=0.40000000000000036>,
 <tf.Tensor: shape=(), dtype=float64, numpy=-1.2000000000000002>)
loss.hessian()
hessianfn called with x=(<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2.2>, <zfit.Parameter 'param_2' floating=True value=2.4>)

array([[2., 0., 0.],
       [0., 2., 0.],
       [0., 0., 2.]])
minimizer_grad = zfit.minimize.Minuit(gradient="zfit")
result_grad = minimizer_grad.minimize(loss)
print(result_grad)
gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

FitResult
 of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  
True
   │    True
     │      False
       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛
Parameters
name       value  (rounded)    at limit
-------  ------------------  ----------
param_0                   1       False
param_1                   2       False
param_2                   3       False

result.hesse(method='hesse_np', name="loss hesse")
print(result)
FitResult
 of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  
True
   │    True
     │      False
       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛
Parameters
name           value  (rounded)    loss hesse    at limit
-----------  ------------------  ------------  ----------
autoparam_0                   1   +/-    0.71       False
autoparam_1                   2   +/-    0.71       False
autoparam_2                   3   +/-    0.71       False

result_grad.hesse(name="iminuit hesse3")  # default uses iminuit, nothing printed
{<zfit.Parameter 'param_0' floating=True value=2>: {'error': np.float64(0.9999999955842103),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>},
 <zfit.Parameter 'param_1' floating=True value=2.2>: {'error': np.float64(0.9999999955839975),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>},
 <zfit.Parameter 'param_2' floating=True value=2.4>: {'error': np.float64(0.9999999955860059),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>}}
result_grad.hesse(method='hesse_np', name="loss hesse")  # uses provided hessian
hessianfn called with x=[<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2.2>, <zfit.Parameter 'param_2' floating=True value=2.4>]

{<zfit.Parameter 'param_0' floating=True value=2>: {'error': np.float64(0.7071067780639629),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>},
 <zfit.Parameter 'param_1' floating=True value=2.2>: {'error': np.float64(0.7071067780639629),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>},
 <zfit.Parameter 'param_2' floating=True value=2.4>: {'error': np.float64(0.7071067780639629),
  'cl': 0.683,
  'weightcorr': <WeightCorr.FALSE: False>}}
result_grad
FitResult of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  True   │    True     │      False       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛

Parameters
name       value  (rounded)    iminuit hesse3    loss hesse    at limit
-------  ------------------  ----------------  ------------  ----------
param_0                   1       +/-       1   +/-    0.71       False
param_1                   2       +/-       1   +/-    0.71       False
param_2                   3       +/-       1   +/-    0.71       False
result_grad.errors(name="minos")
result_grad.errors(name="zfit", method="zfit_errors")
result_grad
gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.4142>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.06066>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.01015>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-0.0002974>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=-1.497e-06>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.414>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.061>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2.01>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.5858>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.9393>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.9898>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=0.9997>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=1>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.414>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.061>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3.01>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=3>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.586>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.939>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=1.99>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=2>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=2>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.414>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.061>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4.01>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=4>]

FitResult of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  True   │    True     │      False       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛

Parameters
name       value  (rounded)    iminuit hesse3    loss hesse                minos                 zfit    at limit
-------  ------------------  ----------------  ------------  -------------------  -------------------  ----------
param_0                   1       +/-       1   +/-    0.71  -      1   +      1  -      1   +      1       False
param_1                   2       +/-       1   +/-    0.71  -      1   +      1  -      1   +      1       False
param_2                   3       +/-       1   +/-    0.71  -      1   +      1  -      1   +      1       False
result.errors(name="minos")
result.errors(name="zfit", method="zfit_errors")
result
FitResult of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  True   │    True     │      False       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛

Parameters
name           value  (rounded)    loss hesse                minos                 zfit    at limit
-----------  ------------------  ------------  -------------------  -------------------  ----------
autoparam_0                   1   +/-    0.71  -      1   +      1  -      1   +      1       False
autoparam_1                   2   +/-    0.71  -      1   +      1  -      1   +      1       False
autoparam_2                   3   +/-    0.71  -      1   +      1  -      1   +      1       False
result.hesse(name="minuit")
result
FitResult of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═════════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │   edm   │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═════════╪══════════════════════════════╡
│  True   │    True     │      False       │ 8.4e-21 │         0.00 |  8.352192e-21 │
╘═════════╧═════════════╧══════════════════╧═════════╧══════════════════════════════╛

Parameters
name           value  (rounded)    loss hesse                minos                 zfit       minuit    at limit
-----------  ------------------  ------------  -------------------  -------------------  -----------  ----------
autoparam_0                   1   +/-    0.71  -      1   +      1  -      1   +      1  +/-       1       False
autoparam_1                   2   +/-    0.71  -      1   +      1  -      1   +      1  +/-       1       False
autoparam_2                   3   +/-    0.71  -      1   +      1  -      1   +      1  +/-       1       False
loss.hessian()
hessianfn called with x=(<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2.2>, <zfit.Parameter 'param_2' floating=True value=2.4>)

array([[2., 0., 0.],
       [0., 2., 0.],
       [0., 0., 2.]])
np.linalg.inv(loss.hessian())
hessianfn called with x=(<zfit.Parameter 'param_0' floating=True value=2>, <zfit.Parameter 'param_1' floating=True value=2.2>, <zfit.Parameter 'param_2' floating=True value=2.4>)

array([[0.5, 0. , 0. ],
       [0. , 0.5, 0. ],
       [0. , 0. , 0.5]])
# Use optimizefn2 which doesn't have errordef set, so we can pass it as parameter
optimizefn2.errordef = 0.5
loss = zfit.loss.SimpleLoss(func=optimizefn2, gradient=gradientfn, params=params)
loss.hessian()
<tf.Tensor: shape=(3, 3), dtype=float64, numpy=
array([[2., 0., 0.],
       [0., 2., 0.],
       [0., 0., 2.]])>
res = minimizer_grad.minimize(loss)
gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

res.hesse()
res.hesse(method="hesse_np", name="loss hesse")
res.errors(name="minos")
res.errors(name="zfit", method="zfit_errors")
res
gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=0.2929>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1.707>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=1.293>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2.707>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=2.293>]

gradientfn called with x=[<zfit.Parameter 'param_0' floating=True value=1>, <zfit.Parameter 'param_1' floating=True value=2>, <zfit.Parameter 'param_2' floating=True value=3.707>]

FitResult of
<SimpleLoss model=[] data=[] constraints=[]> 
with
<Minuit Minuit, tol=0.001>

╒═════════╤═════════════╤══════════════════╤═══════╤══════════════════════════════╕
│  valid  │  converged  │  param at limit  │  edm  │   approx. fmin (full | opt.) │
╞═════════╪═════════════╪══════════════════╪═══════╪══════════════════════════════╡
│  True   │    True     │      False       │ 3e-19 │          0.00 |  3.04937e-19 │
╘═════════╧═════════════╧══════════════════╧═══════╧══════════════════════════════╛

Parameters
name       value  (rounded)        hesse    loss hesse                minos                 zfit    at limit
-------  ------------------  -----------  ------------  -------------------  -------------------  ----------
param_0                   1  +/-    0.71   +/-    0.71  -   0.71   +   0.71  -   0.71   +   0.71       False
param_1                   2  +/-    0.71   +/-    0.71  -   0.71   +   0.71  -   0.71   +   0.71       False
param_2                   3  +/-    0.71   +/-    0.71  -   0.71   +   0.71  -   0.71   +   0.71       False
0.71 ** 2
0.5041
minu = minimizer._minuit_minimizer
minu.errordef = 0.5
minu.hesse()
Migrad
FCN = 8.352e-21 Nfcn = 144
EDM = 8.35e-21 (Goal: 0.001)
Valid Minimum Below EDM threshold (goal x 10)
No parameters at limit Below call limit
Hesse ok Covariance accurate
Name Value Hesse Error Minos Error- Minos Error+ Limit- Limit+ Fixed
0 autoparam_0 1.0 0.7 -1.0 1.0
1 autoparam_1 2.0 0.7 -1.0 1.0
2 autoparam_2 3.0 0.7 -1.0 1.0
autoparam_0 autoparam_1 autoparam_2
Error -1 1 -1 1 -1 1
Valid True True True True True True
At Limit False False False False False False
Max FCN False False False False False False
New Min False False False False False False
autoparam_0 autoparam_1 autoparam_2
autoparam_0 0.5 0.0 0.0
autoparam_1 0.0 0.5 0.0
autoparam_2 0.0 0.0 0.5
minu.covariance
autoparam_0 autoparam_1 autoparam_2
autoparam_0 0.5 0.0 0.0
autoparam_1 0.0 0.5 0.0
autoparam_2 0.0 0.0 0.5
p = list(result.params)[0]
p
<zfit.Parameter 'autoparam_0' floating=True value=1>
result.loss.value(params={p: 2.0})
<tf.Tensor: shape=(), dtype=float64, numpy=1.0000000000305183>