aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
paramEstimator.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 #ifndef GUM_LEARNING_PARAM_ESTIMATOR_H
28 #define GUM_LEARNING_PARAM_ESTIMATOR_H
29 
30 #include <type_traits>
31 
32 #include <agrum/agrum.h>
33 #include <agrum/tools/database/databaseTable.h>
34 #include <agrum/BN/learning/aprioris/apriori.h>
35 #include <agrum/tools/stattests/recordCounter.h>
36 #include <agrum/tools/multidim/potential.h>
37 
38 namespace gum {
39 
40  namespace learning {
41 
42 
43  /** @class ParamEstimator
44  * @brief The base class for estimating parameters of CPTs
45  * @headerfile paramEstimator.h <agrum/BN/learning/paramUtils/paramEstimator.h>
46  * @ingroup learning_param_utils
47  */
48  template < template < typename > class ALLOC = std::allocator >
50  public:
51  /// type for the allocators passed in arguments of methods
53 
54  // ##########################################################################
55  /// @name Constructors / Destructors
56  // ##########################################################################
57  /// @{
58 
59  /// default constructor
60  /** @param parser the parser used to parse the database
61  * @param external_apriori An apriori that we add to the computation
62  * of the score
63  * @param score_internal_apriori The apriori within the score used
64  * to learn the data structure (might be a NoApriori)
65  * @param ranges a set of pairs {(X1,Y1),...,(Xn,Yn)} of database's rows
66  * indices. The countings are then performed only on the union of the
67  * rows [Xi,Yi), i in {1,...,n}. This is useful, e.g, when performing
68  * cross validation tasks, in which part of the database should be ignored.
69  * An empty set of ranges is equivalent to an interval [X,Y) ranging over
70  * the whole database.
71  * @param nodeId2Columns a mapping from the ids of the nodes in the
72  * graphical model to the corresponding column in the DatabaseTable
73  * parsed by the parser. This enables estimating from a database in
74  * which variable A corresponds to the 2nd column the parameters of a BN
75  * in which variable A has a NodeId of 5. An empty nodeId2Columns
76  * bijection means that the mapping is an identity, i.e., the value of a
77  * NodeId is equal to the index of the column in the DatabaseTable.
78  * @param alloc the allocator used to allocate the structures within the
79  * Score.
80  * @warning If nodeId2columns is not empty, then only the scores over the
81  * ids belonging to this bijection can be computed: applying method
82  * score() over other ids will raise exception NotFound. */
84  const DBRowGeneratorParser< ALLOC >& parser,
85  const Apriori< ALLOC >& external_apriori,
86  const Apriori< ALLOC >& score_internal__apriori,
87  const std::vector< std::pair< std::size_t, std::size_t >,
88  ALLOC< std::pair< std::size_t, std::size_t > > >&
89  ranges,
90  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
92  = Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(),
94 
95  /// default constructor
96  /** @param parser the parser used to parse the database
97  * @param external_apriori An apriori that we add to the computation
98  * of the score
99  * @param score_internal_apriori The apriori within the score used
100  * to learn the data structure (might be a NoApriori)
101  * @param nodeId2Columns a mapping from the ids of the nodes in the
102  * graphical model to the corresponding column in the DatabaseTable
103  * parsed by the parser. This enables estimating from a database in
104  * which variable A corresponds to the 2nd column the parameters of a BN
105  * in which variable A has a NodeId of 5. An empty nodeId2Columns
106  * bijection means that the mapping is an identity, i.e., the value of a
107  * NodeId is equal to the index of the column in the DatabaseTable.
108  * @param alloc the allocator used to allocate the structures within the
109  * Score.
110  * @warning If nodeId2columns is not empty, then only the scores over the
111  * ids belonging to this bijection can be computed: applying method
112  * score() over other ids will raise exception NotFound. */
113  ParamEstimator(const DBRowGeneratorParser< ALLOC >& parser,
114  const Apriori< ALLOC >& external_apriori,
115  const Apriori< ALLOC >& score_internal__apriori,
116  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
118  = Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(),
119  const allocator_type& alloc = allocator_type());
120 
121  /// copy constructor
122  ParamEstimator(const ParamEstimator< ALLOC >& from);
123 
124  /// copy constructor with a given allocator
125  ParamEstimator(const ParamEstimator< ALLOC >& from,
126  const allocator_type& alloc);
127 
128  /// move constructor
129  ParamEstimator(ParamEstimator< ALLOC >&& from);
130 
131  /// move constructor with a given allocator
132  ParamEstimator(ParamEstimator< ALLOC >&& from, const allocator_type& alloc);
133 
134  /// virtual copy constructor
135  virtual ParamEstimator< ALLOC >* clone() const = 0;
136 
137  /// virtual copy constructor with a given allocator
138  virtual ParamEstimator< ALLOC >*
139  clone(const allocator_type& alloc) const = 0;
140 
141  /// destructor
142  virtual ~ParamEstimator();
143 
144  /// @}
145 
146 
147  // ##########################################################################
148  /// @name Accessors / Modifiers
149  // ##########################################################################
150  /// @{
151 
152  /// clears all the data structures from memory
153  virtual void clear();
154 
155  /// changes the max number of threads used to parse the database
156  virtual void setMaxNbThreads(std::size_t nb) const;
157 
158  /// returns the number of threads used to parse the database
159  virtual std::size_t nbThreads() const;
160 
161  /** @brief changes the number min of rows a thread should process in a
162  * multithreading context
163  *
164  * When computing score, several threads are used by record counters to
165  * perform countings on the rows of the database, the MinNbRowsPerThread
166  * method indicates how many rows each thread should at least process.
167  * This is used to compute the number of threads actually run. This number
168  * is equal to the min between the max number of threads allowed and the
169  * number of records in the database divided by nb. */
170  virtual void setMinNbRowsPerThread(const std::size_t nb) const;
171 
172  /// returns the minimum of rows that each thread should process
173  virtual std::size_t minNbRowsPerThread() const;
174 
175  /// sets new ranges to perform the countings used by the parameter estimator
176  /** @param ranges a set of pairs {(X1,Y1),...,(Xn,Yn)} of database's rows
177  * indices. The countings are then performed only on the union of the
178  * rows [Xi,Yi), i in {1,...,n}. This is useful, e.g, when performing
179  * cross validation tasks, in which part of the database should be ignored.
180  * An empty set of ranges is equivalent to an interval [X,Y) ranging over
181  * the whole database. */
182  template < template < typename > class XALLOC >
183  void setRanges(
184  const std::vector< std::pair< std::size_t, std::size_t >,
185  XALLOC< std::pair< std::size_t, std::size_t > > >&
186  new_ranges);
187 
188  /// reset the ranges to the one range corresponding to the whole database
189  void clearRanges();
190 
191  /// returns the current ranges
192  const std::vector< std::pair< std::size_t, std::size_t >,
193  ALLOC< std::pair< std::size_t, std::size_t > > >&
194  ranges() const;
195 
196  /// returns the CPT's parameters corresponding to a given target node
197  std::vector< double, ALLOC< double > > parameters(const NodeId target_node);
198 
199  /// returns the CPT's parameters corresponding to a given nodeset
200  /** The vector contains the parameters of an n-dimensional CPT. The
201  * distribution of the dimensions of the CPT within the vector is as
202  * follows:
203  * first, there is the target node, then the conditioning nodes (in the
204  * order in which they were specified). */
205  virtual std::vector< double, ALLOC< double > > parameters(
206  const NodeId target_node,
208  = 0;
209 
210  /// sets the CPT's parameters corresponding to a given Potential
211  /** The potential is assumed to be a conditional probability, the first
212  * variable of its variablesSequence() being the target variable, the
213  * other ones being on the right side of the conditioning bar. */
214  template < typename GUM_SCALAR >
215  void setParameters(
216  const NodeId target_node,
218  Potential< GUM_SCALAR >& pot);
219 
220  /// returns the mapping from ids to column positions in the database
221  /** @warning An empty nodeId2Columns bijection means that the mapping is
222  * an identity, i.e., the value of a NodeId is equal to the index of the
223  * column in the DatabaseTable. */
224  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
225  nodeId2Columns() const;
226 
227  /// returns the database on which we perform the counts
228  const DatabaseTable< ALLOC >& database() const;
229 
230  /// assign a new Bayes net to all the counter's generators depending on a BN
231  /** Typically, generators based on EM or K-means depend on a model to
232  * compute correctly their outputs. Method setBayesNet enables to
233  * update their BN model. */
234  template < typename GUM_SCALAR >
235  void setBayesNet(const BayesNet< GUM_SCALAR >& new_bn);
236 
237  /// returns the allocator used by the score
239 
240  /// @}
241 
242  protected:
243  /// an external a priori
245 
246  /** @brief if a score was used for learning the structure of the PGM, this
247  * is the a priori internal to the score */
249 
250  /// the record counter used to parse the database
252 
253  /// an empty vector of nodes, used for empty conditioning
255 
256 
257  /// copy operator
259 
260  /// move operator
262 
263  private:
264 #ifndef DOXYGEN_SHOULD_SKIP_THIS
265 
266  /** @brief check the coherency between the parameters passed to
267  * the setParameters functions */
268  template < typename GUM_SCALAR >
269  void checkParameters__(
270  const NodeId target_node,
271  const std::vector< NodeId, ALLOC< NodeId > >& conditioning_nodes,
272  Potential< GUM_SCALAR >& pot);
273 
274  // sets the CPT's parameters corresponding to a given Potential
275  // when the potential belongs to a BayesNet<GUM_SCALAR> when
276  // GUM_SCALAR is different from a double
277  template < typename GUM_SCALAR >
278  typename std::enable_if< !std::is_same< GUM_SCALAR, double >::value,
279  void >::type
280  setParameters__(
281  const NodeId target_node,
282  const std::vector< NodeId, ALLOC< NodeId > >& conditioning_nodes,
283  Potential< GUM_SCALAR >& pot);
284 
285  // sets the CPT's parameters corresponding to a given Potential
286  // when the potential belongs to a BayesNet<GUM_SCALAR> when
287  // GUM_SCALAR is equal to double (the code is optimized for doubles)
288  template < typename GUM_SCALAR >
289  typename std::enable_if< std::is_same< GUM_SCALAR, double >::value,
290  void >::type
291  setParameters__(
292  const NodeId target_node,
293  const std::vector< NodeId, ALLOC< NodeId > >& conditioning_nodes,
294  Potential< GUM_SCALAR >& pot);
295 
296 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
297  };
298 
299  } /* namespace learning */
300 
301 } /* namespace gum */
302 
303 /// include the template implementation
304 #include <agrum/BN/learning/paramUtils/paramEstimator_tpl.h>
305 
306 #endif /* GUM_LEARNING_PARAM_ESTIMATOR_H */
ParamEstimator< ALLOC > & operator=(const ParamEstimator< ALLOC > &from)
copy operator
virtual std::vector< double, ALLOC< double > > parameters(const NodeId target_node, const std::vector< NodeId, ALLOC< NodeId > > &conditioning_nodes)=0
returns the CPT&#39;s parameters corresponding to a given nodeset
const Bijection< NodeId, std::size_t, ALLOC< std::size_t > > & nodeId2Columns() const
returns the mapping from ids to column positions in the database
void setParameters(const NodeId target_node, const std::vector< NodeId, ALLOC< NodeId > > &conditioning_nodes, Potential< GUM_SCALAR > &pot)
sets the CPT&#39;s parameters corresponding to a given Potential
ParamEstimator(const ParamEstimator< ALLOC > &from, const allocator_type &alloc)
copy constructor with a given allocator
ParamEstimator(const ParamEstimator< ALLOC > &from)
copy constructor
void clearRanges()
reset the ranges to the one range corresponding to the whole database
ParamEstimator(const DBRowGeneratorParser< ALLOC > &parser, const Apriori< ALLOC > &external_apriori, const Apriori< ALLOC > &score_internal__apriori, const std::vector< std::pair< std::size_t, std::size_t >, ALLOC< std::pair< std::size_t, std::size_t > > > &ranges, const Bijection< NodeId, std::size_t, ALLOC< std::size_t > > &nodeId2columns=Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(), const allocator_type &alloc=allocator_type())
default constructor
void setRanges(const std::vector< std::pair< std::size_t, std::size_t >, XALLOC< std::pair< std::size_t, std::size_t > > > &new_ranges)
sets new ranges to perform the countings used by the parameter estimator
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
ParamEstimator< ALLOC > & operator=(ParamEstimator< ALLOC > &&from)
move operator
ParamEstimator(ParamEstimator< ALLOC > &&from)
move constructor
void setBayesNet(const BayesNet< GUM_SCALAR > &new_bn)
assign a new Bayes net to all the counter&#39;s generators depending on a BN
ParamEstimator(const DBRowGeneratorParser< ALLOC > &parser, const Apriori< ALLOC > &external_apriori, const Apriori< ALLOC > &score_internal__apriori, const Bijection< NodeId, std::size_t, ALLOC< std::size_t > > &nodeId2columns=Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(), const allocator_type &alloc=allocator_type())
default constructor
Apriori< ALLOC > * score_internal_apriori_
if a score was used for learning the structure of the PGM, this is the a priori internal to the score...
allocator_type getAllocator() const
returns the allocator used by the score
virtual void setMinNbRowsPerThread(const std::size_t nb) const
changes the number min of rows a thread should process in a multithreading context ...
virtual ParamEstimator< ALLOC > * clone(const allocator_type &alloc) const =0
virtual copy constructor with a given allocator
virtual ~ParamEstimator()
destructor
const DatabaseTable< ALLOC > & database() const
returns the database on which we perform the counts
std::vector< double, ALLOC< double > > parameters(const NodeId target_node)
returns the CPT&#39;s parameters corresponding to a given target node
virtual void clear()
clears all the data structures from memory
virtual std::size_t nbThreads() const
returns the number of threads used to parse the database
virtual ParamEstimator< ALLOC > * clone() const =0
virtual copy constructor
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
virtual void setMaxNbThreads(std::size_t nb) const
changes the max number of threads used to parse the database
virtual std::size_t minNbRowsPerThread() const
returns the minimum of rows that each thread should process
RecordCounter< ALLOC > counter_
the record counter used to parse the database
Apriori< ALLOC > * external_apriori_
an external a priori
ParamEstimator(ParamEstimator< ALLOC > &&from, const allocator_type &alloc)
move constructor with a given allocator