Пример #1
0
    def testAll(self):
        """ this is actually the Water-sprinkler example """
        c = DiscretePotential(['c'], [2], [0.5,0.5])                  # Pr(C)
        s = DiscretePotential(['s','c'], [2,2], [0.5,0.9,0.5,0.1]) # Pr(S|C)
        r = DiscretePotential(['r','c'], [2,2], [0.8,0.2,0.2,0.8])    # Pr(R|C)
        w = DiscretePotential(['w','s','r'], [2,2,2])                # Pr(W|S,R)
        w[:,0,0] = [0.99, 0.01]
        w[:,0,1] = [0.1, 0.9]
        w[:,1,0] = [0.1, 0.9]
        w[:,1,1] = [0.0, 1.0]

        cr = c * r        # Pr(C,R)     = Pr(R|C) * Pr(C)
        crs = cr * s      # Pr(C,S,R)   = Pr(S|C) * Pr(C,R)
        print crs, crs.names_list
        print crs[:,0,0]
        crsw = crs * w    # Pr(C,S,R,W) = Pr(W|S,R) * Pr(C,R,S)

        # this can be verified using any bayesian network software

        # check the result for the multiplication and marginalisation
        assert(na.allclose(crsw.Marginalise('s r w'.split()).cpt, [0.5,0.5]) and \
               na.allclose(crsw.Marginalise('c r w'.split()).cpt, [0.7,0.3]) and \
               na.allclose(crsw.Marginalise('c s w'.split()).cpt, [0.5,0.5]) and \
               na.allclose(crsw.Marginalise('c s r'.split()).cpt, [0.349099,0.6509])), \
                "Something's wrong on the big Test..."
Пример #2
0
    def testSample(self):
##        cCPT = distributions.MultinomialDistribution(self.c)
##        sCPT = distributions.MultinomialDistribution(self.s)
##        rCPT = distributions.MultinomialDistribution(self.r)
##        wCPT = distributions.MultinomialDistribution(self.w)

        cCPT = self.c.distribution
        sCPT = self.s.distribution
        rCPT = self.r.distribution
        wCPT = self.w.distribution
        
        cCPT.initializeCounts() 
        sCPT.initializeCounts()
        rCPT.initializeCounts()
        wCPT.initializeCounts()

        for i in range(1000):
            sample = self.BNet.Sample()[0]
            # Can use sample in all of these, it will ignore extra variables
            cCPT.incrCounts(sample) 
            sCPT.incrCounts(sample) 
            rCPT.incrCounts(sample) 
            wCPT.incrCounts(sample)        
##            cCPT[sample] += 1
##            sCPT[sample] += 1
##            rCPT[sample] += 1
##            wCPT[sample] += 1
        assert(na.allclose(cCPT,self.c.distribution.cpt,atol=.1) and \
               na.allclose(sCPT,self.s.distribution.cpt,atol=.1) and \
               na.allclose(rCPT,self.r.distribution.cpt,atol=.1) and \
               na.allclose(wCPT,self.w.distribution.cpt,atol=.1)), \
               "Samples did not generate appropriate CPTs"
Пример #3
0
    def testLearning(self):
        """ Sample network and then learn parameters and check that they are relatively close to original.
        """
        ev = self.engine.BNet.Sample(n=10000)
        
        #Remember what the old CPTs looked like and keep track of original dimension order
        cCPT = self.c.distribution.cpt.copy()
        self.c.distribution.isAdjustable=True
        self.c.distribution.uniform()
        sCPT = self.s.distribution.cpt.copy()
        self.s.distribution.isAdjustable=True
        self.s.distribution.uniform()
        rCPT = self.r.distribution.cpt.copy()
        self.r.distribution.isAdjustable=True
        self.r.distribution.uniform()
        wCPT = self.w.distribution.cpt.copy()
        self.w.distribution.isAdjustable=True
        self.w.distribution.uniform()

        # Learn parameters
        self.engine.LearnMLParams(ev)
        
        # Check that they match original parameters
        assert(na.allclose(cCPT,self.c.distribution.cpt,atol=.1) and \
               na.allclose(sCPT,self.s.distribution.cpt,atol=.1) and \
               na.allclose(rCPT,self.r.distribution.cpt,atol=.1) and \
               na.allclose(wCPT,self.w.distribution.cpt,atol=.1)),\
              "CPTs were more than atol=.1 apart"
Пример #4
0
 def testDistributions(self):
     ' test the distributions'
     r = self.G.v['Rain']
     s = self.G.v['Sprinkler']
     w = self.G.v['Watson']
     h = self.G.v['Holmes']
     
     assert(allclose(r.distribution.cpt, [0.2, 0.8]) and \
             allclose(s.distribution.cpt, [0.1, 0.9]) and \
             allclose(w.distribution[{'Rain':1}], [0.2, 0.8]) ), \
             " Distribution values are not correct"
Пример #5
0
    def testInit(self):
        a = self.a
        b = self.b
        assert(a.g == 0.0 and \
               na.allclose(a.h, na.zeros(3)) and \
               na.allclose(a.K, na.zeros(shape=(3,3)))), \
               " Error with standard initialization "

        assert(b.g == 2.0 and \
               na.allclose(b.h, na.array([1,2,3], type='Float32')) and \
               na.allclose(b.K, na.arange(9,shape=(3,3), type='Float32'))), \
               " Error with standard initialization with parameter setting"    
Пример #6
0
    def testGeneral(self):
        """ Check that the overall algorithm works """
        c = self.engine.Marginalise('c')
        r = self.engine.Marginalise('r')
        s = self.engine.Marginalise('s')
        w = self.engine.Marginalise('w')

        assert(na.allclose(c.cpt, [0.5, 0.5]) and \
                na.allclose(r.cpt, [0.5, 0.5]) and \
                na.allclose(s.cpt, [0.7, 0.3]) and \
                na.allclose(w.cpt, [0.34909999, 0.65090001])), \
                " Somethings wrong with JoinTree inference engine"
Пример #7
0
    def testInference(self):
        """ Loads the RainWatson BN, performs inference and checks the results """
        self.engine = JoinTree(self.G)
        r=self.engine.Marginalise('Rain')        
        s=self.engine.Marginalise('Sprinkler')
        w=self.engine.Marginalise('Watson')
        h=self.engine.Marginalise('Holmes')

        assert(allclose(r.cpt,[0.2,0.8]) and \
               allclose(s.cpt,[0.1,0.9]) and \
               allclose(w.cpt,[0.36,0.64]) and \
               allclose(h.cpt,[ 0.272, 0.728]) ), \
               " Somethings wrong with JoinTree inference engine"
Пример #8
0
    def testObservedDiscrete(self):
        """ DISCRETE: Compute and check the probability of water-sprinkler given some evidence
        """
        self.engine.SetObs({'c':1,'s':0})
        res = self.engine.MarginaliseAll()
        
        cprob, sprob, rprob, wprob = res['c'], res['s'], res['r'], res['w']

        error = 0.05        
        assert(na.allclose(cprob.cpt,[0.0,1.0], atol=error) and \
               na.allclose(rprob.cpt,[0.2,0.8], atol=error) and \
               na.allclose(sprob.cpt,[1.0,0.0], atol=error) and \
               na.allclose(wprob.cpt,[ 0.278, 0.722], atol=error) ), \
               " Somethings wrong with MCMC inference with evidence "        
Пример #9
0
    def testEvidence(self):
        """ check that evidence works """
        print 'evidence c=1,s=0'
        self.engine.SetObs({'c':1,'s':0})
        
        c = self.engine.Marginalise('c')
        r = self.engine.Marginalise('r')
        s = self.engine.Marginalise('s')
        w = self.engine.Marginalise('w')

        assert(na.allclose(c.cpt,[0.0,1.0]) and \
                na.allclose(r.cpt,[0.2,0.8]) and \
                na.allclose(s.cpt,[1.0,0.0]) and \
                na.allclose(w.cpt,[ 0.278, 0.722]) ), \
                " Somethings wrong with JoinTree evidence"        
Пример #10
0
    def testUnobservedDiscrete(self):
        """ DISCRETE: Compute and check the probability of water-sprinkler given no evidence
        """
        cprob, rprob, sprob, wprob = self.engine.MarginaliseAll()

        error = 0.05
        #print cprob[True] <= (0.5 + error)and cprob[True] >= (0.5-error)
        #print wprob[True] <= (0.65090001 + 2*error) and wprob[True] >= (0.65090001 - 2*error)
        #print sprob[True] <= (0.3 + error) and sprob[True] >= (0.3 - error)
        
        assert(na.allclose(cprob[True], 0.5, atol = error) and \
               na.allclose(sprob[True], 0.3, atol = error) and \
               na.allclose(rprob[True], 0.5, atol = error) and \
               na.allclose(wprob[True], 0.6509, atol = error)), \
        "Incorrect probability with unobserved water-sprinkler network"
Пример #11
0
    def testEM(self):
        # sample the network 2000 times
        cases = self.BNet.Sample(2000)
        # delete some observations
        for i in range(500):
            case = cases[3*i]
            rand = random.sample(['c','s','r','w'],1)[0]
            case[rand] = '?' 
        for i in range(50):
            case = cases[3*i]
            rand = random.sample(['c','s','r','w'],1)[0]
            case[rand] = '?'

        # create a new BNet with same nodes as self.BNet but all parameters
        # set to 1s
        G = copy.deepcopy(self.BNet)
        
        G.InitDistributions()
        
        engine = EMLearningEngine(G)
        engine.EMLearning(cases, 10)
        
        tol = 0.08
        assert(na.alltrue([na.allclose(v.distribution.cpt, self.BNet.v[v.name].distribution.cpt, atol=tol) \
               for v in engine.BNet.all_v])), \
                " Learning does not converge to true values "
        print 'ok!!!!!!!!!!!!'
Пример #12
0
 def __eq__(a,b):
     """ True if a and b have same elements, size and names """
     if b.__class__ == na.NumArray:
     # in case b is a just a numarray and not a Table instance
     # in this case, variable should absoltely be at the same order
     # otherwise the Table and numArray are considered as different
         return (na.alltrue(a.cpt.flat == b.flat) \
                 and a.shape == b.shape)
         
     
     elif b == None:
     # in case b is None type
         return False
     
     elif isinstance(b, (int, float, long)):
     # b is just a number, int, float, long
         return a.cpt == b
     
     else:
     # the b class should better be a Table or something like that
     # order of variables is not important
         # put the variables in the same order
         # first must get the correspondance vector :
         bcpt = a.prepareOther(b)
         return (a.names == b.names and \
                 bcpt.shape == a.shape and \
                 na.allclose(bcpt, a.cpt))
Пример #13
0
 def testSample(self):
     cCPT = distributions.MultinomialDistribution(self.c)
     sCPT = distributions.MultinomialDistribution(self.s)
     rCPT = distributions.MultinomialDistribution(self.r)
     wCPT = distributions.MultinomialDistribution(self.w)
     for i in range(1000):
         sample = self.BNet.Sample
         # Can use sample in all of these, it will ignore extra variables
         cCPT[sample] += 1
         sCPT[sample] += 1
         rCPT[sample] += 1
         wCPT[sample] += 1
     assert(na.allclose(cCPT,self.c.cpt,atol=.1) and \
            na.allclose(sCPT,self.s.cpt,atol-.1) and \
            na.allclose(rCPT,self.r.cpt,atol-.1) and \
            na.allclose(wCPT,self.w.cpt,atol-.1)), \
            "Samples did not generate appropriate CPTs"
Пример #14
0
 def hasntConverged(self, old, new, precision):
     '''
     Return true if the difference of distribution of at least one vertex 
     of the old and new BNet is bigger than precision
     '''
     if not old :
         return True   
     else:
         return not  na.alltrue([na.allclose(v.distribution, new.v[v.name].distribution, atol=precision) for v in old.v.values()])
Пример #15
0
    def testSampling(self):
        " Test the sample() function "
        a = self.a.distribution

        a.setParameters(mu=5, sigma=1)

        # take 1000 samples from distribution
        samples = [a.sample() for i in range(1000)]

        # verify values
        b = self.a.GetSamplingDistribution()
        b.initializeCounts()
        b.incrCounts(samples)
        b.setCounts()

        error=0.05
        assert(na.allclose(b.mean, a.mean, atol = error) and \
                na.allclose(b.sigma, a.sigma, atol=error)), \
                "Sampling does not seem to produce a gaussian distribution"

        gd = self.g.distribution	#2 discrete parents, 2 continuous parents
Пример #16
0
    def testCounting(self):
        " test counting of samples"
        a = self.a.distribution
        a.initializeCounts()

        assert(a.samples == list()), \
        "Samples list not initialized correctly"

        a.incrCounts(range(10))
        a.incrCounts(5)

        assert(a.samples == range(10) + [5]), \
               "Elements are not added correctly to Samples list"

        a.setCounts()
        error = 0.0001
        assert(na.allclose([a.mean, a.sigma], [4.545454, 2.876324], atol = error)), \
               "Mu and sigma doesn't seem to be calculated correctly..."
Пример #17
0
 def testML(self):
     # sample the network 2000 times
     cases = self.BNet.Sample(2000)
     
     # create a new BNet with same nodes as self.BNet but all parameters
     # set to 1s
     G = copy.deepcopy(self.BNet)
     
     G.InitDistributions()
     
     # create an infeence engine
     engine = JoinTree(G)
     
     # learn according to the test cases
     engine.LearnMLParams(cases)
     
     tol = 0.05
     assert(na.alltrue([na.allclose(v.distribution.cpt, self.BNet.v[v.name].distribution.cpt, atol=tol) \
            for v in G.all_v])), \
             " Learning does not converge to true values "
Пример #18
0
def _isClose(a, b, *args, **kargs):
    return bool(na.allclose(na.ravel(a), na.ravel(b), *args, **kargs))
Пример #19
0
    def testIndexing(self):
        fd = self.f.distribution	# 2 discrete parents : d(2),e(3)

        fd.setParameters(mu=range(6), sigma=range(6))

#		 # test normal indexing
#		 assert(na.allclose(fd[0][0].flat, na.array(range(3),type='Float32')) and \
#				na.allclose(fd[0][1].flat, na.array(range(3), type='Float32')) and \
#				na.allclose(fd[1,2][0].flat, na.array(5, type='Float32')) and \
#				na.allclose(fd[1,2][1].flat, na.array(5, type='Float32'))), \
#		 "Normal indexing does not seem to work..."

        # test dict indexing
        assert(na.allclose(fd[{'d':0}][0].flat, na.array(range(3), type='Float32')) and \
               na.allclose(fd[{'d':0}][1].flat, na.array(range(3), type='Float32')) and \
               na.allclose(fd[{'d':1,'e':2}][0].flat, na.array(5, type='Float32')) and \
               na.allclose(fd[{'d':1,'e':2}][1].flat, na.array(5, type='Float32'))), \
        "Dictionary indexing does not seem to work..." 

        # now test setting of parameters
        fd[{'d':1,'e':2}] = {'mean':0.5, 'sigma':0.6}
        fd[{'d':0}] = {'mean':[0,1.2,2.4],'sigma':[0,0.8,0.9]}
        na.allclose(fd[{'d':0}][0].flat, na.array([0,1.2,2.4],type='Float32'))
        assert(na.allclose(fd[{'d':0}][0].flat, na.array([0,1.2,2.4],type='Float32')) and \
               na.allclose(fd[{'d':0}][1].flat,na.array([0,0.8,0.9],type='Float32')) and \
               na.allclose(fd[{'d':1,'e':2}][0].flat, na.array(0.5, type='Float32')) and \
               na.allclose(fd[{'d':1,'e':2}][1].flat, na.array(0.6, type='Float32'))), \
        "Setting of values using dict does not seem to work..."				

        # now run tests for continuous parents
        cd = self.c.distribution	# 2 continuous parents a(1),b(2)

        cd[{'a':0,'b':1}] = {'weights':69}
        assert(na.allclose(cd[{'a':0,'b':1}][2],69.0)), \
        "Indexing for continuous parents does not work"