Skip to content

Commit d3fac0a

Browse files
committed
extend Poisson loss 2
1 parent 718b5af commit d3fac0a

File tree

3 files changed

+49
-20
lines changed

3 files changed

+49
-20
lines changed

icefit/icepeak.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ def binned_1D_fit(hist: dict, param: dict, fitfunc: dict, techno: dict, par_fixe
515515
### [Chi2 loss function]
516516
def chi2_loss(par):
517517

518-
total = 0
518+
tot = 0
519519

520520
# Over histograms
521521
for key in counts.keys():
@@ -529,14 +529,14 @@ def chi2_loss(par):
529529

530530
residual = (y_pred[fmask] - counts[key][rmask][fmask]) / errors[key][rmask][fmask]
531531

532-
total += np.sum(residual**2)
532+
tot += np.sum(residual**2)
533533

534-
return total
534+
return tot
535535

536536
### [Huber loss function]
537537
def huber_loss(par):
538538

539-
total = 0
539+
tot = 0
540540
delta = techno['huber_delta']
541541

542542
# Over histograms
@@ -552,14 +552,15 @@ def huber_loss(par):
552552
T = huber_lossfunc(y_true=counts[key][rmask][fmask], y_pred=y_pred[fmask],
553553
sigma=errors[key][rmask][fmask], delta=delta)
554554

555-
total += T
555+
tot += T
556556

557-
return total
557+
return tot
558558

559-
### [Poissonian negative log-likelihood loss function]
559+
### [Poissonian negative delta log-likelihood loss function]
560560
def poiss_nll_loss(par):
561561

562-
total = 0
562+
EPS = 1e-9
563+
nll = 0
563564

564565
# Over histograms
565566
for key in counts.keys():
@@ -571,16 +572,27 @@ def poiss_nll_loss(par):
571572
# ** Note use x=cbins[range_mask] here, due to trapz integral in fitfunc ! **
572573
y_pred = fitfunc[key](cbins[key][rmask], par, par_fixed)
573574

574-
valid = (y_pred > 0) & fmask
575+
valid = (y_pred > 0)
575576
if np.sum(valid) == 0: return 1e9
576577

577-
T1 = counts[key][rmask][valid] * np.log(y_pred[valid])
578-
T2 = y_pred[valid]
579-
580-
total += (-1)*(np.sum(T1) - np.sum(T2))
581-
582-
return total
583-
578+
y_pred[~valid] = EPS
579+
580+
# Bohm-Zech scale transform for weighted events (https://arxiv.org/abs/1309.1287)
581+
# https://scikit-hep.org/iminuit/notebooks/weighted_histograms.html
582+
s = counts[key][rmask][fmask] / (errors[key][rmask][fmask]**2) # Per bin
583+
584+
n = counts[key][rmask][fmask] # Observed
585+
mu = y_pred[fmask] # Predicted
586+
587+
# Factor 2 x taken into account by setting `errordef = iminuit.Minuit.LIKELIHOOD`
588+
589+
# Delta log-likelihood with Bohm-Zech scale
590+
nll += np.sum( s * (n * (np.log(n) - np.log(mu)) - (n - mu)) )
591+
592+
# Simple log-likelihood (NB. x -1)
593+
#nll += (-1) * np.sum(n * np.log(mu) - mu)
594+
595+
return nll
584596

585597
# --------------------------------------------------------------------
586598
loss_type = techno['loss_type']
@@ -739,9 +751,11 @@ def optimizer_execute(trials, loss, param, techno):
739751
m1.fixed[k] = param['fixed'][k]
740752
# --------------------------------------------------------------------
741753

742-
if techno['loss_type'] == 'nll':
754+
if 'nll' in techno['loss_type']:
755+
cprint('Setting errordef "LIKELIHOOD" ', 'yellow')
743756
m1.errordef = iminuit.Minuit.LIKELIHOOD
744757
else:
758+
cprint('Setting errordef "LEAST_SQUARES" ', 'yellow')
745759
m1.errordef = iminuit.Minuit.LEAST_SQUARES
746760

747761
# Set parameter bounds

icefit/peakfit.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
# - Keep all pdf functions normalized in the steering yml (norm: True),
77
# otherwise fit stability problems and uncertainty estimation is not consistent.
88
#
9-
# - Use 'chi2' loss if using weighted event histograms (either MC or data)
10-
# Use 'nll' for unweighted Poisson count histograms (both MC and data)
9+
# - Use 'chi2' or 'huber' loss if using weighted event histograms (either MC or data)
10+
# Use 'nll' for unweighted Poisson count histograms
11+
# and a weighted count histograms via a scale transform (experimental)
12+
#
13+
# - For different fit types see: /docs/pdf/peakfit.pdf
14+
#
1115
#
1216
# Run with: python icefit/peakfit.py --analyze --group (--test_mode)
1317
#
@@ -34,7 +38,7 @@
3438

3539
import ray
3640

37-
__VERSION__ = 0.02
41+
__VERSION__ = 0.03
3842
__AUTHOR__ = '[email protected]'
3943

4044
# ========================================================================

tests/test_peakfit.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
#
3+
# Test peakfit
4+
5+
git clone https://github.com/mieskolainen/actions-stash.git
6+
7+
for L in chi2 huber nll; do
8+
for T in single dual dual-unitary-I dual-unitary-II; do
9+
python icefit/peakfit.py --num_cpus 1 --test_mode --analyze --group --loss_type "$L" --fit_type "$T" --output_name "test_${L}_${T}" > "peakfit_${L}_${T}.log"
10+
done
11+
done

0 commit comments

Comments
 (0)