Commit 5bf5c41d authored by Manuel Baum's avatar Manuel Baum
Browse files

Had to change linear dependencies in Exponential and Beta Nodes to sigmoid...

Had to change linear dependencies in Exponential and Beta Nodes to sigmoid functions on weighted sums. Also introduced a more complex example for Continuous Nodes
parent 6b07f5bc
......@@ -8,9 +8,11 @@ the probability of evidence.
from primo.core import BayesNet
from primo.reasoning import DiscreteNode
from primo.reasoning.density import ProbabilityTable
#from primo.reasoning.factorelemination import EasiestFactorElimination
from primo.reasoning.factorelemination import FactorTreeFactory
from primo.reasoning import MCMC
from primo.reasoning import EvidenceEqual as EvEq
import numpy
#==============================================================================
......@@ -123,23 +125,23 @@ print "====MCMC===="
print "Prior Marginal:"
print "AlarmFT: " + str(mcmc_ask.calculate_PriorMarginal([alarm]))
print "John_CallsFT: " + str(mcmc_ask.calculate_PriorMarginal([john_calls]))
print "Baum_CallsFT: " + str(mcmc_ask.calculate_PriorMarginal([baum_calls]))
print "BurglaryFT: " + str(mcmc_ask.calculate_PriorMarginal([burglary]))
print "EarthquakeFT: " + str(mcmc_ask.calculate_PriorMarginal([earthquake]))
print "AlarmFT: " + str(mcmc_ask.calculate_PriorMarginal([alarm],ProbabilityTable))
print "John_CallsFT: " + str(mcmc_ask.calculate_PriorMarginal([john_calls],ProbabilityTable))
print "Baum_CallsFT: " + str(mcmc_ask.calculate_PriorMarginal([baum_calls],ProbabilityTable))
print "BurglaryFT: " + str(mcmc_ask.calculate_PriorMarginal([burglary],ProbabilityTable))
print "EarthquakeFT: " + str(mcmc_ask.calculate_PriorMarginal([earthquake],ProbabilityTable))
evidences = {alarm: "Ringing",earthquake: "Calm"}
evidences = {alarm: EvEq("Ringing"),earthquake: EvEq("Calm")}
print "PoE: " + str(mcmc_ask.calculate_PoE(evidences))
print "Posterior Marginal (alarm->ringing , earthquake->calm):"
print "AlarmFT: " + str(mcmc_ask.calculate_PosteriorMarginal([alarm],evidences))
print "John_CallsFT: " + str(mcmc_ask.calculate_PosteriorMarginal([john_calls],evidences))
print "Baum_CallsFT: " + str(mcmc_ask.calculate_PosteriorMarginal([baum_calls],evidences))
print "BurglaryFT: " + str(mcmc_ask.calculate_PosteriorMarginal([burglary],evidences))
print "EarthquakeFT: " + str(mcmc_ask.calculate_PosteriorMarginal([earthquake],evidences))
print "AlarmFT: " + str(mcmc_ask.calculate_PosteriorMarginal([alarm],evidences,ProbabilityTable))
print "John_CallsFT: " + str(mcmc_ask.calculate_PosteriorMarginal([john_calls],evidences,ProbabilityTable))
print "Baum_CallsFT: " + str(mcmc_ask.calculate_PosteriorMarginal([baum_calls],evidences,ProbabilityTable))
print "BurglaryFT: " + str(mcmc_ask.calculate_PosteriorMarginal([burglary],evidences,ProbabilityTable))
print "EarthquakeFT: " + str(mcmc_ask.calculate_PosteriorMarginal([earthquake],evidences,ProbabilityTable))
......
from primo.core import BayesNet
from primo.reasoning import ContinuousNodeFactory
from primo.reasoning.density import LinearExponentialParameters
from primo.reasoning.density import LinearBetaParameters
from primo.reasoning.density import LinearGaussParameters
from primo.reasoning.density import Gauss
from primo.reasoning import MCMC
from primo.reasoning import EvidenceEqual as EvEqual
from primo.reasoning import EvidenceIntervall as EvInterval
import numpy
#Construct some simple BayesianNetwork. In this example it models
#the linear relationship between the age of a plant and the height that
#it has grown up to (+noise)
bn = BayesNet()
cnf=ContinuousNodeFactory()
#create the nodes
age = cnf.createLinearExponentialNode("Age")
sun = cnf.createLinearBetaNode("Sun")
ground= cnf.createLinearGaussNode("Ground")
growth= cnf.createLinearGaussNode("Growth")
height = cnf.createLinearBetaNode("Height")
diameter = cnf.createLinearExponentialNode("Diameter")
children = cnf.createLinearExponentialNode("Children")
#add the nodes to the network
bn.add_node(age)
bn.add_node(sun)
bn.add_node(ground)
bn.add_node(growth)
bn.add_node(height)
bn.add_node(diameter)
bn.add_node(children)
#include connectivity
bn.add_edge(age,growth)
bn.add_edge(ground,growth)
bn.add_edge(sun,growth)
bn.add_edge(growth,diameter)
bn.add_edge(growth,height)
bn.add_edge(height,children)
bn.add_edge(ground,children)
#parameterization
age_parameters=LinearExponentialParameters(0.0,{})
age.set_density_parameters(age_parameters)
sun.set_density_parameters(LinearBetaParameters(2,{},2,{}))
ground.set_density_parameters(LinearGaussParameters(2.0,{},1.5))
#age,ground,sun
growth.set_density_parameters(LinearGaussParameters(0.1,{age:5.0,ground:1.0,sun:4.0},2.5))
height_parameters=LinearBetaParameters(0.0,{growth:1},0.5,{growth:0.5})
height.set_density_parameters(height_parameters)
diameter_parameters=LinearExponentialParameters(0.01,{growth:0.2})
diameter.set_density_parameters(diameter_parameters)
children.set_density_parameters(LinearExponentialParameters(0,{ground:1.0,height:1.0}))
mcmc_ask=MCMC(bn)
evidence={age:EvEqual(2)}
#print "ProbabilityOfEvidence: "
#poe=mcmc_ask.calculate_PoE(evidence)
#print poe
print "PosteriorMarginal:"
pm=mcmc_ask.calculate_PosteriorMarginal([age,height],evidence,Gauss)
#pm=mcmc_ask.calculate_PosteriorMarginal([height],evidence,Gauss)
print pm
print "PriorMarginal:"
pm=mcmc_ask.calculate_PriorMarginal([age],Gauss)
print pm
#pm=mcmc_ask.calculate_PriorMarginal([height,diameter],Gauss)
pm=mcmc_ask.calculate_PriorMarginal([height],Gauss)
print pm
......@@ -9,6 +9,9 @@ class ContinuousNode(Node):
self.density_class = DensityClass
self.cpd = DensityClass(self)
def __str__(self):
return self.name
def set_density_parameters(self, density_parameters):
self.cpd.set_parameters(density_parameters)
......
......@@ -71,6 +71,7 @@ class MetropolisHastingsTransitionModel(object):
return p
def transition(self, network, state, extern_evidence):
#print state
nodes = network.get_nodes([])
nodes_to_resample=[n for n in nodes if not n in extern_evidence.keys() or extern_evidence[n].get_unambigous_value() == None]
for node in nodes_to_resample:
......@@ -80,7 +81,9 @@ class MetropolisHastingsTransitionModel(object):
p_of_proposal_given_mb = self._compute_p_of_value_given_mb(network, state, node, proposed_value)
p_of_current_given_mb = self._compute_p_of_value_given_mb(network, state, node, current_value)
#print node.name
#print p_of_proposal_given_mb
#print p_of_current_given_mb
acceptance_probability = min(1.0, p_of_proposal_given_mb/p_of_current_given_mb * 1.0/1.0)
if random.random() <= acceptance_probability:
state[node]=proposed_value
......
from primo.reasoning.density import Density
from primo.reasoning import ContinuousNode
from scipy.stats import beta
import random
import math
class LinearBetaParameters():
def __init__(self, b0, b, alpha, beta):
self.b0=b0
self.b=b
self.alpha=alpha
self.beta=beta
def __init__(self, p0, p, q0, q):
self.p=p
self.q=q
self.p0=p0
self.q0=q0
class LinearBeta(Density):
def __init__(self, node):
self.b={}
self.b0=0
self.alpha=1
self.beta=1
self.p0=1
self.q0=1
self.p={}
self.q={}
self.node=node
def set_parameters(self,parameters):
self.b=parameters.b
self.b0=parameters.b0
self.alpha=parameters.alpha
self.beta=parameters.beta
self.p0=parameters.p0
self.q0=parameters.q0
self.p=parameters.p
self.q=parameters.q
def add_variable(self, variable):
'''This method needs some serious reworking: Variables should not be permitted
to be parents because of their value range. Instead it should be evaluated
if they can yield parameters for this distribution that are permitted. This
can in any case happen under bad influence coefficients'''
if( not variable.get_value_range() == (0,float("Inf"))):
raise Exception("Tried to add Variable into Gaussian densitiy, but variable had wrong value-range")
self.b[variable]=0.0
if( not isinstance(variable,ContinuousNode.ContinuousNode)):
raise Exception("Tried to add Variable as parent, but is not a ContinuousNode")
self.p[variable]=0.0
self.q[variable]=0.0
def get_probability(self,value, node_value_pairs):
#print "Probability to compute for value:"+str(value)
#Compute the offset for the density and displace the value accordingly
x = self.b0
#print "X:"+str(x)
p = self.p0
q = self.q0
for node,node_value in node_value_pairs:
x = x + self.b[node]*node_value
#print "X:"+str(x)
#print value
value=value-x
#Evaluate the displaced density at value
#print str(value)
if value<0 or value>1:
return 0
return beta(self.alpha, self.beta).pdf(value)
p = p + self.p[node]*node_value
q = q + self.q[node]*node_value
return beta(p, q).pdf(value)
def _compute_p_given_parents(self, state):
x = self.p0
for node in self.p.keys():
if node in state.keys():
x = x + self.p[node]*state[node]
return 1.0/(1.0+math.exp(-x))
def _compute_offset_given_parents(self, state):
x = self.b0
for node in self.b.keys():
def _compute_q_given_parents(self, state):
x = self.q0
for node in self.q.keys():
if node in state.keys():
x = x + self.b[node]*state[node]
return x
x = x + self.q[node]*state[node]
return 1.0/(1.0+math.exp(-x))
def sample_global(self, state):
value=random.betavariate(self.alpha,self.beta)+self._compute_offset_given_parents(state)
p=self._compute_p_given_parents(state)
q=self._compute_q_given_parents(state)
value=random.betavariate(p,q)
#print "Sampled:"+str(value)
return value
......@@ -2,12 +2,12 @@ from primo.reasoning.density import Density
import scipy.stats
import random
import math
from primo.reasoning import ContinuousNode
class LinearExponentialParameters(object):
def __init__(self, b0, b, lambda0):
def __init__(self, b0, b):
self.b0=b0
self.b=b
self.lambda0=lambda0
......@@ -15,21 +15,19 @@ class LinearExponential(Density):
def __init__(self, node):
self.b={}
self.b0=0
self.lambda0=1
self.node=node
def set_parameters(self,parameters):
self.b=parameters.b
self.b0=parameters.b0
self.lambda0=parameters.lambda0
def add_variable(self, variable):
'''This method needs some serious reworking: Variables should not be denied
to be parents because of their value range. Instead it should be evaluated
if they can yield parameters for this distribution that are permitted. This
can in any case happen under bad influence coefficients'''
if( not variable.get_value_range() == (0,float("Inf"))):
raise Exception("Tried to add Variable into Gaussian densitiy, but variable had wrong value-range")
if( not isinstance(variable,ContinuousNode.ContinuousNode)):
raise Exception("Tried to add Variable as parent, but is not a ContinuousNode")
self.b[variable]=0.0
def get_probability(self,value, node_value_pairs):
......@@ -38,18 +36,19 @@ class LinearExponential(Density):
x = self.b0
for node,value in node_value_pairs:
x = x + self.b[node]*value
value=value-x
_lambda=1.0/(1.0+math.exp(-x))
#print "lambda:"+str(_lambda)
#Evaluate the displaced density at value
if value<0:
return 0
return self.lambda0*math.exp(-self.lambda0*value)
return _lambda*math.exp(-_lambda*value)
def _compute_offset_given_parents(self, state):
def _compute_lambda_given_parents(self, state):
x = self.b0
for node in self.b.keys():
if node in state.keys():
x = x + self.b[node]*state[node]
return x
_lambda=1.0/(1.0+math.exp(-x))
return _lambda
def sample_global(self,state):
return random.expovariate(self.lambda0)+self._compute_offset_given_parents(state)
_lambda=self._compute_lambda_given_parents(state)
return random.expovariate(_lambda)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment