Пример #1
0
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
Пример #2
0
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')
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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