def pgm_generate(self, target, data, stats, subnodes): stats_pd = pd.Series(stats, name='p-values') MK_blanket_frame = stats_pd[stats_pd < 0.05] MK_blanket = [node for node in MK_blanket_frame.index if node in subnodes] subnodes_no_target = [node for node in subnodes if node != target] est = HillClimbSearch(data[subnodes_no_target], scoring_method=BicScore(data)) pgm_no_target = est.estimate() for node in MK_blanket: if node != target: pgm_no_target.add_edge(node,target) # Create the pgm pgm_explanation = BayesianModel() for node in pgm_no_target.nodes(): pgm_explanation.add_node(node) for edge in pgm_no_target.edges(): pgm_explanation.add_edge(edge[0],edge[1]) # Fit the pgm data_ex = data[subnodes].copy() data_ex[target] = data[target].apply(self.generalize_target) for node in subnodes_no_target: data_ex[node] = data[node].apply(self.generalize_others) pgm_explanation.fit(data_ex) return pgm_explanation
def pgm_generate(self, target, data, pgm_stats, subnodes, child=None): subnodes = [str(int(node)) for node in subnodes] target = str(int(target)) subnodes_no_target = [node for node in subnodes if node != target] data.columns = data.columns.astype(str) MK_blanket = self.search_MK(data, target, subnodes_no_target.copy()) if child == None: est = HillClimbSearch(data[subnodes_no_target], scoring_method=BicScore(data)) pgm_no_target = est.estimate() for node in MK_blanket: if node != target: pgm_no_target.add_edge(node, target) # Create the pgm pgm_explanation = BayesianModel() for node in pgm_no_target.nodes(): pgm_explanation.add_node(node) for edge in pgm_no_target.edges(): pgm_explanation.add_edge(edge[0], edge[1]) # Fit the pgm data_ex = data[subnodes].copy() data_ex[target] = data[target].apply(self.generalize_target) for node in subnodes_no_target: data_ex[node] = data[node].apply(self.generalize_others) pgm_explanation.fit(data_ex) else: data_ex = data[subnodes].copy() data_ex[target] = data[target].apply(self.generalize_target) for node in subnodes_no_target: data_ex[node] = data[node].apply(self.generalize_others) est = HillClimbSearch(data_ex, scoring_method=BicScore(data_ex)) pgm_w_target_explanation = est.estimate() # Create the pgm pgm_explanation = BayesianModel() for node in pgm_w_target_explanation.nodes(): pgm_explanation.add_node(node) for edge in pgm_w_target_explanation.edges(): pgm_explanation.add_edge(edge[0], edge[1]) # Fit the pgm data_ex = data[subnodes].copy() data_ex[target] = data[target].apply(self.generalize_target) for node in subnodes_no_target: data_ex[node] = data[node].apply(self.generalize_others) pgm_explanation.fit(data_ex) return pgm_explanation
def pgmpy_test(): raw_data = np.array([0] * 30 + [1] * 70) # Representing heads by 0 and tails by 1 data = pd.DataFrame(raw_data, columns=['coin']) print(data) model = BayesianModel() model.add_node('coin') # Fitting the data to the model using Maximum Likelihood Estimator model.fit(data, estimator=MaximumLikelihoodEstimator) print(model.get_cpds('coin'))
def make_power_plant_net(): BayesNet = BayesianModel() BayesNet.add_node('temperature') BayesNet.add_node('faulty gauge') BayesNet.add_node('gauge') BayesNet.add_node('faulty alarm') BayesNet.add_node('alarm') BayesNet.add_edge('temperature', 'faulty gauge') BayesNet.add_edge('temperature', 'gauge') BayesNet.add_edge('faulty gauge', 'gauge') BayesNet.add_edge('gauge', 'alarm') BayesNet.add_edge('faulty alarm', 'alarm') return BayesNet
def get_game_network(): """Create a Bayes Net representation of the game problem. Name the nodes as "A","B","C","AvB","BvC" and "CvA". """ BayesNet = BayesianModel() # TODO: fill this out BayesNet.add_node("A") BayesNet.add_node("B") BayesNet.add_node("C") BayesNet.add_node("AvB") BayesNet.add_node("BvC") BayesNet.add_node("CvA") BayesNet.add_edge("A","AvB") BayesNet.add_edge("A","CvA") BayesNet.add_edge("B","AvB") BayesNet.add_edge("B","BvC") BayesNet.add_edge("C","BvC") BayesNet.add_edge("C","CvA") cpd_a = TabularCPD('A', 4, values=[[0.15], [0.45],[0.3],[0.1]]) cpd_b = TabularCPD('B', 4, values=[[0.15], [0.45],[0.3],[0.1]]) cpd_c = TabularCPD('C', 4, values=[[0.15], [0.45],[0.3],[0.1]]) cpd_avb=TabularCPD("AvB",3, values=[[0.1,0.2,0.15,0.05,0.6,0.1,0.2,0.15,0.75,0.6,0.1,0.2,0.9,0.75,0.6,0.1],\ [0.1,0.6,0.75,0.9,0.2,0.1,0.6,0.75,0.15,0.2,0.1,0.6,0.05,0.15,0.2,0.1],\ [0.8,0.2,0.1,0.05,0.2,0.8,0.2,0.1,0.1,0.2,0.8,0.2,0.05,0.1,0.2,0.8]],\ evidence=["A","B"], evidence_card=[4, 4]) cpd_bvc=TabularCPD("BvC",3, values=[[0.1,0.2,0.15,0.05,0.6,0.1,0.2,0.15,0.75,0.6,0.1,0.2,0.9,0.75,0.6,0.1],\ [0.1,0.6,0.75,0.9,0.2,0.1,0.6,0.75,0.15,0.2,0.1,0.6,0.05,0.15,0.2,0.1],\ [0.8,0.2,0.1,0.05,0.2,0.8,0.2,0.1,0.1,0.2,0.8,0.2,0.05,0.1,0.2,0.8]],\ evidence=["B","C"], evidence_card=[4, 4]) cpd_cva=TabularCPD("CvA",3, values=[[0.1,0.2,0.15,0.05,0.6,0.1,0.2,0.15,0.75,0.6,0.1,0.2,0.9,0.75,0.6,0.1],\ [0.1,0.6,0.75,0.9,0.2,0.1,0.6,0.75,0.15,0.2,0.1,0.6,0.05,0.15,0.2,0.1],\ [0.8,0.2,0.1,0.05,0.2,0.8,0.2,0.1,0.1,0.2,0.8,0.2,0.05,0.1,0.2,0.8]],\ evidence=["C","A"], evidence_card=[4, 4]) BayesNet.add_cpds(cpd_a,cpd_b,cpd_c,cpd_avb,cpd_bvc,cpd_cva) return BayesNet
def get_game_network(): """Create a Bayes Net representation of the game problem. Name the nodes as "A","B","C","AvB","BvC" and "CvA". """ BayesNet = BayesianModel() # TODO: fill this out BayesNet.add_node("A") BayesNet.add_node("B") BayesNet.add_node("C") BayesNet.add_node("AvB") BayesNet.add_node("BvC") BayesNet.add_node("CvA") BayesNet.add_edge("A", "AvB") BayesNet.add_edge("A", "CvA") BayesNet.add_edge("B", "AvB") BayesNet.add_edge("B", "BvC") BayesNet.add_edge("C", "BvC") BayesNet.add_edge("C", "CvA") skill_dist = [[0.15], [0.45], [0.30], [0.10]] a_cpd = TabularCPD("A", 4, values=skill_dist) b_cpd = TabularCPD("B", 4, values=skill_dist) c_cpd = TabularCPD("C", 4, values=skill_dist) game_dist = [[ 0.1, 0.2, 0.15, 0.05, 0.6, 0.1, 0.2, 0.15, 0.75, 0.6, 0.1, 0.2, 0.9, 0.75, 0.6, 0.1 ], [ 0.1, 0.6, 0.75, 0.9, 0.2, 0.1, 0.6, 0.75, 0.15, 0.2, 0.1, 0.6, 0.05, 0.15, 0.2, 0.1 ], [ 0.8, 0.2, 0.1, 0.05, 0.2, 0.8, 0.2, 0.1, 0.1, 0.2, 0.8, 0.2, 0.05, 0.1, 0.2, 0.8 ]] # avb_cpd = TabularCPD("AvB", 3, values=game_dist, evidence=["A", "B"], evidence_card=[4, 4]) avb_cpd = TabularCPD("AvB", 3, values=game_dist, evidence=["A", "B"], evidence_card=[4, 4]) bvc_cpd = TabularCPD("BvC", 3, values=game_dist, evidence=["B", "C"], evidence_card=[4, 4]) cva_cpd = TabularCPD("CvA", 3, values=game_dist, evidence=["C", "A"], evidence_card=[4, 4]) BayesNet.add_cpds(a_cpd, b_cpd, c_cpd, avb_cpd, bvc_cpd, cva_cpd) return BayesNet
def make_power_plant_net(): """Create a Bayes Net representation of the above power plant problem. Use the following as the name attribute: "alarm","faulty alarm", "gauge","faulty gauge", "temperature". (for the tests to work.) """ BayesNet = BayesianModel() # TODO: finish this function BayesNet.add_node("alarm") BayesNet.add_node("faulty alarm") BayesNet.add_node("gauge") BayesNet.add_node("faulty gauge") BayesNet.add_node("temperature") BayesNet.add_edge("gauge","alarm") BayesNet.add_edge("temperature","gauge") BayesNet.add_edge("temperature","faulty gauge") BayesNet.add_edge("faulty gauge","gauge") BayesNet.add_edge("faulty alarm","alarm") return BayesNet
def join(reference_bayes, second_bayes, new_dependent_vars, new_independent_vars, ref_num_of_records, second_num_of_records): final_bayes = BayesianModel() #all independent variables should stay the same final_bayes.add_nodes_from(new_independent_vars) final_bayes.add_cpds(*[ reference_bayes.get_cpds(node=node) if node in reference_bayes.nodes else second_bayes.get_cpds(node=node) for node in new_independent_vars ]) for node in new_dependent_vars: final_bayes.add_node(node) ref_parents = set() second_parents = set() if node in reference_bayes: ref_parents = set(reference_bayes.get_parents(node)) if node in second_bayes: second_parents = set(second_bayes.get_parents(node)) if (len(ref_parents) == 0): final_bayes.add_edges_from([(parent, node) for parent in second_parents]) final_bayes.add_cpds(second_bayes.get_cpds(node=node)) else: final_bayes.add_edges_from([(parent, node) for parent in ref_parents]) if len(second_parents - ref_parents) > 0: raise ValueError('This join can not be performed since the\ second distribution contains new independent variable\ (s) for node {}. Please consider dropping these new \ dependencies or switching reference distribution. '. format(str(node))) elif ref_parents == second_parents: new_cpd = BayesNetHelper.calculate_weighted_cpds( reference_bayes.get_cpds(node=node), second_bayes.get_cpds(node=node), ref_num_of_records, second_num_of_records) final_bayes.add_cpds(new_cpd) else: final_bayes.add_cpds(reference_bayes.get_cpds(node=node)) return final_bayes
class InferenceEngine: def load_file(self, path): self.data = pd.read_excel(path) self.variables = list(self.data.columns) self.model = BayesianModel() for var in self.variables: self.model.add_node(var) self.model.fit(self.data, estimator=BayesianEstimator) def load_model(self, model): self.data = pd.read_json(model['dataset']) self.variables = list(self.data.columns) self.model = BayesianModel(model['modelStructure']) self.model.fit(self.data, estimator=BayesianEstimator) def load_structure(self, model_structure): self.model = BayesianModel(model_structure) self.model.fit(self.data, estimator=BayesianEstimator) def query(self, variables, evidence): bp = VariableElimination(self.model) return bp.query(variables, evidence=evidence)
def make_power_plant_net(): BayesNet = BayesianModel() # TODO: finish this function BayesNet.add_node("A") BayesNet.add_node("B") BayesNet.add_node("C") BayesNet.add_node("D") BayesNet.add_node("E") BayesNet.add_node("F") BayesNet.add_node("J") BayesNet.add_edge("A", "C") BayesNet.add_edge("B", "C") BayesNet.add_edge("C", "D") BayesNet.add_edge("C", "E") BayesNet.add_edge("E", "J") BayesNet.add_edge("F", "J") return BayesNet
def get_structure(data): """ Structure of model from data (Loaded RDS) Parameters ---------- data : RDS data object model : BayesianModel Empty network Returns ------- model : BayesianModel Model converted from RDS to python """ model = BayesianModel() for k in range(len(data)): node = list(data[k][0])[0] children = list(data[k][2]) model.add_node(node) for child in children: model.add_edge(node, child) return model
def make_power_plant_net(): BayesNet = BayesianModel() # TODO: finish this function BayesNet.add_node("NI") BayesNet.add_node("St") BayesNet.add_node("I") BayesNet.add_node("S") BayesNet.add_node("T") BayesNet.add_node("L") BayesNet.add_node("B") BayesNet.add_edge("NI", "I") BayesNet.add_edge("St", "I") #BayesNet.add_edge("I","S") BayesNet.add_edge("I", "T") BayesNet.add_edge("I", "L") BayesNet.add_edge("S", "L") BayesNet.add_edge("S", "B") return BayesNet
class Utilities(object): def __init__(self, file): ''' no object creation -> opportune ?''' self.keywords = ['BENS', 'MEMS', 'LANS', 'MOTOR', 'WORLD'] self.standard_nodes = { 'RONS': { 'BENS': [], 'MEMS': [] }, 'LANS': { 'LANS': [] }, 'LENS': { 'MOTOR': [], 'WORLD': [] } } self.file = file self.get_json_path(file) self.pgmpy_object = BayesianModel() self.networkx_object = nx.DiGraph() self.header = '' self.dictionary = [] def get_nodes_in_family(self, family, attributes=False): nw_nodes = self.networkx_object.nodes() nw_dim = np.asarray(nw_nodes).ndim nodes = [] for i, node in enumerate(nw_nodes): if nw_dim > 1: node = node[0] if family in node: nodes.append(node) return nodes def check_json_path(directory): """ Checks whether the necessary project_repository directory exists. If not, creates it :param directory: the mother directory to search from downwards :type directory: string :rtype : none """ if not os.path.exists(directory + '\project_repository\\'): os.makedirs(directory + '\project_repository\\') def get_json_path(self, file): """ Creates a string containing the full path for the filename passed so it will be saved in the project_repository directory :param filename: filename without path or extension :return: a full path for the file :type filename :string :rtype : string """ levels = 5 common = os.path.dirname(os.path.realpath(__file__)) for i in range(levels + 1): common = os.path.dirname(common) if 'peepo\peepo' not in common: break Utilities.check_json_path(common) self.file = str(common + '\project_repository\\' + file + '.json') print('in get_json_path :', self.file) def save_json(self, astring): """ This helping function is only needed to have the json file formatted in a user friendly way as the "dump" method does not provide a lot of possibilities to get it "pretty" :param file :the ull path of the json file :param astring: the name of the string containing the whole information :return: void :type file: string :type astring : string :rtype : void """ text_file = open(str(self.file), "w") '''remove all LF written by the dump method''' astring = re.sub('\n', '', astring) '''For keywords -> insert LF and tabs''' astring = re.sub('\"Identification', '\n\"Identification', astring) astring = re.sub('\"Date', '\n\"Date', astring) astring = re.sub('\"Description', '\n\"Description', astring) astring = re.sub('\"Train_from', '\n\"Train_from', astring) astring = re.sub('\"Frozen', '\n\"Frozen', astring) astring = re.sub('\"Nodes', '\n\n\"Nodes', astring) astring = re.sub('\"RONS', '\n\t\t\"RONS', astring) astring = re.sub('\"BENS', '\n\t\t\t\"BENS', astring) astring = re.sub('\"MEMS', '\n\t\t\t\"MEMS', astring) astring = re.sub('\"LANS', '\n\t\t\"LANS', astring) astring = re.sub('\"LENS', '\n\t\t\"LENS', astring) astring = re.sub('\"MOTOR', '\n\t\t\t\"MOTOR', astring) astring = re.sub('\"WORLD', '\n\t\t\t\"WORLD', astring) astring = re.sub('\"Edges', '\n\n\"Edges', astring) astring = re.sub('\"CPDs', '\n\n\"CPDs', astring) astring = re.sub('{', '\n\t\t{', astring) text_file.write(astring) text_file.write('\n') text_file.close() def translation(self, astring, from_man_to_machine): """ Given an array of tuples (a,b) in dictionary, returns the second element of the tuple where astring was found Is used to not loose the users node names as peepo generates standardized names for the corresponding node :param dictionary:an array of tuples -> is created in the method : get_network(file) :param astring: the name of the node passsed by the user :param from_man_to_machine: an integer -> 0 when we want the translation for the user give name to the standardized name, 1 the other way around :return: the corresponding standardized node name :type dictionary: np.array :type astring : string :rtype : string """ source = 0 target = 1 if from_man_to_machine == 1: source = 1 target = 0 for index, item in enumerate(self.dictionary): if item[source] == astring: break return item[target] def clean_edge_list(self, edge_array, parent): '''the get functions for the edges, both in networx as pgmpy contain the parent name this function removes it from the list''' cleaned_list = [] for a in edge_array: if a != parent: cleaned_list.append(a) return cleaned_list def clean_parent_list(self, parent_array, child): '''the get functions for the edges, both in networx as pgmpy contain the parent name this function removes it from the list''' cleaned_list = [] for i, a in enumerate(parent_array): if a[0] != child: cleaned_list.append(a[0]) return cleaned_list def get_edges(self): """ Creates a dictionary with a node as a key and an array with its child as value (the methods get_child give generally a list of tuples (parent,child) :param pgmpy_object: the pgmpy network :return: a dictionary with the edges of all the node :type fpgmpy_object:adress :rtype :dictionary """ edg = self.pgmpy_object.edges() edges = dict() [ edges[str(t[0])].append(str(t[1])) if t[0] in list(edges.keys()) else edges.update({str(t[0]): [str(t[1])]}) for t in edg ] return edges def get_nodes_and_attributes(self): """ Creates an array of tuple with a node as element 0 and a dictionary with cardinalities and cpd as key's and the key cardinality returns an int the key cpd a 2 dimensional matrix :param pgmpy_object: the pgmpy network :return: array of tuple with a node as element 0 and a dictionary with cardinalities and cpd as key's :type :pgmpy_object:adress :rtype :array of tuples """ nodes = self.pgmpy_object.nodes() nod_and_attributes = [] [ nod_and_attributes.append((str(node), { 'cardinality': int(self.pgmpy_object.get_cardinality(node)), 'cpd': self.pgmpy_object.get_cpds(node).values.astype(float) })) for i, node in enumerate(nodes) ] #need to reshape the cpds when more than 1 parent for i, node in enumerate(nod_and_attributes): shape = nod_and_attributes[i][1]['cpd'].shape dimension = nod_and_attributes[i][1]['cpd'].ndim if dimension > 2: col = int(np.prod(shape) / shape[0]) nod_and_attributes[i][1]['cpd'] = nod_and_attributes[i][1][ 'cpd'].reshape(shape[0], col) nod_and_attributes[i][1]['cpd'] = nod_and_attributes[i][1][ 'cpd'].tolist() return nod_and_attributes def translate_pgmpy_to_digraph(self): """ Converts a pgmpy network into a networkx network :param pgmpy_object: the pgmpy network :return networkx : networkx network :type :pgmpy_object:adress :rtype :networkx:adress """ self.networkx_object = nx.DiGraph() edges = self.pgmpy_object.edges() nodes_and_attributes = self.get_nodes_and_attributes() self.networkx_object.add_nodes_from(nodes_and_attributes) self.networkx_object.add_edges_from(edges) return def update_networkx(self, networkx, dic, header): self.header = header self.dictionary = dic self.networkx_object = networkx def update_pgmpy(self, pgmpy, dic, header): self.header = header self.dictionary = dic self.pgmpy_object = pgmpy def save_pgmpy_network(self): """ Saves the passed pgmpy_object class object in a json file """ self.translate_pgmpy_to_digraph() self.save_network() return def translate_digraph_to_pgmpy(self, digraf): """ Converts a pgmpy network into a networkx network :param pgmpy_object: the pgmpy network :return networkx : networkx network :type :pgmpy_object:adress :rtype :networkx:adress """ self.pgmpy_object, x, y = self.get_pgmpy_network(from_object=True, digraph=digraf) return self.pgmpy_object def translate_pgmpy_to_digraph(self): """ Converts a pgmpy network into a networkx network :param pgmpy_object: the pgmpy network :return networkx : networkx network :type :pgmpy_object:adress :rtype :networkx:adress """ self.networkx_object = nx.DiGraph() edges = self.pgmpy_object.edges() nodes_and_attributes = self.get_nodes_and_attributes() self.networkx_object.add_nodes_from(nodes_and_attributes) self.networkx_object.add_edges_from(edges) return def save_network(self): """ Saves the passed networkx class object in a json file """ data = self.get_empty_canvas() data["header"] = self.header nw_nodes = self.networkx_object.nodes(data=True) nw_edges = self.networkx_object.edges() keywords = self.keywords nodes = copy.deepcopy( self.standard_nodes ) #{'RONS': {'BENS': [], 'MEMS': []}, 'LANS': {'LANS': []}, 'LENS': {'MOTOR': [], 'WORLD': []}} edges = [] cpds = [] '''adding edges''' for i, node in enumerate(nw_nodes): node_name = node[0] childs = [] for k, edge in enumerate(nw_edges): if edge[0] == node_name: childs.append(self.translation(edge[1], 1)) if len(childs) != 0: edges.append({self.translation(node_name, 1): childs}) for i, node in enumerate(nw_nodes): node_name = node[0] cardinality = node[1]['cardinality'] cpd = node[1]['cpd'] for pseudonym in keywords: if pseudonym in node_name: node_name_ = self.translation(node_name, 1) if pseudonym == 'BENS' or pseudonym == 'MEMS': nodes['RONS'][pseudonym].append( [node_name_, cardinality]) if pseudonym == 'LANS': nodes['LANS'][pseudonym].append( [node_name_, cardinality]) if pseudonym == 'MOTOR' or pseudonym == 'WORLD': nodes['LENS'][pseudonym].append( [node_name_, cardinality]) cpds.append({self.translation(node_name, 1): cpd}) data['Nodes'] = nodes data['Edges'] = edges data['CPDs'] = cpds data['header']['Date'] = datetime.datetime.now().strftime("%c") self.save_json(json.dumps(data)) return def get_pgmpy_network(self, from_object=False, digraph=None): """ Reads the passed json file and translates it's content to the passed pgmpy class object - uses the get_network(file) to read the json file in a networkx format and translate this to pgmpy - Creates a dictionary for the nodes in the form of an array of tuples : [(names defines by user, standard name)] :param file: : filename without path or extension :pgmp_object : the pgmpy object which will be completed :return: a dictionary as an array of tuples and the header of the json file :type file : string :type pgmp_object : pgmpy class object :rtype : array of tuples, dictionary CAUTION : the method does not perform a check() on the constructed DAG ! -> has to be done in the calling module """ self.pgmpy_object = BayesianModel() if not (from_object): network, dictionary, header = self.get_network() else: network = digraph nw_nodes = network.nodes(data=True) nw_edges = network.edges() '''adding nnodes and edges''' for i, node in enumerate(nw_nodes): node_name = node[0] self.pgmpy_object.add_node(node_name) for k, edge in enumerate(nw_edges): if edge[0] == node_name: self.pgmpy_object.add_edge(node_name, edge[1]) '''add cpd's''' for i, node in enumerate(nw_nodes): parent_nodes = network.in_edges(node[0]) parent_nodes = self.clean_parent_list(parent_nodes, node[0]) cpd = node[1]['cpd'] ''' find the cardinality of the node ''' cardinality_node = node[1]['cardinality'] """ cardinality card of parents has to be determined""" cardinality_parents = [] for i, nod in enumerate(parent_nodes): cardinality_parents.append(network.node[nod]['cardinality']) ''' Depending on the place in the BN and/or the number of parents the PGMPY CPD methods have another call''' if len(cardinality_parents) == 0: self.pgmpy_object.add_cpds( TabularCPD(variable=node[0], variable_card=cardinality_node, values=[cpd])) continue table = TabularCPD(variable=node[0], variable_card= cardinality_node, values=cpd, \ evidence=parent_nodes,\ evidence_card=np.asarray(cardinality_parents)) self.pgmpy_object.add_cpds(table) '''------TO DELETE-------------''' # pgmpy_object.check_model() # draw_network(pgmpy_object) '''-----------------------------''' return self.pgmpy_object, self.dictionary, self.header def get_network(self): """ Reads the passed json file and translate it's content in a networkx class object - The nodes in the object are renamed so they have a standardized signature - Creates a dictionary for the nodes in the form of an array of tuples : [(names defines by user, standard name)] :param file: : filename without path or extension :return: a networkx class object, dictionary as an array of tuples and the header of the json file :type file : string :rtype : networkx class object, array of tuples, dictionary """ self.dictionary = [] self.networkx_object = nx.DiGraph() with open(self.file) as f: data = f.read() '''Remove possible non informative characters''' data = re.sub('\n', '', data) data = re.sub('\t', '', data) data = json.loads(data) self.header = data['header'] '''Feeding G with the nodes''' cardinality = {} for key in data['Nodes'].keys(): for secondkey in data['Nodes'][key].keys(): for c, n in enumerate(data['Nodes'][key][secondkey]): node = secondkey + "_" + str(c) self.networkx_object.add_node(node, { 'cardinality': n[1], 'cpd': [] }) self.dictionary.append((n[0], node)) cardinality.update( {node: n[1]} ) #this contains the cardinality of each node with the node name as dictionary entry '''Feeding G with the edges''' edges = [] for j, pair in enumerate(data['Edges']): for parent in pair.keys(): for child in data['Edges'][j][parent]: parent_ = self.translation(parent, 0) child_ = self.translation(child, 0) edges.append((parent_, child_)) np.ravel(edges) self.networkx_object.add_edges_from(edges) '''Feeding G with the CPD's as nodes attributes''' for j, node in enumerate(data['CPDs']): for parent, cpd in node.items(): node_ = self.translation(parent, 0) self.networkx_object.node[node_]['cpd'] = cpd '''TO REMOVE LATER''' # plt.figure(figsize=(10, 5)) # pos = nx.circular_layout(G, scale=2) # node_labels = nx.get_node_attributes(G, 'cpd') # nx.draw(G, pos, node_size=1200, node_color='lightblue', # linewidths=0.25, font_size=10, font_weight='bold', with_labels=True) # plt.show() return self.networkx_object, self.dictionary, self.header def create_json_file(self, **kwargs): """ EWAMPLE : A helping method if the user prefers to create the BN within the code :param case_name: the file name without path or extension where the json file will be saved :param : **kwargs takes the following variables: description = kwargs.get('description', '') train_from = kwargs.get('train_from', '') cpds = kwargs.get('CPDs', []) bens = kwargs.get('BENS',[]) mems = kwargs.get('MEMS', []) lans = kwargs.get('LANS', []) motors = kwargs.get('MOTORS', []) world = kwargs.get('WORLD', []) edges = kwargs.get('Edges', []) frozen = kwargs.get('frozen',False) . . . :return: void :type case_name : string :type : . . . :rtype : void """ description = kwargs.get('description', '') train_from = kwargs.get('train_from', '') cpds = kwargs.get('CPDs', []) bens = kwargs.get('BENS', []) mems = kwargs.get('MEMS', []) lans = kwargs.get('LANS', []) motors = kwargs.get('MOTORS', []) world = kwargs.get('WORLD', []) edges = kwargs.get('Edges', []) frozen = kwargs.get('frozen', False) #json_tab_file_write = JSONTabIndentFileWriter( Case_name,5a) data = self.get_empty_canvas() ''' - the 3 next items are for tracking purpose only, not fundamentally necessary''' data["header"]['Identification'] = self.file data["header"]['Date'] = datetime.datetime.now().strftime("%c") data["header"]['Description'] = description ''' - the next item gives a file containing possible training data (OPTIONAL)''' data["header"]['Train_from'] = train_from ''' Frozen tells whether or not the model can be considered as final i.e. is there still "training" needed''' data["header"]['Frozen'] = frozen ''' - the 5 next lines tells how much nodes and their names + cardinality the model will start with the names can be any valid python string''' bens = [['pooping', 2], ['peeing', 2], ['constipated', 2]] mems = [['havenotoiletpaper', 2]] lans = [['diarhea', 2], ['happypoop', 2]] motors = [['asshole1', 2], ['asshole2', 2]] world = [['toilet1', 2], ['toilet2', 2], ['garden1', 2], ['garden2', 2], ['doctor', 2]] ''' - the next items describe the edges as a dictionary -> the dictionary entry is always one of the rootnodes, the array following can only contain LANs or LENs''' edges = [] ''' !! in case we start from scratch and we rely on peepo to find the best BN -> leave this array empty''' edges.append({'pooping': ['toilet1', 'diarhea', 'happypoop']}) edges.append({'peeing': ['toilet2', 'garden1', 'garden2']}) edges.append({'constipated': ['doctor']}) edges.append({'havenotoiletpaper': ['garden1', 'garden2']}) edges.append( {'diarhea': ['toilet1', 'doctor', 'asshole1', 'asshole2']}) edges.append( {'happypoop': ['garden1', 'garden2', 'asshole1', 'asshole2']}) ''' - the next items describe the CPD's as a dictionary -> the dictionary entry is the corresponding node''' cpds = [] cpds.append({'pooping': [0.5, 0.5]}) cpds.append({'peeing': [0.2, 0.8]}) cpds.append({'constipated': [0.9, 0.1]}) cpds.append({'havenotoiletpaper': [0.6, 0.4]}) cpds.append({'happypoop': [[0.3, 0.8], [0.7, 0.2]]}) cpds.append({'diarhea': [[0.8, 0.3], [0.2, 0.7]]}) cpds.append({'toilet1': [[0.3, 0.8, 0.8, 0.7], [0.7, 0.2, 0.2, 0.3]]}) cpds.append({'asshole1': [[0.3, 0.8, 0.8, 0.7], [0.7, 0.2, 0.2, 0.3]]}) cpds.append({'asshole2': [[0.3, 0.8, 0.8, 0.7], [0.7, 0.2, 0.2, 0.3]]}) cpds.append({'toilet2': [[0.5, 0.5], [0.5, 0.5]]}) cpds.append({'doctor': [[0.3, 0.8, 0.8, 0.7], [0.7, 0.2, 0.2, 0.3]]}) cpds.append({ 'garden1': [[0.3, 0.8, 0.8, 0.7, 0.8, 0.2, 0.5, 0.5], [0.7, 0.2, 0.2, 0.3, 0.2, 0.8, 0.5, 0.5]] }) cpds.append({ 'garden2': [[0.3, 0.8, 0.8, 0.7, 0.8, 0.2, 0.5, 0.5], [0.7, 0.2, 0.2, 0.3, 0.2, 0.8, 0.5, 0.5]] }) ''' - feeding the data''' data["Nodes"]['RONS']['BENS'] = bens data["Nodes"]['RONS']['MEMS'] = mems data["Nodes"]['LANS']['LANS'] = lans data["Nodes"]['LENS']['MOTOR'] = motors data["Nodes"]['LENS']['WORLD'] = world data["Edges"] = edges data["CPDs"] = cpds ''' dumping to CASENAME file in jason format''' self.save_json(json.dumps(data)) print("Json file for - ", self.file, " - created") def create_json_template(self): """ A helping method if the jason template in the project_repository ditectory has been deleted or corrupted :param : void :return: void :type : void :rtype : void """ self.get_json_path( "Template" ) # creates the right path in which case_name will be saved data = self.get_empty_canvas() data['header']['Identification'] = self.file '''Filling some dummies to facilitate the user''' a_node = ['*', 0] an_edge = {'*': ['&', '&', '&']} a_cpd = {'*': [[0, 0, 0], [0, 0, 0]]} nodes = [] edges = [] cpds = [] for i in range(0, 3): nodes.append(a_node) edges.append(an_edge) cpds.append(a_cpd) data['Nodes']['RONS']['BENS'] = nodes data['Nodes']['RONS']['MEMS'] = nodes data['Nodes']['LANS']['LANS'] = nodes data['Nodes']['LENS']['MOTOR'] = nodes data['Nodes']['LENS']['WORLD'] = nodes data['Edges'] = edges data['CPDs'] = cpds ''' dumping to CASENAME file in jason format''' # with open(case_name, 'w') as f: # json.dump(data, f, separators = (",",":")) self.save_json(json.dumps(data)) print("Empty template created") def get_empty_canvas(self): """ This method creates a json canvas which will be used for the several json creating method :param : void :return: a dictionary with the structure of the json file :type : non :rtype : dictionary """ data = { 'header': { 'Identification': '', 'Date': '', 'Description': '', 'Frozen': '', 'Train_from': '' }, 'Nodes': {}, 'Edges': [], 'CPDs': [] } ''' - the 5 next lines tells how much nodes and their names the model will start with the names can be any valid python string''' bens = [] mems = [] lans = [] motors = [] world = [] ''' - the next items describe the edges as a dictionary -> the dictionary entry is always one of the rootnodes, the array following can only contain LANs or LENs !! in case we start from scratch and we rely on peepo to find the best BN -> leave this array empty''' edges = [] ''' - the next items describe the CPD's as a dictionary -> the dictionary entry is the corresponding node''' cpds = [] ''' - feeding the data''' data['Nodes'] = { 'RONS': { 'BENS': bens, 'MEMS': mems }, 'LANS': { 'LANS': lans }, 'LENS': { 'MOTOR': motors, 'WORLD': world } } data['Edges'] = edges data['CPDs'] = cpds return data
# -*- coding: utf-8 -*- """ Created on Wed Jan 13 20:42:38 2021 @author: zhang """ from pgmpy.models import BayesianModel from pgmpy.factors.discrete import TabularCPD from pgmpy.inference import VariableElimination bayesNet = BayesianModel() bayesNet.add_node("S1") bayesNet.add_node("S2") bayesNet.add_node("S2") bayesNet.add_node("S") bayesNet.add_edge("S1", "S") bayesNet.add_edge("S2", "S") bayesNet.add_edge("S3", "S") cpd_household = TabularCPD('S1', 3, values=[[.13], [.32], [.55]]) cpd_hdbcarp = TabularCPD('S2', 3, values=[[.25], [.28], [.46]]) cpd_publicarp = TabularCPD('S3', 3, values=[[.15], [.38], [.47]]) cpd_society = TabularCPD('S', 3, values=[[ 1, 0.99, 0.95, 0.8, 0.54, 0.56, 0.7, 0.6, 0.52, 0.7, 0.45, 0.1, 0.1, 0.1, 0.12, 0.19, 0.12, 0.18, 0.4, 0.22, 0.12, 0.1, 0.02, 0.02, 0.03, 0.01, 0
# Add all the CPDs to the network # (model is the network object which has references/pointers to all the CPDs, nodes, etc) model.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l) # Check model is done to verify that the network is consistent (i.e. CPD values sum to 1 etc.) model.check_model() # Perform some inference queries using Variable Elimination (this is an exact inference algorithm, we will need # to investigate whether an approximate inference algorithm is possible. I haven't found one yet in the library) infer = VariableElimination(model) print(infer.query(['G'])['G']) """ FROM HERE START CHANGING THE NETWORK WE'RE ADDING ONE NODE S WITH AN EDGE COMING FROM I """ model.add_node('S') model.add_edge('I', 'S') cpd_s = TabularCPD(variable='S', variable_card=2, values=[[0.95, 0.2], [0.05, 0.8]], evidence=['I'], evidence_card=[2]) model.add_cpds(cpd_s) model.check_model() infer = VariableElimination(model) print("========== NEW INFERENCE ============") print(infer.query(['G'])['G']) print(infer.query(['S'])['S'])
plt.title('ROC curve') plt.legend(loc="lower right") ############################################### # Incorporate uncertainty to random variables # ############################################### # convert to Markov network (undirected graph) # model = model.to_markov_model() # can not be a factor graph since not all random variables are connected to factors # # model = model.to_factor_graph() # print(model.check_model()) # add the new received variable and connect # model.add_node('doors_received') model.add_node('persons_received') model.add_node('lug_boot_received') model.add_node('maint_received') model.add_node('safety_received') model.add_node('buying_received') model.add_edges_from([('persons', 'persons_received'), ('doors', 'doors_received'), ('buying', 'buying_received'), ('safety', 'safety_received'), ('maint', 'maint_received'), ('lug_boot', 'lug_boot_received')]) # binary symmetric channel noise # n = 4 cpd1 = []
class BNPlayer2(Player): def __init__(self, character, start_location, players_n): super().__init__(character, start_location) self.model = None self.my_index = CHARACTERS.index(character) # I'm player number - # dictionaries name: cpd self.weapons_cpds = dict() self.room_cpds = dict() self.character_cpds = dict() # accusation material self.murder_char = None self.murder_weapon = None self.murder_room = None self.murder_card_ind = players_n # is the number of players self.card_vals_range = self.murder_card_ind + 1 # The last is Murder-card def update_on_other_player_suggestion(self, suggestion, was_showed, responders): if not self.model: self.create_model() parents = [suggestion[0].name, suggestion[1].name, suggestion[2].name] # For players that didn't answer update that they answered False (0) on the triplet players_didnt_answer = responders[:-1] for p in players_didnt_answer: name, cpd = self.three_cards_q(parents[0], parents[1], parents[2], CHARACTERS.index(p)) self.update_p_of_parents_given_child(parents, name, 0) self.model.remove_node(name) if was_showed: # For player that showed card update that one of them may be his player_answered = responders[-1] name, cpd = self.three_cards_q(parents[0], parents[1], parents[2], CHARACTERS.index(player_answered)) self.update_p_of_parents_given_child(parents, name, 1) self.model.remove_node(name) def see_card(self, responders, card=None): # If card wasn't shown - it's the result if not card: self.murder_char, self.murder_weapon, self.murder_room = self._last_suggestion return parents = [ self._last_suggestion[0].name, self._last_suggestion[1].name, self._last_suggestion[2].name ] # For players that didn't answer update that they answered False (0) on the triplet players_didnt_answer = responders[:-1] for p in players_didnt_answer: name, cpd = self.three_cards_q(parents[0], parents[1], parents[2], CHARACTERS.index(p)) self.update_p_of_parents_given_child(parents, name, 0) self.model.remove_node(name) # For player that showed card update player-exactly-this-card player_answered = responders[-1] name = card.name + "P" + str(CHARACTERS.index(player_answered)) self.update_p_of_parents_given_child([card], name, 1) def make_move_suggestion(self, possible_locations): if not self.model: self.create_model() # weapon is assumed murder weapon, otherwise - high % one weapon = self.murder_weapon if self.murder_weapon else Weapon[ self.most_probable_murder_card(self.weapons_cpds)[0]] # character is assumed culprit, otherwise - high % one character = self.murder_char if self.murder_char else Character[ self.most_probable_murder_card(self.character_cpds)[0]] # weapon is assumed murder weapon, otherwise - None if all are unreachable and room.name if reachable if self.murder_room: room = self.murder_room if LOCATIONS_OF_ROOMS[room] in possible_locations: self._last_suggestion = (character, weapon, room) return LOCATIONS_OF_ROOMS[room], self._last_suggestion probable_rooms = self.most_probable_murder_card(self.room_cpds) room = None for p_room in probable_rooms: if LOCATIONS_OF_ROOMS[Room[p_room]] in possible_locations: room = Room[p_room] break if room is None: # all probable rooms are unreachable, move towards highest P room self._last_suggestion = None return find_location_closest_to_m_room(possible_locations, probable_rooms[0]), None self._last_suggestion = (character, weapon, room) return LOCATIONS_OF_ROOMS[room], self._last_suggestion def most_probable_murder_card(self, cpds): """ Goes through all cards, checks the probability of it being the secret murder card. Sorts from higher to lower probability. :param cpds: Conditional Probability Distribution tables (and their names) to get probability from. :return: sorted list of probable murder cards (excludes impossibles (P = 0)). """ card_prob_dict = dict() for name in cpds: card_prob_dict[name] = cpds[name].values[self.murder_card_ind] card_prob_dict = { k: v for k, v in sorted( card_prob_dict.items(), key=lambda item: item[1], reverse=True) } # use this to print current probabilities distribution # print(card_prob_dict) ordered_l = [v for v in card_prob_dict if card_prob_dict[v] != 0] # what was returned before if card_prob_dict[ordered_l[0]] >= 0.97 or len( ordered_l) == 1: # probability for accusation if ordered_l[0] in Room.__members__: self.murder_room = Room[ordered_l[0]] elif ordered_l[0] in Character.__members__: self.murder_char = Character[ordered_l[0]] else: self.murder_weapon = Weapon[ordered_l[0]] return ordered_l def make_accusation(self): if self.murder_char and self.murder_weapon and self.murder_room: return self.murder_char, self.murder_weapon, self.murder_room return None def create_model(self): """ Create Dynamic Bayesian Model of the game (updated and changed during the gamerun) """ self.model = BayesianModel() # Create weapons self.model_group(util.WEAPONS, self.weapons_cpds) # Create rooms self.model_group(util.ROOMS, self.room_cpds) # Create chars self.model_group(util.CHARACTERS, self.character_cpds) # Answer one card one player self.exact_card_ans_by_player() def exact_card_ans_by_player(self): """ Tables for answers to our question. This update is for a situation where it's known exactly which card was revealed by which player. """ for j in range( self.murder_card_ind): # murder-card can't answer questions for group in [ self.character_cpds, self.weapons_cpds, self.room_cpds ]: for card in group: name = card + "P" + str(j) self.model.add_edge(card, name) has_card_true = [] for value in range(self.card_vals_range): has_card_true.append(1 if value == j else 0) has_card_false = [1 - v for v in has_card_true] tbl = [has_card_false, has_card_true] cpd = TabularCPD(name, 2, tbl, evidence=[card], evidence_card=[self.card_vals_range]) self.model.add_cpds(cpd) def three_cards_q(self, character, weapon, room, player_ind): """ Adds CPDs to our model for a triplet of Char-Weapon-Room that is either answered or not by given player. Probability is True if at least one belongs to the player and False otherwise. :param character: Character card name :param weapon: Weapon card name :param room: Room card name :param player_ind: index of current player :return: name of the created node and added CPD """ name = character + "_" + weapon + "_" + room + "P" + str(player_ind) self.model.add_edge(character, name) self.model.add_edge(weapon, name) self.model.add_edge(room, name) balanced_true = [] for comb in itertools.product(range(self.card_vals_range), repeat=3): if any(comb[i] == player_ind for i in range(len(comb))): balanced_true.append(1) else: balanced_true.append(0) balanced_false = [1 - v for v in balanced_true] tbl = [balanced_false, balanced_true] cpd = TabularCPD(name, 2, tbl, evidence=[character, weapon, room], evidence_card=[self.card_vals_range] * 3) self.model.add_cpds(cpd) return name, cpd def model_group(self, cards, cpd_dic): """ Creates models for a given group of cards. Variable is the name of the card, values are player indexes and one more out of range, that is murder-card. :param cards: Cards of the given group (e.x. weapons cards) :param cpd_dic: dictionary to save the resulting tables """ for card in cards: if card in self._cards: tbl = [[1] if i == self.my_index else [0] for i in range(self.card_vals_range)] else: tbl = [[1 / (self.card_vals_range - 1)] if i != self.my_index else [0] for i in range(self.card_vals_range)] w = TabularCPD(card.name, self.card_vals_range, tbl) cpd_dic[card.name] = w self.model.add_node(card.name) self.model.add_cpds(w) def update_p_of_parents_given_child(self, parents, card_type, value): """ Update probabilities of parents considering that card_type has given value :param parents: :param card_type: :param value: :return: """ # balance variables var_elim = VariableElimination(self.model) for v in parents: if type(v) != str: v = v.name new_vals = var_elim.query(variables=[v], evidence={card_type: value}, show_progress=False) original_vals = self.model.get_cpds(v) original_vals.values = new_vals.values
class TestBayesianModelCPD(unittest.TestCase): def setUp(self): self.G = BayesianModel([('d', 'g'), ('i', 'g'), ('g', 'l'), ('i', 's')]) def test_active_trail_nodes(self): self.assertEqual(sorted(self.G.active_trail_nodes('d')['d']), ['d', 'g', 'l']) self.assertEqual(sorted(self.G.active_trail_nodes('i')['i']), ['g', 'i', 'l', 's']) self.assertEqual(sorted(self.G.active_trail_nodes(['d', 'i'])['d']), ['d', 'g', 'l']) def test_active_trail_nodes_args(self): self.assertEqual( sorted(self.G.active_trail_nodes(['d', 'l'], observed='g')['d']), ['d', 'i', 's']) self.assertEqual( sorted(self.G.active_trail_nodes(['d', 'l'], observed='g')['l']), ['l']) self.assertEqual( sorted(self.G.active_trail_nodes('s', observed=['i', 'l'])['s']), ['s']) self.assertEqual( sorted(self.G.active_trail_nodes('s', observed=['d', 'l'])['s']), ['g', 'i', 's']) def test_is_active_trail_triplets(self): self.assertTrue(self.G.is_active_trail('d', 'l')) self.assertTrue(self.G.is_active_trail('g', 's')) self.assertFalse(self.G.is_active_trail('d', 'i')) self.assertTrue(self.G.is_active_trail('d', 'i', observed='g')) self.assertFalse(self.G.is_active_trail('d', 'l', observed='g')) self.assertFalse(self.G.is_active_trail('i', 'l', observed='g')) self.assertTrue(self.G.is_active_trail('d', 'i', observed='l')) self.assertFalse(self.G.is_active_trail('g', 's', observed='i')) def test_is_active_trail(self): self.assertFalse(self.G.is_active_trail('d', 's')) self.assertTrue(self.G.is_active_trail('s', 'l')) self.assertTrue(self.G.is_active_trail('d', 's', observed='g')) self.assertFalse(self.G.is_active_trail('s', 'l', observed='g')) def test_is_active_trail_args(self): self.assertFalse(self.G.is_active_trail('s', 'l', 'i')) self.assertFalse(self.G.is_active_trail('s', 'l', 'g')) self.assertTrue(self.G.is_active_trail('d', 's', 'l')) self.assertFalse(self.G.is_active_trail('d', 's', ['i', 'l'])) def test_get_cpds(self): cpd_d = TabularCPD('d', 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD('i', 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD('g', 2, values=np.random.rand(2, 4), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_l = TabularCPD('l', 2, values=np.random.rand(2, 2), evidence=['g'], evidence_card=[2]) cpd_s = TabularCPD('s', 2, values=np.random.rand(2, 2), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds('d').variable, 'd') def test_get_cpds1(self): self.model = BayesianModel([('A', 'AB')]) cpd_a = TabularCPD('A', 2, values=np.random.rand(2, 1)) cpd_ab = TabularCPD('AB', 2, values=np.random.rand(2, 2), evidence=['A'], evidence_card=[2]) self.model.add_cpds(cpd_a, cpd_ab) self.assertEqual(self.model.get_cpds('A').variable, 'A') self.assertEqual(self.model.get_cpds('AB').variable, 'AB') self.assertRaises(ValueError, self.model.get_cpds, 'B') self.model.add_node('B') self.assertIsNone(self.model.get_cpds('B')) def test_add_single_cpd(self): cpd_s = TabularCPD('s', 2, np.random.rand(2, 2), ['i'], [2]) self.G.add_cpds(cpd_s) self.assertListEqual(self.G.get_cpds(), [cpd_s]) def test_add_multiple_cpds(self): cpd_d = TabularCPD('d', 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD('i', 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD('g', 2, values=np.random.rand(2, 4), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_l = TabularCPD('l', 2, values=np.random.rand(2, 2), evidence=['g'], evidence_card=[2]) cpd_s = TabularCPD('s', 2, values=np.random.rand(2, 2), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds('d'), cpd_d) self.assertEqual(self.G.get_cpds('i'), cpd_i) self.assertEqual(self.G.get_cpds('g'), cpd_g) self.assertEqual(self.G.get_cpds('l'), cpd_l) self.assertEqual(self.G.get_cpds('s'), cpd_s) def test_check_model(self): cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_s = TabularCPD('s', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['g'], evidence_card=[2]) self.G.add_cpds(cpd_g, cpd_s, cpd_l) self.assertRaises(ValueError, self.G.check_model) cpd_d = TabularCPD('d', 2, values=[[0.8, 0.2]]) cpd_i = TabularCPD('i', 2, values=[[0.7, 0.3]]) self.G.add_cpds(cpd_d, cpd_i) self.assertTrue(self.G.check_model()) def test_check_model1(self): cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 's'], evidence_card=[2, 2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['l'], evidence_card=[2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['d'], evidence_card=[2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD('l', 2, values=np.array( [[0.2, 0.3, 0.4, 0.6, 0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4, 0.8, 0.7, 0.6, 0.4]]), evidence=['g', 'd', 'i'], evidence_card=[2, 2, 2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def test_check_model2(self): cpd_s = TabularCPD('s', 2, values=np.array([[0.5, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_s) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_s) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.3, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.1, 0.7]]), evidence=['g'], evidence_card=[2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def tearDown(self): del self.G
def main(): andPGM = PGM_t() print('loading features..') train_set, test_set = andPGM.load_features() print('loading features.. Done') # Bayesian network of 19 nodes, 9*2 variables of network given # Initial incomplete Bayesian model connected manually based on intuition print('Generating model.. ') initialModel = BayesianModel({}) initialModel.add_nodes_from(andPGM.img_features.columns[1:10].tolist()) initialModel.add_edges_from([('f6_a' , 'f2_a'),\ ('f3_a' , 'f4_a') ,\ ('f5_a' , 'f9_a') ,\ ('f4_a' , 'f7_a') ]) # Use hill climb search algorithm to find network structure of initial 9 nodes hc = HillClimbSearch(data=andPGM.img_features.iloc[0:,1:10], \ scoring_method=BdeuScore(andPGM.img_features.iloc[0:,1:10], \ equivalent_sample_size=0.1*len(andPGM.img_features)), \ state_names = andPGM.states_9) # Get best estimated structure best_model = hc.estimate(start=initialModel) # Edges in the acquired graph print('model of 9 var: ', best_model.edges()) # Create a Clone of generated Bayesian network structure clone_model = BayesianModel({}) for edge in best_model.edges(): new_edge = [edge[0][:-1] + 'b', edge[1][:-1] + 'b'] clone_model.add_edges_from([new_edge]) # Join together the Original and clone network through node 'same' multinetModel = BayesianModel({}) multinetModel.add_edges_from(best_model.edges() + clone_model.edges()) multinetModel.add_node('same') multinetModel.add_edge('f5_a', 'same') multinetModel.add_edge('f9_a', 'same') multinetModel.add_edge('f5_b', 'same') multinetModel.add_edge('f9_b', 'same') print('Generating model.. Done') # Edges in the final structure print('Final model: ', multinetModel.edges()) print('Fit data into model..') # fit the data to model to generate CPDs using maximum likelyhood estimation multinetModel.fit(data=train_set, state_names=andPGM.states_all) print('Fit data into model.. Done') print('CPDs generated: ') cpds = multinetModel.get_cpds() for cpd in cpds: print(cpd) # Inference using Variable Elimination print('Start inference..') inference = VariableElimination(multinetModel) train_set_same = train_set[train_set['same'] == 0] train_set_not_same = train_set[train_set['same'] == 1] # Accuracy of positive inferences acc_same = andPGM.chk_accuracy( train_set_same, inference, variables=train_set_same.columns[0:9].tolist(), evidence=train_set_same.columns[9:19].tolist()) print('accuracy of positives ', acc_same) # Accuracy of negative inferences acc_nt_same = andPGM.chk_accuracy( train_set_not_same, inference, variables=train_set_not_same.columns[0:9].tolist(), evidence=train_set_not_same.columns[9:19].tolist()) print('accuracy of negatives', acc_nt_same)
def get_game_network(): BayesNet = BayesianModel() BayesNet.add_node('A') BayesNet.add_node('B') BayesNet.add_node('C') BayesNet.add_node('AvB') BayesNet.add_node('BvC') BayesNet.add_node('CvA') BayesNet.add_edge('A', 'AvB') BayesNet.add_edge('B', 'AvB') BayesNet.add_edge('B', 'BvC') BayesNet.add_edge('C', 'BvC') BayesNet.add_edge('C', 'CvA') BayesNet.add_edge('A', 'CvA') cpd_a = TabularCPD('A', 4, values=[[0.15], [0.45], [0.3], [0.1]]) cpd_b = TabularCPD('B', 4, values=[[0.15], [0.45], [0.3], [0.1]]) cpd_c = TabularCPD('C', 4, values=[[0.15], [0.45], [0.3], [0.1]]) cpd_avb = TabularCPD('AvB', 3, values=[[ 0.10, 0.20, 0.15, 0.05, 0.60, 0.10, 0.20, 0.15, 0.75, 0.60, 0.10, 0.20, 0.90, 0.75, 0.60, 0.10 ], [ 0.10, 0.60, 0.75, 0.90, 0.20, 0.10, 0.60, 0.75, 0.15, 0.20, 0.10, 0.60, 0.05, 0.15, 0.20, 0.10 ], [ 0.80, 0.20, 0.10, 0.05, 0.20, 0.80, 0.20, 0.10, 0.10, 0.20, 0.80, 0.20, 0.05, 0.10, 0.20, 0.80 ]], evidence=['A', 'B'], evidence_card=[4, 4]) cpd_bvc = TabularCPD('BvC', 3, values=[[ 0.10, 0.20, 0.15, 0.05, 0.60, 0.10, 0.20, 0.15, 0.75, 0.60, 0.10, 0.20, 0.90, 0.75, 0.60, 0.10 ], [ 0.10, 0.60, 0.75, 0.90, 0.20, 0.10, 0.60, 0.75, 0.15, 0.20, 0.10, 0.60, 0.05, 0.15, 0.20, 0.10 ], [ 0.80, 0.20, 0.10, 0.05, 0.20, 0.80, 0.20, 0.10, 0.10, 0.20, 0.80, 0.20, 0.05, 0.10, 0.20, 0.80 ]], evidence=['B', 'C'], evidence_card=[4, 4]) cpd_cva = TabularCPD('CvA', 3, values=[[ 0.10, 0.20, 0.15, 0.05, 0.60, 0.10, 0.20, 0.15, 0.75, 0.60, 0.10, 0.20, 0.90, 0.75, 0.60, 0.10 ], [ 0.10, 0.60, 0.75, 0.90, 0.20, 0.10, 0.60, 0.75, 0.15, 0.20, 0.10, 0.60, 0.05, 0.15, 0.20, 0.10 ], [ 0.80, 0.20, 0.10, 0.05, 0.20, 0.80, 0.20, 0.10, 0.10, 0.20, 0.80, 0.20, 0.05, 0.10, 0.20, 0.80 ]], evidence=['C', 'A'], evidence_card=[4, 4]) BayesNet.add_cpds(cpd_a, cpd_b, cpd_c, cpd_avb, cpd_bvc, cpd_cva) return BayesNet
class BayesianNetworkTester: def __init__(self, filename): # property self.networks = BayesianModel() self.mapper = dict() f = open(filename, 'r') N = int(f.readline()) lines = f.readlines() for line in lines: node, parents, domain, shape, probabilities = self.__extract_model( line) # Create Mapper mapper_node = dict() for index, value in enumerate(domain): mapper_node[value] = index self.mapper[node] = mapper_node # Add node self.networks.add_node(node) # Add edge to modal for parent in parents: self.networks.add_edge(parent, node) # Shape to list if isinstance(shape, tuple): shape = list(shape)[:-1] else: shape = [] reshape = (reduce(lambda r, v: r * v, shape, 1), len(domain)) probabilities = probabilities.reshape(reshape) probabilities = np.transpose(probabilities) cpd = TabularCPD(variable=node, variable_card=len(domain), values=probabilities, evidence=parents, evidence_card=shape) self.networks.add_cpds(cpd) f.close() def exact_inference(self, filename): result = 0 f = open(filename, 'r') query_variables, evidence_variables = self.__extract_query( f.readline()) eliminate = VariableElimination(self.networks) evidence_variables_mapped = dict() for variable in evidence_variables: evidence_variables_mapped[variable] = self.mapper[variable][ evidence_variables[variable]] query_variables_feature = list(query_variables.keys()) result = eliminate.query(variables=query_variables_feature, evidence=evidence_variables_mapped) value = result.values for feature in result.variables: value = value[result.get_state_no( feature, self.mapper[feature][query_variables[feature]])] f.close() return value def approx_inference(self, filename): result = 0 f = open(filename, 'r') # YOUR CODE HERE f.close() return result def __extract_model(self, line): parts = line.split(';') node = parts[0] if parts[1] == '': parents = [] else: parents = parts[1].split(',') domain = parts[2].split(',') shape = eval(parts[3]) probabilities = np.array(eval(parts[4])) return node, parents, domain, shape, probabilities def __extract_query(self, line): parts = line.split(';') # extract query variables query_variables = {} for item in parts[0].split(','): if item is None or item == '': continue lst = item.split('=') query_variables[lst[0]] = lst[1] # extract evidence variables evidence_variables = {} for item in parts[1].split(','): if item is None or item == '': continue lst = item.split('=') evidence_variables[lst[0]] = lst[1] return query_variables, evidence_variables
def __init__( self, # dataset, table, num_samples, algorithm="greedy", max_parents=-1, topological_sampling_order=True, use_pgm=True, discretize=None, discretize_method="equal_size", root=None): from pomegranate import BayesianNetwork self.discretize = discretize self.discretize_method = discretize_method self.table = copy.deepcopy(table) self.dataset = np.stack([ col.discretize(self.table.data[cname]) for cname, col in self.table.columns.items() ], axis=1) self.algorithm = algorithm self.topological_sampling_order = topological_sampling_order self.num_samples = num_samples self.discrete_mapping = self.build_discrete_mapping( self.dataset, discretize, discretize_method) self.discrete_table = self.apply_discrete_mapping( self.dataset, self.discrete_mapping) L.info('calling BayesianNetwork.from_samples...') t = time.time() self.model = BayesianNetwork.from_samples(self.discrete_table, algorithm=self.algorithm, max_parents=max_parents, n_jobs=NUM_THREADS, root=root) L.info(f'done! took {(time.time() - t)/60:.2f} mins') def size(states): n = 0 for state in states: if "distribution" in state: dist = state["distribution"] else: dist = state if dist["name"] == "DiscreteDistribution": for p in dist["parameters"]: n += len(p) elif dist["name"] == "ConditionalProbabilityTable": for t in dist["table"]: n += len(t) if "parents" in dist: for parent in dist["parents"]: n += size(dist["parents"]) else: assert False, dist["name"] return n self.size = 4 * size(json.loads(self.model.to_json())["states"]) L.info(f'model size is {self.size/1024/1024:.2f}MB') # print('json:\n', self.model.to_json()) self.json_size = len(self.model.to_json()) self.use_pgm = use_pgm # print(self.model.to_json()) if topological_sampling_order: self.sampling_order = [] while len(self.sampling_order) < len(self.model.structure): for i, deps in enumerate(self.model.structure): if i in self.sampling_order: continue # already ordered if all(d in self.sampling_order for d in deps): self.sampling_order.append(i) L.debug(f"Building sampling order {self.sampling_order}") else: self.sampling_order = list(range(len(self.model.structure))) L.info(f"Using sampling order {self.sampling_order} {str(self)}") if use_pgm: from pgmpy.models import BayesianModel data = pd.DataFrame(self.discrete_table.astype(np.int64)) spec = [] orphans = [] for i, parents in enumerate(self.model.structure): for p in parents: spec.append((p, i)) if not parents: orphans.append(i) L.info(f"Model spec {spec}") model = BayesianModel(spec) for o in orphans: model.add_node(o) L.info('calling pgm.BayesianModel.fit...') t = time.time() model.fit(data) L.info(f'done! took {(time.time() - t)/60:.2f} mins') self.pgm_model = model
class TestBayesianModelCPD(unittest.TestCase): def setUp(self): self.G = BayesianModel([("d", "g"), ("i", "g"), ("g", "l"), ("i", "s")]) self.G2 = DAG([("d", "g"), ("i", "g"), ("g", "l"), ("i", "s")]) def test_active_trail_nodes(self): self.assertEqual(sorted(self.G2.active_trail_nodes("d")["d"]), ["d", "g", "l"]) self.assertEqual(sorted(self.G2.active_trail_nodes("i")["i"]), ["g", "i", "l", "s"]) self.assertEqual(sorted(self.G2.active_trail_nodes(["d", "i"])["d"]), ["d", "g", "l"]) def test_active_trail_nodes_args(self): self.assertEqual( sorted(self.G2.active_trail_nodes(["d", "l"], observed="g")["d"]), ["d", "i", "s"], ) self.assertEqual( sorted(self.G2.active_trail_nodes(["d", "l"], observed="g")["l"]), ["l"]) self.assertEqual( sorted(self.G2.active_trail_nodes("s", observed=["i", "l"])["s"]), ["s"]) self.assertEqual( sorted(self.G2.active_trail_nodes("s", observed=["d", "l"])["s"]), ["g", "i", "s"], ) def test_is_active_trail_triplets(self): self.assertTrue(self.G.is_active_trail("d", "l")) self.assertTrue(self.G.is_active_trail("g", "s")) self.assertFalse(self.G.is_active_trail("d", "i")) self.assertTrue(self.G.is_active_trail("d", "i", observed="g")) self.assertFalse(self.G.is_active_trail("d", "l", observed="g")) self.assertFalse(self.G.is_active_trail("i", "l", observed="g")) self.assertTrue(self.G.is_active_trail("d", "i", observed="l")) self.assertFalse(self.G.is_active_trail("g", "s", observed="i")) def test_is_active_trail(self): self.assertFalse(self.G.is_active_trail("d", "s")) self.assertTrue(self.G.is_active_trail("s", "l")) self.assertTrue(self.G.is_active_trail("d", "s", observed="g")) self.assertFalse(self.G.is_active_trail("s", "l", observed="g")) def test_is_active_trail_args(self): self.assertFalse(self.G.is_active_trail("s", "l", "i")) self.assertFalse(self.G.is_active_trail("s", "l", "g")) self.assertTrue(self.G.is_active_trail("d", "s", "l")) self.assertFalse(self.G.is_active_trail("d", "s", ["i", "l"])) def test_get_cpds(self): cpd_d = TabularCPD("d", 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD("i", 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD( "g", 2, values=np.random.rand(2, 4), evidence=["d", "i"], evidence_card=[2, 2], ) cpd_l = TabularCPD("l", 2, values=np.random.rand(2, 2), evidence=["g"], evidence_card=[2]) cpd_s = TabularCPD("s", 2, values=np.random.rand(2, 2), evidence=["i"], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds("d").variable, "d") def test_get_cpds1(self): self.model = BayesianModel([("A", "AB")]) cpd_a = TabularCPD("A", 2, values=np.random.rand(2, 1)) cpd_ab = TabularCPD("AB", 2, values=np.random.rand(2, 2), evidence=["A"], evidence_card=[2]) self.model.add_cpds(cpd_a, cpd_ab) self.assertEqual(self.model.get_cpds("A").variable, "A") self.assertEqual(self.model.get_cpds("AB").variable, "AB") self.assertRaises(ValueError, self.model.get_cpds, "B") self.model.add_node("B") self.assertIsNone(self.model.get_cpds("B")) def test_add_single_cpd(self): cpd_s = TabularCPD("s", 2, np.random.rand(2, 2), ["i"], [2]) self.G.add_cpds(cpd_s) self.assertListEqual(self.G.get_cpds(), [cpd_s]) def test_add_multiple_cpds(self): cpd_d = TabularCPD("d", 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD("i", 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD( "g", 2, values=np.random.rand(2, 4), evidence=["d", "i"], evidence_card=[2, 2], ) cpd_l = TabularCPD("l", 2, values=np.random.rand(2, 2), evidence=["g"], evidence_card=[2]) cpd_s = TabularCPD("s", 2, values=np.random.rand(2, 2), evidence=["i"], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds("d"), cpd_d) self.assertEqual(self.G.get_cpds("i"), cpd_i) self.assertEqual(self.G.get_cpds("g"), cpd_g) self.assertEqual(self.G.get_cpds("l"), cpd_l) self.assertEqual(self.G.get_cpds("s"), cpd_s) def test_check_model(self): cpd_g = TabularCPD( "g", 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=["d", "i"], evidence_card=[2, 2], ) cpd_s = TabularCPD( "s", 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=["i"], evidence_card=[2], ) cpd_l = TabularCPD( "l", 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=["g"], evidence_card=[2], ) self.G.add_cpds(cpd_g, cpd_s, cpd_l) self.assertRaises(ValueError, self.G.check_model) cpd_d = TabularCPD("d", 2, values=[[0.8, 0.2]]) cpd_i = TabularCPD("i", 2, values=[[0.7, 0.3]]) self.G.add_cpds(cpd_d, cpd_i) self.assertTrue(self.G.check_model()) def test_check_model1(self): cpd_g = TabularCPD( "g", 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=["i"], evidence_card=[2], ) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD( "g", 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=["d", "s"], evidence_card=[2, 2], ) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD( "g", 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=["l"], evidence_card=[2], ) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD( "l", 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=["d"], evidence_card=[2], ) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD( "l", 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=["d", "i"], evidence_card=[2, 2], ) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD( "l", 2, values=np.array([ [0.2, 0.3, 0.4, 0.6, 0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4, 0.8, 0.7, 0.6, 0.4], ]), evidence=["g", "d", "i"], evidence_card=[2, 2, 2], ) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def test_check_model2(self): cpd_s = TabularCPD( "s", 2, values=np.array([[0.5, 0.3], [0.8, 0.7]]), evidence=["i"], evidence_card=[2], ) self.G.add_cpds(cpd_s) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_s) cpd_g = TabularCPD( "g", 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.3, 0.7, 0.6, 0.4]]), evidence=["d", "i"], evidence_card=[2, 2], ) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD( "l", 2, values=np.array([[0.2, 0.3], [0.1, 0.7]]), evidence=["g"], evidence_card=[2], ) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def tearDown(self): del self.G
class TestBaseModelCreation(unittest.TestCase): def setUp(self): self.G = BayesianModel() def test_class_init_without_data(self): self.assertIsInstance(self.G, nx.DiGraph) def test_class_init_with_data_string(self): self.g = BayesianModel([("a", "b"), ("b", "c")]) self.assertListEqual(sorted(self.g.nodes()), ["a", "b", "c"]) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [["a", "b"], ["b", "c"]]) def test_class_init_with_data_nonstring(self): BayesianModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.G.add_node("a") self.assertListEqual(list(self.G.nodes()), ["a"]) def test_add_node_nonstring(self): self.G.add_node(1) def test_add_nodes_from_string(self): self.G.add_nodes_from(["a", "b", "c", "d"]) self.assertListEqual(sorted(self.G.nodes()), ["a", "b", "c", "d"]) def test_add_nodes_from_non_string(self): self.G.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.G.add_edge("d", "e") self.assertListEqual(sorted(self.G.nodes()), ["d", "e"]) self.assertListEqual(list(self.G.edges()), [("d", "e")]) self.G.add_nodes_from(["a", "b", "c"]) self.G.add_edge("a", "b") self.assertListEqual(hf.recursive_sorted(self.G.edges()), [["a", "b"], ["d", "e"]]) def test_add_edge_nonstring(self): self.G.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.G.add_edge, "a", "a") def test_add_edge_result_cycle(self): self.G.add_edges_from([("a", "b"), ("a", "c")]) self.assertRaises(ValueError, self.G.add_edge, "c", "a") def test_add_edges_from_string(self): self.G.add_edges_from([("a", "b"), ("b", "c")]) self.assertListEqual(sorted(self.G.nodes()), ["a", "b", "c"]) self.assertListEqual(hf.recursive_sorted(self.G.edges()), [["a", "b"], ["b", "c"]]) self.G.add_nodes_from(["d", "e", "f"]) self.G.add_edges_from([("d", "e"), ("e", "f")]) self.assertListEqual(sorted(self.G.nodes()), ["a", "b", "c", "d", "e", "f"]) self.assertListEqual( hf.recursive_sorted(self.G.edges()), hf.recursive_sorted([("a", "b"), ("b", "c"), ("d", "e"), ("e", "f")]), ) def test_add_edges_from_nonstring(self): self.G.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.G.add_edges_from, [("a", "a")]) def test_add_edges_from_result_cycle(self): self.assertRaises(ValueError, self.G.add_edges_from, [("a", "b"), ("b", "c"), ("c", "a")]) def test_update_node_parents_bm_constructor(self): self.g = BayesianModel([("a", "b"), ("b", "c")]) self.assertListEqual(list(self.g.predecessors("a")), []) self.assertListEqual(list(self.g.predecessors("b")), ["a"]) self.assertListEqual(list(self.g.predecessors("c")), ["b"]) def test_update_node_parents(self): self.G.add_nodes_from(["a", "b", "c"]) self.G.add_edges_from([("a", "b"), ("b", "c")]) self.assertListEqual(list(self.G.predecessors("a")), []) self.assertListEqual(list(self.G.predecessors("b")), ["a"]) self.assertListEqual(list(self.G.predecessors("c")), ["b"]) def tearDown(self): del self.G
from pgmpy.models import BayesianModel from pgmpy.factors import TabularCPD # Creating the above bayesian network model = BayesianModel() model.add_nodes_from(['Rain', 'TrafficJam']) model.add_edge('Rain', 'TrafficJam') model.add_edge('Accident', 'TrafficJam') cpd_rain = TabularCPD('Rain', 2, [[0.4], [0.6]]) cpd_accident = TabularCPD('Accident', 2, [[0.2], [0.8]]) cpd_traffic_jam = TabularCPD('TrafficJam', 2, [[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]], evidence=['Rain', 'Accident'], evidence_card=[2, 2]) model.add_cpds(cpd_rain, cpd_accident, cpd_traffic_jam) model.add_node('LongQueues') model.add_edge('TrafficJam', 'LongQueues') cpd_long_queues = TabularCPD('LongQueues', 2, [[0.9, 0.2], [0.1, 0.8]], evidence=['TrafficJam'], evidence_card=[2]) model.add_cpds(cpd_long_queues) model.add_nodes_from(['GettingUpLate', 'LateForSchool']) model.add_edges_from([('GettingUpLate', 'LateForSchool'), ('TrafficJam', 'LateForSchool')]) cpd_getting_up_late = TabularCPD('GettingUpLate', 2, [[0.6], [0.4]]) cpd_late_for_school = TabularCPD('LateForSchool', 2, [[0.9, 0.45, 0.8, 0.1], [0.1, 0.55, 0.2, 0.9]],
class TestBayesianModelCPD(unittest.TestCase): def setUp(self): self.G = BayesianModel([('d', 'g'), ('i', 'g'), ('g', 'l'), ('i', 's')]) def test_active_trail_nodes(self): self.assertEqual(sorted(self.G.active_trail_nodes('d')['d']), ['d', 'g', 'l']) self.assertEqual(sorted(self.G.active_trail_nodes('i')['i']), ['g', 'i', 'l', 's']) self.assertEqual(sorted(self.G.active_trail_nodes(['d', 'i'])['d']), ['d', 'g', 'l']) def test_active_trail_nodes_args(self): self.assertEqual(sorted(self.G.active_trail_nodes(['d', 'l'], observed='g')['d']), ['d', 'i', 's']) self.assertEqual(sorted(self.G.active_trail_nodes(['d', 'l'], observed='g')['l']), ['l']) self.assertEqual(sorted(self.G.active_trail_nodes('s', observed=['i', 'l'])['s']), ['s']) self.assertEqual(sorted(self.G.active_trail_nodes('s', observed=['d', 'l'])['s']), ['g', 'i', 's']) def test_is_active_trail_triplets(self): self.assertTrue(self.G.is_active_trail('d', 'l')) self.assertTrue(self.G.is_active_trail('g', 's')) self.assertFalse(self.G.is_active_trail('d', 'i')) self.assertTrue(self.G.is_active_trail('d', 'i', observed='g')) self.assertFalse(self.G.is_active_trail('d', 'l', observed='g')) self.assertFalse(self.G.is_active_trail('i', 'l', observed='g')) self.assertTrue(self.G.is_active_trail('d', 'i', observed='l')) self.assertFalse(self.G.is_active_trail('g', 's', observed='i')) def test_is_active_trail(self): self.assertFalse(self.G.is_active_trail('d', 's')) self.assertTrue(self.G.is_active_trail('s', 'l')) self.assertTrue(self.G.is_active_trail('d', 's', observed='g')) self.assertFalse(self.G.is_active_trail('s', 'l', observed='g')) def test_is_active_trail_args(self): self.assertFalse(self.G.is_active_trail('s', 'l', 'i')) self.assertFalse(self.G.is_active_trail('s', 'l', 'g')) self.assertTrue(self.G.is_active_trail('d', 's', 'l')) self.assertFalse(self.G.is_active_trail('d', 's', ['i', 'l'])) def test_get_cpds(self): cpd_d = TabularCPD('d', 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD('i', 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD('g', 2, values=np.random.rand(2, 4), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_l = TabularCPD('l', 2, values=np.random.rand(2, 2), evidence=['g'], evidence_card=[2]) cpd_s = TabularCPD('s', 2, values=np.random.rand(2, 2), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds('d').variable, 'd') def test_get_cpds1(self): self.model = BayesianModel([('A', 'AB')]) cpd_a = TabularCPD('A', 2, values=np.random.rand(2, 1)) cpd_ab = TabularCPD('AB', 2, values=np.random.rand(2, 2), evidence=['A'], evidence_card=[2]) self.model.add_cpds(cpd_a, cpd_ab) self.assertEqual(self.model.get_cpds('A').variable, 'A') self.assertEqual(self.model.get_cpds('AB').variable, 'AB') self.assertRaises(ValueError, self.model.get_cpds, 'B') self.model.add_node('B') self.assertIsNone(self.model.get_cpds('B')) def test_add_single_cpd(self): cpd_s = TabularCPD('s', 2, np.random.rand(2, 2), ['i'], [2]) self.G.add_cpds(cpd_s) self.assertListEqual(self.G.get_cpds(), [cpd_s]) def test_add_multiple_cpds(self): cpd_d = TabularCPD('d', 2, values=np.random.rand(2, 1)) cpd_i = TabularCPD('i', 2, values=np.random.rand(2, 1)) cpd_g = TabularCPD('g', 2, values=np.random.rand(2, 4), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_l = TabularCPD('l', 2, values=np.random.rand(2, 2), evidence=['g'], evidence_card=[2]) cpd_s = TabularCPD('s', 2, values=np.random.rand(2, 2), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s) self.assertEqual(self.G.get_cpds('d'), cpd_d) self.assertEqual(self.G.get_cpds('i'), cpd_i) self.assertEqual(self.G.get_cpds('g'), cpd_g) self.assertEqual(self.G.get_cpds('l'), cpd_l) self.assertEqual(self.G.get_cpds('s'), cpd_s) def test_check_model(self): cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) cpd_s = TabularCPD('s', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['g'], evidence_card=[2]) self.G.add_cpds(cpd_g, cpd_s, cpd_l) self.assertRaises(ValueError, self.G.check_model) cpd_d = TabularCPD('d', 2, values=[[0.8, 0.2]]) cpd_i = TabularCPD('i', 2, values=[[0.7, 0.3]]) self.G.add_cpds(cpd_d, cpd_i) self.assertTrue(self.G.check_model()) def test_check_model1(self): cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 's'], evidence_card=[2, 2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['l'], evidence_card=[2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.8, 0.7]]), evidence=['d'], evidence_card=[2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3, 0.4, 0.6, 0.2, 0.3, 0.4, 0.6], [0.8, 0.7, 0.6, 0.4, 0.8, 0.7, 0.6, 0.4]]), evidence=['g', 'd', 'i'], evidence_card=[2, 2, 2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def test_check_model2(self): cpd_s = TabularCPD('s', 2, values=np.array([[0.5, 0.3], [0.8, 0.7]]), evidence=['i'], evidence_card=[2]) self.G.add_cpds(cpd_s) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_s) cpd_g = TabularCPD('g', 2, values=np.array([[0.2, 0.3, 0.4, 0.6], [0.3, 0.7, 0.6, 0.4]]), evidence=['d', 'i'], evidence_card=[2, 2]) self.G.add_cpds(cpd_g) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_g) cpd_l = TabularCPD('l', 2, values=np.array([[0.2, 0.3], [0.1, 0.7]]), evidence=['g'], evidence_card=[2]) self.G.add_cpds(cpd_l) self.assertRaises(ValueError, self.G.check_model) self.G.remove_cpds(cpd_l) def tearDown(self): del self.G
class RaptorModel: RADIUS = 100 def __init__(self, raptor_actor, Pigeons, wall): self.raptor_actor = raptor_actor self.Pigeons = Pigeons self.wall = wall self.n_sectors = raptor_actor.n_sectors self.cardinality_vision = self.n_sectors self.cardinality_delta_azimuth = 2 self.cardinality_correction = 3 self.cardinality_direction = 3 self.resolution = abs( np.angle(self.raptor_actor.sector_L[1]) - np.angle(self.raptor_actor.sector_L[0])) self.target = self.Pigeons.tensor_of_pigeons[0] self.R_previous = 0 #raptor_actor.R_previous self.R_now = 0 #raptor_actor.R_now self.observations = [] self.network = BayesianModel() self.models = self.create_networks() #see generative_model.py self.correction = 0 self.direction = 0 self.compass = 0 self.cpd_left = CPD.create_fixed_parent((self.n_sectors), int(self.n_sectors / 2)) self.cpd_right = CPD.create_fixed_parent((self.n_sectors), int(self.n_sectors / 3)) self.cpd_left_previous = self.cpd_right.copy() self.cpd_right_previous = self.cpd_left.copy() self.cpd_left_observed = self.cpd_right_previous.copy() self.cpd_right_observed = self.cpd_left_previous.copy() self.cpd_action = CPD.create_fixed_parent( self.cardinality_correction, int(self.cardinality_correction / 2)) self.cpd_direction = CPD.create_fixed_parent( self.cardinality_direction, int(self.cardinality_direction / 2)) def create_networks(self): gamma = 1 # this controls how steep the discrimination will be between the classes (gamma << 1 low discrimination, gamma >> 1 : high discrimination sigma = 1 # this controls how steep the squeezing of the action will be index_jump = int( self.raptor_actor.alfa_increment / self.resolution ) #calculates the number of "sector jumps" dpeending on the tuple alfa_ainvrement and sector_resolution index_jump = 2 # print("Index gamma ", index_gamma) ParentNodes = [] ParentNodes.append("MEM_vision_left") ParentNodes.append("MEM_vision_right") ParentNodes.append("BEN_Correction") ParentNodes.append("BEN_Direction") #ParentNodes.append("Reward_Predicted") count = 0 while count < len(ParentNodes): self.network.add_node(ParentNodes[count]) count = count + 1 LeafNodes = [] LeafNodes.append("LEN_vision_left") LeafNodes.append("LEN_vision_right") LeafNodes.append("LEN_motor_Correction") LeafNodes.append("LEN_motor_Direction") count = 0 while count < len(LeafNodes): self.network.add_node(LeafNodes[count]) count = count + 1 self.network.add_edge(ParentNodes[0], LeafNodes[0]) self.network.add_edge(ParentNodes[2], LeafNodes[0]) self.network.add_edge(ParentNodes[3], LeafNodes[0]) self.network.add_edge(ParentNodes[1], LeafNodes[1]) self.network.add_edge(ParentNodes[2], LeafNodes[1]) self.network.add_edge(ParentNodes[3], LeafNodes[1]) self.network.add_edge(ParentNodes[2], LeafNodes[2]) self.network.add_edge(ParentNodes[3], LeafNodes[3]) CPD_Parents = [] CPD_Parents.append( CPD.parent_cpd( ParentNodes[0], self.cardinality_vision, int(random.uniform(0, self.cardinality_vision - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[1], self.cardinality_vision, int(random.uniform(0, self.cardinality_vision - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[2], self.cardinality_correction, int(random.uniform(0, self.cardinality_correction - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[3], self.cardinality_direction, int(random.uniform(0, self.cardinality_direction - 0.4)), sigma / 2, "fixed")) for n in range(0, len(CPD_Parents)): self.network.add_cpds(CPD_Parents[n]) CPD_Leafs = [] CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[0], self.cardinality_vision, [ self.cardinality_vision, self.cardinality_correction, self.cardinality_direction ], [ParentNodes[0], ParentNodes[2], ParentNodes[3]], 'left_vision', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[1], self.cardinality_vision, [ self.cardinality_vision, self.cardinality_correction, self.cardinality_direction ], [ParentNodes[1], ParentNodes[2], ParentNodes[3]], 'right_vision', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[2], self.cardinality_correction, [self.cardinality_correction], [ParentNodes[2]], 'one_2_one', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[3], self.cardinality_direction, [self.cardinality_direction], [ParentNodes[3]], 'one_2_one', index_jump)) for n in range(0, len(CPD_Leafs)): self.network.add_cpds(CPD_Leafs[n]) self.network.check_model() #draw_network(self.network) '''for n in range(0,len(CPD_Latents)): print("Latents :") print(CPD_Latents[n])''' for n in range(0, len(CPD_Leafs)): print("Leafs :") print(CPD_Leafs[n]) #wait = input("PRESS ENTER TO CONTINUE.") relevant_parent_nodes = [2, 3] return { 'main': GenerativeModel(SensoryInputVirtualPeepo(self), self.network) } def process(self): self.calculate_environment() self.network.get_cpds('BEN_Correction').values = self.cpd_action self.network.get_cpds('BEN_Direction').values = self.cpd_direction self.network.get_cpds( 'MEM_vision_left').values = self.cpd_left_previous self.network.get_cpds( 'MEM_vision_right').values = self.cpd_right_previous '''print("PARENT CPD's") print("******************************************************************************************************************") print("Previous left :", self.cpd_left_previous, " Previous right : ", self.cpd_right_previous) print("New correction :", self.action, " New direction : ", self.direction)''' for key in self.models: err = self.models[key].process() self.correction = self.network.get_cpds('BEN_Correction').values self.direction = self.network.get_cpds('BEN_Direction').values self.cpd_action = self.correction self.cpd_direction = self.direction index_direction_angle = np.argmax(self.direction) index_correction_angle = np.argmax(self.correction) angle_increment = 1j if index_direction_angle >= 0: if index_correction_angle == 0: angle_increment = np.exp(-1j * self.raptor_actor.alfa_increment) print("Turning right") if index_correction_angle == 1: angle_increment = np.exp(0 * 1j * self.raptor_actor.alfa_increment) print("No Turning") if index_correction_angle == 2: angle_increment = np.exp(1j * self.raptor_actor.alfa_increment) print("Turning left") if index_direction_angle > 3: if index_correction_angle == 2: angle_increment = np.exp(-1j * self.raptor_actor.alfa_increment) print("Turning right") if index_correction_angle == 1: angle_increment = np.exp(0 * 1j * self.raptor_actor.alfa_increment) print("No Turning") if index_correction_angle == 0: angle_increment = np.exp(1j * self.raptor_actor.alfa_increment) print("Turning left") #print("Incrementing angle with ",angle_increment) #print("Angle from " ,self.raptor_actor.angle) self.raptor_actor.angle *= angle_increment #print ( "to : ", self.raptor_actor.angle) #print("Peepo's new moving direction : ", np.angle(self.raptor_actor.angle)*180/math.pi," degrees") self.cpd_left_previous = self.cpd_left_observed self.cpd_right_previous = self.cpd_right_observed #self.action = CPD.create_fixed_parent(self.cardinality_correction, self.correction) #self.direction = CPD.create_fixed_parent(self.cardinality_correction, self.compass) '''print("Parent nodes ") print(self.network.get_cpds('Delta_alfa_left').values) print(self.network.get_cpds('Delta_alfa_right').values) print("Leaf nodes ") #print(self.network.get_cpds('Correction'))''' #print("Inference ----> ",self.correction) def calculate_environment(obj): pos_target = [obj.target[0], obj.target[1]] pos_raptor_left_eye = [ obj.raptor_actor.left_eye[0], obj.raptor_actor.left_eye[1] ] pos_raptor_right_eye = [ obj.raptor_actor.right_eye[0], obj.raptor_actor.right_eye[1] ] observed_left_angle = (pos_target[0] - pos_raptor_left_eye[0]) + 1j * ( pos_target[1] - pos_raptor_left_eye[1]) observed_right_angle = (pos_target[0] - pos_raptor_right_eye[0]) + 1j * ( pos_target[1] - pos_raptor_right_eye[1]) index_sector_left = RaptorModel.get_sector_index( observed_left_angle, obj.raptor_actor.sector_L, 'Left') obj.raptor_actor.choosen_sector_L = index_sector_left if obj.raptor_actor.choosen_sector_L == len( obj.raptor_actor.sector_L) - 2: obj.raptor_actor.choosen_sector_L = len( obj.raptor_actor.sector_L) - 1 index_sector_right = RaptorModel.get_sector_index( observed_right_angle, obj.raptor_actor.sector_R, 'Right') obj.raptor_actor.choosen_sector_R = index_sector_right if obj.raptor_actor.choosen_sector_R == 0 * ( len(obj.raptor_actor.sector_R) - 2): obj.raptor_actor.choosen_sector_R = ( len(obj.raptor_actor.sector_R) - 1) obj.cpd_left_observed = CPD.create_fixed_parent( obj.cardinality_vision, index_sector_left) obj.cpd_right_observed = CPD.create_fixed_parent( obj.cardinality_vision, index_sector_right) obj.observations.clear() obj.observations.append(obj.cpd_left_observed) obj.observations.append(obj.cpd_right_observed) #print("Observations -------------------", obj.observations) def get_sector_index(angle, sector, side): index = 0 aim = angle.real / abs(angle.real) if side == 'Left': for sec in range(0, len(sector) - 1): #print("Angle :" , 180/math.pi*angle, " for sectors ", sec , " to ", sec+1 ," (",180/math.pi*np.angle(sector[sec]),",", 180/math.pi*np.angle(sector[sec+1]),")") if (np.angle(angle) >= np.angle(sector[sec]) and np.angle(angle) < np.angle(sector[sec + 1])): index = sec if (np.angle(angle) >= np.angle(sector[len(sector) - 2]) and np.angle(angle) < np.angle(sector[len(sector) - 1])): index = len(sector) - 2 if side == 'Right': for sec in range(1, len(sector) - 1): #print("Angle :" , 180/math.pi*angle, " for sectors ", sec , " to ", sec+1 ," (",180/math.pi*np.angle(sector[sec]),",", 180/math.pi*np.angle(sector[sec+1]),")") if (np.angle(angle) > np.angle(sector[sec]) and np.angle(angle) <= np.angle(sector[sec + 1])): index = sec if (np.angle(angle) >= np.angle(sector[0]) and np.angle(angle) <= np.angle(sector[1])): index = len(sector) - 2 if side == 'Left': if aim * angle.real <= aim * sector[ 0].real and aim * angle.real >= aim * sector[len(sector) - 1].real: index = int((len(sector) - 2) / 2) if side == 'Right': if aim * angle.real >= aim * sector[ 0].real and aim * angle.real <= aim * sector[len(sector) - 1].real: index = int((len(sector) - 2) / 2) #print("Angle :", 180 / math.pi * angle, " for sectors ", len(sector)-2, " to ", len(sector)-2 + 1, " (", 180 / math.pi * sector[len(sector)-2], ",", 180 / math.pi * sector[len(sector)-2+ 1], ")") #print("Index for angle ",angle , " and sector : ", sector, " : ", index) #print(side , " sector Index for angle ", 180/math.pi*np.angle(angle), " ------> ", index, " for sectors angles(", 180/math.pi*np.angle(sector[index]),", ", 180/math.pi*np.angle(sector[index+1]),")") return index def normalize(s): som = 0 for sec in range(0, len(s)): som += s[sec] for sec in range(0, len(s)): s[sec] /= som return s
class Inference(object): """ Base class for all inference algorithms. Converts BayesianModel and MarkovModel to a uniform representation so that inference algorithms can be applied. Also it checks if all the associated CPDs / Factors are consistent with the model. Initialize inference for a model. Parameters ---------- model: pgmpy.models.BayesianModel or pgmpy.models.MarkovModel or pgmpy.models.NoisyOrModel or pgmpy.models.IntervalTemporalBayesianNetwork.py model for which to initialize the inference object. Examples -------- >>> from pgmpy.inference import Inference >>> from pgmpy.models import BayesianModel >>> from pgmpy.factors.discrete import TabularCPD >>> student = BayesianModel([('diff', 'grade'), ('intel', 'grade')]) >>> diff_cpd = TabularCPD('diff', 2, [[0.2, 0.8]]) >>> intel_cpd = TabularCPD('intel', 2, [[0.3, 0.7]]) >>> grade_cpd = TabularCPD('grade', 3, [[0.1, 0.1, 0.1, 0.1], ... [0.1, 0.1, 0.1, 0.1], ... [0.8, 0.8, 0.8, 0.8]], ... evidence=['diff', 'intel'], evidence_card=[2, 2]) >>> student.add_cpds(diff_cpd, intel_cpd, grade_cpd) >>> model = Inference(student) >>> from pgmpy.models import MarkovModel >>> from pgmpy.factors import DiscreteFactor >>> import numpy as np >>> student = MarkovModel([('Alice', 'Bob'), ('Bob', 'Charles'), ... ('Charles', 'Debbie'), ('Debbie', 'Alice')]) >>> factor_a_b = DiscreteFactor(['Alice', 'Bob'], cardinality=[2, 2], value=np.random.rand(4)) >>> factor_b_c = DiscreteFactor(['Bob', 'Charles'], cardinality=[2, 2], value=np.random.rand(4)) >>> factor_c_d = DiscreteFactor(['Charles', 'Debbie'], cardinality=[2, 2], value=np.random.rand(4)) >>> factor_d_a = DiscreteFactor(['Debbie', 'Alice'], cardinality=[2, 2], value=np.random.rand(4)) >>> student.add_factors(factor_a_b, factor_b_c, factor_c_d, factor_d_a) >>> model = Inference(student) """ @StateNameInit() def __init__(self, model): self.model = model model.check_model() if isinstance(model, JunctionTree): self.variables = set(chain(*model.nodes())) else: self.variables = model.nodes() self.cardinality = {} self.factors = defaultdict(list) if isinstance(model, BayesianModel): for node in model.nodes(): cpd = model.get_cpds(node) cpd_as_factor = cpd.to_factor() self.cardinality[node] = cpd.variable_card for var in cpd.variables: self.factors[var].append(cpd_as_factor) elif isinstance(model, (MarkovModel, FactorGraph, JunctionTree)): self.cardinality = model.get_cardinality() for factor in model.get_factors(): for var in factor.variables: self.factors[var].append(factor) elif isinstance(model, DynamicBayesianNetwork): self.start_bayesian_model = BayesianModel(model.get_intra_edges(0)) start_cpds = model.get_cpds(time_slice=0) for cpd in start_cpds: for variable in cpd.variables: if variable[1] == 0: self.start_bayesian_model.add_node(variable) self.start_bayesian_model.add_cpds(*start_cpds) cpd_inter = [ model.get_cpds(node) for node in set(model.get_interface_nodes(1)) ] self.interface_nodes = set(model.get_interface_nodes(0)) self.one_and_half_model = BayesianModel(model.get_inter_edges() + model.get_intra_edges(1)) one_and_half_cpds = model.get_cpds(time_slice=1) for cpd in one_and_half_cpds: for variable in cpd.variables: if variable[1] == 1: self.one_and_half_model.add_node(variable) self.one_and_half_model.add_cpds(*(one_and_half_cpds + cpd_inter))
class TestBaseModelCreation(unittest.TestCase): def setUp(self): self.G = BayesianModel() def test_class_init_without_data(self): self.assertIsInstance(self.G, nx.DiGraph) def test_class_init_with_data_string(self): self.g = BayesianModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.g.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [['a', 'b'], ['b', 'c']]) def test_class_init_with_data_nonstring(self): BayesianModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.G.add_node('a') self.assertListEqual(self.G.nodes(), ['a']) def test_add_node_nonstring(self): self.G.add_node(1) def test_add_nodes_from_string(self): self.G.add_nodes_from(['a', 'b', 'c', 'd']) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c', 'd']) def test_add_nodes_from_non_string(self): self.G.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.G.add_edge('d', 'e') self.assertListEqual(sorted(self.G.nodes()), ['d', 'e']) self.assertListEqual(self.G.edges(), [('d', 'e')]) self.G.add_nodes_from(['a', 'b', 'c']) self.G.add_edge('a', 'b') self.assertListEqual(hf.recursive_sorted(self.G.edges()), [['a', 'b'], ['d', 'e']]) def test_add_edge_nonstring(self): self.G.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.G.add_edge, 'a', 'a') def test_add_edge_result_cycle(self): self.G.add_edges_from([('a', 'b'), ('a', 'c')]) self.assertRaises(ValueError, self.G.add_edge, 'c', 'a') def test_add_edges_from_string(self): self.G.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.G.edges()), [['a', 'b'], ['b', 'c']]) self.G.add_nodes_from(['d', 'e', 'f']) self.G.add_edges_from([('d', 'e'), ('e', 'f')]) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c', 'd', 'e', 'f']) self.assertListEqual(hf.recursive_sorted(self.G.edges()), hf.recursive_sorted([('a', 'b'), ('b', 'c'), ('d', 'e'), ('e', 'f')])) def test_add_edges_from_nonstring(self): self.G.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.G.add_edges_from, [('a', 'a')]) def test_add_edges_from_result_cycle(self): self.assertRaises(ValueError, self.G.add_edges_from, [('a', 'b'), ('b', 'c'), ('c', 'a')]) def test_update_node_parents_bm_constructor(self): self.g = BayesianModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.g.predecessors('a'), []) self.assertListEqual(self.g.predecessors('b'), ['a']) self.assertListEqual(self.g.predecessors('c'), ['b']) def test_update_node_parents(self): self.G.add_nodes_from(['a', 'b', 'c']) self.G.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.G.predecessors('a'), []) self.assertListEqual(self.G.predecessors('b'), ['a']) self.assertListEqual(self.G.predecessors('c'), ['b']) def tearDown(self): del self.G
""" np_all = np.loadtxt(open("dishwasher.out", "rb"), delimiter=",", skiprows=0) print(np_all.shape) print(np_all) plt.plot(np_all[:, 266]) plt.show() #np_all = np_all[33:-34,:] #print(np_all.shape) #""" G = BayesianModel() G.add_node('time_slot') G.add_edge('time_slot', 'device_on') G.add_edge('time_slot', 'energy') G.add_edge('time_slot', 'duration') G.add_edge('device_on', 'energy') G.add_edge('device_on', 'duration') for i in range(np_all.shape[1]): gtz_idxb = np_all[:, i] > 10 total_energy = np_all[gtz_idxb, i].sum() gtz_idx = np.argwhere(np_all[:, i] > 10) train_list = [] if gtz_idx.shape[0] > 0 and total_energy < 60000:
class TestBaseModelCreation(unittest.TestCase): def setUp(self): self.G = BayesianModel() def test_class_init_without_data(self): self.assertIsInstance(self.G, nx.DiGraph) def test_class_init_with_data_string(self): self.g = BayesianModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.g.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [['a', 'b'], ['b', 'c']]) def test_class_init_with_data_nonstring(self): BayesianModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.G.add_node('a') self.assertListEqual(self.G.nodes(), ['a']) def test_add_node_nonstring(self): self.G.add_node(1) def test_add_nodes_from_string(self): self.G.add_nodes_from(['a', 'b', 'c', 'd']) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c', 'd']) def test_add_nodes_from_non_string(self): self.G.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.G.add_edge('d', 'e') self.assertListEqual(sorted(self.G.nodes()), ['d', 'e']) self.assertListEqual(self.G.edges(), [('d', 'e')]) self.G.add_nodes_from(['a', 'b', 'c']) self.G.add_edge('a', 'b') self.assertListEqual(hf.recursive_sorted(self.G.edges()), [['a', 'b'], ['d', 'e']]) def test_add_edge_nonstring(self): self.G.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.G.add_edge, 'a', 'a') def test_add_edge_result_cycle(self): self.G.add_edges_from([('a', 'b'), ('a', 'c')]) self.assertRaises(ValueError, self.G.add_edge, 'c', 'a') def test_add_edges_from_string(self): self.G.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.G.edges()), [['a', 'b'], ['b', 'c']]) self.G.add_nodes_from(['d', 'e', 'f']) self.G.add_edges_from([('d', 'e'), ('e', 'f')]) self.assertListEqual(sorted(self.G.nodes()), ['a', 'b', 'c', 'd', 'e', 'f']) self.assertListEqual( hf.recursive_sorted(self.G.edges()), hf.recursive_sorted([('a', 'b'), ('b', 'c'), ('d', 'e'), ('e', 'f')])) def test_add_edges_from_nonstring(self): self.G.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.G.add_edges_from, [('a', 'a')]) def test_add_edges_from_result_cycle(self): self.assertRaises(ValueError, self.G.add_edges_from, [('a', 'b'), ('b', 'c'), ('c', 'a')]) def test_update_node_parents_bm_constructor(self): self.g = BayesianModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.g.predecessors('a'), []) self.assertListEqual(self.g.predecessors('b'), ['a']) self.assertListEqual(self.g.predecessors('c'), ['b']) def test_update_node_parents(self): self.G.add_nodes_from(['a', 'b', 'c']) self.G.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(self.G.predecessors('a'), []) self.assertListEqual(self.G.predecessors('b'), ['a']) self.assertListEqual(self.G.predecessors('c'), ['b']) def tearDown(self): del self.G
[[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]], evdience=['rain', 'accident'], evidence_card=[2, 2]) # associate each CPD to model model.add_cpds(cpd_rain, cpd_accident, cpd_traffic_jam) model.get_cpds() " [<TabularCPD representing P(rain: 2) at fsjidfsjdfaskdf>, " " [<TabularCPD representing P(accident: 2) at fsxfgsdfgfsjdfaskdf>, " " [<TabularCPD representing P(traffic_jam: 2 | rain:2, accident:2) at fsjidf234sjdfaskdf>, " # Adding the remaining variables and their CPDs # ------------------------------------------------------ ( traffic_jam -> long_queues ) model.add_node('long_queues') model.add_edge('traffic_jam', 'long_queues') cpd_long_queues = TabularCPD('long_queues', 2, [[0.9, 0.2], [0.1, 0.8]], evidence=['traffic_jam'], evidence_card=[2]) model.add_cpds(cpd_long_queues) # ------------------------------------------------------ ( getting_up_late -> late_for_school ) # ------------------------------------------------------ ( traffic_jam -> late_for_school ) model.add_nodes_from(['getting_up_late', 'late_for_school']) model.add_edges_from([('getting_up_late', 'late_for_school'), ('traffic_jam', 'late_for_school')])