def test_reduce_factor(self): f = Factor(self.bn, 'Alarm') f.reduce_factor('Burglary','Yes') self.assertListEqual(list(f.cpt), [ 0.06, 0.94, 0.05, 0.95])
def gibbs_sample(bn, n=1000, burn=200): """ Approximate Marginal probabilities from Gibbs Sampling over a BayesNet object. Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take *burn* : an integer The number of beginning samples to throw away for the MCMC mixing. Returns ------- *sample_dict* : a dictionary where key = rv and value = another dictionary where key = rv instantiation and value = marginal probability Notes ----- """ sample_dict = {} for rv in bn.nodes(): sample_dict[rv] = {} for val in bn.values(rv): sample_dict[rv][val] = 0 state = {} for rv in bn.nodes(): state[rv] = np.random.choice(bn.values(rv)) # uniform sample for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i for rv in bn.nodes(): # get possible values conditioned on everything else parents = bn.parents(rv) # no parents - prior if len(parents) == 0: choice_vals = bn.values(rv) choice_probs = bn.cpt(rv) # has parent - filter cpt else: f = Factor(bn, rv) for p in parents: f.reduce_factor(p, state[p]) choice_vals = bn.values(rv) choice_probs = f.cpt # sample over remaining possibilities chosen_val = np.random.choice(choice_vals, p=choice_probs) state[rv] = chosen_val # update sample_dict dictionary if i > burn: for rv, val in state.items(): sample_dict[rv][val] += 1 for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] = round( int(sample_dict[rv][val]) / float(n - burn), 4) return sample_dict
def forward_sample(bn, n=1000): """ Approximate marginal probabilities from forward sampling algorithm on a BayesNet object. This algorithm works by repeatedly sampling from the BN and taking the ratio of observations as their marginal probabilities. One sample is done by first sampling from any prior random variables, then moving down the network in topological sort order - sampling from each successive random variable by conditioning on its parents (which have already been sampled higher up the network). Note that there is no evidence to include in this algorithm - the comparative algorithm which includes evidence is the likelihood weighted algorithm (see "lw_sample" function). Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take Returns ------- *sample_dict* : a dictionary, where key = rv, value = another dict where key = instance, value = its probability value Notes ----- - Evidence is not currently implemented. """ sample_dict = {} for var in bn.nodes(): sample_dict[var] = {} for val in bn.values(var): sample_dict[var][val] = 0 for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i new_sample = {} for rv in bn.nodes(): f = Factor(bn, rv) for p in bn.parents(rv): f.reduce_factor(p, new_sample[p]) choice_vals = bn.values(rv) choice_probs = f.cpt chosen_val = np.random.choice(choice_vals, p=choice_probs) sample_dict[rv][chosen_val] += 1 new_sample[rv] = chosen_val for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] = int(sample_dict[rv][val]) / float(n) return sample_dict
def lw_sample(bn, evidence={}, target=None, n=1000): """ Approximate Marginal probabilities from likelihood weighted sample algorithm on a BayesNet object. Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take *evidence* : a dictionary, where key = rv, value = instantiation Returns ------- *sample_dict* : a dictionary where key = rv and value = another dictionary where key = rv instantiation and value = marginal probability Effects ------- None Notes ----- """ sample_dict = {} weight_list = np.ones(n) #factor_dict = dict([(var,Factor(bn, var)) for var in bn.V]) #parent_dict = dict([(var, bn.data[var]['parents']) for var in bn.V]) for var in bn.nodes(): sample_dict[var] = {} for val in bn.values(var): sample_dict[var][val] = 0 for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i new_sample = {} for rv in bn.nodes(): f = Factor(bn, rv) # reduce_factor by parent samples for p in bn.parents(rv): f.reduce_factor(p, new_sample[p]) # if rv in evidence, choose that value and weight if rv in evidence: chosen_val = evidence[rv] weight_list[i] *= f.cpt[bn.values(rv).index(evidence[rv])] # if rv not in evidence, sample as usual else: choice_vals = bn.values(rv) choice_probs = f.cpt chosen_val = np.random.choice(choice_vals, p=choice_probs) new_sample[rv] = chosen_val # weight the choice by the evidence likelihood for rv in new_sample: sample_dict[rv][new_sample[rv]] += 1 * weight_list[i] weight_sum = sum(weight_list) for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] /= weight_sum sample_dict[rv][val] = round(sample_dict[rv][val], 4) if target is not None: return sample_dict[target] else: return sample_dict
def gibbs_sample(bn, n=1000, burn=200): """ Approximate Marginal probabilities from Gibbs Sampling over a BayesNet object. Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take *burn* : an integer The number of beginning samples to throw away for the MCMC mixing. Returns ------- *sample_dict* : a dictionary where key = rv and value = another dictionary where key = rv instantiation and value = marginal probability Notes ----- """ sample_dict ={} for rv in bn.nodes(): sample_dict[rv]={} for val in bn.values(rv): sample_dict[rv][val] = 0 state = {} for rv in bn.nodes(): state[rv] = np.random.choice(bn.values(rv)) # uniform sample for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i for rv in bn.nodes(): # get possible values conditioned on everything else parents = bn.parents(rv) # no parents - prior if len(parents) == 0: choice_vals = bn.values(rv) choice_probs = bn.cpt(rv) # has parent - filter cpt else: f = Factor(bn,rv) for p in parents: f.reduce_factor(p,state[p]) choice_vals = bn.values(rv) choice_probs = f.cpt # sample over remaining possibilities chosen_val = np.random.choice(choice_vals,p=choice_probs) state[rv]=chosen_val # update sample_dict dictionary if i > burn: for rv,val in state.items(): sample_dict[rv][val] +=1 for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] = round(int(sample_dict[rv][val]) / float(n-burn),4) return sample_dict
def lw_sample(bn, evidence={}, target=None, n=1000): """ Approximate Marginal probabilities from likelihood weighted sample algorithm on a BayesNet object. Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take *evidence* : a dictionary, where key = rv, value = instantiation Returns ------- *sample_dict* : a dictionary where key = rv and value = another dictionary where key = rv instantiation and value = marginal probability Effects ------- None Notes ----- """ sample_dict = {} weight_list = np.ones(n) # factor_dict = dict([(var,Factor(bn, var)) for var in bn.V]) # parent_dict = dict([(var, bn.data[var]['parents']) for var in bn.V]) # create sample diction ct_discard = 0 for var in bn.nodes(): sample_dict[var] = {} # print(var) for val in bn.values(var): # print (val) sample_dict[var][val] = 0 # start to draw sample for i in range(n): new_sample = {} for rv in bn.nodes(): # _get_variable_nodes() # for rv in a: # print(rv,'rv is variable') f = Factor(bn, rv) # reduce_factor by parent samples for p in bn.parents(rv): if p in new_sample: f.reduce_factor(p, new_sample[p]) #this line has problem else: #austin add this line to cheat on sampling algorithm # pass new_sample[p] = '1' f.reduce_factor(p, new_sample[p]) # f2 = Factor(bn, p) # choice_vals = bn.values(p) # choice_probs = f2.cpt # chosen_val = np.random.choice(choice_vals, p=choice_probs) # new_sample[rv] = chosen_val # if rv in evidence, choose that value and weight if rv in evidence: # print(rv,'in evidence') chosen_val = evidence[rv] # print(chosen_val,'chosen_val in evidence') weight_list[i] *= f.cpt[bn.values(rv).index(evidence[rv])] # print(weight_list[i],'weight') # if rv not in evidence, sample as usual else: # print(new_sample) choice_vals = bn.values(rv) choice_probs = f.cpt # print(choice_probs) # print(choice_probs) # print(len(choice_vals),len(choice_probs)) chosen_val = np.random.choice(choice_vals, p=choice_probs) # print(weight_list) new_sample[rv] = chosen_val # weight the choice by the evidence likelihood for rv in new_sample: sample_dict[rv][new_sample[rv]] += 1 * weight_list[i] if weight_list[i] == 0: ct_discard += 1 weight_sum = sum(weight_list) # print("total discard sample", ct_discard) # I only add this line for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] /= weight_sum sample_dict[rv][val] = round(sample_dict[rv][val], 4) if target is not None: return sample_dict[target] else: return sample_dict, ct_discard
def lw_sample(bn, evidence={}, target=None, n=1000): """ Approximate Marginal probabilities from likelihood weighted sample algorithm on a BayesNet object. Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take *evidence* : a dictionary, where key = rv, value = instantiation Returns ------- *sample_dict* : a dictionary where key = rv and value = another dictionary where key = rv instantiation and value = marginal probability Effects ------- None Notes ----- """ sample_dict = {} weight_list = np.ones(n) #factor_dict = dict([(var,Factor(bn, var)) for var in bn.V]) #parent_dict = dict([(var, bn.data[var]['parents']) for var in bn.V]) for var in bn.nodes(): sample_dict[var] = {} for val in bn.values(var): sample_dict[var][val] = 0 for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i new_sample = {} for rv in bn.nodes(): f = Factor(bn,rv) # reduce_factor by parent samples for p in bn.parents(rv): f.reduce_factor(p,new_sample[p]) # if rv in evidence, choose that value and weight if rv in evidence: chosen_val = evidence[rv] weight_list[i] *= f.cpt[bn.values(rv).index(evidence[rv])] # if rv not in evidence, sample as usual else: choice_vals = bn.values(rv) choice_probs = f.cpt chosen_val = np.random.choice(choice_vals, p=choice_probs) new_sample[rv] = chosen_val # weight the choice by the evidence likelihood for rv in new_sample: sample_dict[rv][new_sample[rv]] += 1*weight_list[i] weight_sum = sum(weight_list) for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] /= weight_sum sample_dict[rv][val] = round(sample_dict[rv][val],4) if target is not None: return sample_dict[target] else: return sample_dict
def forward_sample(bn, n=1000): """ Approximate marginal probabilities from forward sampling algorithm on a BayesNet object. This algorithm works by repeatedly sampling from the BN and taking the ratio of observations as their marginal probabilities. One sample is done by first sampling from any prior random variables, then moving down the network in topological sort order - sampling from each successive random variable by conditioning on its parents (which have already been sampled higher up the network). Note that there is no evidence to include in this algorithm - the comparative algorithm which includes evidence is the likelihood weighted algorithm (see "lw_sample" function). Arguments --------- *bn* : a BayesNet object *n* : an integer The number of samples to take Returns ------- *sample_dict* : a dictionary, where key = rv, value = another dict where key = instance, value = its probability value Notes ----- - Evidence is not currently implemented. """ sample_dict = {} for var in bn.nodes(): sample_dict[var] = {} for val in bn.values(var): sample_dict[var][val] = 0 for i in range(n): #if i % (n/float(10)) == 0: # print 'Sample: ' , i new_sample = {} for rv in bn.nodes(): f = Factor(bn,rv) for p in bn.parents(rv): f.reduce_factor(p,new_sample[p]) choice_vals = bn.values(rv) choice_probs = f.cpt chosen_val = np.random.choice(choice_vals, p=choice_probs) sample_dict[rv][chosen_val] += 1 new_sample[rv] = chosen_val for rv in sample_dict: for val in sample_dict[rv]: sample_dict[rv][val] = int(sample_dict[rv][val]) / float(n) return sample_dict