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)
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
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)
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)
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)
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)