Changeset 202
- Timestamp:
- 05/28/08 23:43:21 (6 months ago)
- Files:
-
- projects/AsynCluster/trunk/svpmc/model.c (modified) (8 diffs)
- projects/AsynCluster/trunk/svpmc/model.py (modified) (1 diff)
- projects/AsynCluster/trunk/svpmc/test/test_model.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
projects/AsynCluster/trunk/svpmc/model.c
r201 r202 175 175 176 176 177 // Random variate from a truncated normal distribution 178 double truncnorm(double a, double b) 179 { 180 int k; 181 register double x; 182 double c, cp; 183 const double diff = b-a; 184 // Compute the scale value c as the maximum possible pdf (regular normal 185 // distribution) within the truncated range 186 if(a < 0) { 187 if(b > 0) { 188 // Center is within the range, so use its pdf 189 c = 1; 190 } else { 191 // Range is below center, so use pdf at its right edge 192 c = EXP(-0.5*b*b); 193 } 194 } else { 195 // Range is above center, so use pdf at its left edge 196 c = EXP(-0.5*a*a); 197 } 198 // Accept-reject sampling for the truncated normal distribution 199 do { 200 // Generate a proposal within the truncated range 201 x = a + diff*drand48(); 202 // Compute the pdf of the proposal, using the regular normal distribution 203 cp = EXP(-0.5*x*x); 204 // Accept (and exit the loop) when the scaled uniform variate is less than 205 // the proposal's pdf 206 } while(c*drand48() > cp); 207 return x; 208 } 209 210 177 211 // Matrix multiplication x*y -> z, where the square matrix 'x' is a 178 212 // PyArrayObject and 'y' and 'z' are 1-D arrays. … … 234 268 //SPA1(S, x0, k) = exp(-0.5 * SPA1(S, h, k)) * PA1(x, k); 235 269 // 236 // This is very fast, but has error of about +/-2% 270 // This is very fast, but has error of about +/-2%. However, the error 271 // doesn't seem to make any difference in the variance of log-likelihood 272 // estimates. 237 273 SPA1(S, x0, k) = EXP(-0.5 * SPA1(S, h, k)) * PA1(x, k); 238 274 … … 310 346 int ki, ke; 311 347 int k0, k1, k2, k3; 312 double val ;348 double val, maxVal; 313 349 314 350 // Multivariate innovation for one current time-series sample … … 319 355 // first time-series sample of the evaluation interval 320 356 double he[2][Nt]; 321 // Log probability density of the value of z for current and proposal322 // evaluations, working values323 double Lzk[2];324 357 // Log-likelihood of the innovation for the first time-series sample in current 325 358 // and proposal evalutions, working values and accumulated for each iteration … … 372 405 // Clear the log-likelihood and normal log-density accumulators of each 373 406 // evaluation struct for the next pair of evaluations. 374 for(k2=0; k2<2; k2++) {407 for(k2=0; k2<2; k2++) 375 408 se[k2].Lx = 0; 376 Lzk[k2] = 0;377 409 // Lxk[.] will be set to a value in se[.].Lx that has already been 378 410 // multivariate-accumulated, so it doesn't need clearing here 379 }380 411 381 412 do { … … 395 426 // First time-series sample for the second evaluation, use a 396 427 // proposal on z instead of z itself 397 val += uniform(-w,+w);428 val = truncnorm(val-w, val+w); 398 429 zp[k3] = val; 399 430 } 400 // Store the log-density of z for the first time-series sample to401 // compare current vs. proposal402 Lzk[k2] += normLogDensity(val);403 431 } 404 432 PA1(se[k2].z, k3) = val; … … 430 458 } while (k1<Ns && (val > MIN_DIFF || val < -MIN_DIFF)); 431 459 432 // Metropolis-hastings selection of current or proposal using Lz+Lx for 433 // each evaluation 434 val = Lzk[1] + se[1].Lx - Lzk[0] - se[0].Lx; 460 // Metropolis-hastings selection of current or proposal 461 val = se[1].Lx - se[0].Lx; 435 462 if(val > 0 || log(uniform(0, 1)) < val) { 436 463 // Proposal accepted … … 486 513 } 487 514 488 // Compute the result, the integrated P(x|w) over the last halfof the515 // Compute the result, the integrated P(x|w) over the last 3/4 of the 489 516 // simulations on z 490 491 // Compute the maximum log density // and save it to subtract from everybody 517 k0 = (int)(100*ni/400); 518 519 // Compute the maximum log density and save it to subtract from everybody so 492 520 // that the maximum log density is normalized to zero 493 val = -HUGE_VAL;494 for(ki= ni/2; ki<ni; ki++) {495 if(Lx[ki] > val)496 val = Lx[ki];497 } 498 // Accumulate the linearized normalized densities , borrowing Lzk[0] to do so499 Lzk[0]= 0;500 for(ki= ni/2; ki<ni; ki++)501 Lzk[0] += exp(Lx[ki] - val);521 maxVal = -HUGE_VAL; 522 for(ki=k0; ki<ni; ki++) { 523 if(Lx[ki] > maxVal) 524 maxVal = Lx[ki]; 525 } 526 // Accumulate the linearized normalized densities 527 val = 0; 528 for(ki=k0; ki<ni; ki++) 529 val += exp(Lx[ki] - maxVal); 502 530 // ...and return the denormalized, log mean of the linear densities... 503 return_val = log( Lzk[0]) + val - log(ni/2);531 return_val = log(val) + maxVal - log(ni-k0); projects/AsynCluster/trunk/svpmc/model.py
r201 r202 187 187 188 188 """ 189 keyAttrs = {'y':None, 'wiggle':1.0, 'Ni': 30}189 keyAttrs = {'y':None, 'wiggle':1.0, 'Ni':100} 190 190 191 191 #--- Properties ----------------------------------------------------------- projects/AsynCluster/trunk/svpmc/test/test_model.py
r201 r202 318 318 self.failUnlessEqual(len(s.unique(z)), N) 319 319 320 def test_support_truncnorm(self): 321 pass 322 code = """ 323 int k; 324 for(k=0; k<Nx[0]; k++) 325 X1(k) = truncnorm(a, b); 326 """ 327 Ns = 100 328 ranges = ((-1, +1), (-0.5, +1.5), (1.0, 2.0), (3.0, 5.0)) 329 fig = self.fig 330 spNumBase = 100*len(ranges) + 11 331 k = 0 332 for a, b in ranges: 333 title = "%+3.1f to %+3.1f" % (a, b) 334 print "\n%s\n" % title 335 x = s.empty(Ns) 336 self.inline(code, x=x, a=a, b=b) 337 sp = fig.add_subplot(spNumBase+k) 338 sp.hist(x, bins=20) 339 sp.set_title(title) 340 k += 1 341 print "\n" 342 320 343 def test_support_matrixMultiply(self): 321 344 code = """ … … 650 673 651 674 def test_Lx(self): 652 wiggle = 0.5 675 # Wiggle seems fairly critical, best at 0.5-1.0. 676 # Tried independent proposals +/- 4.0, didn't work well. 677 wiggle = 1.0 653 678 eValue = 0.97 654 679 Ns, Ni, Nr = 200, 100, 100 … … 676 701 fig = self._plot(*plotArgs) 677 702 fig.text(0.05, 0.95, "Best", size='x-large') 678 679 703 680 704 def test_optimize_Ni(self): … … 685 709 """ 686 710 Nr = 1000 687 wiggle = 0.5711 wiggle = 1.0 688 712 eValue = 0.95 689 713 Ns = 1000
