Beispiel #1
0
 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])
Beispiel #2
0
 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])
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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