Changeset 147
- Timestamp:
- 04/16/08 16:27:16 (9 months ago)
- Files:
-
- projects/AsynCluster/trunk/svpmc/model.c (modified) (1 diff)
- projects/AsynCluster/trunk/svpmc/model.py (modified) (4 diffs)
- projects/AsynCluster/trunk/svpmc/sample.py (modified) (4 diffs)
- projects/AsynCluster/trunk/svpmc/test/test_model.py (modified) (1 diff)
- projects/AsynCluster/trunk/svpmc/test/test_sample.py (modified) (3 diffs)
- projects/AsynCluster/trunk/svpmc/test/test_weave.py (modified) (3 diffs)
- projects/AsynCluster/trunk/svpmc/weave.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
projects/AsynCluster/trunk/svpmc/model.c
r145 r147 112 112 } 113 113 } 114 115 116 117 // Model.decorrelate 118 // 119 // Supplied variables 120 // ---------------------------------------------------------------------------- 121 // y 2-D array of correlated random variates (to be overwritten) 122 // x 2-D array of independent random variates 123 // r 2-D array of inverted correlations between values in each column of x 124 125 int i, j, k; 126 double sum; 127 128 // For each column of independent variates to be decorrelated... 129 for(i=0; i<Nx[1]; i++) { 130 // For each of the values in the column... 131 for(j=0; j<Nx[0]; j++) { 132 // The product of the inverted cross-correlation matrix and the correlated 133 // variates... 134 sum = 0; 135 for(k=0; k<Nx[0]; k++) 136 sum += R2(j,k) * X2(k,i); 137 // ...is the correlated output 138 Y2(j, i) = sum; 139 } 140 } projects/AsynCluster/trunk/svpmc/model.py
r146 r147 266 266 267 267 def reverse(self, a, b): 268 return self. c('v', 'y', 'a', 'b', v=s.empty_like(self.y))268 return self.inline('v', 'y', 'a', 'b', v=s.empty_like(self.y)) 269 269 270 270 def forward(self, v, a, b): 271 return self. c('y', 'v', 'a', 'b', y=s.empty_like(v))271 return self.inline('y', 'v', 'a', 'b', y=s.empty_like(v)) 272 272 273 273 … … 290 290 'b', # Lag-1 cross-correlation for VAR of returns (p x p) 291 291 292 # The attribute name 'c' is used by the Weaver inline method 292 'c', # Innovation shock concurrent correlations (vector with 293 # r01, r02,..., r0p, r12,..., r1p,...) 293 294 294 295 'd', # Volatility offset (p x 1) … … 300 301 # r01, r02,..., r0p, r12,..., r1p,...) 301 302 302 #--- TODO ----------------303 303 'g', # Volatility/innovation shock correlations (p x 1) 304 #-------------------------305 304 306 305 ] … … 354 353 self.h = s.empty_like(self.nw.x) 355 354 self.nw.step(wiggle) 356 return self.c('h', 'v', 'd', 'e', v=self.nw.correlate(self.f)) 355 return self.inline('h', 'v', 'd', 'e', v=self.nw.correlate(self.f)) 356 357 def decorrelate(self, x, h=None): 358 """ 359 Call this method with a C{[pn]} array I{x} containing one row of C{n} 360 innovations for each of C{p} Wiener processes, with unit variance 361 assumed and correlated by a covariance matrix constructed from my 362 correlation parameters I{c}. The result will be the decorrelated 363 innovations of the Wiener processes. 364 365 You can supply a C{[pn]} array I{h} of log-volatilities for each of the 366 innovations. Then the innovations I{x} are assumed to be scaled by 367 their respective volatilities, and will be inversely scaled to meet the 368 assumption of unit variance. 369 """ 370 xs = x.shape 371 if xs[0] != self.p: 372 raise ValueError("Data array must have %d rows" % self.p) 373 hs = s.shape(h) 374 if hs: 375 if hs != xs: 376 raise ValueError("Need one log-volatility per innovation") 377 x *= s.exp(-0.5*h) 378 if 'decorrelate' not in self.cache: 379 self.cache['decorrelate'] = linalg.inv( 380 linalg.cholesky(self.nw.covarMatrix(self.c), lower=True)) 381 r = self.cache['decorrelate'] 382 return self.inline('y', 'x', 'r', y=s.empty_like(x)) 383 384 def pInnovations(self, y): 385 """ 386 Call this method with a C{[pn]} array I{y} of uncorrelated 387 innovations. 388 389 The result will be the probability density of each innovation, given my 390 volatility/innovation shock correlations C{g} and the volatility shocks 391 currently in my random walker C{nw}. 392 """ 357 393 358 394 359 395 #--- The API -------------------------------------------------------------- 360 396 361 def likelihood(self, wiggle, paramSequence): 362 """ 363 Returns a log-likelihood of my observations for one set of simulated 364 volatilies, given the supplied fractional I{wiggle} and the parameter 365 arrays in the supplied sequence I{paramSequence}. 366 367 This method returns the likelihood of the data given the parameters. It 368 does not consider the prior probability of the parameters. You have to 369 do that yourself, preferably before calling this method. If the prior 370 probability of any parameter is zero, the posterior density for that 371 parameter will also be zero, and a call to this method will be 372 unnecessary. 397 def likelihood(self, paramSequence, v, wiggle): 398 """ 399 Call this method with a sequence of arrays I{paramSequence} defining my 400 model parameters and a C{[pn]} array of volatility shocks I{v} to be 401 used as a starting point for another simulation draw of volatilities. 402 403 A new 2-D array of log-volatilities will be drawn from a relatively 404 short Metropolis-Hastings random walk simulation of the volatility 405 shocks coupled with a VAR(1) from the shocks to the 406 log-volatilities. The Metropolis-Hastings proposals are scaled by the 407 supplied fractional I{wiggle}. The simulation is governed by the 408 log-likelihood of my observation data given the supplied parameters and 409 the simulated volatilities. 410 411 The value of that log-likelihood at the end of the log-volatility 412 simulation is returned along with the with the volatility shocks 413 underlying the log-volatilities drawn at that point. 414 415 The returned likelihood does not consider the prior probability of the 416 parameters. You have to account for that yourself, preferably before 417 calling this method. If the prior probability of any parameter is zero, 418 the posterior density for that parameter will also be zero no matter 419 what, making any call to this method that uses it a waste of computing 420 time. 373 421 """ 374 422 self.setParamSequence(paramSequence) 375 423 # Obtain innovations as residuals of the reversed VAR(1) 376 424 x = self.var.reverse(self.a, self.b) 377 # Draw a new set of simulated volatilities378 h = self.draw_h( wiggle)425 # Simulate log-volatilities for a while 426 h = self.draw_h(v, wiggle) 379 427 # Compute the conditional densities 380 428 projects/AsynCluster/trunk/svpmc/sample.py
r146 r147 63 63 x[:,0] = K*W[I0] 64 64 a = s.less(x[:,0], 1.0).nonzero()[0] 65 x = self. c('x', 'a', 'b', b=s.setdiff1d(s.arange(0, K), a))65 x = self.inline('x', 'a', 'b', b=s.setdiff1d(s.arange(0, K), a)) 66 66 V = s.rand(N) 67 67 RI = s.random.randint(0, K, N) … … 89 89 A reference to the updated array is returned. 90 90 """ 91 return self. c('x', 'p', 'm', 'wiggle')91 return self.inline('x', 'p', 'm', 'wiggle') 92 92 93 def _covarMatrix(self, correlations):93 def covarMatrix(self, correlations): 94 94 """ 95 Returns a covariance matrix from the supplied vector or sequence of 96 I{correlations}, in the form used by L{correlate}. 95 Returns a covariance matrix from the vector or sequence of 96 I{correlations} supplied in the form used by L{correlate}. 97 98 Assumes that the independent components have unit variance, as is the 99 case with my random walkers C{x}. 97 100 """ 98 101 i = 0 … … 124 127 # next time 125 128 self.r = linalg.cholesky( 126 self. _covarMatrix(correlations), lower=True)129 self.covarMatrix(correlations), lower=True) 127 130 self.y = s.empty_like(self.x) 128 131 n = self.x.shape[0] … … 131 134 "Must have a [%d x %d] cross-correlation matrix defined" \ 132 135 % (n, n)) 133 return self. c('y', 'x', 'r', y=s.empty_like(self.x))136 return self.inline('y', 'x', 'r', y=s.empty_like(self.x)) 134 137 135 138 projects/AsynCluster/trunk/svpmc/test/test_model.py
r146 r147 280 280 self.model.f = [0.5] 281 281 self._check_xcorr(0) 282 283 284 class Test_Model_decorrelate(util.TestCase): 285 def setUp(self): 286 self.model = model.Model() 287 288 def test_basic(self): 289 n = 1000 290 for p in xrange(2, 6): 291 for correlation in s.linspace(0.1, 0.9, 10): 292 # Generate some multivariate normal test data 293 r = s.maximum(s.identity(p), correlation*s.ones((p,p))) 294 x = random.multivariate_normal(s.zeros(p), r, n).transpose() 295 # Tweak the model object to make it testable for this p value 296 self.model.tsList = [util.TS_LIST[0]] * p 297 self.model.c = correlation * s.ones( 298 sum([p-k-1 for k in xrange(p)])) 299 # Get the decorrelated values 300 y = self.model.decorrelate(x) 301 # Check for non-correlation 302 for j in xrange(p): 303 for k in xrange(p): 304 if j == k: 305 continue 306 corrInfo = stats.spearmanr(y[j,:], y[k,:]) 307 self.failUnless( 308 abs(corrInfo[0]) < 0.1, 309 "Doesn't appear uncorrelated") projects/AsynCluster/trunk/svpmc/test/test_sample.py
r145 r147 116 116 def test_covarMatrix_2x2(self): 117 117 walker = sample.NormalWalk(2, 2) 118 x = walker. _covarMatrix([0.5])118 x = walker.covarMatrix([0.5]) 119 119 y = s.array([[1, 0.5], [0.5, 1.0]]) 120 120 self.failUnless(s.equal(x, y).all()) … … 122 122 def test_covarMatrix_3x3(self): 123 123 walker = sample.NormalWalk(3, 67) 124 x = walker. _covarMatrix([0.12, 0.13, 0.23, 0.24])124 x = walker.covarMatrix([0.12, 0.13, 0.23, 0.24]) 125 125 y = s.array([ 126 126 [1.00, 0.12, 0.13], … … 131 131 def test_covarMatrix_4x4(self): 132 132 walker = sample.NormalWalk(4, 100) 133 x = walker. _covarMatrix([0.12, 0.13, 0.14, 0.23, 0.24, 0.34])133 x = walker.covarMatrix([0.12, 0.13, 0.14, 0.23, 0.24, 0.34]) 134 134 y = s.array([ 135 135 [1.00, 0.12, 0.13, 0.14], projects/AsynCluster/trunk/svpmc/test/test_weave.py
r145 r147 56 56 57 57 def __call__(self, x): 58 return self. c('x')[0]58 return self.inline('x')[0] 59 59 60 60 def foo(self, x): 61 return self. c('x', 'y', x=2*s.array([x]))[0]61 return self.inline('x', 'y', x=2*s.array([x]))[0] 62 62 63 63 … … 66 66 self.weaver = TestableWeaver() 67 67 68 def test_ c_alone(self):68 def test_inline_alone(self): 69 69 self.weaver._code = {'support':None, 'foo':CODE} 70 70 self.failUnlessEqual(self.weaver.foo(s.array([1])), 1164) … … 74 74 self.failUnlessElementsEqual(code.keys(), ['support', 'foo', '__call__']) 75 75 76 def test_ c_normal(self):76 def test_inline_normal(self): 77 77 self.weaver._code = self.weaver._parseCode(CODE) 78 78 self.failUnlessEqual(self.weaver.foo(10), 625) 79 79 80 def test_ c_privateMethod(self):80 def test_inline_privateMethod(self): 81 81 self.weaver._code = self.weaver._parseCode(CODE) 82 82 self.failUnlessEqual(self.weaver(s.array([7])), 107) projects/AsynCluster/trunk/svpmc/weave.py
r145 r147 76 76 code = property(_get_code) 77 77 78 def c(self, *args, **kw):78 def inline(self, *args, **kw): 79 79 """ 80 80 Call this method to run the inline code for the calling method of the
