aGrUM  0.16.0
DAG2BNLearner_tpl.h
Go to the documentation of this file.
1 
31 #include <algorithm>
32 #include <string>
33 #include <vector>
34 
35 namespace gum {
36 
37  namespace learning {
38 
40  template < template < typename > class ALLOC >
43  return *this;
44  }
45 
46 
48  template < template < typename > class ALLOC >
50  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
51  ALLOC< NodeId >(alloc) {
52  GUM_CONSTRUCTOR(DAG2BNLearner);
53  }
54 
55 
57  template < template < typename > class ALLOC >
59  const DAG2BNLearner< ALLOC >& from,
60  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
61  ApproximationScheme(from),
62  ALLOC< NodeId >(alloc) {
63  GUM_CONS_CPY(DAG2BNLearner);
64  }
65 
66 
68  template < template < typename > class ALLOC >
70  DAG2BNLearner(from, from.getAllocator()) {}
71 
72 
74  template < template < typename > class ALLOC >
77  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) :
78  ApproximationScheme(std::move(from)),
79  ALLOC< NodeId >(alloc) {
80  GUM_CONS_MOV(DAG2BNLearner);
81  }
82 
83 
85  template < template < typename > class ALLOC >
87  DAG2BNLearner(std::move(from), from.getAllocator()) {}
88 
89 
91  template < template < typename > class ALLOC >
93  const typename DAG2BNLearner< ALLOC >::allocator_type& alloc) const {
94  ALLOC< DAG2BNLearner< ALLOC > > allocator(alloc);
95  DAG2BNLearner< ALLOC >* new_learner = allocator.allocate(1);
96  try {
97  allocator.construct(new_learner, *this, alloc);
98  } catch (...) {
99  allocator.deallocate(new_learner, 1);
100  throw;
101  }
102 
103  return new_learner;
104  }
105 
106 
108  template < template < typename > class ALLOC >
110  return clone(this->getAllocator());
111  }
112 
113 
115  template < template < typename > class ALLOC >
117  GUM_DESTRUCTOR(DAG2BNLearner);
118  }
119 
120 
122  template < template < typename > class ALLOC >
125  ApproximationScheme::operator=(from);
126  return *this;
127  }
128 
129 
131  template < template < typename > class ALLOC >
134  ApproximationScheme::operator=(std::move(from));
135  return *this;
136  }
137 
138 
140  template < template < typename > class ALLOC >
141  template < typename GUM_SCALAR >
144  const gum::Potential< GUM_SCALAR >& other_pot) {
145  // check that the variables are identical
146  if (!pot.variablesSequence()
147  .diffSet(other_pot.variablesSequence())
148  .empty()) {
149  GUM_ERROR(gum::CPTError, "the potentials do not have the same variables");
150  }
151 
152  // perform the copy
153  Instantiation i(other_pot);
154  Instantiation j(pot);
155  for (i.setFirst(); !i.end(); ++i) {
156  j.setVals(i);
157  pot.set(j, other_pot[i]);
158  }
159  }
160 
162  template < template < typename > class ALLOC >
163  template < typename GUM_SCALAR >
166  const DAG& dag) {
168 
169  // create a bn with dummy parameters corresponding to the dag
170  const auto& node2cols = estimator.nodeId2Columns();
171  const auto& database = estimator.database();
172  if (node2cols.empty()) {
173  for (const auto id : dag) {
174  bn.add(dynamic_cast< const DiscreteVariable& >(database.variable(id)),
175  id);
176  }
177  } else {
178  for (const auto id : dag) {
179  const std::size_t col = node2cols.second(id);
180  bn.add(dynamic_cast< const DiscreteVariable& >(database.variable(col)),
181  id);
182  }
183  }
184 
185  // add the arcs
187  for (const auto& arc : dag.arcs()) {
188  bn.addArc(arc.tail(), arc.head());
189  }
191 
192  // estimate the parameters
193  const VariableNodeMap& varmap = bn.variableNodeMap();
194  for (const auto id : dag) {
195  // get the sequence of variables and make the targets be the last
196  auto& pot = const_cast< Potential< GUM_SCALAR >& >(bn.cpt(id));
197 
198  // get the variables of the CPT of id in the correct order
200 
201  // setup the estimation
202  std::vector< NodeId > conditioning_ids(vars.size() - 1);
203  for (auto 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  }
208 
209  return bn;
210  }
211 
213  template < template < typename > class ALLOC >
214  template < typename GUM_SCALAR >
216  ParamEstimator< ALLOC >& bootstrap_estimator,
217  ParamEstimator< ALLOC >& general_estimator,
218  const DAG& dag) {
219  // bootstrap EM by learning an initial model
220  BayesNet< GUM_SCALAR > bn = createBN< GUM_SCALAR >(bootstrap_estimator, dag);
221  for (const auto& nod : bn.nodes()) {
222  bn.cpt(nod).noising(0.1);
223  }
224  general_estimator.setBayesNet(bn);
225 
226  // perform EM
228 
229  GUM_SCALAR delta;
230  do {
231  // bugfix for parallel execution of VariableElimination
232  const auto& xdag = bn.dag();
233  for (const auto node : xdag) {
234  xdag.parents(node);
235  xdag.children(node);
236  }
237 
238  BayesNet< GUM_SCALAR > new_bn =
239  createBN< GUM_SCALAR >(general_estimator, dag);
241 
242  delta = GUM_SCALAR(0.0);
243  for (const auto node : dag) {
244  const auto& old_cpt = bn.cpt(node);
245  const auto& new_cpt = new_bn.cpt(node);
246 
247  Instantiation old_inst(old_cpt);
248  Instantiation new_inst(new_cpt);
249 
250  for (; !old_inst.end(); ++old_inst, ++new_inst) {
251  const GUM_SCALAR old_val = old_cpt.get(old_inst);
252  if (old_val > 0.0) {
253  const GUM_SCALAR new_val = new_cpt.get(new_inst);
254  const GUM_SCALAR diff = new_val - old_val;
255  const auto diffrel =
256  (diff < 0.0) ? (-diff / old_val) : (diff / old_val);
257  if (delta < diffrel) delta = diffrel;
258  }
259  }
260  }
261 
262  bn = std::move(new_bn);
263  } while (continueApproximationScheme(double(delta)));
264 
265  stopApproximationScheme(); // just to be sure of the approximationScheme
266  // has been notified of the end of loop
267 
268  return bn;
269  } // namespace learning
270 
271 
273  template < template < typename > class ALLOC >
275  return *this;
276  }
277 
278 
279  } // namespace learning
280 
281 } /* 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:348
aGrUM&#39;s Potential is a multi-dimensional array with tensor operators.
Definition: potential.h:60
Class representing a Bayesian Network.
Definition: BayesNet.h:78
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:232
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
Container used to map discrete variables with nodes.
STL namespace.
virtual ~DAG2BNLearner()
destructor
void initApproximationScheme()
Initialise the scheme.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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
ApproximationScheme(bool verbosity=false)
void beginTopologyTransformation()
When inserting/removing arcs, node CPTs change their dimension with a cost in time.
Definition: BayesNet_tpl.h:613
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:57
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:320
const NodeGraphPart & nodes() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:115
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:315
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:83
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:620
A class that, given a structure and a parameter estimator returns a full Bayes net.
Definition: DAG2BNLearner.h:52
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:102
const DAG & dag() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:63
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
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