class IsingModel: def __init__(self, theta, seed=None): if seed is not None: np.random.seed(seed) # graph self.G = MarkovModel() for _, row in theta.iterrows(): # unary if row["j"]==row["k"]: self.G.add_node(str(int(row["j"]))) theta_jj = row["value"] self.G.add_factors(DiscreteFactor([str(int(row["j"]))], [2], np.exp([-theta_jj,theta_jj]))) # pairwise elif row["value"]!=0: self.G.add_edge(str(int(row["j"])), str(int(row["k"]))) theta_jk = row["value"] self.G.add_factors(DiscreteFactor([str(int(row["j"])), str(int(row["k"]))], [2, 2], np.exp([theta_jk, -theta_jk, -theta_jk, theta_jk]))) self.G.check_model() self.infer = BeliefPropagation(self.G) self.infer.calibrate() def get_moments(self): p = len(list(self.G.nodes)) factor_dict = self.infer.get_clique_beliefs() mom_matrix = np.zeros([p,p]) for clique in factor_dict: for pair in it.combinations(clique,2): moment = factor_dict[clique].marginalize(set(clique).difference(set(pair)),inplace=False) moment = moment.normalize(inplace=False) pair_int = [int(x) for x in pair] moment = moment.values[0,0]+moment.values[1,1]-moment.values[0,1]-moment.values[1,0] mom_matrix[pair_int[0],pair_int[1]] = moment mom_matrix[pair_int[1],pair_int[0]] = moment for unary in it.combinations(clique,1): unary_int = [int(x) for x in unary][0] moment = factor_dict[clique].marginalize(set(clique).difference(set(unary)),inplace=False).normalize(inplace=False).values moment = moment[1]-moment[0] mom_matrix[unary_int,unary_int] = moment return mom_matrix
def main(): # maximum size of segments grid cell map_size = 50 # minimum number of pixels to consider segment pixels_thresh = 500 # number of image in the database num_images = 70 # counter for incorrectly classified segments num_incorrect = 0 for idx in range(num_images): print('\n\nImage ', idx) # read image from disk image = cv2.imread('export/image_%04d.jpg' % idx) # read ground truth classes labels_gt_im = cv2.imread('export/labels_%04d.png' % idx, cv2.IMREAD_ANYDEPTH).astype(np.int) labels_gt_im[labels_gt_im == 65535] = -1 # read a priori probabilities from classifier prob_im = cv2.imread('export/prob_%04d.png' % idx, cv2.IMREAD_ANYDEPTH) / 65535.0 # read image division into segments segments_im = cv2.imread('export/segments_%04d.png' % idx, cv2.IMREAD_ANYDEPTH) # display image cv2.imshow('original image', image) cv2.waitKey(1) # mean R, G, B values for each segment mean_rgb = np.zeros([map_size, map_size, 3], dtype=np.float) # number of pixels for each segment num_pixels = np.zeros([map_size, map_size], dtype=np.uint) # a priori probabilities for each segment prob = np.zeros([map_size, map_size, 2], dtype=np.float) # ground truth classes for each segment labels_gt = -1 * np.ones([map_size, map_size], dtype=np.int) for y in range(map_size): for x in range(map_size): # segment identifier cur_seg = y * map_size + x # indices of pixels belonging to the segment cur_pixels = np.nonzero(segments_im == cur_seg) if len(cur_pixels[0]) > 0: num_pixels[y, x] = len(cur_pixels[0]) # flip because opencv stores images as BGR by default mean_rgb[y, x, :] = np.flip(np.mean(image[cur_pixels], axis=0)) # average results from the classifier - should not be necessary prob[y, x, 0] = np.mean(prob_im[cur_pixels]) prob[y, x, 1] = 1.0 - prob[y, x, 0] # labeling boundaries don't have to be aligned with segments boundaties # count which label is the most common in this segment labels_unique, count = np.unique(labels_gt_im[cur_pixels], return_counts=True) labels_gt[y, x] = labels_unique[np.argmax(count)] pass # build model # PUT YOUR CODE HERE nodes = [] # if segment size is bigger than pixels_thresh, add current segment to node list for y in range(map_size): for x in range(map_size): if num_pixels[y, x] > pixels_thresh: nodes.append("s_" + str(y) + "_" + str(x)) factors_unary = [] # if segment size is bigger than pixels_thresh, add unary factor of segment to list for y in range(map_size): for x in range(map_size): if num_pixels[y, x] > pixels_thresh: # print(prob[y, x] * 0.9/1 + 0.05) cur_f = create_factor(["s_" + str(y) + "_" + str(x)], [[0, 1]], [0.945212], [unary_feat], [prob[y, x]]) factors_unary.append(cur_f) factors_pairway = [] edges_pairway = [] # if segment size is bigger than pixels_thresh and his neighbour too, add pairway factor to list for y in range(map_size - 1): for x in range(map_size - 1): if num_pixels[y, x] > pixels_thresh: # check neighnour to the right if num_pixels[y, x + 1] > pixels_thresh: cur_f = create_factor([ "s_" + str(y) + "_" + str(x), "s_" + str(y) + "_" + str(x + 1) ], [[0, 1], [0, 1]], [1.86891, 1.07741, 1.89271], [ pairway_feat_red, pairway_feat_green, pairway_feat_blue ], [mean_rgb[y, x], mean_rgb[y, x + 1]]) factors_pairway.append(cur_f) edges_pairway.append( ("s_" + str(y) + "_" + str(x), "s_" + str(y) + "_" + str(x + 1))) # check neighbour under if num_pixels[y + 1, x] > pixels_thresh: cur_f = create_factor([ "s_" + str(y) + "_" + str(x), "s_" + str(y + 1) + "_" + str(x) ], [[0, 1], [0, 1]], [1.86891, 1.07741, 1.89271], [ pairway_feat_red, pairway_feat_green, pairway_feat_blue ], [mean_rgb[y, x], mean_rgb[y + 1, x]]) factors_pairway.append(cur_f) edges_pairway.append( ("s_" + str(y) + "_" + str(x), "s_" + str(y + 1) + "_" + str(x))) # use Markov model, because MPLP doesn't support factor graphs G = MarkovModel() G.add_nodes_from(nodes) # add nodes G.add_factors(*factors_unary) # add unary factors G.add_factors(*factors_pairway) # add pairway factors G.add_edges_from(edges_pairway) # add edges # check if everything is ok print("Check model: ", G.check_model()) # ------------------ # inferred image pixels labels_infer = -1 * np.ones([map_size, map_size], dtype=np.int) # read results of the inference # PUT YOUR CODE HERE mplp_infer = Mplp(G) q = mplp_infer.map_query() segment_cnt = 0 for y in range(map_size): for x in range(map_size): if num_pixels[y, x] > pixels_thresh: val = q["s_" + str(y) + "_" + str(x)] rv = None if val == factors_unary[segment_cnt].values[0]: rv = 0 else: rv = 1 labels_infer[y, x] = rv segment_cnt += 1 # ------------------ labels_class = -1 * np.ones([map_size, map_size], dtype=np.int) for y in range(map_size - 1): for x in range(map_size - 1): if num_pixels[y, x] > pixels_thresh: # label as the class with the highest probability if prob[y, x, 0] >= 0.5: labels_class[y, x] = 0 else: labels_class[y, x] = 1 # count correct pixels cnt_corr = np.sum( np.logical_and(labels_gt == labels_infer, labels_gt != -1)) print('Accuracy = ', cnt_corr / np.sum(labels_gt != -1)) num_incorrect += np.sum(labels_gt != -1) - cnt_corr # transfer results for segments onto image labels_infer_im = -1 * np.ones_like(labels_gt_im) labels_class_im = -1 * np.ones_like(labels_gt_im) for y in range(map_size - 1): for x in range(map_size - 1): if labels_infer[y, x] >= 0: cur_seg = y * map_size + x cur_pixels = np.nonzero(segments_im == cur_seg) labels_infer_im[cur_pixels] = labels_infer[y, x] labels_class_im[cur_pixels] = labels_class[y, x] # class 0 - green, class 1 - red in BGR colors = np.array([[0, 255, 0], [0, 0, 255]], dtype=np.uint8) image_infer = image.copy() image_class = image.copy() image_gt = image.copy() # color pixels according to label for l in range(2): image_infer[labels_infer_im == l] = colors[l] image_class[labels_class_im == l] = colors[l] image_gt[labels_gt_im == l] = colors[l] # show inferred, classified, and gt image by blending the original image with the colored one image_infer_vis = (0.75 * image + 0.25 * image_infer).astype(np.uint8) cv2.imshow('inferred', image_infer_vis) image_class_vis = (0.75 * image + 0.25 * image_class).astype(np.uint8) cv2.imshow('classified', image_class_vis) image_gt_vis = (0.75 * image + 0.25 * image_gt).astype(np.uint8) cv2.imshow('ground truth', image_gt_vis) # uncomment to stop after each image # cv2.waitKey() cv2.waitKey(10) print('Incorrectly inferred ', num_incorrect, ' segments')
class TestMarkovModelMethods(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_get_cardinality(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {'a': 1, 'b': 2}) self.graph.remove_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4)) phi2 = Factor(['c', 'd'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertDictEqual(self.graph.get_cardinality(), { 'd': 2, 'a': 2, 'b': 2, 'c': 1 }) phi3 = Factor(['d', 'a'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi3) self.assertDictEqual(self.graph.get_cardinality(), { 'd': 1, 'c': 1, 'b': 2, 'a': 2 }) self.graph.remove_factors(phi1, phi2, phi3) self.assertDictEqual(self.graph.get_cardinality(), {}) def test_get_cardinality_check_cardinality(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True) phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi2) self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True) phi3 = Factor(['c', 'd'], [2, 2], np.random.rand(4)) self.graph.add_factors(phi3) self.assertDictEqual( self.graph.get_cardinality(check_cardinality=True), { 'd': 2, 'c': 2, 'b': 2, 'a': 1 }) def test_check_model(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['c', 'b'], [3, 2], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4)) self.graph.add_factors(phi1, phi2, phi3, phi4) self.assertTrue(self.graph.check_model()) self.graph.remove_factors(phi1, phi4) phi1 = Factor(['a', 'b'], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1) self.assertTrue(self.graph.check_model()) def test_check_model1(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['b', 'c'], [3, 3], np.random.rand(9)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) phi3 = Factor(['c', 'a'], [4, 4], np.random.rand(16)) self.graph.add_factors(phi3) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi3) phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 3], np.random.rand(12)) self.graph.add_factors(phi2, phi3, phi4) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2, phi3, phi4) phi2 = Factor(['a', 'b'], [1, 3], np.random.rand(3)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) def test_check_model2(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4)) phi5 = Factor(['d', 'b'], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1, phi2, phi3, phi4, phi5) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5) def test_factor_graph(self): phi1 = Factor(['Alice', 'Bob'], [3, 2], np.random.rand(6)) phi2 = Factor(['Bob', 'Charles'], [2, 2], np.random.rand(4)) self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')]) self.graph.add_factors(phi1, phi2) factor_graph = self.graph.to_factor_graph() self.assertIsInstance(factor_graph, FactorGraph) self.assertListEqual( sorted(factor_graph.nodes()), ['Alice', 'Bob', 'Charles', 'phi_Alice_Bob', 'phi_Bob_Charles']) self.assertListEqual( hf.recursive_sorted(factor_graph.edges()), [['Alice', 'phi_Alice_Bob'], ['Bob', 'phi_Alice_Bob'], ['Bob', 'phi_Bob_Charles'], ['Charles', 'phi_Bob_Charles']]) self.assertListEqual(factor_graph.get_factors(), [phi1, phi2]) def test_factor_graph_raises_error(self): self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')]) self.assertRaises(ValueError, self.graph.to_factor_graph) def test_junction_tree(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6)) phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12)) phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20)) phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) junction_tree = self.graph.to_junction_tree() self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()), [['a', 'b', 'd'], ['b', 'c', 'd']]) self.assertEqual(len(junction_tree.edges()), 1) def test_junction_tree_single_clique(self): self.graph.add_edges_from([('x1', 'x2'), ('x2', 'x3'), ('x1', 'x3')]) phi = [ Factor(edge, [2, 2], np.random.rand(4)) for edge in self.graph.edges() ] self.graph.add_factors(*phi) junction_tree = self.graph.to_junction_tree() self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()), [['x1', 'x2', 'x3']]) factors = junction_tree.get_factors() self.assertEqual(factors[0], factor_product(*phi)) def test_markov_blanket(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.graph.markov_blanket('a'), ['b']) self.assertListEqual(sorted(self.graph.markov_blanket('b')), ['a', 'c']) def test_local_independencies(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) independencies = self.graph.get_local_independencies() self.assertIsInstance(independencies, Independencies) self.assertEqual(independencies, Independencies(['a', 'c', 'b'])) def test_bayesian_model(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6)) phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12)) phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20)) phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) bm = self.graph.to_bayesian_model() self.assertIsInstance(bm, BayesianModel) self.assertListEqual(sorted(bm.nodes()), ['a', 'b', 'c', 'd']) self.assertTrue(nx.is_chordal(bm.to_undirected())) def tearDown(self): del self.graph
class TestMarkovModelMethods(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_get_cardinality(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {"a": 1, "b": 2}) self.graph.remove_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = DiscreteFactor(["a", "b"], [2, 2], np.random.rand(4)) phi2 = DiscreteFactor(["c", "d"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertDictEqual(self.graph.get_cardinality(), { "d": 2, "a": 2, "b": 2, "c": 1 }) phi3 = DiscreteFactor(["d", "a"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi3) self.assertDictEqual(self.graph.get_cardinality(), { "d": 1, "c": 1, "b": 2, "a": 2 }) self.graph.remove_factors(phi1, phi2, phi3) self.assertDictEqual(self.graph.get_cardinality(), {}) def test_get_cardinality_with_node(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [2, 2], np.random.rand(4)) phi2 = DiscreteFactor(["c", "d"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertEqual(self.graph.get_cardinality("a"), 2) self.assertEqual(self.graph.get_cardinality("b"), 2) self.assertEqual(self.graph.get_cardinality("c"), 1) self.assertEqual(self.graph.get_cardinality("d"), 2) def test_check_model(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.check_model) phi2 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi2) self.assertRaises(ValueError, self.graph.check_model) def test_check_model1(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) phi2 = DiscreteFactor(["c", "b"], [3, 2], np.random.rand(6)) phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12)) phi4 = DiscreteFactor(["d", "a"], [4, 1], np.random.rand(4)) self.graph.add_factors(phi1, phi2, phi3, phi4) self.assertTrue(self.graph.check_model()) self.graph.remove_factors(phi1, phi4) phi1 = DiscreteFactor(["a", "b"], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1) self.assertTrue(self.graph.check_model()) def test_check_model2(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) phi2 = DiscreteFactor(["b", "c"], [3, 3], np.random.rand(9)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) phi3 = DiscreteFactor(["c", "a"], [4, 4], np.random.rand(16)) self.graph.add_factors(phi3) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi3) phi2 = DiscreteFactor(["b", "c"], [2, 3], np.random.rand(6)) phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12)) phi4 = DiscreteFactor(["d", "a"], [4, 3], np.random.rand(12)) self.graph.add_factors(phi2, phi3, phi4) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2, phi3, phi4) phi2 = DiscreteFactor(["a", "b"], [1, 3], np.random.rand(3)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) def test_check_model3(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) phi2 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2) phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2)) phi2 = DiscreteFactor(["b", "c"], [2, 3], np.random.rand(6)) phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12)) phi4 = DiscreteFactor(["d", "a"], [4, 1], np.random.rand(4)) phi5 = DiscreteFactor(["d", "b"], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1, phi2, phi3, phi4, phi5) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5) def test_factor_graph(self): phi1 = DiscreteFactor(["Alice", "Bob"], [3, 2], np.random.rand(6)) phi2 = DiscreteFactor(["Bob", "Charles"], [2, 2], np.random.rand(4)) self.graph.add_edges_from([("Alice", "Bob"), ("Bob", "Charles")]) self.graph.add_factors(phi1, phi2) factor_graph = self.graph.to_factor_graph() self.assertIsInstance(factor_graph, FactorGraph) self.assertListEqual( sorted(factor_graph.nodes()), ["Alice", "Bob", "Charles", "phi_Alice_Bob", "phi_Bob_Charles"], ) self.assertListEqual( hf.recursive_sorted(factor_graph.edges()), [ ["Alice", "phi_Alice_Bob"], ["Bob", "phi_Alice_Bob"], ["Bob", "phi_Bob_Charles"], ["Charles", "phi_Bob_Charles"], ], ) self.assertListEqual(factor_graph.get_factors(), [phi1, phi2]) def test_factor_graph_raises_error(self): self.graph.add_edges_from([("Alice", "Bob"), ("Bob", "Charles")]) self.assertRaises(ValueError, self.graph.to_factor_graph) def test_junction_tree(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6)) phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12)) phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20)) phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) junction_tree = self.graph.to_junction_tree() self.assertListEqual( hf.recursive_sorted(junction_tree.nodes()), [["a", "b", "d"], ["b", "c", "d"]], ) self.assertEqual(len(junction_tree.edges()), 1) def test_junction_tree_single_clique(self): self.graph.add_edges_from([("x1", "x2"), ("x2", "x3"), ("x1", "x3")]) phi = [ DiscreteFactor(edge, [2, 2], np.random.rand(4)) for edge in self.graph.edges() ] self.graph.add_factors(*phi) junction_tree = self.graph.to_junction_tree() self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()), [["x1", "x2", "x3"]]) factors = junction_tree.get_factors() self.assertEqual(factors[0], factor_product(*phi)) def test_markov_blanket(self): self.graph.add_edges_from([("a", "b"), ("b", "c")]) self.assertListEqual(list(self.graph.markov_blanket("a")), ["b"]) self.assertListEqual(sorted(self.graph.markov_blanket("b")), ["a", "c"]) def test_local_independencies(self): self.graph.add_edges_from([("a", "b"), ("b", "c")]) independencies = self.graph.get_local_independencies() self.assertIsInstance(independencies, Independencies) self.assertEqual(independencies, Independencies(["a", "c", "b"])) def test_bayesian_model(self): self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"), ("d", "a")]) phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6)) phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12)) phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20)) phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) bm = self.graph.to_bayesian_model() self.assertIsInstance(bm, BayesianModel) self.assertListEqual(sorted(bm.nodes()), ["a", "b", "c", "d"]) self.assertTrue(nx.is_chordal(bm.to_undirected())) def tearDown(self): del self.graph
class TestMarkovModelMethods(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_get_cardinality(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {'a': 1, 'b': 2}) self.graph.remove_factors(phi1) self.assertDictEqual(self.graph.get_cardinality(), {}) phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4)) phi2 = Factor(['c', 'd'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertDictEqual(self.graph.get_cardinality(), {'d': 2, 'a': 2, 'b': 2, 'c': 1}) phi3 = Factor(['d', 'a'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi3) self.assertDictEqual(self.graph.get_cardinality(), {'d': 1, 'c': 1, 'b': 2, 'a': 2}) self.graph.remove_factors(phi1, phi2, phi3) self.assertDictEqual(self.graph.get_cardinality(), {}) def test_get_cardinality_check_cardinality(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True) phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi2) self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True) phi3 = Factor(['c', 'd'], [2, 2], np.random.rand(4)) self.graph.add_factors(phi3) self.assertDictEqual(self.graph.get_cardinality(check_cardinality=True), {'d': 2, 'c': 2, 'b': 2, 'a': 1}) def test_check_model(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['c', 'b'], [3, 2], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4)) self.graph.add_factors(phi1, phi2, phi3, phi4) self.assertTrue(self.graph.check_model()) self.graph.remove_factors(phi1, phi4) phi1 = Factor(['a', 'b'], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1) self.assertTrue(self.graph.check_model()) def test_check_model1(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['b', 'c'], [3, 3], np.random.rand(9)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) phi3 = Factor(['c', 'a'], [4, 4], np.random.rand(16)) self.graph.add_factors(phi3) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi3) phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 3], np.random.rand(12)) self.graph.add_factors(phi2, phi3, phi4) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2, phi3, phi4) phi2 = Factor(['a', 'b'], [1, 3], np.random.rand(3)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi2) def test_check_model2(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2)) self.graph.add_factors(phi1, phi2) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2) phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2)) phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6)) phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12)) phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4)) phi5 = Factor(['d', 'b'], [4, 2], np.random.rand(8)) self.graph.add_factors(phi1, phi2, phi3, phi4, phi5) self.assertRaises(ValueError, self.graph.check_model) self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5) def test_factor_graph(self): from pgmpy.models import FactorGraph phi1 = Factor(['Alice', 'Bob'], [3, 2], np.random.rand(6)) phi2 = Factor(['Bob', 'Charles'], [2, 2], np.random.rand(4)) self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')]) self.graph.add_factors(phi1, phi2) factor_graph = self.graph.to_factor_graph() self.assertIsInstance(factor_graph, FactorGraph) self.assertListEqual(sorted(factor_graph.nodes()), ['Alice', 'Bob', 'Charles', 'phi_Alice_Bob', 'phi_Bob_Charles']) self.assertListEqual(hf.recursive_sorted(factor_graph.edges()), [['Alice', 'phi_Alice_Bob'], ['Bob', 'phi_Alice_Bob'], ['Bob', 'phi_Bob_Charles'], ['Charles', 'phi_Bob_Charles']]) self.assertListEqual(factor_graph.get_factors(), [phi1, phi2]) def test_factor_graph_raises_error(self): self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')]) self.assertRaises(ValueError, self.graph.to_factor_graph) def test_junction_tree(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6)) phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12)) phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20)) phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) junction_tree = self.graph.to_junction_tree() self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()), [['a', 'b', 'd'], ['b', 'c', 'd']]) self.assertEqual(len(junction_tree.edges()), 1) def test_junction_tree_single_clique(self): from pgmpy.factors import factor_product self.graph.add_edges_from([('x1','x2'), ('x2', 'x3'), ('x1', 'x3')]) phi = [Factor(edge, [2, 2], np.random.rand(4)) for edge in self.graph.edges()] self.graph.add_factors(*phi) junction_tree = self.graph.to_junction_tree() self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()), [['x1', 'x2', 'x3']]) factors = junction_tree.get_factors() self.assertEqual(factors[0], factor_product(*phi)) def test_markov_blanket(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.graph.markov_blanket('a'), ['b']) self.assertListEqual(sorted(self.graph.markov_blanket('b')), ['a', 'c']) def test_local_independencies(self): from pgmpy.independencies import Independencies self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) independencies = self.graph.get_local_independencies() self.assertIsInstance(independencies, Independencies) self.assertEqual(len(independencies.get_assertions()), 2) string = '' for assertion in sorted(independencies.get_assertions(), key=lambda x: list(x.event1)): string += str(assertion) + '\n' self.assertEqual(string, '(a _|_ c | b)\n(c _|_ a | b)\n') def test_bayesian_model(self): from pgmpy.models import BayesianModel import networkx as nx self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]) phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6)) phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12)) phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20)) phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10)) self.graph.add_factors(phi1, phi2, phi3, phi4) bm = self.graph.to_bayesian_model() self.assertIsInstance(bm, BayesianModel) self.assertListEqual(sorted(bm.nodes()), ['a', 'b', 'c', 'd']) self.assertTrue(nx.is_chordal(bm.to_undirected())) def tearDown(self): del self.graph