Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add docstrings and examples to infer fitting methods #849

Merged
merged 12 commits into from
May 1, 2020
21 changes: 21 additions & 0 deletions src/pyhf/infer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@ def hypotest(
r"""
Compute :math:`p`-values and test statistics for a single value of the parameter of interest.

Example:
>>> import pyhf
>>> pyhf.set_backend("numpy")
>>> model = pyhf.simplemodels.hepdata_like(
... signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
... )
>>> observations = [51, 48]
>>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
>>> test_poi = 1.0
>>> CLs_obs, CLs_exp_band = pyhf.infer.hypotest(
... test_poi, data, model, qtilde=True, return_expected_set=True
... )
>>> print(CLs_obs)
[0.05251554]
>>> print(CLs_exp_band)
[[0.00260641]
[0.01382066]
[0.06445521]
[0.23526104]
[0.57304182]]

Args:
poi_test (Number or Tensor): The value of the parameter of interest (POI)
data (Number or Tensor): The root of the calculated test statistic given the Asimov data, :math:`\sqrt{q_{\mu,A}}`
Expand Down
70 changes: 62 additions & 8 deletions src/pyhf/infer/mle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def twice_nll(pars, data, pdf):
Twice the negative Log-Likelihood.

Args:
data (`tensor`): the data
data (`tensor`): The data
pdf (~pyhf.pdf.Model): The statistical model adhering to the schema model.json

Returns:
Expand All @@ -21,13 +21,53 @@ def fit(data, pdf, init_pars=None, par_bounds=None, **kwargs):
"""
Run a unconstrained maximum likelihood fit.

Example:
matthewfeickert marked this conversation as resolved.
Show resolved Hide resolved
>>> import pyhf
>>> pyhf.set_backend("numpy")
>>> model = pyhf.simplemodels.hepdata_like(
... signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
... )
>>> observations = [51, 48]
>>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
>>> pyhf.infer.mle.fit(data, model, return_fitted_val=True)
(array([0. , 1.0030512 , 0.96266961]), 24.98393521454011)
>>> # Run the same fit with a different optimizer
...
>>> pyhf.set_backend("numpy", pyhf.optimize.minuit_optimizer(verbose=True))
>>> best_fit_result = pyhf.infer.mle.fit(
... data, model, return_fitted_val=True, return_uncertainties=True
... )
------------------------------------------------------------------
| FCN = 24.98 | Ncalls=84 (84 total) |
| EDM = 8.09E-07 (Goal: 0.0002) | up = 1.0 |
------------------------------------------------------------------
| Valid Min. | Valid Param. | Above EDM | Reached call limit |
------------------------------------------------------------------
| True | True | False | False |
------------------------------------------------------------------
| Hesse failed | Has cov. | Accurate | Pos. def. | Forced |
------------------------------------------------------------------
| False | True | True | True | False |
------------------------------------------------------------------
>>> best_fit_pars = best_fit_result[0][:, 0]
>>> best_fit_pars_uncert = best_fit_result[0][:, 1]
>>> best_fit_lhood_value = best_fit_result[1]
>>> print(best_fit_pars) # doctest: +SKIP
[2.23857553e-07 1.00308914e+00 9.62725456e-01]
>>> print(best_fit_pars_uncert) # doctest: +SKIP
[1.86505494 0.05531769 0.09476047]
>>> print(best_fit_lhood_value) # doctest: +SKIP
24.983936012961976

Args:
data (`tensor`): the data
data (`tensor`): The data
pdf (~pyhf.pdf.Model): The statistical model adhering to the schema model.json
kwargs: keyword arguments passed through to the optimizer API
init_pars (`list`): Values to initialize the model paramters at for the fit
par_bounds (`list` of `list`\s or `tuple`\s): The extrema of values the model paramters are allowed to reach in the fit
kwargs: Keyword arguments passed through to the optimizer API
kratsg marked this conversation as resolved.
Show resolved Hide resolved

Returns:
see optimizer API
See optimizer API
kratsg marked this conversation as resolved.
Show resolved Hide resolved

"""
_, opt = get_backend()
Expand All @@ -38,15 +78,29 @@ def fit(data, pdf, init_pars=None, par_bounds=None, **kwargs):

def fixed_poi_fit(poi_val, data, pdf, init_pars=None, par_bounds=None, **kwargs):
"""
Run a maximum likelihood fit with the POI value fixzed.
Run a maximum likelihood fit with the POI value fixed.

Example:
>>> import pyhf
>>> pyhf.set_backend("numpy")
>>> model = pyhf.simplemodels.hepdata_like(
... signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
... )
>>> observations = [51, 48]
>>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
>>> test_poi = 1.0
>>> pyhf.infer.mle.fixed_poi_fit(test_poi, data, model, return_fitted_val=True)
(array([1. , 0.97224597, 0.87553894]), 28.92218013492061)

Args:
data: the data
data: The data
pdf (~pyhf.pdf.Model): The statistical model adhering to the schema model.json
kwargs: keyword arguments passed through to the optimizer API
init_pars (`list`): Values to initialize the model paramters at for the fit
par_bounds (`list` of `list`\s or `tuple`\s): The extrema of values the model paramters are allowed to reach in the fit
kwargs: Keyword arguments passed through to the optimizer API
kratsg marked this conversation as resolved.
Show resolved Hide resolved

Returns:
see optimizer API
See optimizer API
kratsg marked this conversation as resolved.
Show resolved Hide resolved

"""
_, opt = get_backend()
Expand Down
17 changes: 15 additions & 2 deletions src/pyhf/infer/test_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,26 @@ def qmu(mu, data, pdf, init_pars, par_bounds):
\end{array}\right.
\end{equation}

Example:
>>> import pyhf
>>> pyhf.set_backend("numpy")
>>> model = pyhf.simplemodels.hepdata_like(
... signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
... )
>>> observations = [51, 48]
>>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
>>> test_mu = 1.0
>>> init_pars = model.config.suggested_init()
>>> par_bounds = model.config.suggested_bounds()
>>> pyhf.infer.test_statistics.qmu(test_mu, data, model, init_pars, par_bounds)
3.938244920380498

Args:
mu (Number or Tensor): The signal strength parameter
data (Tensor): The data to be considered
pdf (~pyhf.pdf.Model): The HistFactory statistical model used in the likelihood ratio calculation
init_pars (Tensor): The initial parameters
par_bounds(Tensor): The bounds on the paramter values
init_pars (`list`): Values to initialize the model paramters at for the fit
par_bounds (`list` of `list`\s or `tuple`\s): The extrema of values the model paramters are allowed to reach in the fit

Returns:
Float: The calculated test statistic, :math:`q_{\mu}`
Expand Down