def test_dep_empirical_distrib_continuous(self): bn = BNetwork() builder = CategoricalTableBuilder("var1") builder.add_row(ValueFactory.create("one"), 0.7) builder.add_row(ValueFactory.create("two"), 0.3) var1 = ChanceNode("var1", builder.build()) bn.add_node(var1) continuous = ContinuousDistribution("var2", UniformDensityFunction(-1.0, 3.0)) continuous2 = ContinuousDistribution( "var2", GaussianDensityFunction(3.0, 10.0)) table = ConditionalTable("var2") table.add_distrib(Assignment("var1", "one"), continuous) table.add_distrib(Assignment("var1", "two"), continuous2) var2 = ChanceNode("var2", table) var2.add_input_node(var1) bn.add_node(var2) inference = InferenceChecks() inference.check_cdf(bn, "var2", -1.5, 0.021) inference.check_cdf(bn, "var2", 0., 0.22) inference.check_cdf(bn, "var2", 2., 0.632) inference.check_cdf(bn, "var2", 8., 0.98)
def test_switching(self): old_factor = SwitchingAlgorithm.max_branching_factor SwitchingAlgorithm.max_branching_factor = 4 network = NetworkExamples.construct_basic_network2() distrib = SwitchingAlgorithm().query_prob( network, ["Burglary"], Assignment(["JohnCalls", "MaryCalls"])) assert isinstance(distrib, MultivariateTable) builder = CategoricalTableBuilder("n1") builder.add_row(ValueFactory.create("aha"), 1.0) n1 = ChanceNode("n1", builder.build()) network.add_node(n1) builder = CategoricalTableBuilder("n2") builder.add_row(ValueFactory.create("oho"), 0.7) n2 = ChanceNode("n2", builder.build()) network.add_node(n2) builder = CategoricalTableBuilder("n3") builder.add_row(ValueFactory.create("ihi"), 0.7) n3 = ChanceNode("n3", builder.build()) network.add_node(n3) network.get_node("Alarm").add_input_node(n1) network.get_node("Alarm").add_input_node(n2) network.get_node("Alarm").add_input_node(n3) distrib = SwitchingAlgorithm().query_prob( network, ["Burglary"], Assignment(["JohnCalls", "MaryCalls"])) assert distrib.__class__ == EmpiricalDistribution network.remove_node(n1.get_id()) network.remove_node(n2.get_id()) distrib = SwitchingAlgorithm().query_prob( network, ["Burglary"], Assignment(["JohnCalls", "MaryCalls"])) assert isinstance(distrib, MultivariateTable) n1 = ChanceNode( "n1", ContinuousDistribution("n1", UniformDensityFunction(-2.0, 2.0))) n2 = ChanceNode( "n2", ContinuousDistribution("n2", GaussianDensityFunction(-1.0, 3.0))) network.add_node(n1) network.add_node(n2) network.get_node("Earthquake").add_input_node(n1) network.get_node("Earthquake").add_input_node(n2) distrib = SwitchingAlgorithm().query_prob( network, ["Burglary"], Assignment(["JohnCalls", "MaryCalls"])) assert isinstance(distrib, EmpiricalDistribution) SwitchingAlgorithm.max_branching_factor = old_factor
def create_chance_node(node): """ Creates a new chance node corresponding to the XML specification :param node: the XML node :return: the resulting chance node encoded """ if len(node.attrib) == 0: raise ValueError() try: label = node.attrib['id'].strip() except: raise ValueError() if len(label) == 0: raise ValueError() builder = CategoricalTableBuilder(label) distrib = None for child_node in node: if child_node.tag == 'value': # first case: the chance node is described as a categorical table. # extracting the value prob = XMLStateReader._get_probability(child_node) value = ValueFactory.create(child_node.text.strip()) builder.add_row(value, prob) elif child_node.tag == 'distrib': # second case: the chance node is described by a parametric continuous distribution. try: distrib_type = child_node.attrib['type'].lower() if distrib_type == 'gaussian': distrib = ContinuousDistribution( label, XMLStateReader._get_gaussian(child_node)) elif distrib_type == 'uniform': distrib = ContinuousDistribution( label, XMLStateReader._get_uniform(child_node)) elif distrib_type == 'dirichlet': distrib = ContinuousDistribution( label, XMLStateReader._get_dirichlet(child_node)) except: raise ValueError() if distrib is not None: return ChanceNode(label, distrib) total_prob = builder.get_total_prob() # TODO: check eps eps = 1e-8 if total_prob > 1.0 + eps: raise ValueError() return ChanceNode(label, builder.build())
def construct_basic_network4(): network = NetworkExamples.construct_basic_network() node = ChanceNode( "gaussian", ContinuousDistribution("gaussian", UniformDensityFunction(-2, 3))) network.add_node(node) return network
def test_continuous(self): distrib = ContinuousDistribution("X", UniformDensityFunction(-2.0, 4.0)) assert distrib.get_prob_density(1.0) == pytest.approx(1 / 6.0, abs=0.0001) assert distrib.get_prob_density(4.0) == pytest.approx(1 / 6.0, abs=0.0001) assert distrib.get_prob_density(-3.0) == pytest.approx(0.0, abs=0.0001) assert distrib.get_prob_density(6.0) == pytest.approx(0.0, abs=0.0001) assert distrib.to_discrete().get_prob(0.5) == pytest.approx(0.01, abs=0.01) assert distrib.to_discrete().get_prob(4) == pytest.approx(0.01, abs=0.01) total_prob = 0.0 for value in distrib.to_discrete().get_posterior( Assignment()).get_values(): total_prob += distrib.to_discrete().get_prob(value) assert total_prob == pytest.approx(1.0, abs=0.03)
def test_empirical_distrib_continuous(self): continuous = ContinuousDistribution("var1", UniformDensityFunction(-1.0, 3.0)) bn = BNetwork() var1 = ChanceNode("var1", continuous) bn.add_node(var1) sampling = SamplingAlgorithm(2000, 200) distrib2 = sampling.query_prob(bn, "var1") assert len(distrib2.get_posterior( Assignment()).get_values()) == pytest.approx( Settings.discretization_buckets, abs=2) assert distrib2.to_continuous().get_cumulative_prob( -1.1) == pytest.approx(0, abs=0.001) assert distrib2.to_continuous().get_cumulative_prob( 1.0) == pytest.approx(0.5, abs=0.06) assert distrib2.to_continuous().get_cumulative_prob( 3.1) == pytest.approx(1.0, abs=0.00) assert continuous.get_prob_density(-2.0) == pytest.approx( distrib2.to_continuous().get_prob_density(-2.0), abs=0.1) assert continuous.get_prob_density(-0.5) == pytest.approx( distrib2.to_continuous().get_prob_density(-0.5), abs=0.1) assert continuous.get_prob_density(1.8) == pytest.approx( distrib2.to_continuous().get_prob_density(1.8), abs=0.1) assert continuous.get_prob_density(3.2) == pytest.approx( distrib2.to_continuous().get_prob_density(3.2), abs=0.1)
def test_gaussian_distrib(self): continuous2 = ContinuousDistribution("var2", GaussianDensityFunction(2.0, 3.0)) assert continuous2.get_prob_density(1.2) == pytest.approx(0.2070, abs=0.001) assert continuous2.get_prob_density(2.0) == pytest.approx(0.23033, abs=0.001) assert continuous2.get_cumulative_prob(2.0) == pytest.approx(0.5, abs=0.001) assert continuous2.get_cumulative_prob(3.0) == pytest.approx(0.7181, abs=0.001) assert len(continuous2.to_discrete().get_values() ) > Settings.discretization_buckets / 2 assert len(continuous2.to_discrete().get_values() ) <= Settings.discretization_buckets assert continuous2.to_discrete().get_prob(2) == pytest.approx(0.06205, abs=0.01) sum = 0. for _ in range(10000): sum += continuous2.sample().get_double() assert sum / 10000.0 == pytest.approx(2.0, abs=0.1)
def create_continuous(self, head_variable): """ Creates a continuous with the defined head variable given the samples :param head_variable: the variable for which to create the distribution :return: the resulting continuous distribution """ values = [] for assignment in self._samples: value = assignment.get_value(head_variable) if isinstance(value, ArrayVal): values.append(value.get_array()) elif isinstance(value, DoubleVal): values.append([value.get_double()]) values = np.array(values) return ContinuousDistribution(head_variable, KernelDensityFunction(values))
def test_uniform_distrib(self): continuous2 = ContinuousDistribution("var2", UniformDensityFunction(-2.0, 3.0)) assert continuous2.get_prob_density(1.2) == pytest.approx(1 / 5.0, abs=0.001) # assert continuous2.get_cumulative_prob(Assignment("var2", # 2)), 4 / 5.0 == 0.001 assert len(continuous2.to_discrete().get_values() ) == Settings.discretization_buckets assert continuous2.get_prob(ValueFactory.create(1.2)) == pytest.approx( 0.01, abs=0.01) sum = 0. for _ in range(10000): sum += continuous2.sample().get_double() assert sum / 10000.0 == pytest.approx(0.5, abs=0.1) assert continuous2.get_function().get_mean()[0] == pytest.approx( 0.5, abs=0.01) assert continuous2.get_function().get_variance()[0] == pytest.approx( 2.08, abs=0.01)
def test_kernel_distrib2(self): mkds = KernelDensityFunction( np.array([[0.1], [-1.5], [0.6], [1.3], [1.3]])) continuous2 = ContinuousDistribution("var2", mkds) assert continuous2.get_prob_density(np.array([-2.0])) == pytest.approx( 0.086, abs=0.003) assert continuous2.get_prob_density(np.array([0.6])) == pytest.approx( 0.32, abs=0.02) assert continuous2.get_prob_density(np.array([1.3])) == pytest.approx( 0.30, abs=0.02) sum = 0. for _ in range(10000): sum += continuous2.sample().get_double() assert sum / 10000.0 == pytest.approx(0.424, abs=0.15) assert continuous2.to_discrete().get_prob(-1.5) == pytest.approx( 0.2, abs=0.1)
def to_continuous(self): """ Returns the continuous probability distribution equivalent to the current table :return: the continuous equivalent for the distribution could not be converted """ if self._is_continuous(): points = dict() for v in self.get_values(): if isinstance(v, ArrayVal): points[v.get_array()] = self.get_prob(v) elif isinstance(v, DoubleVal): points[(v.get_double(), )] = self.get_prob(v) discrete_density_func = DiscreteDensityFunction(points) from bn.distribs.continuous_distribution import ContinuousDistribution return ContinuousDistribution(self._variable, discrete_density_func) raise ValueError()
def test_dirichlet(self): old_discretisation_settings = Settings.discretization_buckets Settings.discretization_buckets = 250 alphas = list() alphas.append(40.0) alphas.append(80.0) alphas = np.array(alphas) dirichlet = DirichletDensityFunction(alphas) distrib = ContinuousDistribution("x", dirichlet) assert isinstance(distrib.sample(), ArrayVal) assert 2 == len(distrib.sample()) assert distrib.sample().get_array()[0] == pytest.approx(0.33, abs=0.15) ############################################## # dirichlet distribution 자바 코드에 버그가 있음. ############################################## # assert distrib.get_prob_density(ArrayVal([1./3, 2./3])) == pytest.approx(8.0, abs=0.5) n = ChanceNode("x", distrib) network = BNetwork() network.add_node(n) table = VariableElimination().query_prob(network, "x") sum = 0. for value in table.get_values(): if value.get_array()[0] < 0.33333: sum += table.get_prob(value) assert sum == pytest.approx(0.5, abs=0.1) conversion1 = VariableElimination().query_prob(network, "x") assert abs( len(conversion1.get_posterior(Assignment()).get_values()) - Settings.discretization_buckets) < 10 assert conversion1.get_posterior(Assignment()).get_prob( ValueFactory.create("[0.3333,0.6666]")) == pytest.approx(0.02, abs=0.05) conversion3 = SamplingAlgorithm(4000, 1000).query_prob(network, "x") # DistributionViewer(conversion3) # Thread.sleep(3000000) # TODO: 아래 테스트 케이스 문제 없는지 확인 필요. # assert conversion3.to_continuous().get_prob_density(ValueFactory.create("[0.3333,0.6666]")) == pytest.approx(9.0, abs=1.5) assert distrib.get_function().get_mean()[0] == pytest.approx(0.333333, abs=0.01) assert distrib.get_function().get_variance()[0] == pytest.approx( 0.002, abs=0.01) assert conversion3.to_continuous().get_function().get_mean( )[0] == pytest.approx(0.333333, abs=0.05) assert conversion3.to_continuous().get_function().get_variance( )[0] == pytest.approx(0.002, abs=0.05) Settings.discretization_buckets = old_discretisation_settings
def test_kernel_distrib(self): kds = KernelDensityFunction( np.array([[0.1], [-1.5], [0.6], [1.3], [1.3]])) continuous2 = ContinuousDistribution("var2", kds) assert continuous2.get_prob_density(-2.0) == pytest.approx(0.086, abs=0.01) assert continuous2.get_prob_density(0.6) == pytest.approx(0.32, abs=0.1) assert continuous2.get_prob_density(1.3) == pytest.approx(0.30, abs=0.1) assert continuous2.get_cumulative_prob( ValueFactory.create(-1.6)) == pytest.approx(0.0, abs=0.01) assert continuous2.get_cumulative_prob( ValueFactory.create(-1.4)) == pytest.approx(0.2, abs=0.01) assert continuous2.get_cumulative_prob( ValueFactory.create(1.29)) == pytest.approx(0.6, abs=0.01) assert continuous2.get_cumulative_prob( ValueFactory.create(1.3)) == pytest.approx(1.0, abs=0.01) assert continuous2.get_cumulative_prob( ValueFactory.create(1.31)) == pytest.approx(1.0, abs=0.01) sum = 0. for _ in range(20000): sum += continuous2.sample().get_double() assert sum / 20000.0 == pytest.approx(0.424, abs=0.1) # DistributionViewer.showDistributionViewer(continuous2) # Thread.sleep(300000000) assert continuous2.to_discrete().get_prob(-1.5) == pytest.approx( 0.2, abs=0.05) assert continuous2.get_function().get_mean()[0] == pytest.approx( 0.36, abs=0.01) assert continuous2.get_function().get_variance()[0] == pytest.approx( 1.07, abs=0.01)
def test_gaussian(self): distrib = ContinuousDistribution("X", GaussianDensityFunction(1.0, 3.0)) assert distrib.get_prob_density(1.0) == pytest.approx(0.23032, abs=0.001) assert distrib.get_prob_density(-3.0) == pytest.approx(0.016, abs=0.01) assert distrib.get_prob_density(6.0) == pytest.approx(0.00357, abs=0.01) assert distrib.to_discrete().get_prob(1.0) == pytest.approx(0.06290, abs=0.01) assert distrib.to_discrete().get_prob(0.5) == pytest.approx(0.060615, abs=0.01) assert distrib.to_discrete().get_prob(4) == pytest.approx(0.014486, abs=0.01) total_prob = 0.0 for value in distrib.to_discrete().get_posterior( Assignment()).get_values(): total_prob += distrib.to_discrete().get_prob(value) assert total_prob == pytest.approx(1.0, abs=0.05) assert distrib.get_function().get_mean()[0] == pytest.approx(1.0, abs=0.01) assert distrib.get_function().get_variance()[0] == pytest.approx( 3.0, abs=0.01) samples = list() for _ in range(20000): val = [distrib.sample().get_double()] samples.append(val) samples = np.array(samples) estimated = GaussianDensityFunction(samples) assert estimated.get_mean()[0] == pytest.approx( distrib.get_function().get_mean()[0], abs=0.05) assert estimated.get_variance()[0] == pytest.approx( distrib.get_function().get_variance()[0], abs=0.1)