scikit-hep / pyhf

pure-Python HistFactory implementation with tensors and autodiff
https://pyhf.readthedocs.io/
Apache License 2.0
283 stars 83 forks source link

default minuit settings fail on pretty simple model #1591

Open lukasheinrich opened 3 years ago

lukasheinrich commented 3 years ago

Summary

Fairly easy histosys + normfactor model, but our minuit settings aren't great.. any tips @alexander-held ? (I saw it first in cabinetry but realized it's the minuit backend)

def make_model(s,b,bup,bdn):
    m = {
        'channels': [{'name': 'singlechannel',
        'samples': [{'name': 'signal',
            'data': [s],
            'modifiers': [{'name': 'mu', 'type': 'normfactor', 'data': None}]},
            {'name': 'background',
            'data': [b],
            'modifiers': [
                {'name': 'bkguncrt',
            'type': 'histosys',
            'data': {'hi_data': [bup], 'lo_data': [bdn]}
            }]}]}]
        }
    return pyhf.Model(m)

m = make_model(7,50,40,60)
d = [50] + m.config.auxdata
pyhf.set_backend('jax',pyhf.optimize.minuit_optimizer())
print(pyhf.infer.mle.fit(d,m))
pyhf.set_backend('jax',pyhf.optimize.scipy_optimizer())
print(pyhf.infer.mle.fit(d,m))
[0.74700387 0.38452911]
[3.07345898e-19 6.20569308e-06]

OS / Environment

n/a

Steps to Reproduce

see above

File Upload (optional)

No response

Expected Results

this should work trivially :-/

Actual Results

not working :)

pyhf Version

0.6.1

Code of Conduct

alexander-held commented 3 years ago

With pyhf 0.6.3 and iminuit 2.8.2 I get a slightly better result using the code above:

[0.02092916 0.0063749 ]
[3.07345898e-19 6.20569308e-06]

where [0 0] is expected.

I think the failure is due to the best-fit point being at the parameter boundary. When extending bounds to [-10, 20], the result is

[0.00025564 0.00021155]
[-0.00022858  0.00029254]

and the HESSE and MINOS errors match well (the HESSE errors are nonsensical without that boundary change).

For completeness, here is the addition to turn the model config into a workspace with the boundary changed:

"measurements": [
    {
        "config": {
            "parameters": [{"bounds": [[-10, 20]], "inits": [1], "name": "mu"}],
            "poi": "mu",
        },
        "name": "meas",
    }
],
"observations": [{"data": [50], "name": "singlechannel"}],
"version": "1.0.0",
alexander-held commented 3 years ago

Suggestion for a possible concrete action: maybe add a warning if result_obj.minuit.fmin.has_parameters_at_limit is True after a fit.