Changeset 176
- Timestamp:
- 05/09/08 22:13:35 (8 months ago)
- Files:
-
- projects/AsynCluster/trunk/svpmc/model.py (modified) (7 diffs)
- projects/AsynCluster/trunk/svpmc/params.py (modified) (5 diffs)
- projects/AsynCluster/trunk/svpmc/pmc.py (modified) (2 diffs)
- projects/AsynCluster/trunk/svpmc/test/test_params.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
projects/AsynCluster/trunk/svpmc/model.py
r175 r176 123 123 # An error from the remote likelihood method call is treated as 124 124 # infinitely low likelihood 125 result = (-s.inf, [], [], 0 )125 result = (-s.inf, [], [], 0, 0) 126 126 elif isinstance(result, str): 127 127 # Unpack string result from remote call 128 128 result = list(pack.Unpacker(result)) 129 for k, name in enumerate(('Lx', 'h', 'z', ' acceptanceRate')):129 for k, name in enumerate(('Lx', 'h', 'z', 'Lh', 'acceptanceRate')): 130 130 setattr(paramContainer, name, result[k]) 131 131 return paramContainer … … 312 312 Updates the IID normal variates in place. Returns the likelihood of the 313 313 innovations in I{x}, given the simulated log-volatilities, along with 314 the last sample's multivariate log-volatility value and the fractional 315 acceptance rate of the MCMC steps. 316 314 the last sample's multivariate log-volatility value, the 315 log-probability of the simulated result, and the fractional acceptance 316 rate of the MCMC steps. 317 317 318 The method will account for the effect of log-volatility proposals on 318 319 downstream samples. You can specify the maximum fractional effect to … … 321 322 """ 322 323 L_total = 0 324 L_result = 0 323 325 acceptances = 0 324 326 N = self.decaySamples(tol) … … 343 345 # Metropolis-Hastings accept/reject of the proposal 344 346 dL = LVp[1] - LV[1] 345 if dL > 0 or self.logUniform() < dL: 347 if dL < -600 or not s.isfinite(dL): 348 # Bogus likelihood or infintesimally small probability of 349 # acceptance, just reject 350 accept = False 351 elif dL > 0: 352 # Always accept if the proposal's likelihood is better 353 accept = True 354 elif self.logUniform() < dL: 355 # Proposal likelihood worse, but accepted 356 L_result += dL 357 accept = True 358 else: 359 # Proposal likelihood worse and rejected 360 L_result += s.log(1 - s.exp(dL)) 361 accept = False 362 if accept: 346 363 LV = LVp 347 364 z[:,k] = zp[:,k] … … 354 371 # guaranteed not to be resampled, just bail out now and save time 355 372 if L_total < -1E6: 356 return -s.inf, s.zeros_like(h0), 0.0 357 return L_total, h0, float(acceptances)/self.n373 return -s.inf, s.zeros_like(h0), 0.0, 0.0 374 return L_total, h0, L_result, float(acceptances)/self.n 358 375 359 376 … … 395 412 3. The IID normal variates underlying the log-volatilities. 396 413 397 4. The mean acceptance rate of the Metropolis-Hastings proposals. 414 4. The log-probability of the simulated result. 415 416 5. The mean acceptance rate of the Metropolis-Hastings proposals. 398 417 399 418 The returned likelihood does not consider the prior probability of the … … 419 438 # one along with the state of the IID variate vector at that point, 420 439 # bailing out with no result if invalid parameter raises exception 440 L_result = 0 421 441 acceptRates = [] 422 442 try: 423 for k in xrange(self.Mv-1): 424 acceptRates.append(self.hybridGibbs(z, x, rv, sigma)[2]) 443 for k in xrange(self.Mv): 444 info = self.hybridGibbs(z, x, rv, sigma) 445 L_result += info[2] 446 acceptRates.append(info[3]) 425 447 except linalg.LinAlgError: 426 448 return 427 L, h0, thisRate = self.hybridGibbs(z, x, rv, sigma) 428 return L, h0, z, sum(acceptRates + [thisRate])/self.Mv 429 449 return info[0], info[1], z, L_result, sum(acceptRates)/self.Mv 450 projects/AsynCluster/trunk/svpmc/params.py
r174 r176 290 290 return self.distObj.rvs(1)[0] 291 291 292 def rJump(self): 293 """ 294 Returns a value that jumps from zero by a random amount that is drawn 295 from a normal distribution with a pre-scaled standard deviation that is 296 set to approximate the 70% probability width of my distribution. (That 297 is the +/- 1 standard deviation width of a normal distribution.) 298 """ 299 return self.rdsObj.rvs(1)[0] 300 301 def pJump(self, x, V, pV): 302 """ 303 Returns the probability density of the supplied jump value I{x} given a 304 mixture distribution of normals with standard deviations in the 305 supplied 1-D array I{V} of jump deviations and like-dimensioned array 306 I{pV} of mixture weights for normals having those deviations. 307 """ 308 densities = self.rdsObj.pdf(x/V) / V 309 return (pV * densities).sum() 292 def rJump(self, wiggle): 293 """ 294 Returns a value that jumps from zero by a random amount that, before 295 scaling by the supplied I{wiggle}, is drawn from a normal distribution 296 with a pre-scaled standard deviation that is set to approximate the 70% 297 probability width of my distribution. (That is the +/- 1 standard 298 deviation width of a normal distribution.) 299 """ 300 return wiggle * self.rdsObj.rvs(1)[0] 301 302 def pJump(self, x, wiggle): 303 """ 304 Returns the probability density of the supplied jump value I{x}, given 305 that it was generated by a call to my L{rJump} method with the 306 specified I{wiggle}. 307 308 For my Gaussian-PDF deviate generator, the probability density of the 309 jump is inversely proportional to the scaling to its standard deviation 310 imparted by I{wiggle}. Thus, the unit-normal PDF is divided by the 311 I{wiggle} in the result. 312 """ 313 return self.rdsObj.pdf(x/wiggle) / wiggle 310 314 311 315 … … 360 364 Returns a new instance of L{ParameterContainer} with a random-walk 361 365 proposal based on the supplied I{paramContainer}, my priors, the jump 362 deviation defined at the I{vIndex} position of my 1-D array tof jump366 deviation defined at the I{vIndex} position of my 1-D array of jump 363 367 deviations, and a 1-D array I{pV} of mixture weights for the jump 364 368 deviations in the jump distribution. … … 376 380 if vIndex < 0 or vIndex >= len(self.V): 377 381 raise ValueError("Invalid jump deviation index %d" % vIndex) 378 if len(pV) != len(self.V):382 if getattr(pV, 'shape', 0) != self.V.shape: 379 383 raise ValueError( 380 "M ixture weight sequence must haveone element per "+\384 "Must supply a mixture weight array with one element per "+\ 381 385 "jump deviation") 382 386 if self.typeChecking and \ … … 388 392 newVersion = ParameterContainer( 389 393 paramNames=self.paramNames, z=s.array(paramContainer.z).copy()) 390 Lp, Lj = 0, 0 394 Lp = 0 395 # Define a 1-D array holding the probability density for each jump, 396 # joint across all parameters. Since the densities will be scaled by 397 # the weight for each jump deviation, just start the array with the 398 # weights. 399 pJumps = pV.copy() 391 400 for name in self.paramNames: 392 401 priorFlexArray = getattr(self, name) 393 402 for attempt in xrange(self.attempts): 394 jumps = vJump * priorFlexArray.call('rJump')403 jumps = priorFlexArray.call('rJump', vJump) 395 404 paramArray = getattr(paramContainer, name) + jumps 396 405 pPriors = priorFlexArray.call('pdf', paramArray) … … 401 410 return paramContainer 402 411 Lp += s.log(pPriors).sum() 403 pMixtures = priorFlexArray.call( 404 'pJump', jumps, self.V, pV, arrayArgs=(1,2)) 405 Lj += s.log(pMixtures).sum() 412 for k, v in enumerate(self.V): 413 pJumps[k] *= priorFlexArray.call('pJump', jumps, v).prod() 406 414 setattr(newVersion, name, paramArray) 407 415 newVersion.Lp = Lp 408 newVersion.Lj = Lj416 newVersion.Lj = s.log(pJumps.sum()) 409 417 return newVersion projects/AsynCluster/trunk/svpmc/pmc.py
r175 r176 199 199 def weight(paramContainer): 200 200 if s.isfinite(paramContainer.Lx): 201 L = paramContainer.Lx + paramContainer.Lp - paramContainer.Lj 201 L = paramContainer.Lx + paramContainer.Lp \ 202 - paramContainer.Lj #- paramContainer.Lh 202 203 info = " ".join([ 203 204 "%+12.2f" % (getattr(paramContainer, x),) 204 for x in ( "Lx", "Lp", "Lj")])205 for x in ('Lx', 'Lp', 'Lj', 'Lh')]) 205 206 info += "\t\t%02d%%" % (100*paramContainer.acceptanceRate,) 206 207 else: 207 208 info = "" 208 209 L = -s.inf 209 print "%6.4f\t% s" % (self.pm.V[vIndex], info)210 print "%6.4f\t%+12.2f\t%s" % (self.pm.V[vIndex], L, info) 210 211 return L 211 212 … … 256 257 % (N_iter, N_members) 257 258 for i in xrange(N_iter): 258 print "\n%03d\n%s" % (i+1, "-"* 79)259 print "\n%03d\n%s" % (i+1, "-"*100) 259 260 dList, resultList = [], [] 260 261 for vIndex, I, d in self.allocator.assembler(resultList): projects/AsynCluster/trunk/svpmc/test/test_params.py
r174 r176 290 290 def test_proposal_basic(self): 291 291 old = util.Mock_ParameterContainer(0.0) 292 new = self.priorContainer.proposal(old, 0, [1.0, 0.0, 0.0]) 292 new = self.priorContainer.proposal(old, 0, s.array([1.0, 0.0, 0.0])) 293 self.failUnless(s.isfinite(new.Lj)) 294 #print new.Lj, sum([ 295 # (x**2).sum() 296 # for x in [ 297 # getattr(new, y) for y in self.priorContainer.paramNames]]) 293 298 return self._check_basic(new) 294 299 … … 300 305 #X = self.priorContainer.new() 301 306 for k in xrange(N): 302 XP = self.priorContainer.proposal(X, 1, [0.0, 1.0, 0.0])307 XP = self.priorContainer.proposal(X, 1, s.array([0.0, 1.0, 0.0])) 303 308 if k == 0 or XP.Lp > X.Lp or s.log(s.rand()) < (XP.Lp - X.Lp): 304 309 print "+",
