Changeset 186
- Timestamp:
- 05/20/08 15:42:21 (8 months ago)
- Files:
-
- projects/AsynCluster/trunk/svpmc/model.c (modified) (16 diffs)
- projects/AsynCluster/trunk/svpmc/model.py (modified) (3 diffs)
- projects/AsynCluster/trunk/svpmc/test/test_model.py (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
projects/AsynCluster/trunk/svpmc/model.c
r185 r186 122 122 123 123 124 // A selection of a propos al sample124 // A selection of a proposed log-volatility simulation 125 125 struct selection 126 126 { 127 127 int kp; 128 double L p;128 double Lh; 129 129 }; 130 130 … … 213 213 // preparation for decorrelation 214 214 for(k=0; k<N; k++) 215 // TODO: Should we use a stripped-down version of exp here for speed? 215 216 SPA1(S, x0, k) = exp(-0.5 * SPA1(S, h, k)) * PA1(x, k); 216 217 … … 247 248 // Returns with zero only if the post-first proposals are close enough to 248 249 // finish likelihood computation 249 int notCloseEnough(struct sample *sp[][2], int n)250 int notCloseEnough(struct sample sp[][2], int n) 250 251 { 251 252 int k; … … 254 255 double Lmax = -HUGE_VAL; // Anything will be more positive 255 256 for(k=0; k<n; k++) { 256 L = sp[k][1] ->Lx;257 L = sp[k][1].Lx; 257 258 if(L < Lmin) 258 259 Lmin = L; … … 271 272 // the log-probability of the proposal's having been selected. 272 273 struct selection \ 273 importanceSample(struct sample *sp[][2], double Lz[], int n)274 importanceSample(struct sample sp[][2], double Lz[], int n) 274 275 { 275 276 int k, kpMax; 276 277 double val; 277 double pSum = 0;278 double Dp[n]; 278 279 double pMax = -HUGE_VAL; // Anything will be more positive 279 double Dp[n];280 280 struct selection result; 281 281 282 // Compute linear probability density for each proposal 282 // Compute linear probability density for each proposal and their maximum 283 283 for(k=0; k<n; k++) { 284 val = exp(sp[k][1] ->Lx + Lz[k]);284 val = exp(sp[k][1].Lx + Lz[k]); 285 285 Dp[k] = val; 286 pSum += val;287 286 if(val > pMax) { 288 287 pMax = val; … … 299 298 } while(result.kp != kpMax && uniform(0, pMax) > Dp[result.kp]); 300 299 301 // Only one division operation is needed! 302 result.Lp = log(Dp[result.kp] / (pMax*pSum)); 300 // The probability density of the selected log-volatility proposal is just 301 // the linear weight of the selected sample 302 result.Lh = log(Dp[result.kp]); 303 303 return result; 304 304 } … … 342 342 double val; 343 343 double Lx = 0; 344 double L p= 0;344 double Lh = 0; 345 345 346 346 // Multivariate innovation for one current time-series sample … … 348 348 // Log probability density of each proposal on z 349 349 double Lz[n]; 350 // Linear probability density of each log-volatility proposal351 double Dp[n];352 350 353 351 // A struct for the result of the importance-sampling function … … 373 371 for(k1=0; k1<2; k1++) { 374 372 sp[k0][k1].Lx = 0; 375 sp[k0][k1].h = (double *) calloc(sizeof(double), Nt); 376 sp[k0][k1].x0 = (double *) calloc(sizeof(double), Nt); 377 sp[k0][k1].x1 = (double *) calloc(sizeof(double), Nt); 378 } 373 sp[k0][k1].z = (double *) malloc(sizeof(double) * Nt); 374 sp[k0][k1].h = (double *) malloc(sizeof(double) * Nt); 375 sp[k0][k1].x0 = (double *) malloc(sizeof(double) * Nt); 376 sp[k0][k1].x1 = (double *) malloc(sizeof(double) * Nt); 377 } 378 // The "previous" log-volatility of the first time-series sample is zero 379 for(k1=0; k1<Nt; k1++) 380 PA1(sp[k0][0].h, k1) = 0; 379 381 } 380 382 … … 389 391 for(k2=0; k2<n; k2++) 390 392 Lz[k2] = 0; 391 393 392 394 do { 393 395 … … 405 407 Lz[k2] += normLogDensity(val); 406 408 } 407 SPA1(sp[k2][notFirst],z, k3) = val;409 PA1(sp[k2][notFirst].z, k3) = val; 408 410 } 409 411 } … … 426 428 for(k2=0; k2<n; k2++) { 427 429 for(k3=0; k3<Nt; k3++) 428 SPA1(sp[k2][1], h, k3) = SPA1(sp[k2][0],h, k3);430 PA1(sp[k2][1].h, k3) = PA1(sp[k2][0].h, k3); 429 431 } 430 432 } … … 432 434 } while (k1==k0+1 || (k1<Ns && notCloseEnough(sp, n))); 433 435 434 // Importance sample proposal using pProb=exp(Lz+Lx) for each 435 spSelection = importanceSample(sp, Lz, Dp, n); 436 Lp += log(spSelection.Lp); 436 // Importance sample proposal using pProb=exp(Lz+Lx) for each... 437 spSelection = importanceSample(sp, Lz, n); 438 // ...add the log-density of the selected log-volatility proposal to what 439 // will be the total log-density of the entire simulated h... 440 Lh += spSelection.Lh; 441 // ...and update the normal variate underlying the curent time-series sample 442 // to that on which the selected log-volatility proposal was based. 437 443 for(k1=0; k1<Nt; k1++) 438 Z2(k1,k0) = SPA1(sp[spSelection.kp][1],z, k1);439 444 Z2(k1,k0) = PA1(sp[spSelection.kp][0].z, k1); 445 440 446 // Set the initial log-volatility of the proposals for the next time-series 441 447 // sample to the log-volatility of the selected proposal for this time-series 442 448 // sample. 443 for(k1=0; k1< n; k1++) {444 val = SPA1(sp[spSelection.kp][1],h, k1);445 for(k2=0; k2< Nt; k2++)446 SPA1(sp[k1][0], h, k2) = val;449 for(k1=0; k1<Nt; k1++) { 450 val = PA1(sp[spSelection.kp][1].h, k1); 451 for(k2=0; k2<n; k2++) 452 PA1(sp[k2][0].h, k1) = val; 447 453 } 448 454 … … 453 459 // sample 454 460 for(k0=0; k0<Nt; k0++) 455 H1(k0) = SPA1(sp[kp][1],h, k0);461 H1(k0) = PA1(sp[kp][1].h, k0); 456 462 457 463 // Free array memory … … 459 465 for(k0=0; k0<n; k0++) { 460 466 for(k1=0; k1<2; k1++) { 467 free(sp[k0][k1].z); 461 468 free(sp[k0][k1].h); 462 469 free(sp[k0][k1].x0); … … 465 472 } 466 473 467 // All done 468 result[0] = 0; 469 for(k0=0; k0<Nt; k0++) { 470 result[0] += sp[k0][0]->Lx; 471 result[1] = Lp; 474 // The pair of results is Lx, the log-likelihood of each innovation given its 475 // simulated log-volatility... 476 for(k0=0; k0<Nt; k0++) 477 Lx += sp[k0][0].Lx; 478 // ..and Lh, the total log-density of all of the simulated log-volatilities 479 result[0] = Lx; 480 result[1] = Lh; 472 481 return_val = result; projects/AsynCluster/trunk/svpmc/model.py
r184 r186 276 276 # ...including the latent parameter of IID normal variates 277 277 z = paramContainer.z.copy() 278 print self.fs, self.fr 278 279 279 280 # Set up arary variables for the inline call, including innovations as … … 293 294 return 294 295 # ...scaling constants for multivariate normal pdf 296 sc = s.empty((self.p, 2)) 295 297 sc[:,0] = s.sqrt(1 - self.g**2) 296 298 sc[:,1] = s.log(s.sqrt(2*s.pi) * sc[:,0]) … … 299 301 # one along with the state of the IID variate vector at that point. 300 302 Lx = 0 301 Lp = 0 302 for k in xrange(self.Mv): 303 Lh = 0 304 print "\n\n", z[0,:], rz, ri 305 for k in xrange(self.N2): 303 306 result = self.inline( 304 307 'z', 'h', 'x', 'w', 'n', 'd', 'e', 'g', 'rz', 'ri', 'sc', 305 308 w=self.wiggle, n=self.N1) 309 print "\n", k, result 310 print z[0,:] 306 311 Lx += result[0] 307 L p+= result[1]308 return Lx, L p, z, h312 Lh += result[1] 313 return Lx, Lh, z, h projects/AsynCluster/trunk/svpmc/test/test_model.py
r185 r186 27 27 from twisted.spread import pb 28 28 from asynqueue import ThreadQueue 29 from twisted_goodies.pybywire import pack, params 30 31 import model, tseries 29 from twisted_goodies.pybywire import pack 30 from twisted_goodies.pybywire.params import Parameterized 31 32 import params, model 32 33 import util 33 34 … … 40 41 41 42 42 class Mock_Model( params.Parameterized, util.Mock):43 class Mock_Model(Parameterized, util.Mock): 43 44 drift = 1.5 44 45 p, n = 8, 937 … … 109 110 self.nextCall(Mock_Client.calls) 110 111 self.nextCall( 111 'registerClasses', params.Parameterized.registry)112 'registerClasses', Parameterized.registry) 112 113 self.nextCall( 113 114 'update', ('newModel', self.model)) … … 144 145 } 145 146 146 def modelFactory(self, **kw):147 """148 Instantiate a model to be tested and set its parameters149 """150 kw['paramNames'] = util.PARAM_NAMES151 for name, value in self.params.iteritems():152 if name != 'y':153 if name in kw:154 value = kw[name]155 kw[name] = s.array(value)156 if 'y' not in kw:157 if hasattr(self, 'y'):158 kw['y'] = self.y159 else:160 kw['y'] = s.zeros((len(kw['fs']), self.N))161 return model.Model(**kw)162 163 147 def inline(self, code, **kw): 164 148 """ 165 149 Do an inline call with the model's Weaver API and support code. 166 150 """ 167 return self.modelFactory().inlineDirect(textwrap.dedent(code), **kw)151 return model.Model().inlineDirect(textwrap.dedent(code), **kw) 168 152 169 153 def _covarMatrix(self, cs, cr): … … 313 297 "Generated array \n%s\n != \n%s" % (y, x)) 314 298 315 modelObj = self.modelFactory()299 modelObj = model.Model() 316 300 tryCoeffs([1.0], [], [[1.0]]) 317 301 tryCoeffs([1.0, 1.0], [0.2], [[1.0, 0.2], [0.2, 1.0]]) … … 523 507 524 508 class Test_Model_spArray(BaseCase): 525 code = """509 codeBase = """ 526 510 int k; 527 const int n = NL[0]; 528 struct selection spSelection; 511 const int n = NX[0]; 529 512 struct sample sp[n][2]; 513 for(k=0; k<n; k++) 514 sp[k][1].Lx = X1(k); 515 """ 516 517 codeNCE = codeBase + """ 518 return_val = notCloseEnough(sp, n); 519 """ 520 521 codeIS = codeBase + """ 530 522 double Lz[n]; 531 523 py::tuple result(2); 532 533 for(k=0; k<n; k++) {524 struct selection spSelection; 525 for(k=0; k<n; k++) 534 526 Lz[k] = Z1(k); 535 sp[k][1].Lx = L1(k);536 }537 538 return_val = S.Lx;527 spSelection = importanceSample(sp, Lz, n); 528 result[0] = spSelection.kp; 529 result[1] = spSelection.Lp; 530 return_val = result; 539 531 """ 540 532 533 def _notCloseEnough(self, Lx_array): 534 return self.inline(self.codeNCE, X=Lx_array) 535 536 def _importanceSample(self, Lx_array, Lz_array=None): 537 if Lz_array is None: 538 Lz_array = s.zeros_like(Lx_array) 539 return self.inline(self.codeIS, X=Lx_array, Z=Lz_array) 540 541 def test_notCloseEnough_basic(self): 542 N = 8 543 Lx_array = s.zeros(N) 544 self.failUnlessEqual(self._notCloseEnough(Lx_array), 0) 545 Lx_array[0] = 1 546 self.failUnlessEqual(self._notCloseEnough(Lx_array), 1) 547 548 def test_importanceSample_basic(self): 549 N = 8 550 N_iter = 1000 551 Lx_array = s.zeros(N) 552 I = [self._importanceSample(Lx_array)[0] for k in xrange(N_iter)] 553 for k in xrange(N): 554 self.failUnless(k in I) 555 556 def test_importanceSample_normal(self): 557 N = 10 558 N_iter = 1000 559 distObj = stats.distributions.norm() 560 X = 8.0*s.rand(N_iter, N) - 4.0 561 Y = s.empty(N_iter) 562 Lp = s.empty(N_iter) 563 for k, Xk in enumerate(X): 564 Lx_array = s.log(distObj.pdf(Xk)) 565 kp, Lpk = self._importanceSample(Lx_array) 566 Y[k] = Xk[kp] 567 Lp[k] = Lpk 568 if VERBOSE: 569 I = Y.argsort() 570 sp = self.fig.add_subplot(111) 571 sp.plot(Y, s.exp(Lp), '.', Y[I], distObj.pdf(Y[I])) 572 self.failUnlessNormal(Y) 573 541 574 542 575 class Test_Model_likelihood(BaseCase): 543 N = 1000576 N = 6 544 577 corr = 0.0 545 578 params = { 546 579 'a': [0], 547 580 'b': [[0]], 548 'cs': [1.0],549 581 'cr': [], 550 582 'd': [0], … … 555 587 } 556 588 557 def _setupModel(self, **kw): 558 self.model = self.modelFactory(**kw) 559 # Simulate a single time series of data per the parameters 589 def _zToh(self, z, e, fs): 590 return signal.lfilter([1], [1.0, -e[0][0]], fs[0]*z) 591 592 def _modelAndParamFactory(self, N1, N2, **kw): 593 # Create a parameter container with the parameters set by my params 594 # dict, optionally overridden by keywords, and a zero log-volatility 595 # starting point 596 pc = params.ParameterContainer() 597 pc.paramNames = util.PARAM_NAMES 598 for name, value in self.params.iteritems(): 599 setattr(pc, name, s.array(kw.get(name, self.params[name]))) 600 print pc.paramSequence() 601 pc.z = 3*s.ones((1, self.N)) 602 # Simulate a single time series of innovation data per the parameters 560 603 self.iv = random.multivariate_normal( 561 604 [0, 0], 562 [[1.0, self.model.g[0]], [self.model.g[0], 1.0]], 563 self.N).transpose() 564 self.h = signal.lfilter( 565 [1], [1.0, -self.model.e[0][0]], self.model.fs[0]*self.iv[1,:]) 566 x = s.exp(0.5 * self.h) * self.iv[0,:] 567 # Instantiate a model to be tested and set its parameters 568 self.x = s.row_stack([x]) 569 self.model.y = self.x 570 571 def _runHG(self, N, sigma): 572 L = [] 573 z = s.randn(1, self.N) 574 rv = self._rv(self.model.fs, self.model.fr) 575 print "RV\n", rv, "\n" 576 for k in xrange(N): 577 L_this = self.model.hybridGibbs(z, self.x, rv, sigma)[0] 578 L.append(L_this) 579 print "%03d: L=%6.1f" % (k, L_this) 580 h = self.model.logVolatilities( 581 z, s.array(rv*z), self.x, self.model.d.copy())[-1] 605 [[1.0, pc.g[0]], [pc.g[0], 1.0]], self.N).transpose() 606 self.h = self._zToh(self.iv[1,:], pc.e, pc.fs) 607 self.x = s.exp(0.5 * self.h) * self.iv[0,:] 608 # Run the innovations through the VAR(1) to get the simulated 609 # observations 610 y = signal.lfilter([1], [1.0, -pc.b[0][0]], self.x) + \ 611 pc.a * s.ones_like(self.x) 612 # Return the parameter container along with a model to be tested 613 modelObj = model.Model(N1=N1, N2=N2) 614 modelObj.paramNames = util.PARAM_NAMES 615 modelObj.y = s.row_stack([y]) 616 return pc, modelObj 617 618 def _check(self, wiggle, N1, N2, **kw): 619 pc, modelObj = self._modelAndParamFactory(N1, N2, **kw) 620 modelObj.wiggle = wiggle 621 Lx, Lh, z, hn = modelObj.likelihood(pc) 622 # Reconstruct simulated h from z 623 h = self._zToh(z[0,:], pc.e, pc.fs) 582 624 if VERBOSE: 583 625 fig = self.fig 584 vectors = (self.x [0,:], (self.h, h[0,:]))626 vectors = (self.x, (self.h, h)) 585 627 for k, vector in enumerate(vectors): 586 spNumber = 100* (len(vectors)+1) + k + 11628 spNumber = 100*len(vectors) + k + 11 587 629 sp = fig.add_subplot(spNumber) 588 630 if not isinstance(vector, (tuple, list)): … … 590 632 for v in vector: 591 633 sp.plot(v) 592 fig.add_subplot(spNumber+1).plot(L) 593 self._check_corr(self.h, h[0,:]) 634 self._check_corr(self.h, h) 594 635 595 def test_hybridGibbs_highCorrelation(self): 596 self._setupModel(e=[[0.95]]) 597 # Sigma=0.5 seems to give us the supposedly ideal ~44% acceptance rate 598 self._runHG(20, 0.5) 636 def test_highCorrelation(self): 637 self._check(0.1, 10, 10, e=[[0.95]]) 599 638 600 639 def test_hybridGibbs_lowCorrelation(self):
