def setUp(self): """Create all data required to instantiate the bnet object""" nodes = 4 dag = np.zeros((nodes, nodes)) C = 0 S = 1 R = 2 W = 3 dag[C, [R, S]] = 1 dag[R, W] = 1 dag[S, W] = 1 ns = 2 * np.ones((1, nodes)) """Instantiate the CPD for each node in the network""" node_cpds = [[], [], [], []] CPT = np.array([0.5, 0.5]) node_cpds[C] = cpds.tabular_CPD(C, ns, dag, CPT) CPT = np.array([[0.8, 0.2], [0.2, 0.8]]) node_cpds[R] = cpds.tabular_CPD(R, ns, dag, CPT) CPT = np.array([[0.5, 0.5], [0.9, 0.1]]) node_cpds[S] = cpds.tabular_CPD(S, ns, dag, CPT) CPT = np.array([[[1, 0], [0.1, 0.9]], [[0.1, 0.9], [0.01, 0.99]]]) node_cpds[W] = cpds.tabular_CPD(W, ns, dag, CPT) """Instantiate the object""" self.net = models.bnet(dag, ns, node_cpds)
def learn_params_mle(self, samples): """ Maximum liklihood estimation (MLE) parameter learing for a BNET. Parameters ---------- samples: List A list of fully observed samples for the spanning the total domain of this BNET. Where samples[i][n] is the i'th sample for node n. """ """Convert the samples list to an array""" samples = np.array(samples) """If the CPD's have not yet been initialized""" if len(self.cpds) == 0: """For every node in the BNET""" for i in range(0, self.num_nodes): """Create a blank CPD for the node""" family = graph.family(self.model_graph, i) self.cpds.append(cpds.tabular_CPD(i, self.node_sizes, \ self.model_graph)) """Get the samples within this nodes CPDs domain""" local_samples = samples[:, family] """Learn the node parameters""" if len(local_samples.tolist()) != 0: self.cpds[i].learn_params_mle(local_samples) else: """For every node in the BNET""" for i in range(0, self.num_nodes): """Get the samples within this nodes CPDs domain""" family = graph.family(self.model_graph, i) local_samples = samples[:, family] """Learn the node parameters""" if len(local_samples.tolist()) != 0: self.cpds[i].learn_params_mle(local_samples)
def test_bnet_approx_sum_product(): """EXAMPLE: Loopy belief sum-product on BNET""" """Create all data required to instantiate the bnet object""" nodes = 4 dag = np.zeros((nodes, nodes)) C = 0 S = 1 R = 2 W = 3 dag[C, [R, S]] = 1 dag[R, W] = 1 dag[S, W] = 1 ns = 2 * np.ones((1, nodes)) """Instantiate the CPD for each node in the network""" node_cpds = [[], [], [], []] CPT = np.array([0.5, 0.5]) node_cpds[C] = cpds.tabular_CPD(C, ns, dag, CPT) CPT = np.array([[0.8, 0.2], [0.2, 0.8]]) node_cpds[R] = cpds.tabular_CPD(R, ns, dag, CPT) CPT = np.array([[0.5, 0.5], [0.9, 0.1]]) node_cpds[S] = cpds.tabular_CPD(S, ns, dag, CPT) CPT = np.array([[[1, 0], [0.1, 0.9]], [[0.1, 0.9], [0.01, 0.99]]]) node_cpds[W] = cpds.tabular_CPD(W, ns, dag, CPT) """Instantiate the object""" net = models.bnet(dag, ns, node_cpds) net.init_inference_engine(exact=False) """Create and enter evidence""" evidences = create_all_evidence(4, 2) results = [] for evidence in evidences: net.sum_product(evidence) result = [] result.append(np.max(net.marginal_nodes([0]).T)) result.append(np.max(net.marginal_nodes([1]).T)) result.append(np.max(net.marginal_nodes([2]).T)) result.append(np.max(net.marginal_nodes([3]).T)) results.append(result) results = np.array(results) """Get the expected results""" exp_results = np.array( pylab.load('./Data/bnet_approx_sum_product_res.txt')) """Assert that the output matched the expected values""" assert_array_equal(results, exp_results)
def learn_params_EM(self, samples, max_iter=10, thresh=np.exp(-4), \ exact=True, inf_max_iter=10): """ EM algorithm parameter learing for a BNET, accepts partially observed samples. Parameters ---------- samples: List A list of partially observed samples for the spanning the total domain of this BNET. Where samples[i][n] is the i'th sample for node n. samples[i][n] can be [] if node n was not observed in the i'th sample. """ """If the CPDs have not yet been defined, then create them""" if len(self.cpds) == 0: """For every node in the BNET""" for i in range(0, self.num_nodes): """Create a blank CPD for the node""" family = graph.family(self.model_graph, i) self.cpds.append(cpds.tabular_CPD(i, self.node_sizes, \ self.model_graph)) else: """If they have been defined, reset the CPT's""" for i in range(0, self.num_nodes): self.cpds[i].CPT = np.ones(self.cpds[i].CPT.shape) """Create data used in the EM algorithm""" loglik = 0 prev_loglik = -1*np.Inf converged = False num_iter = 0 """Init the training inference engine for the new BNET""" self.init_inference_engine(exact, inf_max_iter) while ((not converged) and (num_iter < max_iter)): """Perform an EM iteration and gain the new log likelihood""" loglik = self.EM_step(samples) """Check for convergence""" delta_loglik = np.abs(loglik - prev_loglik) avg_loglik = np.nan_to_num((np.abs(loglik) + \ np.abs(prev_loglik))/2) if (delta_loglik / avg_loglik) < thresh: """Algorithm has converged""" break prev_loglik = loglik """Increase the iteration counter""" num_iter = num_iter + 1
def test_bnet_approx_max_sum(): """EXAMPLE: Loopy belief max-sum on BNET""" """Create all data required to instantiate the bnet object""" nodes = 4 dag = np.zeros((nodes, nodes)) C = 0 S = 1 R = 2 W = 3 dag[C, [R, S]] = 1 dag[R, W] = 1 dag[S, W] = 1 ns = 2 * np.ones((1, nodes)) """Instantiate the CPD for each node in the network""" node_cpds = [[], [], [], []] CPT = np.array([0.5, 0.5]) node_cpds[C] = cpds.tabular_CPD(C, ns, dag, CPT) CPT = np.array([[0.8, 0.2], [0.2, 0.8]]) node_cpds[R] = cpds.tabular_CPD(R, ns, dag, CPT) CPT = np.array([[0.5, 0.5], [0.9, 0.1]]) node_cpds[S] = cpds.tabular_CPD(S, ns, dag, CPT) CPT = np.array([[[1, 0], [0.1, 0.9]], [[0.1, 0.9], [0.01, 0.99]]]) node_cpds[W] = cpds.tabular_CPD(W, ns, dag, CPT) """Instantiate the object""" net = models.bnet(dag, ns, node_cpds) net.init_inference_engine(exact=False) """Create and enter evidence""" evidences = create_all_evidence(4, 2) mlcs = np.array([0, 0, 0, 0]) for evidence in evidences: mlc = net.max_sum(evidence) mlcs = np.vstack((mlcs, mlc)) """Read in expected values""" exp_mlcs = np.array(pylab.load('./Data/bnet_approx_max_sum_res.txt')) """Assert that the output matched the expected values""" assert_array_equal(mlcs, exp_mlcs)
dag[S, W] = 1 """ Define the size of each node, which is the number of different values a node could observed at. For example, if a node is either True of False, it has only 2 possible values it could be, therefore its size is 2. All the nodes in this graph has a size 2. """ ns = 2 * np.ones((1, nodes)) """ We now need to assign a conditional probability distribution to each node. """ node_cpds = [[], [], [], []] """Define the CPD for node 0""" CPT = np.array([0.5, 0.5]) node_cpds[C] = cpds.tabular_CPD(C, ns, dag, CPT) """Define the CPD for node 1""" CPT = np.array([[0.8, 0.2], [0.2, 0.8]]) node_cpds[R] = cpds.tabular_CPD(R, ns, dag, CPT) """Define the CPD for node 2""" CPT = np.array([[0.5, 0.5], [0.9, 0.1]]) node_cpds[S] = cpds.tabular_CPD(S, ns, dag, CPT) """Define the CPD for node 3""" CPT = np.array([[[1, 0], [0.1, 0.9]], [[0.1, 0.9], [0.01, 0.99]]]) node_cpds[W] = cpds.tabular_CPD(W, ns, dag, CPT) """Create the Bayesian network""" net = models.bnet(dag, ns, node_cpds) """ Intialize the BNET's inference engine to use EXACT inference, by setting exact=True. """