Skip to content
Snippets Groups Projects
Commit 3ca3d590 authored by Manuel Baum's avatar Manuel Baum
Browse files

Worked on MCMC examples

parent 3f5e87bf
No related branches found
No related tags found
No related merge requests found
...@@ -5,15 +5,14 @@ from primo.reasoning.density import LinearBetaParameters ...@@ -5,15 +5,14 @@ from primo.reasoning.density import LinearBetaParameters
from primo.reasoning.density import LinearGaussParameters from primo.reasoning.density import LinearGaussParameters
from primo.reasoning.density import Gauss from primo.reasoning.density import Gauss
from primo.reasoning import MCMC from primo.reasoning import MCMC
from primo.reasoning.convergence_test import ConvergenceTestSimpleCounting
from primo.reasoning import EvidenceEqual as EvEqual from primo.reasoning import EvidenceEqual as EvEqual
from primo.reasoning import EvidenceIntervall as EvInterval from primo.reasoning import EvidenceLower as EvLower
import numpy import numpy
#Construct some simple BayesianNetwork. In this example it models #Construct some simple BayesianNetwork.
#the linear relationship between the age of a plant and the height that
#it has grown up to (+noise)
#topology #topology
bn = BayesNet() bn = BayesNet()
...@@ -28,17 +27,34 @@ bn.add_edge(age,height) ...@@ -28,17 +27,34 @@ bn.add_edge(age,height)
bn.add_edge(age,diameter) bn.add_edge(age,diameter)
#parameterization #parameterization
age_parameters=LinearExponentialParameters(1.0,{},2.0) #Semantics: Many young plants and the higher the age the lower the probabilty
#->lambda=2.0
age_parameters=LinearExponentialParameters(0.0,{})
age.set_density_parameters(age_parameters) age.set_density_parameters(age_parameters)
height_parameters=LinearGaussParameters(0.1,{age:1},0.3) #Semantics: plants start at 0.1 meters underground and grow each year by 1 meter.
# variance is 0.3
height_parameters=LinearGaussParameters(-0.1,{age:1},0.3)
height.set_density_parameters(height_parameters) height.set_density_parameters(height_parameters)
diameter_parameters=LinearBetaParameters(0.01,{age:0.2},2,5) #Semantics: At small age: low alpha, high beta -> skew to the left: thin plants
# At higher age: high alpha, low beta -> skew to the right: thick plants
diameter_parameters=LinearBetaParameters(-10.0,{age:4.0},10.0,{age:-4.0})
diameter.set_density_parameters(diameter_parameters) diameter.set_density_parameters(diameter_parameters)
mcmc_ask=MCMC(bn,1000) mcmc_ask=MCMC(bn,100000,convergence_test=ConvergenceTestSimpleCounting(50000))
print "------PriorMarginal:------"
pm=mcmc_ask.calculate_PriorMarginal([age],Gauss)
print pm
print "Ground truth: mu=0.5 C=[0.25]"
#pm=mcmc_ask.calculate_PriorMarginal([height,diameter],Gauss)
pm=mcmc_ask.calculate_PriorMarginal([height],Gauss)
print pm
print ""
evidence={age:EvEqual(2)} evidence={age:EvEqual(2)}
...@@ -47,14 +63,18 @@ evidence={age:EvEqual(2)} ...@@ -47,14 +63,18 @@ evidence={age:EvEqual(2)}
#poe=mcmc_ask.calculate_PoE(evidence) #poe=mcmc_ask.calculate_PoE(evidence)
#print poe #print poe
print "PosteriorMarginal:" print "------PosteriorMarginal:------"
pm=mcmc_ask.calculate_PosteriorMarginal([age,height],evidence,Gauss) pm=mcmc_ask.calculate_PosteriorMarginal([age,height],evidence,Gauss)
#pm=mcmc_ask.calculate_PosteriorMarginal([height],evidence,Gauss) #pm=mcmc_ask.calculate_PosteriorMarginal([height],evidence,Gauss)
print "P(age,height|age=2):"
print pm print pm
print "Ground truth: age=2, height=mu:1.9,C=0.3"
print "------PropabilityOfEvidence------"
poe=mcmc_ask.calculate_PoE({age:EvLower(0.347)})
print "Probabilty that age is lower than it's median:"
print "p(age<0.347)="+str(poe)
print "Ground truth=0.5"
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
...@@ -11,13 +11,15 @@ import pdb ...@@ -11,13 +11,15 @@ import pdb
#Construct some simple BayesianNetwork #Construct some simple BayesianNetwork
bn = BayesNet() bn = BayesNet()
burglary = DiscreteNode("Burglary", ["Intruder","Safe"]) burglary = DiscreteNode("Burglary", ["Intruder","Safe"])
alarm = DiscreteNode("Alarm", ["Ringing", "Silent","Kaputt"]) alarm = DiscreteNode("Alarm", ["Ringing", "Silent","Destroyed"])
bn.add_node(burglary) bn.add_node(burglary)
bn.add_node(alarm) bn.add_node(alarm)
bn.add_edge(burglary,alarm) bn.add_edge(burglary,alarm)
#Parametrize the network
burglary_cpt=numpy.array([0.2,0.8]) burglary_cpt=numpy.array([0.2,0.8])
burglary.set_probability_table(burglary_cpt, [burglary]) burglary.set_probability_table(burglary_cpt, [burglary])
...@@ -25,29 +27,36 @@ alarm_cpt=numpy.array([[0.8,0.15,0.05],[0.05,0.9,0.05]]) ...@@ -25,29 +27,36 @@ alarm_cpt=numpy.array([[0.8,0.15,0.05],[0.05,0.9,0.05]])
alarm.set_probability_table(alarm_cpt, [burglary,alarm]) alarm.set_probability_table(alarm_cpt, [burglary,alarm])
#Get some inference object
mcmc_ask=MCMC(bn,5000)
#Do some Inferences
mcmc_ask=MCMC(bn,1000)
evidence={burglary:EvEq("Intruder")} evidence={burglary:EvEq("Intruder")}
print "-------ProbabilityOfEvidence:-------"
print "---ProbabilityOfEvidence:---"
poe=mcmc_ask.calculate_PoE(evidence) poe=mcmc_ask.calculate_PoE(evidence)
print poe print "p(evidence=Intruder)="+str(poe)
print "Ground truth=0.2\n"
print "---PosteriorMarginal:---" print "-------PosteriorMarginal:-------"
pm=mcmc_ask.calculate_PosteriorMarginal([alarm],evidence,ProbabilityTable) pm=mcmc_ask.calculate_PosteriorMarginal([alarm],evidence,ProbabilityTable)
print pm print "P(alarm|burglary=Intruder)="+str(pm)
print "Ground truth=[0.8, 0.15, 0.05]\n"
print "---PriorMarginal:---" print "-------PriorMarginal:-------"
pm=mcmc_ask.calculate_PriorMarginal([alarm],ProbabilityTable) pm=mcmc_ask.calculate_PriorMarginal([alarm],ProbabilityTable)
print "Alarm: " + str(pm) print "P(Alarm)= " + str(pm)
print "Ground truth=[0.2, 0.75, 0.05]\n"
pm=mcmc_ask.calculate_PriorMarginal([burglary],ProbabilityTable) pm=mcmc_ask.calculate_PriorMarginal([burglary],ProbabilityTable)
print "Burglary: " + str(pm) print "P(Burglary)= " + str(pm)
print "Ground truth=[0.2, 0.8]\n"
print "---MAP:---" print "-------MAP:-------"
hyp=mcmc_ask.calculate_MAP([alarm],evidence,ProbabilityTable) hyp=mcmc_ask.calculate_MAP([alarm],evidence,ProbabilityTable)
print str(evidence) + ": " + str(hyp) print "MAP(alarm|burglary=intruder)=" + str(hyp)
hyp=mcmc_ask.calculate_MAP([alarm],{},ProbabilityTable) print "Ground truth=\"Ringing\"\n"
print str({}) + ": "+str(hyp)
hyp=mcmc_ask.calculate_MAP([burglary,alarm],{},ProbabilityTable)
print "MAP(burglary,alarm)="+str(hyp)
print "Ground truth=\"Safe\",\"Silent\"\n"
from primo.core import BayesNet
from primo.reasoning import ContinuousNodeFactory
from primo.reasoning.density import LinearGaussParameters
from primo.reasoning.density import Gauss
from primo.reasoning import MCMC
from primo.reasoning import EvidenceEqual as EvEq
from primo.reasoning import EvidenceLower as EvLower
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)
#topology
bn = BayesNet()
cnf=ContinuousNodeFactory()
age = cnf.createLinearGaussNode("Plant_age")
height = cnf.createLinearGaussNode("Plant_height")
diameter = cnf.createLinearGaussNode("Plant_diameter")
bn.add_node(age)
bn.add_node(height)
bn.add_node(diameter)
bn.add_edge(age,height)
bn.add_edge(age,diameter)
#parameterization
age_b0=4.0
age_var=2.0
age_b={}
age_parameters=LinearGaussParameters(age_b0,age_b,age_var)
age.set_density_parameters(age_parameters)
height_b0=2.0
height_var=1.5
height_b={age:0.5}
height_parameters=LinearGaussParameters(height_b0,height_b,height_var)
height.set_density_parameters(height_parameters)
diameter_parameters=LinearGaussParameters(0.1,{age:-0.2},0.1)
diameter.set_density_parameters(diameter_parameters)
mcmc_ask=MCMC(bn,1000)
evidence={age:EvEq(2)}
#print "ProbabilityOfEvidence: "
#poe=mcmc_ask.calculate_PoE(evidence)
#print poe
print "PosteriorMarginal:"
pm=mcmc_ask.calculate_PosteriorMarginal([height,diameter],evidence,Gauss)
print pm
print "PriorMarginal:"
pm=mcmc_ask.calculate_PriorMarginal([height,diameter],Gauss)
print pm
print "ProbabilityOfEvidence:"
poe=mcmc_ask.calculate_PoE({age:EvLower(4.0)})
print "p(age<4.0):"+str(poe)+ " GroundTruth:0.5"
poe=mcmc_ask.calculate_PoE({age:EvInterval(4.0-2.0**0.5,4.0)})
print "p(4.0-2.0^0.5<age<4.0):"+str(poe)+ " GroundTruth:1/3"
#print "PriorMarginal:"
#pm=mcmc_ask.calculate_PriorMarginal([alarm])
#print "Alarm: " + str(pm)
#pm=mcmc_ask.calculate_PriorMarginal([burglary])
#print "Burglary: " + str(pm)
...@@ -24,6 +24,9 @@ class ContinuousNode(RandomNode): ...@@ -24,6 +24,9 @@ class ContinuousNode(RandomNode):
def __str__(self): def __str__(self):
return self.name return self.name
def __repr__(self):
return "str(ContinuousNode)"+self.name+")"
def set_density_parameters(self, density_parameters): def set_density_parameters(self, density_parameters):
self.cpd.set_parameters(density_parameters) self.cpd.set_parameters(density_parameters)
...@@ -50,10 +53,15 @@ class ContinuousNode(RandomNode): ...@@ -50,10 +53,15 @@ class ContinuousNode(RandomNode):
reimplement it by constructing the integral over the normalvariate in the reimplement it by constructing the integral over the normalvariate in the
intervalls allowed by the evidence and then generate a sample directly. intervalls allowed by the evidence and then generate a sample directly.
Currently this method has O(inf).''' Currently this method has O(inf).'''
v=random.normalvariate(x,1.0) std_walk=0.1
v=random.normalvariate(x,std_walk)
if self in evidence.keys(): if self in evidence.keys():
while not evidence[self].is_compatible(v): while not (evidence[self].is_compatible(v) and self.value_range[0]<v and v<self.value_range[1]):
v=random.normalvariate(x,1.0) v=random.normalvariate(x,std_walk)
else:
while not (self.value_range[0]<v and v<self.value_range[1]):
v=random.normalvariate(x,std_walk)
#print "REEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"+self.name+" " +str(v)
return v return v
def sample_global(self, state): def sample_global(self, state):
......
...@@ -14,6 +14,12 @@ class DiscreteNode(RandomNode): ...@@ -14,6 +14,12 @@ class DiscreteNode(RandomNode):
self.value_range = value_range self.value_range = value_range
self.cpd = ProbabilityTable() self.cpd = ProbabilityTable()
self.cpd.add_variable(self) self.cpd.add_variable(self)
def __str__(self):
return self.name
def __repr__(self):
return "DiscreteNode("+self.name+")"
def set_probability(self, value, node_value_pairs): def set_probability(self, value, node_value_pairs):
self.cpd.set_probability(value, node_value_pairs) self.cpd.set_probability(value, node_value_pairs)
......
...@@ -61,9 +61,5 @@ class Gauss(Density): ...@@ -61,9 +61,5 @@ class Gauss(Density):
return self return self
def __str__(self): def __str__(self):
ret= "Gauss:\n" ret= "Gauss(\nmu="+str(self.mu)+"\nC="+str(self.C)+")"
ret=ret+ "--mu--\n"
ret=ret+ str(self.mu)+"\n"
ret=ret+ "--C--\n"
ret=ret+ str(self.C)+"\n"
return ret return ret
...@@ -10,6 +10,7 @@ class LinearBetaParameters(): ...@@ -10,6 +10,7 @@ class LinearBetaParameters():
self.p0=p0 self.p0=p0
self.q0=q0 self.q0=q0
class LinearBeta(Density): class LinearBeta(Density):
def __init__(self, node): def __init__(self, node):
self.p0=1 self.p0=1
...@@ -18,6 +19,9 @@ class LinearBeta(Density): ...@@ -18,6 +19,9 @@ class LinearBeta(Density):
self.q={} self.q={}
self.node=node self.node=node
self.input_scale=0.1
self.output_scale=5.0
def set_parameters(self,parameters): def set_parameters(self,parameters):
self.p0=parameters.p0 self.p0=parameters.p0
self.q0=parameters.q0 self.q0=parameters.q0
...@@ -38,28 +42,35 @@ class LinearBeta(Density): ...@@ -38,28 +42,35 @@ class LinearBeta(Density):
def get_probability(self,value, node_value_pairs): def get_probability(self,value, node_value_pairs):
#print "Probability to compute for value:"+str(value) #print "Probability to compute for value:"+str(value)
#Compute the offset for the density and displace the value accordingly #Compute the offset for the density and displace the value accordingly
p = self.p0 #p = self.p0
q = self.q0 #q = self.q0
for node,node_value in node_value_pairs:
p = p + self.p[node]*node_value
q = q + self.q[node]*node_value
return beta(p, q).pdf(value) #for node,node_value in node_value_pairs:
# p = p + self.p[node]*node_value
# q = q + self.q[node]*node_value
#p=1.0/(1.0+math.exp(-p))
#q=1.0/(1.0+math.exp(-q))
p=self._compute_p_given_parents(dict(node_value_pairs))
q=self._compute_q_given_parents(dict(node_value_pairs))
#print node_value_pairs
#print "beta "+str(p)+" "+str(q)
probability = beta(p, q).pdf(value)
#print "/beta"
return probability
def _compute_p_given_parents(self, state): def _compute_p_given_parents(self, state):
x = self.p0 x = self.p0
for node in self.p.keys(): for node in self.p.keys():
if node in state.keys(): if node in state.keys():
x = x + self.p[node]*state[node] x = x + self.p[node]*state[node]
return 1.0/(1.0+math.exp(-x)) return self.output_scale*1.0/(1.0+math.exp(-x*self.input_scale))
def _compute_q_given_parents(self, state): def _compute_q_given_parents(self, state):
x = self.q0 x = self.q0
for node in self.q.keys(): for node in self.q.keys():
if node in state.keys(): if node in state.keys():
x = x + self.q[node]*state[node] x = x + self.q[node]*state[node]
return 1.0/(1.0+math.exp(-x)) return self.output_scale*1.0/(1.0+math.exp(-x*self.input_scale))
def sample_global(self, state): def sample_global(self, state):
......
...@@ -17,6 +17,9 @@ class LinearExponential(Density): ...@@ -17,6 +17,9 @@ class LinearExponential(Density):
self.b0=0 self.b0=0
self.node=node self.node=node
self.input_scale=1.0
self.output_scale=4.0
def set_parameters(self,parameters): def set_parameters(self,parameters):
self.b=parameters.b self.b=parameters.b
self.b0=parameters.b0 self.b0=parameters.b0
...@@ -33,10 +36,7 @@ class LinearExponential(Density): ...@@ -33,10 +36,7 @@ class LinearExponential(Density):
def get_probability(self,value, node_value_pairs): def get_probability(self,value, node_value_pairs):
#Compute the offset for the density and displace the value accordingly #Compute the offset for the density and displace the value accordingly
x = self.b0 _lambda = self._compute_lambda_given_parents(dict(node_value_pairs))
for node,value in node_value_pairs:
x = x + self.b[node]*value
_lambda=1.0/(1.0+math.exp(-x))
#print "lambda:"+str(_lambda) #print "lambda:"+str(_lambda)
#Evaluate the displaced density at value #Evaluate the displaced density at value
return _lambda*math.exp(-_lambda*value) return _lambda*math.exp(-_lambda*value)
...@@ -46,9 +46,11 @@ class LinearExponential(Density): ...@@ -46,9 +46,11 @@ class LinearExponential(Density):
for node in self.b.keys(): for node in self.b.keys():
if node in state.keys(): if node in state.keys():
x = x + self.b[node]*state[node] x = x + self.b[node]*state[node]
_lambda=1.0/(1.0+math.exp(-x)) _lambda=self.output_scale*1.0/(1.0+math.exp(-x*self.input_scale))
return _lambda return _lambda
def sample_global(self,state): def sample_global(self,state):
_lambda=self._compute_lambda_given_parents(state) _lambda=self._compute_lambda_given_parents(state)
return random.expovariate(_lambda) sample=random.expovariate(_lambda)
#print "EXPO-SAMPLE: "+str(sample)+" at lambda: "+str(_lambda)
return sample
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment