57 template < GUM_Numeric GUM_SCALAR >
58 void DAG2BNLearner::_probaVarReordering_(gum::Tensor< GUM_SCALAR >& pot,
59 const gum::Tensor< GUM_SCALAR >& other_pot) {
62 GUM_ERROR(gum::CPTError,
"the tensors do not have the same variables")
66 Instantiation i(other_pot);
68 for (i.setFirst(); !i.end(); ++i) {
70 pot.
set(j, other_pot[i]);
75 template < GUM_Numeric GUM_SCALAR >
81 template < GUM_Numeric GUM_SCALAR >
82 BayesNet< GUM_SCALAR > DAG2BNLearner::_createBN_(
ParamEstimator& estimator,
84 const bool compute_log_likelihood) {
85 BayesNet< GUM_SCALAR > bn;
86 log_likelihood_EM_ = 0.0;
90 const auto& database = estimator.
database();
91 if (node2cols.empty()) {
92 for (
const auto id: dag) {
96 for (
const auto id: dag) {
97 const std::size_t col = node2cols.second(
id);
98 bn.add(
dynamic_cast< const DiscreteVariable&
>(database.variable(col)),
id);
103 bn.beginTopologyTransformation();
104 for (
const auto& arc: dag.arcs()) {
105 bn.addArc(arc.tail(), arc.head());
107 bn.endTopologyTransformation();
110 const VariableNodeMap& varmap = bn.variableNodeMap();
111 for (
const auto id: dag) {
113 auto& pot =
const_cast< Tensor< GUM_SCALAR >&
>(bn.cpt(
id));
118 std::vector< NodeId > conditioning_ids(vars.size() - 1);
119 for (
auto i = std::size_t(1); i < vars.size(); ++i) {
120 conditioning_ids[i - 1] = varmap.get(*(vars[i]));
124 += estimator.
setParameters(
id, conditioning_ids, pot, compute_log_likelihood);
131 template < GUM_Numeric GUM_SCALAR >
136 bootstrap_estimator.
clear();
137 EM_estimator.
clear();
142 return _performEM_(bootstrap_estimator, EM_estimator, std::move(bn));
146 template < GUM_Numeric GUM_SCALAR >
149 const BayesNet< GUM_SCALAR >& bn) {
151 bootstrap_estimator.
clear();
152 EM_estimator.
clear();
155 return createBNwithEM(bootstrap_estimator, EM_estimator, std::move(bn_copy));
159 template < GUM_Numeric GUM_SCALAR >
162 BayesNet< GUM_SCALAR >&& bn) {
165 for (
const auto id: bn.internalDag()) {
167 auto& pot =
const_cast< Tensor< GUM_SCALAR >&
>(bn.cpt(
id));
170 bool all_zeroed =
true;
172 if (pot[inst] != 0.0) {
183 std::vector< NodeId > conditioning_ids(vars.size() - 1);
184 for (
auto i = std::size_t(1); i < vars.size(); ++i) {
185 conditioning_ids[i - 1] = varmap.
get(*(vars[i]));
189 bootstrap_estimator.
setParameters(
id, conditioning_ids, pot,
false);
193 return _performEM_(bootstrap_estimator, EM_estimator, std::move(bn));
197 template < GUM_Numeric GUM_SCALAR >
198 BayesNet< GUM_SCALAR > DAG2BNLearner::_performEM_(
ParamEstimator& bootstrap_estimator,
200 BayesNet< GUM_SCALAR >&& bn) {
215 "EM cannot be executed because no stopping criterion among "
216 <<
"{min rate, min diff, max iter, max time} has been selected")
220 const DAG dag = bn.internalDag();
223 if (noiseEM_ != 0.0) {
224 for (
const auto& node: bn.nodes()) {
225 bn.cpt(node).noising(noiseEM_).normalizeAsCPT();
234 log_likelihood_EM_ = 0.0;
235 const VariableNodeMap& varmap = bn.variableNodeMap();
237 for (
const auto& node: bn.nodes()) {
240 const auto& pot =
const_cast< Tensor< GUM_SCALAR >&
>(bn.cpt(node));
242 std::vector< NodeId > conditioning_ids(vars.size() - 1);
243 for (
auto i = std::size_t(1); i < vars.size(); ++i) {
244 conditioning_ids[i - 1] = varmap.get(*(vars[i]));
248 IdCondSet idset(node, conditioning_ids,
true);
250 Instantiation inst(pot);
251 for (std::size_t k = 0, end = pot.
domainSize(); k < end; ++k, inst.inc()) {
252 if (N_ijk[k]) { log_likelihood_EM_ += N_ijk[k] * std::log(pot[inst]); }
255 double current_log_likelihood = log_likelihood_EM_;
263 BayesNet< GUM_SCALAR > best_bn;
264 bool must_return_best_bn =
false;
265 unsigned int nb_dec_likelihood_iter = 0;
270 const auto& xdag = bn.internalDag();
271 for (
const auto node: xdag) {
277 BayesNet< GUM_SCALAR > new_bn = _createBN_< GUM_SCALAR >(EM_estimator, dag,
true);
280 if (log_likelihood_EM_ >= current_log_likelihood) {
282 nb_dec_likelihood_iter = 0;
283 must_return_best_bn =
false;
288 ++nb_dec_likelihood_iter;
289 if (nb_dec_likelihood_iter == 1) {
291 must_return_best_bn =
true;
293 if (nb_dec_likelihood_iter > max_nb_dec_likelihood_iter_) {
300 delta = log_likelihood_EM_ - current_log_likelihood;
301 current_log_likelihood = log_likelihood_EM_;
303 bn = std::move(new_bn);
310 return must_return_best_bn ? best_bn : bn;
A class that, given a structure and a parameter estimator returns a full Bayes net.
void updateApproximationScheme(unsigned int incr=1)
Update the scheme w.r.t the new error and increment steps.
bool isEnabledEpsilon() const override
Returns true if stopping criterion on epsilon is enabled, false otherwise.
bool isEnabledMaxTime() const override
Returns true if stopping criterion on timeout is enabled, false otherwise.
bool isEnabledMinEpsilonRate() const override
Returns true if stopping criterion on epsilon rate is enabled, false otherwise.
bool continueApproximationScheme(double error)
Update the scheme w.r.t the new error.
void initApproximationScheme()
Initialise the scheme.
void stopApproximationScheme()
Stop the approximation scheme.
bool isEnabledMaxIter() const override
Returns true if stopping criterion on max iterations is enabled, false otherwise.
Base class for discrete random variable.
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
const Sequence< const DiscreteVariable * > & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
void set(const Instantiation &i, const GUM_ELEMENT &value) const final
Default implementation of MultiDimContainer::set().
Size domainSize() const final
Returns the product of the variables domain size.
Exception : operation not allowed.
Container used to map discrete variables with nodes.
const DiscreteVariable & get(NodeId id) const
Returns a discrete variable given it's node id.
static BayesNet< GUM_SCALAR > createBN(ParamEstimator &estimator, const DAG &dag)
create a BN from a DAG using a one pass generator (typically ML)
DAG2BNLearner()
default constructor
BayesNet< GUM_SCALAR > createBNwithEM(ParamEstimator &bootstrap_estimator, ParamEstimator &EM_estimator, const DAG &dag)
creates a BN with a given structure (dag) using the EM algorithm
bool hasMissingValues() const
indicates whether the database contains some missing values
The base class for estimating parameters of CPTs.
RecordCounter counter_
the record counter used to parse the database
const Bijection< NodeId, std::size_t > & nodeId2Columns() const
returns the mapping from ids to column positions in the database
double setParameters(const NodeId target_node, const std::vector< NodeId > &conditioning_nodes, Tensor< GUM_SCALAR > &pot, const bool compute_log_likelihood=false)
sets a CPT's parameters and, possibly, return its log-likelihhod
virtual void clear()
clears all the data structures from memory
void setBayesNet(const BayesNet< GUM_SCALAR > &new_bn)
assign a new Bayes net to all the counter's generators depending on a BN
const DatabaseTable & database() const
returns the database on which we perform the counts
void clear()
clears all the last database-parsed counting from memory
const std::vector< double > & counts(const IdCondSet &ids, const bool check_discrete_vars=false)
returns the counts over all the variables in an IdCondSet
#define GUM_ERROR(type, msg)
include the inlined functions if necessary
gum is the global namespace for all aGrUM entities