Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooUnbinnedL.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * PB, Patrick Bos, Netherlands eScience Center, p.bos@esciencecenter.nl
5 *
6 * Copyright (c) 2021, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13/**
14\file RooUnbinnedL.cxx
15\class RooUnbinnedL
16\ingroup Roofitcore
17
18Class RooUnbinnedL implements a -log(likelihood) calculation from a dataset
19(assumed to be unbinned) and a PDF. The NLL is calculated as
20\f[
21 \sum_\mathrm{data} -\log( \mathrm{pdf}(x_\mathrm{data}))
22\f]
23In extended mode, a
24\f$ N_\mathrm{expect} - N_\mathrm{observed}*log(N_\mathrm{expect}) \f$ term is added.
25**/
26
28
29#include "RooAbsData.h"
30#include "RooAbsPdf.h"
31#include "RooAbsDataStore.h"
32#include "RooNLLVar.h" // RooNLLVar::ComputeScalar
33#include "RunContext.h"
34#include "RooChangeTracker.h"
35
36namespace RooFit {
37namespace TestStatistics {
38
40 bool useBatchedEvaluations)
41 : RooAbsL(RooAbsL::ClonePdfData{pdf, data}, data->numEntries(), 1, extended),
42 useBatchedEvaluations_(useBatchedEvaluations)
43{
44 std::unique_ptr<RooArgSet> params(pdf->getParameters(data));
45 paramTracker_ = std::make_unique<RooChangeTracker>("chtracker","change tracker",*params,true);
46}
47
49 : RooAbsL(other), apply_weight_squared(other.apply_weight_squared), _first(other._first),
50 useBatchedEvaluations_(other.useBatchedEvaluations_)
51{
52 paramTracker_ = std::make_unique<RooChangeTracker>(*other.paramTracker_);
53}
54
56
57//////////////////////////////////////////////////////////////////////////////////
58
59/// Returns true if value was changed, false otherwise.
61{
62 if (apply_weight_squared != flag) {
64 return true;
65 }
66 // setValueDirty();
67 return false;
68}
69
72}
73
74//////////////////////////////////////////////////////////////////////////////////
75/// Calculate and return likelihood on subset of data from firstEvent to lastEvent
76/// processed with a step size of 'stepSize'. If this an extended likelihood and
77/// and the zero event is processed the extended term is added to the return
78/// likelihood.
79///
81RooUnbinnedL::evaluatePartition(Section events, std::size_t /*components_begin*/, std::size_t /*components_end*/)
82{
83 // Throughout the calculation, we use Kahan's algorithm for summing to
84 // prevent loss of precision - this is a factor four more expensive than
85 // straight addition, but since evaluating the PDF is usually much more
86 // expensive than that, we tolerate the additional cost...
88 double sumWeight;
89
90 // Do not reevaluate likelihood if parameters have not changed
91 if (!paramTracker_->hasChanged(true) & (cachedResult_ != 0)) return cachedResult_;
92
93 data_->store()->recalculateCache(nullptr, events.begin(N_events_), events.end(N_events_), 1, true);
94
96 std::unique_ptr<RooBatchCompute::RunContext> evalData;
97 std::tie(result, sumWeight) = RooNLLVar::computeBatchedFunc(pdf_.get(), data_.get(), evalData, normSet_.get(), apply_weight_squared,
98 1, events.begin(N_events_), events.end(N_events_));
99 } else {
100 std::tie(result, sumWeight) = RooNLLVar::computeScalarFunc(pdf_.get(), data_.get(), normSet_.get(), apply_weight_squared,
101 1, events.begin(N_events_), events.end(N_events_));
102 }
103
104 // include the extended maximum likelihood term, if requested
105 if (extended_) {
107
108 // TODO: the following should also be factored out into free/static functions like RooNLLVar::Compute*
109 // Calculate sum of weights-squared here for extended term
110 Double_t sumW2;
112 const RooSpan<const double> eventWeights = data_->getWeightBatch(0, N_events_);
113 if (eventWeights.empty()) {
114 sumW2 = (events.end(N_events_) - events.begin(N_events_)) * data_->weightSquared();
115 } else {
117 for (std::size_t i = 0; i < eventWeights.size(); ++i) {
118 kahanWeight.AddIndexed(eventWeights[i] * eventWeights[i], i);
119 }
120 sumW2 = kahanWeight.Sum();
121 }
122 } else { // scalar mode
123 ROOT::Math::KahanSum<double> sumW2KahanSum;
124 for (Int_t i = 0; i < data_->numEntries(); i++) {
125 data_->get(i);
126 sumW2KahanSum += data_->weightSquared();
127 }
128 sumW2 = sumW2KahanSum.Sum();
129 }
130
131 Double_t expected = pdf_->expectedEvents(data_->get());
132
133 // Adjust calculation of extended term with W^2 weighting: adjust poisson such that
134 // estimate of Nexpected stays at the same value, but has a different variance, rescale
135 // both the observed and expected count of the Poisson with a factor sum[w] / sum[w^2] which is
136 // the effective weight of the Poisson term.
137 // i.e. change Poisson(Nobs = sum[w]| Nexp ) --> Poisson( sum[w] * sum[w] / sum[w^2] | Nexp * sum[w] /
138 // sum[w^2] ) weighted by the effective weight sum[w^2]/ sum[w] in the likelihood. Since here we compute
139 // the likelihood with the weight square we need to multiply by the square of the effective weight expectedW
140 // = expected * sum[w] / sum[w^2] : effective expected entries observedW = sum[w] * sum[w] / sum[w^2] :
141 // effective observed entries The extended term for the likelihood weighted by the square of the weight will
142 // be then:
143 // (sum[w^2]/ sum[w] )^2 * expectedW - (sum[w^2]/ sum[w] )^2 * observedW * log (expectedW) and this is
144 // using the previous expressions for expectedW and observedW
145 // sum[w^2] / sum[w] * expected - sum[w^2] * log (expectedW)
146 // and since the weights are constants in the likelihood we can use log(expected) instead of log(expectedW)
147
148 Double_t expectedW2 = expected * sumW2 / data_->sumEntries();
149 Double_t extra = expectedW2 - sumW2 * log(expected);
150
151 // Double_t y = pdf->extendedTerm(sumW2, data->get()) - carry;
152
153 result += extra;
154 } else {
155 result += pdf_->extendedTerm(data_->sumEntries(), data_->get());
156 }
157 }
158
159 // If part of simultaneous PDF normalize probability over
160 // number of simultaneous PDFs: -sum(log(p/n)) = -sum(log(p)) + N*log(n)
161 if (sim_count_ > 1) {
162 result += sumWeight * log(1.0 * sim_count_);
163 }
164
165 // At the end of the first full calculation, wire the caches
166 if (_first) {
167 _first = false;
168 pdf_->wireAllCaches();
169 }
170
171 cachedResult_ = result;
172 return result;
173}
174
175} // namespace TestStatistics
176} // namespace RooFit
double Double_t
Definition RtypesCore.h:59
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Definition Util.h:122
T Sum() const
Definition Util.h:240
void AddIndexed(T input, std::size_t index)
Add input to the sum.
Definition Util.h:231
RooArgSet * getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:82
std::shared_ptr< RooAbsData > data_
Definition RooAbsL.h:130
std::unique_ptr< RooArgSet > normSet_
Definition RooAbsL.h:131
std::shared_ptr< RooAbsPdf > pdf_
Definition RooAbsL.h:129
ROOT::Math::KahanSum< double > cachedResult_
bool setApplyWeightSquared(bool flag)
Returns true if value was changed, false otherwise.
ROOT::Math::KahanSum< double > evaluatePartition(Section events, std::size_t components_begin, std::size_t components_end) override
Calculate and return likelihood on subset of data from firstEvent to lastEvent processed with a step ...
std::unique_ptr< RooChangeTracker > paramTracker_
RooUnbinnedL(RooAbsPdf *pdf, RooAbsData *data, RooAbsL::Extended extended=RooAbsL::Extended::Auto, bool useBatchedEvaluations=false)
static RooNLLVar::ComputeResult computeScalarFunc(const RooAbsPdf *pdfClone, RooAbsData *dataClone, RooArgSet *normSet, bool weightSq, std::size_t stepSize, std::size_t firstEvent, std::size_t lastEvent)
static RooNLLVar::ComputeResult computeBatchedFunc(const RooAbsPdf *pdfClone, RooAbsData *dataClone, std::unique_ptr< RooBatchCompute::RunContext > &evalData, RooArgSet *normSet, bool weightSq, std::size_t stepSize, std::size_t firstEvent, std::size_t lastEvent)
A simple container to hold a batch of data values.
Definition RooSpan.h:34
constexpr std::span< T >::index_type size() const noexcept
Definition RooSpan.h:121
constexpr bool empty() const noexcept
Definition RooSpan.h:125
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition Common.h:18
Convenience wrapper class used to distinguish between pdf/data owning and non-owning constructors.
Definition RooAbsL.h:38
A part of some range delimited by two fractional points between 0 and 1 (inclusive).
Definition RooAbsL.h:57
std::size_t begin(std::size_t N_total) const
Definition RooAbsL.h:67
std::size_t end(std::size_t N_total) const
Definition RooAbsL.h:69