def main():
    """
    Main functiont to lunch the belief propagation algorithm
    """

    M = model()
    M.check_model()

    #Belief propagation
    bp = BeliefPropagation(M)
    bp.calibrate()
    print("maximal cliques are:")
    print(bp.get_cliques())

    # first query
    print("computing probability of B=")
    query1 = bp.query(variables=list('b'), show_progress=True)
    print(query1)

    #second query
    print("computing probability of B|C")
    query2 = bp.query(variables=['b', 'c'])
    query2.marginalize(['c'])
    print(query2)

    #Third query
    print("computing joint")
    query3 = bp.query(['a', 'b', 'c', 'd', 'e'])
    query3.normalize()
    print(query3)
Exemple #2
0
def get_partition_function_BP(G):
    '''
	Calculate partition function of G using belief propogation

	'''
    bp = BeliefPropagation(G)
    bp.calibrate()
    clique_beliefs = bp.get_clique_beliefs()
    partition_function = np.sum(clique_beliefs.values()[0].values)
    return partition_function
Exemple #3
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
    def test_calibrate_clique_belief(self):
        belief_propagation = BeliefPropagation(self.junction_tree)
        belief_propagation.calibrate()
        clique_belief = belief_propagation.get_clique_beliefs()

        phi1 = Factor(['A', 'B'], [2, 3], range(6))
        phi2 = Factor(['B', 'C'], [3, 2], range(6))
        phi3 = Factor(['C', 'D'], [2, 2], range(4))

        b_A_B = phi1 * (phi3.marginalize(['D'], inplace=False) * phi2).marginalize(['C'], inplace=False)
        b_B_C = phi2 * (phi1.marginalize(['A'], inplace=False) * phi3.marginalize(['D'], inplace=False))
        b_C_D = phi3 * (phi1.marginalize(['A'], inplace=False) * phi2).marginalize(['B'], inplace=False)

        np_test.assert_array_almost_equal(clique_belief[('A', 'B')].values, b_A_B.values)
        np_test.assert_array_almost_equal(clique_belief[('B', 'C')].values, b_B_C.values)
        np_test.assert_array_almost_equal(clique_belief[('C', 'D')].values, b_C_D.values)
    def test_calibrate_sepset_belief(self):
        belief_propagation = BeliefPropagation(self.junction_tree)
        belief_propagation.calibrate()
        sepset_belief = belief_propagation.get_sepset_beliefs()

        phi1 = Factor(['A', 'B'], [2, 3], range(6))
        phi2 = Factor(['B', 'C'], [3, 2], range(6))
        phi3 = Factor(['C', 'D'], [2, 2], range(4))

        b_B = (phi1 * (phi3.marginalize(['D'], inplace=False) *
                       phi2).marginalize(['C'], inplace=False)).marginalize(['A'], inplace=False)

        b_C = (phi2 * (phi1.marginalize(['A'], inplace=False) *
                       phi3.marginalize(['D'], inplace=False))).marginalize(['B'], inplace=False)

        np_test.assert_array_almost_equal(sepset_belief[frozenset((('A', 'B'), ('B', 'C')))].values, b_B.values)
        np_test.assert_array_almost_equal(sepset_belief[frozenset((('B', 'C'), ('C', 'D')))].values, b_C.values)
Exemple #6
0
    def test_calibrate_clique_belief(self):
        belief_propagation = BeliefPropagation(self.junction_tree)
        belief_propagation.calibrate()
        clique_belief = belief_propagation.get_clique_beliefs()

        phi1 = Factor(['A', 'B'], [2, 3], range(6))
        phi2 = Factor(['B', 'C'], [3, 2], range(6))
        phi3 = Factor(['C', 'D'], [2, 2], range(4))

        b_A_B = phi1 * (phi3.marginalize(['D'], inplace=False) *
                        phi2).marginalize(['C'], inplace=False)
        b_B_C = phi2 * (phi1.marginalize(['A'], inplace=False) *
                        phi3.marginalize(['D'], inplace=False))
        b_C_D = phi3 * (phi1.marginalize(['A'], inplace=False) *
                        phi2).marginalize(['B'], inplace=False)

        np_test.assert_array_almost_equal(clique_belief[('A', 'B')].values,
                                          b_A_B.values)
        np_test.assert_array_almost_equal(clique_belief[('B', 'C')].values,
                                          b_B_C.values)
        np_test.assert_array_almost_equal(clique_belief[('C', 'D')].values,
                                          b_C_D.values)
Exemple #7
0
    def test_calibrate_clique_belief(self):
        belief_propagation = BeliefPropagation(self.junction_tree)
        belief_propagation.calibrate()
        clique_belief = belief_propagation.get_clique_beliefs()

        phi1 = DiscreteFactor(["A", "B"], [2, 3], range(6))
        phi2 = DiscreteFactor(["B", "C"], [3, 2], range(6))
        phi3 = DiscreteFactor(["C", "D"], [2, 2], range(4))

        b_A_B = phi1 * (phi3.marginalize(["D"], inplace=False) *
                        phi2).marginalize(["C"], inplace=False)
        b_B_C = phi2 * (phi1.marginalize(["A"], inplace=False) *
                        phi3.marginalize(["D"], inplace=False))
        b_C_D = phi3 * (phi1.marginalize(["A"], inplace=False) *
                        phi2).marginalize(["B"], inplace=False)

        np_test.assert_array_almost_equal(clique_belief[("A", "B")].values,
                                          b_A_B.values)
        np_test.assert_array_almost_equal(clique_belief[("B", "C")].values,
                                          b_B_C.values)
        np_test.assert_array_almost_equal(clique_belief[("C", "D")].values,
                                          b_C_D.values)
Exemple #8
0
    def test_calibrate_sepset_belief(self):
        belief_propagation = BeliefPropagation(self.junction_tree)
        belief_propagation.calibrate()
        sepset_belief = belief_propagation.get_sepset_beliefs()

        phi1 = Factor(['A', 'B'], [2, 3], range(6))
        phi2 = Factor(['B', 'C'], [3, 2], range(6))
        phi3 = Factor(['C', 'D'], [2, 2], range(4))

        b_B = (phi1 *
               (phi3.marginalize(['D'], inplace=False) * phi2).marginalize(
                   ['C'], inplace=False)).marginalize(['A'], inplace=False)

        b_C = (phi2 * (phi1.marginalize(['A'], inplace=False) *
                       phi3.marginalize(['D'], inplace=False))).marginalize(
                           ['B'], inplace=False)

        np_test.assert_array_almost_equal(
            sepset_belief[frozenset((('A', 'B'), ('B', 'C')))].values,
            b_B.values)
        np_test.assert_array_almost_equal(
            sepset_belief[frozenset((('B', 'C'), ('C', 'D')))].values,
            b_C.values)
Exemple #9
0
PGM.add_nodes_from(['w1', 'w2', 'w3'])
PGM.add_edges_from([('w1', 'w2'), ('w2', 'w3')])
tr_matrix = np.array([1, 10, 3, 2, 1, 5, 3, 3, 2])
tr_matrix = np.array([1, 2, 3, 10, 1, 3, 3, 5, 2]).reshape(3, 3).T.reshape(-1)
phi = [DiscreteFactor(edge, [3, 3], tr_matrix) for edge in PGM.edges()]
print(phi[0])
print(phi[1])
PGM.add_factors(*phi)

# Calculate partition funtion
Z = PGM.get_partition_function()
print('The partition function is:', Z)

# Calibrate the click
belief_propagation = BeliefPropagation(PGM)
belief_propagation.calibrate()

# Output calibration result, which you should get
query = belief_propagation.query(variables=['w2'])
print('After calibration you should get the following mu(S):\n', query * Z)

# Get marginal distribution over third word
query = belief_propagation.query(variables=['w3'])
print('Marginal distribution over the third word is:\n', query)

#Get conditional distribution over third word
query = belief_propagation.query(variables=['w3'],
                                 evidence={'w1': 0})  # 0 stays for "noun"
print(
    'Conditional distribution over the third word, given that the first word is noun is:\n',
    query)
import numpy as np
from pgmpy.models import FactorGraph
from pgmpy.factors.discrete import DiscreteFactor
from pgmpy.inference import BeliefPropagation

G = FactorGraph()
G.add_node(0)
G.add_node(1)
G.add_node(2)

f01 = DiscreteFactor([0, 1], [2, 2], np.random.rand(4))
f02 = DiscreteFactor([0, 2], [2, 2], np.random.rand(4))
f12 = DiscreteFactor([1, 2], [2, 2], np.random.rand(4))
G.add_factors(f01)
G.add_factors(f02)
G.add_factors(f12)

G.add_edges_from([(0, f01), (1, f01), (0, f02), (2, f02), (1, f12), (2, f12)])
bp = BeliefPropagation(G)
bp.calibrate()
    def plot_causal_influence(self, file_path):
        """
        Computes the odds of the target variable being value 1 over value 0 (i.e. the odds ratio)
        by iterating through all other network variables/nodes, changing their values,
        and observing how the probability of the target variable changes. Belief propagation
        is used for inference. A forest plot is produced from this and saved to disk.

        Arguments:
            file_path: str, the absolute path to save the file to (e.g. "~/Desktop/forest_plot.png")

        Returns:
            None
        """

        # Estimate CPTs
        self._estimate_CPT()

        if self.verbose:
            print(f"Calculating influence of all nodes on target node")

        if not self.bn_model.check_model():
            print("""
                There is a problem with your network structure. You have disconnected nodes
                or separated sub-networks. Please examine your network plot and re-learn your
                network structure with tweaked settings.
                """)
            return None

        if self.target_variable not in self.bn_model.nodes:
            print("""
                Your target variable has no parent nodes! Can't perform inference! Please examine
                your network plot and re-learn your network structure with tweaked settings.
                """)
            return None

        # Prep for belief propagation
        belief_propagation = BeliefPropagation(self.bn_model)
        belief_propagation.calibrate()

        # Iterate over all intervention nodes and values, calculating odds ratios w.r.t target variable
        overall_dict = {}

        variables_to_test = list(
            set(list(self.bn_model.nodes)) - set(list(self.target_variable)))

        for node in variables_to_test:
            results = []
            for value in self.filtered_df[node].unique():
                prob = belief_propagation.query(
                    variables=[self.target_variable],
                    evidence={
                        node: value
                    },
                    show_progress=False,
                ).values
                results.append([node, value, prob[0], prob[1]])

            results_df = pd.DataFrame(
                results,
                columns=["node", "value", "probability_0", "probability_1"])
            results_df["odds_1"] = (results_df["probability_1"] /
                                    results_df["probability_0"])
            results_df = results_df.sort_values(
                "value", ascending=True, inplace=False).reset_index(drop=True)

            overall_dict[node] = results_df

        final_df_list = []

        for node, temp_df in overall_dict.items():
            first_value = temp_df["odds_1"].iloc[0]
            temp_df["odds_ratio"] = (temp_df["odds_1"] / first_value).round(3)
            final_df_list.append(temp_df)

        final_df = pd.concat(final_df_list)[["node", "value", "odds_ratio"]]
        self.odds_ratios = final_df

        if self.verbose:
            print(f"Saving forest plot to the following PNG file: {file_path}")

        # Clean up the dataframe of odds ratios so plot can have nice labels
        final_df2 = (pd.concat([
            final_df,
            final_df.groupby("node")["value"].apply(
                lambda x: x.shift(-1).iloc[-1]).reset_index(),
        ]).sort_values(by=["node", "value"],
                       ascending=True).reset_index(drop=True))
        final_df2["node"][final_df2["value"].isnull()] = np.nan
        final_df2["value"] = final_df2["value"].astype("Int32").astype(str)
        final_df2["value"].replace({np.nan: ""}, inplace=True)
        final_df3 = final_df2.reset_index(drop=True).reset_index()
        final_df3.rename(columns={"index": "vertical_index"}, inplace=True)
        final_df3["y_label"] = final_df3["node"] + " = " + final_df3["value"]
        final_df3["y_label"][final_df3["odds_ratio"] == 1.0] = (
            final_df3["y_label"] + " (ref)")
        final_df3["y_label"].fillna("", inplace=True)

        # Produce large plot
        plt.clf()
        plt.title(
            "Strength of Associations Between Interventions and Target Variable"
        )
        plt.scatter(
            x=final_df3["odds_ratio"],
            y=final_df3["vertical_index"],
            s=70,
            color="b",
            alpha=0.5,
        )
        plt.xlabel("Odds Ratio")
        plt.axvline(x=1.0, color="red", linewidth="1.5", linestyle="--")
        plt.yticks(final_df3["vertical_index"], final_df3["y_label"])

        for _, row in final_df3.iterrows():
            if not np.isnan(row["odds_ratio"]):
                plt.plot(
                    [0, row["odds_ratio"]],
                    [row["vertical_index"], row["vertical_index"]],
                    color="black",
                    linewidth="0.4",
                )

        plt.xlim([0, final_df3["odds_ratio"].max() + 1])

        figure = plt.gcf()
        figure.set_size_inches(12, 7)

        plt.savefig(expanduser(file_path),
                    bbox_inches="tight",
                    format="PNG",
                    dpi=300)