aGrUM  0.14.2
DAG2BNLearner_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}@lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it wil be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
28 #include <algorithm>
29 #include <string>
30 #include <vector>
31 
32 namespace gum {
33 
34  namespace learning {
35 
37  template < template < typename > class ALLOC >
40  return *this;
41  }
42 
43 
45  template < template < typename > class ALLOC >
47  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
48  ALLOC< NodeId >(alloc) {
49  GUM_CONSTRUCTOR(DAG2BNLearner);
50  }
51 
52 
54  template < template < typename > class ALLOC >
56  const DAG2BNLearner< ALLOC >& from,
57  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
58  ApproximationScheme(from),
59  ALLOC< NodeId >(alloc) {
60  GUM_CONS_CPY(DAG2BNLearner);
61  }
62 
63 
65  template < template < typename > class ALLOC >
67  DAG2BNLearner(from, from.getAllocator()) {}
68 
69 
71  template < template < typename > class ALLOC >
74  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
75  ApproximationScheme(std::move(from)),
76  ALLOC< NodeId >(alloc) {
77  GUM_CONS_MOV(DAG2BNLearner);
78  }
79 
80 
82  template < template < typename > class ALLOC >
84  DAG2BNLearner(std::move(from), from.getAllocator()) {}
85 
86 
88  template < template < typename > class ALLOC >
90  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) const {
91  ALLOC< DAG2BNLearner< ALLOC > > allocator(alloc);
92  DAG2BNLearner< ALLOC >* new_learner = allocator.allocate(1);
93  try {
94  allocator.construct(new_learner, *this, alloc);
95  } catch (...) {
96  allocator.deallocate(new_learner, 1);
97  throw;
98  }
99 
100  return new_learner;
101  }
102 
103 
105  template < template < typename > class ALLOC >
107  return clone(this->getAllocator());
108  }
109 
110 
112  template < template < typename > class ALLOC >
114  GUM_DESTRUCTOR(DAG2BNLearner);
115  }
116 
117 
119  template < template < typename > class ALLOC >
122  ApproximationScheme::operator=(from);
123  return *this;
124  }
125 
126 
128  template < template < typename > class ALLOC >
131  ApproximationScheme::operator=(std::move(from));
132  return *this;
133  }
134 
135 
137  template < template < typename > class ALLOC >
138  template < typename GUM_SCALAR >
141  const gum::Potential< GUM_SCALAR >& other_pot) {
142  // check that the variables are identical
143  if (!pot.variablesSequence()
144  .diffSet(other_pot.variablesSequence())
145  .empty()) {
146  GUM_ERROR(gum::CPTError, "the potentials do not have the same variables");
147  }
148 
149  // perform the copy
150  Instantiation i(other_pot);
151  Instantiation j(pot);
152  for (i.setFirst(); !i.end(); ++i) {
153  j.setVals(i);
154  pot.set(j, other_pot[i]);
155  }
156  }
157 
159  template < template < typename > class ALLOC >
160  template < typename GUM_SCALAR >
163  const DAG& dag) {
165 
166  // create a bn with dummy parameters corresponding to the dag
167  const auto& node2cols = estimator.nodeId2Columns();
168  const auto& database = estimator.database();
169  if (node2cols.empty()) {
170  for (const auto id : dag) {
171  bn.add(dynamic_cast< const DiscreteVariable& >(database.variable(id)),
172  id);
173  }
174  } else {
175  for (const auto id : dag) {
176  const std::size_t col = node2cols.second(id);
177  bn.add(dynamic_cast< const DiscreteVariable& >(database.variable(col)),
178  id);
179  }
180  }
181 
182  // add the arcs
184  for (const auto& arc : dag.arcs()) {
185  bn.addArc(arc.tail(), arc.head());
186  }
188 
189  // estimate the parameters
190  const VariableNodeMap& varmap = bn.variableNodeMap();
191  for (const auto id : dag) {
192  try {
193  // get the sequence of variables and make the targets be the last
195  const_cast< Potential< GUM_SCALAR >& >(bn.cpt(id));
196 
197  // get the variables of the CPT of id in the correct order
199  pot.variablesSequence();
200 
201  // setup the estimation
202  std::vector< NodeId > conditioning_ids(vars.size() - 1);
203  for (std::size_t i = std::size_t(1); i < vars.size(); ++i) {
204  conditioning_ids[i - 1] = varmap.get(*(vars[i]));
205  }
206  estimator.setParameters(id, conditioning_ids, pot);
207  } catch (DatabaseError&) { bn.generateCPT(id); }
208  }
209 
210  return bn;
211  }
212 
214  template < template < typename > class ALLOC >
215  template < typename GUM_SCALAR >
217  ParamEstimator< ALLOC >& bootstrap_estimator,
218  ParamEstimator< ALLOC >& general_estimator,
219  const DAG& dag) {
220  // bootstrap EM by learning an initial model
221  BayesNet< GUM_SCALAR > bn = createBN< GUM_SCALAR >(bootstrap_estimator, dag);
222  general_estimator.setBayesNet(bn);
223 
224  // perform EM
226 
227  GUM_SCALAR delta;
228  do {
229  // bugfix for parallel execution of VariableElimination
230  const auto& xdag = bn.dag();
231  for (const auto node : xdag) {
232  xdag.parents(node);
233  xdag.children(node);
234  }
235 
236  BayesNet< GUM_SCALAR > new_bn =
237  createBN< GUM_SCALAR >(general_estimator, dag);
239 
240  delta = GUM_SCALAR(0.0);
241  for (const auto node : dag) {
242  const auto& old_cpt = bn.cpt(node);
243  const auto& new_cpt = new_bn.cpt(node);
244 
245  Instantiation old_inst(old_cpt);
246  Instantiation new_inst(new_cpt);
247 
248  for (; !old_inst.end(); ++old_inst, ++new_inst) {
249  const GUM_SCALAR old_val = old_cpt.get(old_inst);
250  if (old_val > 0.0) {
251  const GUM_SCALAR new_val = new_cpt.get(new_inst);
252  const GUM_SCALAR diff = new_val - old_val;
253  const auto diffrel =
254  (diff < 0.0) ? (-diff / old_val) : (diff / old_val);
255  if (delta < diffrel) delta = diffrel;
256  }
257  }
258  }
259 
260  bn = std::move(new_bn);
261  } while (continueApproximationScheme(double(delta)));
262 
263  stopApproximationScheme(); // just to be sure of the approximationScheme
264  // has been notified of the end of loop
265 
266  return bn;
267  } // namespace learning
268 
269 
271  template < template < typename > class ALLOC >
273  return *this;
274  }
275 
276 
277  } // namespace learning
278 
279 } /* namespace gum */
void addArc(NodeId tail, NodeId head)
Add an arc in the BN, and update arc.head&#39;s CPT.
Definition: BayesNet_tpl.h:345
aGrUM&#39;s Potential is a multi-dimensional array with tensor operators.
Definition: potential.h:57
Class representing a Bayesian Network.
Definition: BayesNet.h:76
static BayesNet< GUM_SCALAR > createBN(ParamEstimator< ALLOC > &estimator, const DAG &dag)
create a BN from a DAG using a one pass generator (typically ML)
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
Approximation Scheme.
NodeId add(const DiscreteVariable &var)
Add a variable to the gum::BayesNet.
Definition: BayesNet_tpl.h:229
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1019
Container used to map discrete variables with nodes.
STL namespace.
virtual ~DAG2BNLearner()
destructor
void generateCPT(NodeId node) const
randomly generate CPT for a given node in a given structure
Definition: BayesNet_tpl.h:641
void initApproximationScheme()
Initialise the scheme.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
void setBayesNet(const BayesNet< GUM_SCALAR > &new_bn)
assign a new Bayes net to all the counter&#39;s generators depending on a BN
void beginTopologyTransformation()
When inserting/removing arcs, node CPTs change their dimension with a cost in time.
Definition: BayesNet_tpl.h:591
allocator_type getAllocator() const
returns the allocator used by the score
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: DAG2BNLearner.h:54
bool continueApproximationScheme(double error)
Update the scheme w.r.t the new error.
const VariableNodeMap & variableNodeMap() const final
Returns a map between variables and nodes of this gum::BayesNet.
Definition: BayesNet_tpl.h:317
DAG2BNLearner< ALLOC > & operator=(const DAG2BNLearner< ALLOC > &from)
copy operator
void stopApproximationScheme()
Stop the approximation scheme.
ApproximationScheme & approximationScheme()
returns the approximation policy of the learning algorithm
const Potential< GUM_SCALAR > & cpt(NodeId varId) const final
Returns the CPT of a variable.
Definition: BayesNet_tpl.h:312
const DatabaseTable< ALLOC > & database() const
returns the database on which we perform the counts
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:80
const ArcSet & arcs() const
returns the set of arcs stored within the ArcGraphPart
virtual DAG2BNLearner< ALLOC > * clone() const
virtual copy constructor
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const final
Default implementation of MultiDimContainer::set().
void setFirst()
Assign the first values to the tuple of the Instantiation.
void endTopologyTransformation()
terminates a sequence of insertions/deletions of arcs by adjusting all CPTs dimensions.
Definition: BayesNet_tpl.h:598
A class that, given a structure and a parameter estimator returns a full Bayes net.
Definition: DAG2BNLearner.h:49
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
The base class for estimating parameters of CPTs.
Base class for dag.
Definition: DAG.h:99
const DAG & dag() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:60
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
const DiscreteVariable & get(NodeId id) const
Returns a discrete variable given it&#39;s node id.
bool end() const
Returns true if the Instantiation reached the end.
void updateApproximationScheme(unsigned int incr=1)
Update the scheme w.r.t the new error and increment steps.
DAG2BNLearner(const allocator_type &alloc=allocator_type())
default constructor