示例#1
0
    def sum(inputs,
            indices,
            latent_indicators,
            num_sums,
            inf_type=None,
            log=False,
            output=None):
        if indices is None:
            inputs = [inputs]
        else:
            inputs = [(inputs, indices)]

        # Generate 'num_sums' Sum nodes, connecting each to inputs and latent_indicators
        s = []
        weights = []
        for i in range(0, num_sums):
            s = s + [spn.Sum(*inputs, latent_indicators=latent_indicators[i])]
            weights = weights + [s[-1].generate_weights()]

        # Connect all sum nodes to a single root Sum node and generate its weights
        root = spn.Sum(*s)
        root.generate_weights()

        if log:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=True)
        else:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type,
                                       log=False)

        mpe_path_gen.get_mpe_path(root)
        path_ops = [mpe_path_gen.counts[w] for w in weights]
        return spn.initialize_weights(root), path_ops
示例#2
0
    def test_group_initialization(self):
        """Group initialization of weights nodes"""
        v1 = spn.IVs(num_vars=1, num_vals=2)
        v2 = spn.IVs(num_vars=1, num_vals=4)
        s1 = spn.Sum(v1)
        s1.generate_weights([0.2, 0.3])
        s2 = spn.Sum(v2)
        s2.generate_weights(5)
        p = spn.Product(s1, s2)
        init = spn.initialize_weights(p)

        with tf.Session() as sess:
            sess.run([init])
            val1 = sess.run(s1.weights.node.get_value())
            val2 = sess.run(s2.weights.node.get_value())
            val1_log = sess.run(tf.exp(s1.weights.node.get_log_value()))
            val2_log = sess.run(tf.exp(s2.weights.node.get_log_value()))

        self.assertEqual(val1.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val2.dtype, spn.conf.dtype.as_numpy_dtype())
        np.testing.assert_array_almost_equal(val1, [0.4, 0.6])
        np.testing.assert_array_almost_equal(val2, [0.25, 0.25, 0.25, 0.25])
        self.assertEqual(val1_log.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val2_log.dtype, spn.conf.dtype.as_numpy_dtype())
        np.testing.assert_array_almost_equal(val1_log, [0.4, 0.6])
        np.testing.assert_array_almost_equal(val2_log,
                                             [0.25, 0.25, 0.25, 0.25])
示例#3
0
    def poon_single(inputs,
                    num_vals,
                    num_mixtures,
                    num_subsets,
                    inf_type,
                    log=False,
                    output=None):

        # Build a POON-like network with single-op nodes
        subsets = [[
            spn.Sum((inputs, list(range(i * num_vals, (i + 1) * num_vals))))
            for _ in range(num_mixtures)
        ] for i in range(num_subsets)]
        products = [
            spn.Product(*list(inp))
            for inp in list(product(*[s for s in subsets]))
        ]
        root = spn.Sum(*products, name="root")

        # Generate dense SPN and all weights in the network
        spn.generate_weights(root)

        # Generate path ops based on inf_type and log
        if log:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=True)
        else:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type,
                                       log=False)

        mpe_path_gen.get_mpe_path(root)
        path_ops = [
            mpe_path_gen.counts[inp]
            for inp in (inputs if isinstance(inputs, list) else [inputs])
        ]
        return root, spn.initialize_weights(root), path_ops
示例#4
0
 def test_is_valid_false(self):
     """Checking validity of the SPN"""
     # Create graph
     v12 = spn.IVs(num_vars=2, num_vals=4, name="V12")
     v34 = spn.ContVars(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     p1 = spn.Product((v12, [0, 7]), name="P1")
     p2 = spn.Product((v12, [2, 3, 4]), name="P2")
     p3 = spn.Product(v34, name="P3")
     n1 = spn.Concat(s1, s2, p3, name="N1")
     n2 = spn.Concat(p1, p2, name="N2")
     p4 = spn.Product((n1, [0]), (n1, [1]), name="P4")
     p5 = spn.Product((n2, [0]), (n1, [2]), name="P5")
     s3 = spn.Sum(p4, n2, name="S3")
     p6 = spn.Product(s3, (n1, [2]), name="P6")
     s4 = spn.Sum(p5, p6, name="S4")
     # Test
     self.assertTrue(v12.is_valid())
     self.assertTrue(v34.is_valid())
     self.assertTrue(s1.is_valid())
     self.assertTrue(s2.is_valid())
     self.assertTrue(p1.is_valid())
     self.assertTrue(p3.is_valid())
     self.assertTrue(p4.is_valid())
     self.assertTrue(n1.is_valid())
     self.assertFalse(p2.is_valid())
     self.assertFalse(n2.is_valid())
     self.assertFalse(s3.is_valid())
     self.assertFalse(s4.is_valid())
     self.assertFalse(p5.is_valid())
     self.assertFalse(p6.is_valid())
示例#5
0
    def sum(inputs,
            indices,
            latent_indicators,
            num_sums,
            inf_type,
            log=False,
            output=None):
        if indices is None:
            inputs = [inputs for _ in range(num_sums)]
        else:
            inputs = [(inputs, ind) for ind in indices]

        # Generate 'num_sums' Sum nodes, connecting each to inputs and latent_indicators
        s = []
        for inp, iv in zip(inputs, latent_indicators):
            s = s + [spn.Sum(inp, latent_indicators=iv)]
            # Generate weights for each Sum node
            s[-1].generate_weights()

        # Connect all sum nodes to a single root Sum node and generate its weights
        root = spn.Sum(*s)
        root.generate_weights()

        if log:
            value_op = root.get_log_value(inference_type=inf_type)
        else:
            value_op = root.get_value(inference_type=inf_type)

        return spn.initialize_weights(root), value_op
示例#6
0
    def test_get_out_size(self):
        """Computing the sizes of the outputs of nodes in SPN graph"""
        # Generate graph
        v1 = spn.ContVars(num_vars=5)
        v2 = spn.ContVars(num_vars=5)
        v3 = spn.ContVars(num_vars=5)
        s1 = spn.Sum((v1, [1, 3]), (v1, [1, 4]), v2)  # v1 included twice
        s2 = spn.Sum(v1, (v3, [0, 1, 2, 3, 4]))
        s3 = spn.Sum(v2, v3, v3)  # v3 included twice
        n4 = spn.Concat(s1, v1)
        n5 = spn.Concat((v3, [0, 4]), s3)
        n6 = spn.Concat(n4, s2, n5, (n4, [0]), (n5, [1]))  # n4 and n5 included twice

        # Test
        num = v1.get_out_size()
        self.assertEqual(num, 5)
        num = v2.get_out_size()
        self.assertEqual(num, 5)
        num = v3.get_out_size()
        self.assertEqual(num, 5)
        num = s1.get_out_size()
        self.assertEqual(num, 1)
        num = s2.get_out_size()
        self.assertEqual(num, 1)
        num = s3.get_out_size()
        self.assertEqual(num, 1)
        num = n4.get_out_size()
        self.assertEqual(num, 6)
        num = n5.get_out_size()
        self.assertEqual(num, 3)
        num = n6.get_out_size()
        self.assertEqual(num, 12)
示例#7
0
 def test_compute_valid(self):
     """Calculating validity of Sum"""
     # Without IVs
     v12 = spn.IVs(num_vars=2, num_vals=4)
     v34 = spn.ContVars(num_vars=2)
     s1 = spn.Sum((v12, [0, 1, 2, 3]))
     s2 = spn.Sum((v12, [0, 1, 2, 4]))
     s3 = spn.Sum((v12, [0, 1, 2, 3]), (v34, 0))
     p1 = spn.Product((v12, [0, 5]), (v34, 0))
     p2 = spn.Product((v12, [1, 6]), (v34, 0))
     p3 = spn.Product((v12, [1, 6]), (v34, 1))
     s4 = spn.Sum(p1, p2)
     s5 = spn.Sum(p1, p3)
     self.assertTrue(v12.is_valid())
     self.assertTrue(v34.is_valid())
     self.assertTrue(s1.is_valid())
     self.assertFalse(s2.is_valid())
     self.assertFalse(s3.is_valid())
     self.assertTrue(s4.is_valid())
     self.assertFalse(s5.is_valid())
     # With IVS
     s6 = spn.Sum(p1, p2)
     s6.generate_ivs()
     self.assertTrue(s6.is_valid())
     s7 = spn.Sum(p1, p2)
     s7.set_ivs(spn.ContVars(num_vars=2))
     self.assertFalse(s7.is_valid())
     s8 = spn.Sum(p1, p2)
     s8.set_ivs(spn.IVs(num_vars=2, num_vals=2))
     with self.assertRaises(spn.StructureError):
         s8.is_valid()
     s9 = spn.Sum(p1, p2)
     s9.set_ivs((v12, [0, 3]))
     self.assertTrue(s9.is_valid())
示例#8
0
 def test_get_scope(self):
     """Computing the scope of nodes of the SPN graph"""
     # Create graph
     v12 = spn.IVs(num_vars=2, num_vals=4, name="V12")
     v34 = spn.ContVars(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     p1 = spn.Product((v12, [0, 7]), name="P1")
     p2 = spn.Product((v12, [3, 4]), name="P2")
     p3 = spn.Product(v34, name="P3")
     n1 = spn.Concat(s1, s2, p3, name="N1")
     n2 = spn.Concat(p1, p2, name="N2")
     p4 = spn.Product((n1, [0]), (n1, [1]), name="P4")
     p5 = spn.Product((n2, [0]), (n1, [2]), name="P5")
     s3 = spn.Sum(p4, n2, name="S3")
     p6 = spn.Product(s3, (n1, [2]), name="P6")
     s4 = spn.Sum(p5, p6, name="S4")
     # Test
     self.assertListEqual(v12.get_scope(),
                          [spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 1), spn.Scope(v12, 1),
                           spn.Scope(v12, 1), spn.Scope(v12, 1)])
     self.assertListEqual(v34.get_scope(),
                          [spn.Scope(v34, 0), spn.Scope(v34, 1)])
     self.assertListEqual(s1.get_scope(),
                          [spn.Scope(v12, 0)])
     self.assertListEqual(s2.get_scope(),
                          [spn.Scope(v12, 1)])
     self.assertListEqual(p1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p3.get_scope(),
                          [spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n1.get_scope(),
                          [spn.Scope(v12, 0),
                           spn.Scope(v12, 1),
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p5.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p6.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
示例#9
0
    def test_group_initialization(self):
        """Group initialization of weights nodes"""
        v1 = spn.IVs(num_vars=1, num_vals=2)
        v2 = spn.IVs(num_vars=1, num_vals=4)
        v3 = spn.IVs(num_vars=1, num_vals=2)
        v4 = spn.IVs(num_vars=1, num_vals=2)
        # Sum
        s1 = spn.Sum(v1)
        s1.generate_weights(tf.initializers.constant([0.2, 0.3]))
        s2 = spn.Sum(v2)
        s2.generate_weights(tf.initializers.constant(5))
        # ParSums
        s3 = spn.ParSums(*[v3, v4], num_sums=2)
        s3.generate_weights(
            tf.initializers.constant([0.1, 0.2, 0.3, 0.4, 0.4, 0.3, 0.2, 0.1]))
        s4 = spn.ParSums(*[v1, v2, v3, v4], num_sums=3)
        s4.generate_weights(tf.initializers.constant(2.0))
        # Product
        p = spn.Product(s1, s2, s3, s4)
        init = spn.initialize_weights(p)

        with self.test_session() as sess:
            sess.run([init])
            val1 = sess.run(s1.weights.node.get_value())
            val2 = sess.run(s2.weights.node.get_value())
            val3 = sess.run(s3.weights.node.get_value())
            val4 = sess.run(s4.weights.node.get_value())
            val1_log = sess.run(tf.exp(s1.weights.node.get_log_value()))
            val2_log = sess.run(tf.exp(s2.weights.node.get_log_value()))
            val3_log = sess.run(tf.exp(s3.weights.node.get_log_value()))
            val4_log = sess.run(tf.exp(s4.weights.node.get_log_value()))

        self.assertEqual(val1.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val2.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val3.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val4.dtype, spn.conf.dtype.as_numpy_dtype())
        np.testing.assert_array_almost_equal(val1, [[0.4, 0.6]])
        np.testing.assert_array_almost_equal(val2, [[0.25, 0.25, 0.25, 0.25]])
        np.testing.assert_array_almost_equal(
            val3, [[0.1, 0.2, 0.3, 0.4], [0.4, 0.3, 0.2, 0.1]])
        np.testing.assert_array_almost_equal(
            val4, [[0.1] * 10, [0.1] * 10, [0.1] * 10])
        self.assertEqual(val1_log.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val2_log.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val3_log.dtype, spn.conf.dtype.as_numpy_dtype())
        self.assertEqual(val4_log.dtype, spn.conf.dtype.as_numpy_dtype())
        np.testing.assert_array_almost_equal(val1_log, [[0.4, 0.6]])
        np.testing.assert_array_almost_equal(val2_log,
                                             [[0.25, 0.25, 0.25, 0.25]])
        np.testing.assert_array_almost_equal(
            val3, [[0.1, 0.2, 0.3, 0.4], [0.4, 0.3, 0.2, 0.1]])
        np.testing.assert_array_almost_equal(
            val4, [[0.1] * 10, [0.1] * 10, [0.1] * 10])
示例#10
0
    def _build_op(self, inputs, placeholders, conf):
        """ Creates the graph using only ParSum nodes """
        # TODO make sure the ivs are correct
        sum_indices, weights, ivs = inputs.indices, inputs.weights, None
        log, inf_type = conf.log, conf.inf_type
        weights = np.split(
            weights,
            np.cumsum([len(ind) * inputs.num_parallel
                       for ind in sum_indices])[:-1])

        parallel_sum_nodes = []
        for ind in sum_indices:
            parallel_sum_nodes.append(
                spn.ParSums((placeholders[0], ind),
                            num_sums=inputs.num_parallel))

        weight_nodes = [
            self._generate_weights(node, w.tolist())
            for node, w in zip(parallel_sum_nodes, weights)
        ]
        if ivs:
            [s.set_ivs(iv) for s, iv in zip(parallel_sum_nodes, ivs)]
        root = spn.Sum(*parallel_sum_nodes)
        self._generate_weights(root)

        mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=log)
        mpe_path_gen.get_mpe_path(root)
        path_op = [mpe_path_gen.counts[w] for w in weight_nodes]
        input_counts = [mpe_path_gen.counts[inp] for inp in placeholders]

        return tf.tuple(
            path_op + input_counts)[:len(path_op)], self._initialize_from(root)
示例#11
0
    def mnist_01(inputs, num_decomps, num_subsets, num_mixtures, num_input_mixtures,
                 balanced, input_dist, node_type, inf_type, log=False):

        # Learning Parameters
        additive_smoothing = 100
        min_additive_smoothing = 1

        # Weight initialization
        weight_init_value = tf.initializers.random_uniform(10, 11)

        # Generate SPN structure
        dense_gen = spn.DenseSPNGenerator(num_decomps=num_decomps,
                                                    num_subsets=num_subsets,
                                                    num_mixtures=num_mixtures,
                                                    input_dist=(spn.DenseSPNGenerator.
                                                                InputDist.RAW if input_dist is
                                                                "RAW" else spn.
                                                                DenseSPNGenerator.
                                                                InputDist.MIXTURE),
                                                    num_input_mixtures=num_input_mixtures,
                                                    balanced=balanced,
                                                    node_type=node_type)
        root0 = dense_gen.generate(inputs, root_name="root_0")
        root1 = dense_gen.generate(inputs, root_name="root_1")
        root = spn.Sum(root0, root1, name="root")
        spn.generate_weights(root, initializer=weight_init_value)
        latent = root.generate_latent_indicators()

        # Add EM Learning
        additive_smoothing_var = tf.Variable(additive_smoothing, dtype=spn.conf.dtype)
        learning = spn.HardEMLearning(root, log=log, value_inference_type=inf_type,
                                  additive_smoothing=additive_smoothing_var)

        return root, latent, learning, additive_smoothing, min_additive_smoothing, \
            additive_smoothing_var
示例#12
0
    def sums(inputs,
             indices,
             ivs,
             num_sums,
             inf_type=None,
             log=True,
             output=None):
        if indices is None:
            inputs = [inputs for _ in range(num_sums)]
        else:
            inputs = [(inputs, indices) for _ in range(num_sums)]

        # Generate a single Sums node, modeling 'num_sums' sum nodes within,
        # connecting it to inputs and ivs
        s = spn.Sums(*inputs, num_sums=num_sums, ivs=ivs[-1])
        # Generate weights of the Sums node
        weights = s.generate_weights()

        # Connect the Sums nodes to a single root Sum node and generate its weights
        root = spn.Sum(s)
        root.generate_weights()

        if log:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=True)
        else:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type,
                                       log=False)

        mpe_path_gen.get_mpe_path(root)
        path_op = [mpe_path_gen.counts[weights]]
        return spn.initialize_weights(root), path_op
示例#13
0
    def par_sums(inputs,
                 indices,
                 latent_indicators,
                 num_sums,
                 inf_type=None,
                 log=True,
                 output=None):
        if indices is None:
            inputs = [inputs]
        else:
            inputs = [(inputs, indices)]

        # Generate a single ParallelSums node, modeling 'num_sums' sum nodes
        # within, connecting it to inputs and latent_indicators
        s = spn.ParallelSums(*inputs,
                             num_sums=num_sums,
                             latent_indicators=latent_indicators[-1])
        # Generate weights of the ParallelSums node
        weights = s.generate_weights()

        # Connect the ParallelSums nodes to a single root Sum node and generate
        # its weights
        root = spn.Sum(s)
        root.generate_weights()

        if log:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=True)
        else:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type,
                                       log=False)

        mpe_path_gen.get_mpe_path(root)
        path_op = [mpe_path_gen.counts[weights]]
        return spn.initialize_weights(root), path_op
示例#14
0
    def par_sums(inputs,
                 indices,
                 ivs,
                 num_sums,
                 inf_type,
                 log=True,
                 output=None):
        if indices is None:
            inputs = [inputs]
        else:
            inputs = [(inputs, indices)]

        # Generate a single ParSums node, modeling 'num_sums' sum nodes
        # within, connecting it to inputs and ivs
        s = spn.ParSums(*inputs, num_sums=num_sums, ivs=ivs[0])
        # Generate weights of the ParSums node
        s.generate_weights()

        # Connect the ParSums nodes to a single root Sum node and generate
        # its weights
        root = spn.Sum(s)
        root.generate_weights()

        if log:
            value_op = root.get_log_value(inference_type=inf_type)
        else:
            value_op = root.get_value(inference_type=inf_type)

        return spn.initialize_weights(root), value_op
示例#15
0
    def sums(inputs,
             indices,
             latent_indicators,
             num_sums,
             inf_type,
             log=True,
             output=None):
        if indices is None:
            inputs = [inputs for _ in range(num_sums)]
        else:
            inputs = [(inputs, ind) for ind in indices]

        # Generate a single Sums node, modeling 'num_sums' sum nodes within,
        # connecting it to inputs and latent_indicators
        s = spn.Sums(*inputs,
                     num_sums=num_sums,
                     latent_indicators=latent_indicators[0])
        # Generate weights of the Sums node
        s.generate_weights()

        # Connect the Sums nodes to a single root Sum node and generate its weights
        root = spn.Sum(s)
        root.generate_weights()

        if log:
            value_op = root.get_log_value(inference_type=inf_type)
        else:
            value_op = root.get_value(inference_type=inf_type)

        return spn.initialize_weights(root), value_op
示例#16
0
    def test_input_flags(self):
        """Detection of different types of inputs"""
        inpt = spn.Input()
        self.assertFalse(inpt)
        self.assertFalse(inpt.is_op)
        self.assertFalse(inpt.is_var)
        self.assertFalse(inpt.is_param)

        n = spn.Sum()
        inpt = spn.Input(n)
        self.assertTrue(inpt)
        self.assertTrue(inpt.is_op)
        self.assertFalse(inpt.is_var)
        self.assertFalse(inpt.is_param)

        n = spn.ContVars()
        inpt = spn.Input(n)
        self.assertTrue(inpt)
        self.assertFalse(inpt.is_op)
        self.assertTrue(inpt.is_var)
        self.assertFalse(inpt.is_param)

        n = spn.Weights()
        inpt = spn.Input(n)
        self.assertTrue(inpt)
        self.assertFalse(inpt.is_op)
        self.assertFalse(inpt.is_var)
        self.assertTrue(inpt.is_param)
 def _build_root_and_value(inf_type, log, sum_nodes):
     """ Connects the sum node outputs to a single root as a way of grouping Ops """
     root = spn.Sum(*sum_nodes)
     root.generate_weights()
     if log:
         value_op = root.get_log_value(inference_type=inf_type)
     else:
         value_op = root.get_value(inference_type=inf_type)
     return root, value_op
示例#18
0
    def mnist_all(inputs,
                  num_decomps,
                  num_subsets,
                  num_mixtures,
                  num_input_mixtures,
                  balanced,
                  input_dist,
                  node_type,
                  inf_type,
                  log=False):

        # Learning Parameters
        additive_smoothing = 0
        min_additive_smoothing = 0
        initial_accum_value = 20

        # Weight initialization
        weight_init_value = tf.initializers.random_uniform(0, 1)

        # Add random values before max
        add_random = None
        use_unweighted = True

        # Generate SPN structure
        dense_gen = spn.DenseSPNGenerator(
            num_decomps=num_decomps,
            num_subsets=num_subsets,
            num_mixtures=num_mixtures,
            input_dist=(spn.DenseSPNGenerator.InputDist.RAW
                        if input_dist is "RAW" else
                        spn.DenseSPNGenerator.InputDist.MIXTURE),
            num_input_mixtures=num_input_mixtures,
            balanced=balanced,
            node_type=node_type)
        class_roots = [
            dense_gen.generate(inputs, root_name=("Class_%d" % i))
            for i in range(10)
        ]
        root = spn.Sum(*class_roots, name="root")
        spn.generate_weights(root, init_value=weight_init_value)
        latent = root.generate_ivs()

        # Add EM Learning
        additive_smoothing_var = tf.Variable(additive_smoothing,
                                             dtype=spn.conf.dtype)
        learning = spn.EMLearning(root,
                                  log=log,
                                  value_inference_type=inf_type,
                                  additive_smoothing=additive_smoothing_var,
                                  add_random=add_random,
                                  initial_accum_value=initial_accum_value,
                                  use_unweighted=use_unweighted)

        return root, latent, learning, additive_smoothing, min_additive_smoothing, \
            additive_smoothing_var
示例#19
0
    def test_compute_mpe_path_noivs(self):
        spn.conf.argmax_zero = True
        v12 = spn.IVs(num_vars=2, num_vals=4)
        v34 = spn.ContVars(num_vars=2)
        v5 = spn.ContVars(num_vars=1)
        s = spn.Sum((v12, [0, 5]), v34, (v12, [3]), v5)
        w = s.generate_weights()
        counts = tf.placeholder(tf.float32, shape=(None, 1))
        op = s._compute_log_mpe_path(tf.identity(counts), w.get_log_value(),
                                     None, v12.get_log_value(),
                                     v34.get_log_value(), v12.get_log_value(),
                                     v5.get_log_value())
        init = w.initialize()
        counts_feed = [[10], [11], [12], [13]]
        v12_feed = [[0, 1], [1, 1], [0, 0], [3, 3]]
        v34_feed = [[0.1, 0.2], [1.2, 0.2], [0.1, 0.2], [0.9, 0.8]]
        v5_feed = [[0.5], [0.5], [1.2], [0.9]]

        with self.test_session() as sess:
            sess.run(init)
            # Skip the IVs op
            out = sess.run(op[:1] + op[2:],
                           feed_dict={
                               counts: counts_feed,
                               v12: v12_feed,
                               v34: v34_feed,
                               v5: v5_feed
                           })
        # Weights
        np.testing.assert_array_almost_equal(
            np.squeeze(out[0]),
            np.array([[10., 0., 0., 0., 0., 0.], [0., 0., 11., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 12.], [0., 0., 0., 0., 13., 0.]],
                     dtype=np.float32))
        np.testing.assert_array_almost_equal(
            out[1],
            np.array([[10., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 0., 0., 0.]],
                     dtype=np.float32))
        np.testing.assert_array_almost_equal(
            out[2],
            np.array([[0., 0.], [11., 0.], [0., 0.], [0., 0.]],
                     dtype=np.float32))
        np.testing.assert_array_almost_equal(
            out[3],
            np.array([[0., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 13., 0., 0., 0., 0.]],
                     dtype=np.float32))
        np.testing.assert_array_almost_equal(
            out[4], np.array([[0.], [0.], [12.], [0.]], dtype=np.float32))
示例#20
0
    def poon_single(inputs, num_vals, num_mixtures, num_subsets, inf_type,
                    log=False, output=None):

        # Build a POON-like network with single-op nodes
        subsets = [[spn.Sum((inputs, list(range(i*num_vals, (i+1)*num_vals))))
                   for _ in range(num_mixtures)] for i in range(num_subsets)]
        products = [spn.Product(*list(inp)) for inp in list(product(*[s for s in
                                                                      subsets]))]
        root = spn.Sum(*products, name="root")

        # Generate dense SPN and all weights in the network
        spn.generate_weights(root)

        # Generate value ops based on inf_type and log
        if log:
            value_op = root.get_log_value(inference_type=inf_type)
        else:
            value_op = root.get_value(inference_type=inf_type)

        return root, spn.initialize_weights(root), value_op
示例#21
0
    def test_traverse_graph_nostop_noparams(self):
        """Traversing the whole graph excluding param nodes"""
        counter = [0]
        nodes = [None] * 10

        def fun(node):
            nodes[counter[0]] = node
            counter[0] += 1

        # Generate graph
        v1 = spn.RawLeaf(num_vars=1)
        v2 = spn.RawLeaf(num_vars=1)
        v3 = spn.RawLeaf(num_vars=1)
        s1 = spn.Sum(v1, v1, v2)  # v1 included twice
        s2 = spn.Sum(v1, v3)
        s3 = spn.Sum(v2, v3, v3)  # v3 included twice
        s4 = spn.Sum(s1, v1)
        s5 = spn.Sum(s2, v3, s3)
        s6 = spn.Sum(s4, s2, s5, s4, s5)  # s4 and s5 included twice
        spn.generate_weights(s6)

        # Traverse
        spn.traverse_graph(s6, fun=fun, skip_params=True)

        # Test
        self.assertEqual(counter[0], 9)
        self.assertIs(nodes[0], s6)
        self.assertIs(nodes[1], s4)
        self.assertIs(nodes[2], s2)
        self.assertIs(nodes[3], s5)
        self.assertIs(nodes[4], s1)
        self.assertIs(nodes[5], v1)
        self.assertIs(nodes[6], v3)
        self.assertIs(nodes[7], s3)
        self.assertIs(nodes[8], v2)
示例#22
0
    def test_compute_graph_up_noconst(self):
        """Computing value assuming no constant functions"""
        # Number of times val_fun was called
        # Use list to avoid creating local fun variable during assignment
        counter = [0]

        def val_fun(node, *inputs):
            counter[0] += 1
            if isinstance(node, spn.graph.node.VarNode):
                return 1
            elif isinstance(node, spn.graph.node.ParamNode):
                return 0.1
            else:
                weight_val, iv_val, *values = inputs
                return weight_val + sum(values) + 1

        # Generate graph
        v1 = spn.RawLeaf(num_vars=1)
        v2 = spn.RawLeaf(num_vars=1)
        v3 = spn.RawLeaf(num_vars=1)
        s1 = spn.Sum(v1, v1, v2)  # v1 included twice
        s2 = spn.Sum(v1, v3)
        s3 = spn.Sum(v2, v3, v3)  # v3 included twice
        s4 = spn.Sum(s1, v1)
        s5 = spn.Sum(s2, v3, s3)
        s6 = spn.Sum(s4, s2, s5, s4, s5)  # s4 and s5 included twice
        spn.generate_weights(s6)

        # Calculate value
        val = spn.compute_graph_up(s6, val_fun)

        # Test
        self.assertAlmostEqual(val, 35.2)
        self.assertEqual(counter[0], 15)
示例#23
0
    def perm_products(inputs,
                      num_inputs,
                      num_input_cols,
                      num_prods,
                      inf_type,
                      indices=None,
                      log=False,
                      output=None):
        if indices is not None:
            # Create inputs list with indices
            inputs = [[(inp, ind) for inp, ind in zip(inps, inds)]
                      for inps, inds in zip(inputs, indices)]

        if isinstance(inputs,
                      list):  # Is a list of ContVars inputs - Multiple inputs
            # Generate 'len(inputs)' PermProducts nodes, modeling 'n_prods' products
            # within each
            p = [spn.PermProducts(*inps) for inps in inputs]
        else:  # Is a single input of type ContVars - A single input
            num_inputs_array = np.array(num_inputs)
            num_input_cols_array = np.array(num_input_cols)
            num_cols = num_input_cols[0]
            num_vars = int(np.sum(num_inputs_array * num_input_cols_array))

            indices_list = [
                list(range(i, i + num_cols))
                for i in range(0, num_vars, num_cols)
            ]
            num_inputs_cumsum = np.cumsum(num_inputs_array).tolist()
            num_inputs_cumsum.insert(0, 0)

            inputs_list = [[(inputs, inds)
                            for inds in indices_list[start:stop]]
                           for start, stop in zip(num_inputs_cumsum[:-1],
                                                  num_inputs_cumsum[1:])]

            # Generate 'len(inputs)' PermProducts nodes, modeling 'n_prods'
            # products within each, and inputs for each node emination from a
            # commoninput source
            p = [spn.PermProducts(*inps) for inps in inputs_list]

        # Connect all PermProducts nodes to a single root Sum node and generate
        # its weights
        root = spn.Sum(*p)
        root.generate_weights()

        if log:
            value_op = root.get_log_value(inference_type=inf_type)
        else:
            value_op = root.get_value(inference_type=inf_type)

        return spn.initialize_weights(root), value_op
示例#24
0
    def test_get_num_nodes(self):
        """Computing the number of nodes in the SPN graph"""
        # Generate graph
        v1 = spn.ContVars(num_vars=1)
        v2 = spn.ContVars(num_vars=1)
        v3 = spn.ContVars(num_vars=1)
        s1 = spn.Sum(v1, v1, v2)  # v1 included twice
        s2 = spn.Sum(v1, v3)
        s3 = spn.Sum(v2, v3, v3)  # v3 included twice
        s4 = spn.Sum(s1, v1)
        s5 = spn.Sum(s2, v3, s3)
        s6 = spn.Sum(s4, s2, s5, s4, s5)  # s4 and s5 included twice
        spn.generate_weights(s6)

        # Test
        num = v1.get_num_nodes(skip_params=True)
        self.assertEqual(num, 1)
        num = v1.get_num_nodes(skip_params=False)
        self.assertEqual(num, 1)

        num = v2.get_num_nodes(skip_params=True)
        self.assertEqual(num, 1)
        num = v2.get_num_nodes(skip_params=False)
        self.assertEqual(num, 1)

        num = v3.get_num_nodes(skip_params=True)
        self.assertEqual(num, 1)
        num = v3.get_num_nodes(skip_params=False)
        self.assertEqual(num, 1)

        num = s1.get_num_nodes(skip_params=True)
        self.assertEqual(num, 3)
        num = s1.get_num_nodes(skip_params=False)
        self.assertEqual(num, 4)

        num = s2.get_num_nodes(skip_params=True)
        self.assertEqual(num, 3)
        num = s2.get_num_nodes(skip_params=False)
        self.assertEqual(num, 4)

        num = s3.get_num_nodes(skip_params=True)
        self.assertEqual(num, 3)
        num = s3.get_num_nodes(skip_params=False)
        self.assertEqual(num, 4)

        num = s4.get_num_nodes(skip_params=True)
        self.assertEqual(num, 4)
        num = s4.get_num_nodes(skip_params=False)
        self.assertEqual(num, 6)

        num = s5.get_num_nodes(skip_params=True)
        self.assertEqual(num, 6)
        num = s5.get_num_nodes(skip_params=False)
        self.assertEqual(num, 9)

        num = s6.get_num_nodes(skip_params=True)
        self.assertEqual(num, 9)
        num = s6.get_num_nodes(skip_params=False)
        self.assertEqual(num, 15)
示例#25
0
 def test_gather_input_scopes(self):
     v12 = spn.IVs(num_vars=2, num_vals=4, name="V12")
     v34 = spn.ContVars(num_vars=2, name="V34")
     s1 = spn.Sum(v12, v12, v34, (v12, [7, 3, 1, 0]), (v34, 0), name="S1")
     scopes_v12 = v12._compute_scope()
     scopes_v34 = v34._compute_scope()
     # Note: weights/ivs are disconnected, so None should be output these
     scopes = s1._gather_input_scopes(None, None, None, scopes_v12,
                                      scopes_v34, scopes_v12, scopes_v34)
     self.assertTupleEqual(
         scopes, (None, None, None, scopes_v12, scopes_v34, [
             scopes_v12[7], scopes_v12[3], scopes_v12[1], scopes_v12[0]
         ], [scopes_v34[0]]))
    def sum(inputs, sum_indices, repetitions, inf_type, log=False, ivs=None):
        """ Creates the graph using only Sum nodes """
        sum_nodes = []
        for ind in sum_indices:
            sum_nodes.extend(
                [spn.Sum((inputs, ind)) for _ in range(repetitions)])
        [s.generate_weights() for s in sum_nodes]
        if ivs:
            [s.set_ivs(iv) for s, iv in zip(sum_nodes, ivs)]

        root, value_op = Ops._build_root_and_value(inf_type, log, sum_nodes)

        return spn.initialize_weights(root), value_op
示例#27
0
    def products(inputs,
                 num_inputs,
                 num_input_cols,
                 num_prods,
                 inf_type,
                 indices=None,
                 log=False,
                 output=None):
        p = []
        # Generate 'len(inputs)' Products node, modelling 'n_prods' ∈ 'num_prods'
        # products within each
        for inps, n_inp_cols, n_prods in zip(inputs, num_input_cols,
                                             num_prods):
            num_inputs = len(inps)
            # Create permuted indices based on number and size of inps
            inds = map(int, np.arange(n_inp_cols))
            permuted_inds = list(product(inds, repeat=num_inputs))
            permuted_inds_list = [list(elem) for elem in permuted_inds]
            permuted_inds_list_of_list = []
            for elem in permuted_inds_list:
                permuted_inds_list_of_list.append(
                    [elem[i:i + 1] for i in range(0, len(elem), 1)])

            # Create inputs-list by combining inps and indices
            permuted_inputs = []
            for indices in permuted_inds_list_of_list:
                permuted_inputs.append([tuple(i) for i in zip(inps, indices)])
            permuted_inputs = list(chain.from_iterable(permuted_inputs))

            # Generate a single Products node, modeling 'n_prods' product nodes
            # within, connecting it to inputs
            p = p + [spn.Products(*permuted_inputs, num_prods=n_prods)]

        # Connect all product nodes to a single root Sum node and generate its
        # weights
        root = spn.Sum(*p)
        root.generate_weights()

        if log:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type, log=True)
        else:
            mpe_path_gen = spn.MPEPath(value_inference_type=inf_type,
                                       log=False)

        mpe_path_gen.get_mpe_path(root)
        path_ops = [
            mpe_path_gen.counts[inp]
            for inp in list(chain.from_iterable(inputs))
        ]
        return spn.initialize_weights(root), path_ops
示例#28
0
 def test(values, ivs, weights, feed, output):
     with self.subTest(values=values, ivs=ivs, weights=weights,
                       feed=feed):
         n = spn.Sum(*values, ivs=ivs)
         n.generate_weights(weights)
         op = n.get_value(spn.InferenceType.MARGINAL)
         op_log = n.get_log_value(spn.InferenceType.MARGINAL)
         with tf.Session() as sess:
             spn.initialize_weights(n).run()
             out = sess.run(op, feed_dict=feed)
             out_log = sess.run(tf.exp(op_log), feed_dict=feed)
         np.testing.assert_array_almost_equal(
             out,
             np.array(output, dtype=spn.conf.dtype.as_numpy_dtype()))
         np.testing.assert_array_almost_equal(
             out_log,
             np.array(output, dtype=spn.conf.dtype.as_numpy_dtype()))
示例#29
0
    def test_generte_set_errors(self):
        """Detecting structure errors in __generate_set"""
        gen = spn.DenseSPNGenerator(num_decomps=2,
                                    num_subsets=3,
                                    num_mixtures=2)
        v1 = spn.IVs(num_vars=2, num_vals=4)
        v2 = spn.ContVars(num_vars=3, name="ContVars1")
        v3 = spn.ContVars(num_vars=2, name="ContVars2")
        s1 = spn.Sum(v3, v2)
        n1 = spn.Concat(v2)

        with self.assertRaises(spn.StructureError):
            gen._DenseSPNGenerator__generate_set([
                spn.Input(v1, [0, 3, 2, 6, 7]),
                spn.Input(v2, [1, 2]),
                spn.Input(s1, None),
                spn.Input(n1, None)
            ])
    def test_sum_update_1(self):
        child1 = spn.GaussianLeaf(num_vars=1,
                                  num_components=1,
                                  total_counts_init=3,
                                  loc_init=0.0,
                                  scale_init=1.0,
                                  learn_dist_params=True)
        child2 = spn.GaussianLeaf(num_vars=1,
                                  num_components=1,
                                  total_counts_init=7,
                                  loc_init=1.0,
                                  scale_init=4.0,
                                  learn_dist_params=True)
        root = spn.Sum(child1, child2)
        root.generate_weights()

        value_inference_type = spn.InferenceType.MARGINAL
        init_weights = spn.initialize_weights(root)
        learning = spn.EMLearning(root,
                                  log=True,
                                  value_inference_type=value_inference_type,
                                  use_unweighted=True)
        reset_accumulators = learning.reset_accumulators()
        accumulate_updates = learning.accumulate_updates()
        update_spn = learning.update_spn()
        train_likelihood = learning.value.values[root]

        with self.test_session() as sess:
            sess.run(init_weights)
            sess.run(reset_accumulators)
            sess.run(accumulate_updates, {child1: [[0.0]], child2: [[0.0]]})
            sess.run(update_spn)

            child1_n = sess.run(child1._total_count_variable)
            child2_n = sess.run(child2._total_count_variable)

        # equalWeight is true, so update passes the data point to the component
        # with highest likelihood without considering the weight of each component.
        # In this case, N(0|0,1) > N(0|1,4), so child1 is picked.
        # If component weights are taken into account, then child2 will be picked
        # since 0.3*N(0|0,1) < 0.7*N(0|1,4).
        # self.assertEqual(root.n, 11)
        self.assertEqual(child1_n, 4)
        self.assertEqual(child2_n, 7)