aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
paramEstimator_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/** @file
23
* @brief the base class for estimating parameters of CPTs
24
*
25
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26
*/
27
28
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
29
30
namespace
gum
{
31
32
namespace
learning
{
33
34
/// returns the allocator used by the score
35
template
<
template
<
typename
>
class
ALLOC
>
36
INLINE
typename
ParamEstimator
<
ALLOC
>::
allocator_type
37
ParamEstimator
<
ALLOC
>::
getAllocator
()
const
{
38
return
counter_
.
getAllocator
();
39
}
40
41
42
/// default constructor
43
template
<
template
<
typename
>
class
ALLOC
>
44
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
45
const
DBRowGeneratorParser
<
ALLOC
>&
parser
,
46
const
Apriori
<
ALLOC
>&
external_apriori
,
47
const
Apriori
<
ALLOC
>&
score_internal_apriori
,
48
const
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
>,
49
ALLOC
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> > >&
ranges
,
50
const
Bijection
<
NodeId
,
std
::
size_t
,
ALLOC
<
std
::
size_t
> >&
nodeId2columns
,
51
const
typename
ParamEstimator
<
ALLOC
>::
allocator_type
&
alloc
) :
52
counter_
(
parser
,
ranges
,
nodeId2columns
,
alloc
) {
53
// copy the a prioris
54
external_apriori_
=
external_apriori
.
clone
(
alloc
);
55
try
{
56
score_internal_apriori_
=
score_internal_apriori
.
clone
();
57
}
catch
(...) {
58
ALLOC
<
Apriori
<
ALLOC
> >
allocator
(
alloc
);
59
allocator
.
destroy
(
external_apriori_
);
60
allocator
.
deallocate
(
external_apriori_
, 1);
61
throw
;
62
}
63
64
GUM_CONSTRUCTOR
(
ParamEstimator
);
65
}
66
67
68
/// default constructor
69
template
<
template
<
typename
>
class
ALLOC
>
70
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
71
const
DBRowGeneratorParser
<
ALLOC
>&
parser
,
72
const
Apriori
<
ALLOC
>&
external_apriori
,
73
const
Apriori
<
ALLOC
>&
score_internal_apriori
,
74
const
Bijection
<
NodeId
,
std
::
size_t
,
ALLOC
<
std
::
size_t
> >&
nodeId2columns
,
75
const
typename
ParamEstimator
<
ALLOC
>::
allocator_type
&
alloc
) :
76
counter_
(
parser
,
nodeId2columns
,
alloc
) {
77
// copy the a prioris
78
external_apriori_
=
external_apriori
.
clone
(
alloc
);
79
try
{
80
score_internal_apriori_
=
score_internal_apriori
.
clone
();
81
}
catch
(...) {
82
ALLOC
<
Apriori
<
ALLOC
> >
allocator
(
alloc
);
83
allocator
.
destroy
(
external_apriori_
);
84
allocator
.
deallocate
(
external_apriori_
, 1);
85
throw
;
86
}
87
88
GUM_CONSTRUCTOR
(
ParamEstimator
);
89
}
90
91
92
/// copy constructor with a given allocator
93
template
<
template
<
typename
>
class
ALLOC
>
94
INLINE
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
95
const
ParamEstimator
<
ALLOC
>&
from
,
96
const
typename
ParamEstimator
<
ALLOC
>::
allocator_type
&
alloc
) :
97
external_apriori_
(
from
.
external_apriori_
->
clone
(
alloc
)),
98
score_internal_apriori_
(
from
.
score_internal_apriori_
->
clone
(
alloc
)),
99
counter_
(
from
.
counter_
,
alloc
) {
100
GUM_CONS_CPY
(
ParamEstimator
);
101
}
102
103
104
/// copy constructor
105
template
<
template
<
typename
>
class
ALLOC
>
106
INLINE
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
const
ParamEstimator
<
ALLOC
>&
from
) :
107
ParamEstimator
<
ALLOC
>(
from
,
from
.
getAllocator
()) {}
108
109
110
/// move constructor with a given allocator
111
template
<
template
<
typename
>
class
ALLOC
>
112
INLINE
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
113
ParamEstimator
<
ALLOC
>&&
from
,
114
const
typename
ParamEstimator
<
ALLOC
>::
allocator_type
&
alloc
) :
115
external_apriori_
(
from
.
external_apriori_
),
116
score_internal_apriori_
(
from
.
score_internal_apriori_
),
117
counter_
(
std
::
move
(
from
.
counter_
),
alloc
) {
118
from
.
external_apriori_
=
nullptr
;
119
from
.
score_internal_apriori_
=
nullptr
;
120
GUM_CONS_MOV
(
ParamEstimator
);
121
}
122
123
124
/// move constructor
125
template
<
template
<
typename
>
class
ALLOC
>
126
INLINE
ParamEstimator
<
ALLOC
>::
ParamEstimator
(
ParamEstimator
<
ALLOC
>&&
from
) :
127
ParamEstimator
<
ALLOC
>(
std
::
move
(
from
),
from
.
getAllocator
()) {}
128
129
130
/// destructor
131
template
<
template
<
typename
>
class
ALLOC
>
132
ParamEstimator
<
ALLOC
>::~
ParamEstimator
() {
133
ALLOC
<
Apriori
<
ALLOC
> >
allocator
(
this
->
getAllocator
());
134
if
(
external_apriori_
!=
nullptr
) {
135
allocator
.
destroy
(
external_apriori_
);
136
allocator
.
deallocate
(
external_apriori_
, 1);
137
}
138
139
if
(
score_internal_apriori_
!=
nullptr
) {
140
allocator
.
destroy
(
score_internal_apriori_
);
141
allocator
.
deallocate
(
score_internal_apriori_
, 1);
142
}
143
144
GUM_DESTRUCTOR
(
ParamEstimator
);
145
}
146
147
148
/// copy operator
149
template
<
template
<
typename
>
class
ALLOC
>
150
ParamEstimator
<
ALLOC
>&
151
ParamEstimator
<
ALLOC
>::
operator
=(
const
ParamEstimator
<
ALLOC
>&
from
) {
152
if
(
this
!= &
from
) {
153
ALLOC
<
Apriori
<
ALLOC
> >
allocator
(
this
->
getAllocator
());
154
if
(
external_apriori_
!=
nullptr
) {
155
allocator
.
destroy
(
external_apriori_
);
156
allocator
.
deallocate
(
external_apriori_
, 1);
157
external_apriori_
=
nullptr
;
158
}
159
external_apriori_
=
from
.
external_apriori_
->
clone
(
this
->
getAllocator
());
160
161
if
(
score_internal_apriori_
!=
nullptr
) {
162
allocator
.
destroy
(
score_internal_apriori_
);
163
allocator
.
deallocate
(
score_internal_apriori_
, 1);
164
external_apriori_
=
nullptr
;
165
}
166
score_internal_apriori_
=
from
.
score_internal_apriori_
->
clone
(
this
->
getAllocator
());
167
168
counter_
=
from
.
counter_
;
169
}
170
return
*
this
;
171
}
172
173
174
/// move operator
175
template
<
template
<
typename
>
class
ALLOC
>
176
ParamEstimator
<
ALLOC
>&
ParamEstimator
<
ALLOC
>::
operator
=(
ParamEstimator
<
ALLOC
>&&
from
) {
177
if
(
this
!= &
from
) {
178
external_apriori_
=
from
.
external_apriori_
;
179
score_internal_apriori_
=
from
.
score_internal_apriori_
;
180
counter_
=
std
::
move
(
from
.
counter_
);
181
from
.
external_apriori_
=
nullptr
;
182
from
.
score_internal_apriori_
=
nullptr
;
183
}
184
return
*
this
;
185
}
186
187
188
/// clears all the data structures from memory
189
template
<
template
<
typename
>
class
ALLOC
>
190
INLINE
void
ParamEstimator
<
ALLOC
>::
clear
() {
191
counter_
.
clear
();
192
}
193
194
195
/// changes the max number of threads used to parse the database
196
template
<
template
<
typename
>
class
ALLOC
>
197
void
ParamEstimator
<
ALLOC
>::
setMaxNbThreads
(
std
::
size_t
nb
)
const
{
198
counter_
.
setMaxNbThreads
(
nb
);
199
}
200
201
202
/// returns the number of threads used to parse the database
203
template
<
template
<
typename
>
class
ALLOC
>
204
std
::
size_t
ParamEstimator
<
ALLOC
>::
nbThreads
()
const
{
205
return
counter_
.
nbThreads
();
206
}
207
208
209
/** @brief changes the number min of rows a thread should process in a
210
* multithreading context */
211
template
<
template
<
typename
>
class
ALLOC
>
212
INLINE
void
ParamEstimator
<
ALLOC
>::
setMinNbRowsPerThread
(
const
std
::
size_t
nb
)
const
{
213
counter_
.
setMinNbRowsPerThread
(
nb
);
214
}
215
216
217
/// returns the minimum of rows that each thread should process
218
template
<
template
<
typename
>
class
ALLOC
>
219
INLINE
std
::
size_t
ParamEstimator
<
ALLOC
>::
minNbRowsPerThread
()
const
{
220
return
counter_
.
minNbRowsPerThread
();
221
}
222
223
224
/// sets new ranges to perform the countings used by the score
225
/** @param ranges a set of pairs {(X1,Y1),...,(Xn,Yn)} of database's rows
226
* indices. The countings are then performed only on the union of the
227
* rows [Xi,Yi), i in {1,...,n}. This is useful, e.g, when performing
228
* cross validation tasks, in which part of the database should be ignored.
229
* An empty set of ranges is equivalent to an interval [X,Y) ranging over
230
* the whole database. */
231
template
<
template
<
typename
>
class
ALLOC
>
232
template
<
template
<
typename
>
class
XALLOC
>
233
void
ParamEstimator
<
ALLOC
>::
setRanges
(
234
const
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
>,
235
XALLOC
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> > >&
new_ranges
) {
236
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
>,
237
ALLOC
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> > >
238
old_ranges
=
ranges
();
239
counter_
.
setRanges
(
new_ranges
);
240
if
(
old_ranges
!=
ranges
())
clear
();
241
}
242
243
244
/// reset the ranges to the one range corresponding to the whole database
245
template
<
template
<
typename
>
class
ALLOC
>
246
void
ParamEstimator
<
ALLOC
>::
clearRanges
() {
247
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
>,
248
ALLOC
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> > >
249
old_ranges
=
ranges
();
250
counter_
.
clearRanges
();
251
if
(
old_ranges
!=
ranges
())
clear
();
252
}
253
254
255
/// returns the current ranges
256
template
<
template
<
typename
>
class
ALLOC
>
257
INLINE
const
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
>,
258
ALLOC
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> > >&
259
ParamEstimator
<
ALLOC
>::
ranges
()
const
{
260
return
counter_
.
ranges
();
261
}
262
263
264
/// returns the CPT's parameters corresponding to a given target node
265
template
<
template
<
typename
>
class
ALLOC
>
266
INLINE
std
::
vector
<
double
,
ALLOC
<
double
> >
267
ParamEstimator
<
ALLOC
>::
parameters
(
const
NodeId
target_node
) {
268
return
parameters
(
target_node
,
empty_nodevect_
);
269
}
270
271
272
// check the coherency between the parameters passed to setParameters functions
273
template
<
template
<
typename
>
class
ALLOC
>
274
template
<
typename
GUM_SCALAR
>
275
void
ParamEstimator
<
ALLOC
>::
_checkParameters_
(
276
const
NodeId
target_node
,
277
const
std
::
vector
<
NodeId
,
ALLOC
<
NodeId
> >&
conditioning_nodes
,
278
Potential
<
GUM_SCALAR
>&
pot
) {
279
// check that the nodes passed in arguments correspond to those of pot
280
const
Sequence
<
const
DiscreteVariable
* >&
vars
=
pot
.
variablesSequence
();
281
if
(
vars
.
size
() == 0) {
GUM_ERROR
(
SizeError
,
"the potential contains no variable"
) }
282
283
const
auto
&
database
=
counter_
.
database
();
284
const
auto
&
node2cols
=
counter_
.
nodeId2Columns
();
285
if
(
node2cols
.
empty
()) {
286
if
(
database
.
domainSize
(
target_node
) !=
vars
[0]->
domainSize
()) {
287
GUM_ERROR
(
SizeError
,
288
"Variable "
<<
vars
[0]->
name
() <<
"of the potential to be filled "
289
<<
"has a domain size of "
<<
vars
[0]->
domainSize
()
290
<<
", which is different from that of node "
<<
target_node
291
<<
" which is equal to "
<<
database
.
domainSize
(
target_node
));
292
}
293
for
(
std
::
size_t
i
= 1;
i
<
vars
.
size
(); ++
i
) {
294
if
(
database
.
domainSize
(
conditioning_nodes
[
i
- 1]) !=
vars
[
i
]->
domainSize
()) {
295
GUM_ERROR
(
SizeError
,
296
"Variable "
<<
vars
[
i
]->
name
() <<
"of the potential to be filled "
297
<<
"has a domain size of "
<<
vars
[
i
]->
domainSize
()
298
<<
", which is different from that of node "
299
<<
conditioning_nodes
[
i
- 1] <<
" which is equal to "
300
<<
database
.
domainSize
(
conditioning_nodes
[
i
- 1]));
301
}
302
}
303
}
else
{
304
std
::
size_t
col
=
node2cols
.
second
(
target_node
);
305
if
(
database
.
domainSize
(
col
) !=
vars
[0]->
domainSize
()) {
306
GUM_ERROR
(
SizeError
,
307
"Variable "
<<
vars
[0]->
name
() <<
"of the potential to be filled "
308
<<
"has a domain size of "
<<
vars
[0]->
domainSize
()
309
<<
", which is different from that of node "
<<
target_node
310
<<
" which is equal to "
<<
database
.
domainSize
(
col
));
311
}
312
for
(
std
::
size_t
i
= 1;
i
<
vars
.
size
(); ++
i
) {
313
col
=
node2cols
.
second
(
conditioning_nodes
[
i
- 1]);
314
if
(
database
.
domainSize
(
col
) !=
vars
[
i
]->
domainSize
()) {
315
GUM_ERROR
(
SizeError
,
316
"Variable "
<<
vars
[
i
]->
name
() <<
"of the potential to be filled "
317
<<
"has a domain size of "
<<
vars
[
i
]->
domainSize
()
318
<<
", which is different from that of node "
319
<<
conditioning_nodes
[
i
- 1] <<
" which is equal to "
320
<<
database
.
domainSize
(
col
));
321
}
322
}
323
}
324
}
325
326
327
/// sets the CPT's parameters corresponding to a given nodeset
328
template
<
template
<
typename
>
class
ALLOC
>
329
template
<
typename
GUM_SCALAR
>
330
INLINE
typename
std
::
enable_if
< !
std
::
is_same
<
GUM_SCALAR
,
double
>::
value
,
void
>::
type
331
ParamEstimator
<
ALLOC
>::
_setParameters_
(
332
const
NodeId
target_node
,
333
const
std
::
vector
<
NodeId
,
ALLOC
<
NodeId
> >&
conditioning_nodes
,
334
Potential
<
GUM_SCALAR
>&
pot
) {
335
_checkParameters_
(
target_node
,
conditioning_nodes
,
pot
);
336
337
const
std
::
vector
<
double
,
ALLOC
<
double
> >
params
(
338
parameters
(
target_node
,
conditioning_nodes
));
339
340
// transform the vector of double into a vector of GUM_SCALAR
341
const
std
::
size_t
size
=
params
.
size
();
342
std
::
vector
<
GUM_SCALAR
,
ALLOC
<
GUM_SCALAR
> >
xparams
(
size
);
343
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
size
; ++
i
)
344
xparams
[
i
] =
GUM_SCALAR
(
params
[
i
]);
345
346
pot
.
fillWith
(
xparams
);
347
}
348
349
350
/// sets the CPT's parameters corresponding to a given nodeset
351
template
<
template
<
typename
>
class
ALLOC
>
352
template
<
typename
GUM_SCALAR
>
353
INLINE
typename
std
::
enable_if
<
std
::
is_same
<
GUM_SCALAR
,
double
>::
value
,
void
>::
type
354
ParamEstimator
<
ALLOC
>::
_setParameters_
(
355
const
NodeId
target_node
,
356
const
std
::
vector
<
NodeId
,
ALLOC
<
NodeId
> >&
conditioning_nodes
,
357
Potential
<
GUM_SCALAR
>&
pot
) {
358
_checkParameters_
(
target_node
,
conditioning_nodes
,
pot
);
359
360
const
std
::
vector
<
double
,
ALLOC
<
double
> >
params
(
361
parameters
(
target_node
,
conditioning_nodes
));
362
pot
.
fillWith
(
params
);
363
}
364
365
366
/// sets the CPT's parameters corresponding to a given nodeset
367
template
<
template
<
typename
>
class
ALLOC
>
368
template
<
typename
GUM_SCALAR
>
369
INLINE
void
ParamEstimator
<
ALLOC
>::
setParameters
(
370
const
NodeId
target_node
,
371
const
std
::
vector
<
NodeId
,
ALLOC
<
NodeId
> >&
conditioning_nodes
,
372
Potential
<
GUM_SCALAR
>&
pot
) {
373
_setParameters_
(
target_node
,
conditioning_nodes
,
pot
);
374
}
375
376
377
/// returns the mapping from ids to column positions in the database
378
template
<
template
<
typename
>
class
ALLOC
>
379
INLINE
const
Bijection
<
NodeId
,
std
::
size_t
,
ALLOC
<
std
::
size_t
> >&
380
ParamEstimator
<
ALLOC
>::
nodeId2Columns
()
const
{
381
return
counter_
.
nodeId2Columns
();
382
}
383
384
385
/// returns the database on which we perform the counts
386
template
<
template
<
typename
>
class
ALLOC
>
387
INLINE
const
DatabaseTable
<
ALLOC
>&
ParamEstimator
<
ALLOC
>::
database
()
const
{
388
return
counter_
.
database
();
389
}
390
391
392
/// assign a new Bayes net to all the counter's generators depending on a BN
393
template
<
template
<
typename
>
class
ALLOC
>
394
template
<
typename
GUM_SCALAR
>
395
INLINE
void
ParamEstimator
<
ALLOC
>::
setBayesNet
(
const
BayesNet
<
GUM_SCALAR
>&
new_bn
) {
396
counter_
.
setBayesNet
(
new_bn
);
397
}
398
399
400
}
/* namespace learning */
401
402
}
/* namespace gum */
403
404
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::learning::genericBNLearner::Database::Database
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
Definition:
genericBNLearner_tpl.h:31