Changeset 154

Show
Ignore:
Timestamp:
04/22/08 19:38:33 (8 months ago)
Author:
edsuom
Message:

weave.Weaver.inline has the same value-returning behavior as weave.inline; working on Model.likelihood

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • projects/AsynCluster/trunk/svpmc/model.c

    r153 r154  
    8787// Supplied variables 
    8888// ---------------------------------------------------------------------------- 
    89 // p    Log-likelihoods [2n] array (overwritten) 
    9089 
    9190//--- Supplied arrays --- 
    9291// z    Independent normal variates for log-volatilities, [pn] array (updated) 
    93 // h    Log-volatilities, [pn] (overwritten) 
     92// v    Log-volatility shocks, [pn] (overwritten) 
    9493// x    Innovation values, [pn] array 
    95 // rvc  Concurrent cross-correlations between volatility shocks, [pp] 
    96 // rvi  Inverse, concurrent cross-correlations between volatility shocks, [pp] 
    97 // rii  Inverse, concurrent cross-correlations between innovation shocks, [pp] 
     94// rv   Concurrent cross-correlations between volatility shocks, [pp] 
     95// ri   Inverse, concurrent cross-correlations between innovation shocks, [pp] 
    9896// y    Miscellaneous multivariate scratchpad, [p8] array (overwritten) 
     97// h    Log-volatility scratchpad, [p2] array, for VAR(1) 
    9998 
    10099//--- Model parameters --- 
     
    106105// n0   Number of volatility draws per likelihood evaluation.   
    107106// n3   Number of random-walk normal draws per volatility draw. 
     107// nv   Number of samples after current one to compute VAR effect 
    108108// sigma = Standard deviation of random-walk normal proposal 
    109  
    110  
    111 // The log-likelihood array is used as follows, by column: 
    112 // ---------------------------------------------------------------------------- 
    113 // 0    Log Pr(x[t]|hp[t]), the sum of which for all t is the log-likelihood of 
    114 //      the innovation values given the simulated log-volatilities 
    115 // 1    Log Pr(hp[t]|x[t],h[t+1]), which is used in each M-H accept/reject step 
    116 //      for the log-volatility simulation 
    117109 
    118110 
     
    125117// 4    Innovation values after inverse-scaling by log-volatility 
    126118// 5    Inverse-scaled innovation values after decorrelation 
    127 // 6    Next-sample log-volatility values after VAR term removal 
    128 // 7    VAR-term removed log-volatility values after decorrelation 
     119// 6    - 
     120// 7    - 
    129121 
    130122 
     
    133125 
    134126int km, kh; 
    135 int k0, k1, k2, k3
    136 double sum, normp, dL, L0, L1
     127int k0, k1, k2, k3, nd
     128double sum, norm, normp, dL, L0, L1, L
    137129 
    138130double wiggle = sigma * pow(n3, -0.5); 
     
    146138 
    147139 
     140// Initialize volatility shocks by correlating the current (supplied) set of 
     141// iid random-walk variates 
     142 
     143// for each multivariate sample... 
     144for(k1=0; k1<Nz[1]; k1++) { 
     145     
     146  // For each time series... 
     147  for(k2=0; k2<Nz[0]; k2++) { 
     148    // The matrix product of the cross-correlations and the independent 
     149    // variates for this sample... 
     150    sum = 0; 
     151    for(km=0; km<Nz[0]; km++) 
     152      sum += RV2(k2, km) * Y2(k2, 2); 
     153    // ...is the correlated volatility shock for this time series and sample 
     154    V2(k2, k1) = sum; 
     155  } 
     156} 
     157 
     158 
     159// Hybrid Gibbs sampler with Metropolis-Hastings accept/reject step for each 
     160// conditional density draw. 
     161 
    148162// For each overall iteration... 
    149163for(k0=0; k0<n0; k0++) { 
     
    152166  for(k1=0; k1<Nz[1]; k1++) { 
    153167 
    154     // Unless this is the first, initialization iteration, update this column 
    155     // of independent random-walk normal variates to produce a multivariate 
    156     // i.i.d. normal proposal. It is this on which we build a multivariate 
    157     // log-volatility proposal for this multivariate sample. 
     168    // Do a random walk from this column of independent random-walk normal 
     169    // variates to produce a multivariate iid normal proposal. It is this on 
     170    // which we build a multivariate log-volatility proposal for this 
     171    // multivariate sample. 
    158172 
    159173    // For each time series... 
     
    163177      Y2(k2, 2) = Z2(k2, k1); 
    164178      L0 = -0.5 * pow(Y2(k2, 2), 2); 
    165       // Proceed with the random walk only if this isn't the first, 
    166       // initialization iteration... 
    167       if(k0 > 0) { 
    168         // For each oversampling iteration... 
    169         for(k3=0; k3<n3; k3++) { 
    170           // Generate a uniform, symmetric, random walk proposal 
    171           normp = Y2(k2, 2) + wiggle * (drand48() - 0.5); 
    172           // Do the ratio in log space 
    173           L1 = -0.5 * pow(normp, 2); 
    174           dL = L1 - L0; 
    175           // The uniform random variate thus needs to be in logspace as well, 
    176           // but it's not always even needed. Thus the log operation is done 
    177           // just once, and only some of the time. 
    178           if(dL > 0  || log(drand48()) < dL) { 
    179             // Update current value and its log probability when proposal 
    180             // accepted 
    181             Y2(k2, 2) = normp; 
    182             L0 = L1; 
    183           } 
     179      // For each oversampling iteration... 
     180      for(k3=0; k3<n3; k3++) { 
     181        // Generate a uniform, symmetric, random walk proposal 
     182        normp = Y2(k2, 2) + wiggle * (drand48() - 0.5); 
     183        // Do the ratio in log space 
     184        L1 = -0.5 * pow(normp, 2); 
     185        dL = L1 - L0; 
     186        // The uniform random variate thus needs to be in logspace as well, but 
     187        // it's not always even needed. Thus the log operation is done just 
     188        // once, and only some of the time. 
     189        if(dL > 0  || log(drand48()) < dL) { 
     190          // Update current value and its log probability when proposal 
     191          // accepted 
     192          Y2(k2, 2) = normp; 
     193          L0 = L1; 
    184194        } 
    185195      } 
    186196    } 
    187197     
    188     // Now correlate the i.i.d. proposal to form a proposed column of 
    189     // volatility shocks 
     198    // Now correlate the iid proposal to form a proposed column of volatility 
     199    // shocks 
    190200     
    191201    // For each time series... 
     
    195205      sum = 0; 
    196206      for(km=0; km<Nz[0]; km++) 
    197         sum += RVC2(k2, km) * Y2(k2, 2); 
     207        sum += RV2(k2, km) * Y2(k2, 2); 
    198208      // ...is the correlated volatility shock proposal for this time series 
    199209      Y2(k2, 3) = sum; 
    200210    } 
    201211     
    202     // Now do the VAR(1) to get a multivariate log-volatility proposal. The 
    203     // proposals are generated from "left to right" based solely on the 
    204     // random-walk normal proposals, so there's no need to worry about 
    205     // overwriting anything. 
    206  
    207     // For each time series... 
    208     for(k2=0; k2<Nz[0]; k2++) { 
    209       if(k1 == 0) { 
    210         // The log-volatility value of the first multivariate sample is just the 
    211         // offset scaled by its VAR gain. 
    212         H2(k2, 0) = D1(k2) / (1 - E2(k2, k2)); 
    213       } else { 
    214         // For all other samples, the offset plus the current proposed shock... 
    215         sum = D1(k2) + Y2(k2, 3); 
    216         // ...plus the dot product for the VAR(1) term... 
    217         for(km=0; km<Nz[0]; km++) 
    218           sum += E2(k2, km) * H2(k2, k1-1); 
    219         // ...is the proposed log-volatility value 
    220         H2(k2, k1) = sum; 
    221       } 
     212    // Now do the VAR(1) starting with this proposed volatility shock and 
     213    // proceeding through the other shocks subsequent to it to compute 
     214    // Pr(hp[t]|x,h[:t],h[t+1:]). 
     215    L = 0; 
     216    if(k3+nv >= Nz[1]) { 
     217      nd = Nz[1]; 
     218    } else { 
     219      nd = k3+nv; 
    222220    } 
    223      
    224     // Now inverse-scale the innovations for this sample by the square root of 
    225     // the volatilities in preparation for decorrelating the innovations 
    226     for(k2=0; k2<Nz[0]; k2++) 
    227       Y2(k2, 4) = exp(-0.5 * H2(k2, k1)) * X2(k2, k1); 
    228      
    229     // Now decorrelate the equi-variance innovations in preparation for the 
    230     // log-likelihood computation for this multivariate log-volatility proposal 
    231      
    232     // For each time series... 
    233     for(k2=0; k2<Nz[0]; k2++) { 
    234       // The product of the inverted cross-correlation matrix and the 
    235       // correlated variates... 
    236       sum = 0; 
    237       for(km=0; km<Nz[0]; km++) 
    238         sum += RII2(k2, km) * Y2(k2, 4); 
    239       // ...is the decorrelated multivariate innovation for this sample, given 
    240       // its proposed log-volatility 
    241       Y2(k2, 5) = sum; 
    242     } 
    243  
    244     // Now compute log Pr(x[t]|hp[t]), the log-likelihood of the decorrelated 
    245     // multivariate innovation, conditional on the proposed log-volatility 
    246     // hp[t], which has been generated conditional on the log-volatility of the 
    247     // previous sample. Consider the proposal as a draw from Pr(hp[t]|h[t-1]). 
    248      
    249     sum = 0; 
    250     // For each time series... 
    251     for(k2=0; k2<Nz[0]; k2++) { 
    252       // Offset the decorrelated innovation by the mean, which is the 
    253       // correlation between the normal variates for innovation and proposed 
    254       // volatility shocks, times the value of the normal variate value for the 
    255       // proposed volatility shock for this sample 
    256       Y2(k2, 5) = Y2(k2, 5)  -  G1(k2) * H2(k2, k1); 
    257       // The log-likelihood is simply the argument of the exponential of the 
    258       // normal pdf, with the reciprocal scaling of the exponential being done 
    259       // in log space by subtraction. 
    260       sum -= pow(Y2(k2, 5) / Y2(k2, 0), 2) + Y2(k2, 1); 
    261       // Since the innovation has been inverse-scaled by the square root of the 
    262       // proposed volatility, the probability density needs to be scaled as 
    263       // well. In log space, this is a subtraction of half the proposed 
    264       // log-volatility. 
    265       sum -= 0.5 * H2(k2, k1); 
    266     } 
    267     P2(0, k1) = sum; 
    268      
    269     // The probability density that we need for our Metropolis-Hastings 
    270     // accept/reject decision is Pr(hp[t]|x[t],h[t+1]), where h[t+1] is the 
    271     // current log-volatility of the next sample. 
    272     // 
    273     // According to Bayes' Rule, the required density is proportional to 
    274     // Pr(x[t]|hp[t],h[t+1]) * Pr(hp[t]|h[t+1]). So, we need to compute and 
    275     // scale by the probability density of the log-volatility proposal given 
    276     // the current log-volatility of the next sample, which is, by Bayes rule: 
    277     // 
    278     // Pr(h[t+1]|hp[t]) * Pr(hp[t]) / Pr(h[t+1]) 
    279     //                    <-----+--------------> 
    280     //                          | 
    281     //                          +--- But this = 1 because both are equiprobable 
    282     // 
    283     // So, we now compute Pr(h[t+1]|hp[t]), which is Pr(h[t+1] - E2*hp[t]) 
    284     // unless we're at the last sample, in which case it is = 1. 
    285  
    286     if(k1 < Nz[1]) { 
    287       // First we need to remove the offset and the current proposal's VAR term 
    288       // from the next sample's current log-volatility 
    289  
     221 
     222    // For the current sample and some samples subsequent to it... 
     223    for(k3=k1; k3<nd; k3++) { 
     224      // We alternate between the two columns of the log-volatility scratchpad 
     225      // for current & previous multivariate log-volatility values 
     226      kh = k3 % 2; 
    290227      // For each time series... 
    291228      for(k2=0; k2<Nz[0]; k2++) { 
    292         // ...the offset 
    293         sum = D1(k2); 
    294         // ...plus the matrix product of the Lag-1 cross-correlations and the 
    295         // proposed multivariate log-volatility components... 
    296         for(km=0; km<Nz[0]; km++) 
    297           sum += E2(k2, km) * H2(k2, k1); 
    298         // ...is the VAR term to subtract from the next sample's log-volatility 
    299         // value 
    300         Y2(k2, 6) = H2(k2, k1+1) - sum; 
    301       } 
    302  
    303       // Then we need to decorrelate the residuals to get independent normal 
    304       // variates 
    305  
     229        if(k1 == 0) { 
     230          // The log-volatility value of the first multivariate sample is just 
     231          // the offset scaled by its VAR gain, plus the proposed shock 
     232          H2(k2, 0) = D1(k2) / (1 - E2(k2, k2))  +  Y2(k2, 3); 
     233        } else { 
     234          // For all other samples, the offset plus the proposed shock... 
     235          sum = D1(k2) + Y2(k2, 3); 
     236          // ...plus the dot product for the VAR(1) term... 
     237          for(km=0; km<Nz[0]; km++) 
     238            sum += E2(k2, km) * H2(k2, 1-kh); 
     239          // ...is the proposed log-volatility value 
     240          H2(k2, kh) = sum; 
     241        } 
     242      } 
     243     
     244      // Now inverse-scale the innovations for this sample by the square root 
     245      // of the volatilities in preparation for decorrelating the innovations 
     246      for(k2=0; k2<Nz[0]; k2++) 
     247        Y2(k2, 4) = exp(-0.5 * H2(k2, kh)) * X2(k2, k3); 
     248     
     249      // Now decorrelate the equi-variance innovations in preparation for the 
     250      // log-likelihood computation for this multivariate log-volatility 
     251      // proposal 
     252     
    306253      // For each time series... 
    307254      for(k2=0; k2<Nz[0]; k2++) { 
     
    310257        sum = 0; 
    311258        for(km=0; km<Nz[0]; km++) 
    312           sum += RVI2(k2, km) * Y2(k2, 6); 
    313         // ...is the decorrelated multivariate normal that would generate the 
    314         // next sample's log-volatility given the one proposed for the current 
    315         // sample. 
    316         Y2(k2, 7) = sum; 
    317       } 
    318  
    319       // Then we need to compute the joint log-density of the decorrelated 
    320       // multivariate normal values 
    321       sum = - Nz[0] * 0.918938533205; // N*log(sqrt(2*pi)) 
     259          sum += RI2(k2, km) * Y2(k2, 4); 
     260        // ...is the decorrelated multivariate innovation for this sample, 
     261        // given its proposed log-volatility 
     262        Y2(k2, 5) = sum; 
     263      } 
     264     
     265      // Now compute log Pr(x[t]|hp[t],h[t+1:]), the log-likelihood of the 
     266      // decorrelated multivariate innovation, conditional on the proposed 
     267      // log-volatility hp[t] and the log-volatilities of all subsequent 
     268      // samples. The proposed log-volatility hp[t] is itself generated 
     269      // conditional on the log-volatilities of earlier samples, so no further 
     270      // account of such samples needs be made. 
     271       
    322272      // For each time series... 
    323       for(k2=0; k2<Nz[0]; k2++) 
    324         sum -= 0.5 * pow(Y2(k2, 7), 2); 
    325         
    326       // Now do the scaling 
    327       // TODO 
    328  
    329     } 
    330  
    331  
    332            
    333         
    334        
    335        
    336  
    337      
    338  
    339     // Do a Metropolis-Hastings accept/reject based on the log-likelihood of 
    340     // the proposal, now in the "sum" variable, versus the log-likelihood of 
    341     // the previously accepted normal value for this sample. 
     273      for(k2=0; k2<Nz[0]; k2++) { 
     274        // Offset the decorrelated innovation by the mean, which is the 
     275        // correlation between the normal variates for innovation and proposed 
     276        // volatility shocks, times the value of the normal variate value for 
     277        // the proposed volatility shock for this sample (or the current normal 
     278        // variate value, for subsequent samples) 
     279        if(k3 == k1) { 
     280          norm = V2(k2, 2); 
     281        } else { 
     282          norm = Z2(k2, k3); 
     283        } 
     284        Y2(k2, 5) = Y2(k2, 5)  -  G1(k2) * H2(k2, kh); 
     285        // The log-likelihood for this sample is simply the argument of the 
     286        // exponential of the normal pdf, with the reciprocal scaling of the 
     287        // exponential being done in log space by subtraction. 
     288        L -= pow(Y2(k2, 5) / Y2(k2, 0), 2) + Y2(k2, 1); 
     289        // Since the innovation has been inverse-scaled by the square root of 
     290        // the proposed volatility, the probability density needs to be scaled 
     291        // as well. In log space, this is a subtraction of half the proposed 
     292        // log-volatility. 
     293        L -= 0.5 * H2(k2, kh); 
     294      } 
     295    }     
     296 
     297    // TODO 
     298    // Need to record L for this sample to compare in next MH iteration 
     299 
     300 
     301 
     302    // Do a Metropolis-Hastings accept/reject based on the log-likelihood for 
     303    // the proposal versus the log-likelihood for the previously accepted 
     304    // normal value for this sample. 
    342305 
    343306    // If this is the first, initialization iteration, we always accept the 
     
    368331} 
    369332 
    370 // End of MCMC run. The array Z2 has been overwritten with updated 
    371 // i.i.d. normal variates underlying an updated set of log-volatilities, and 
    372 // the vector P1 has been overwritten with the log-likelihood of each 
    373 // multivariate innovation sample given those log-volatilities. 
    374  
    375  
     333// End of MCMC run. The array Z2 has been overwritten with updated iid normal 
     334// variates underlying an updated set of log-volatilities, and the vector P1 
     335// has been overwritten with the log-likelihood of each multivariate innovation 
     336// sample given those log-volatilities. 
     337 
     338 
  • projects/AsynCluster/trunk/svpmc/model.py

    r153 r154  
    165165     
    166166    def reverse(self, a, b): 
    167         return self.inline('v', 'y', 'a', 'b', v=s.empty_like(self.y)) 
     167        v = s.empty_like(self.y) 
     168        self.inline('v', 'y', 'a', 'b') 
     169        return v 
    168170 
    169171    def forward(self, v, a, b): 
    170         return self.inline('y', 'v', 'a', 'b', y=s.empty_like(v)) 
     172        y = s.empty_like(v) 
     173        self.inline('y', 'v', 'a', 'b') 
     174        return y 
    171175 
    172176 
     
    222226    #--- Support -------------------------------------------------------------- 
    223227 
     228    def decaySamples(self, tol): 
     229        """ 
     230        """ 
     231         
     232 
     233 
    224234    def covarMatrix(self, correlations): 
    225235        """ 
     
    280290        x = self.var.reverse(self.a, self.b) 
    281291        # Concurrent cross-correlations between volatility shocks 
    282         rvc = linalg.cholesky(self.covarMatrix(self.f), lower=True) 
    283         # Inverse of concurrent cross-correlations between volatility shocks 
    284         rii = linalg.inv(rvc) 
     292        rv = linalg.cholesky(self.covarMatrix(self.f), lower=True) 
    285293        # Inverse of concurrent cross-correlations between innovation shocks 
    286         rii = linalg.inv(linalg.cholesky(self.covarMatrix(self.c), lower=True)) 
     294        ri = linalg.inv(linalg.cholesky(self.covarMatrix(self.c), lower=True)) 
    287295        # Declare working array with zeros 
    288296        y = s.zeros((self.p, 8)) 
     
    290298        # log-likelihood that is not (very) conditional on the latent 
    291299        # parameters that the volatilities represent 
    292         p = s.zeros((2, self.n)
    293         h = s.zeros(self.p, self.n)) 
     300        v = s.empty(*self.p, self.n
     301        h = s.empty((self.p, 2)) 
    294302        L = self.inline( 
    295             'p', 
    296             'z', 'x', 'rvc', 'rvi', 'rii', 'h', 'y', 
     303            'z', 'v', 'x', 'rv', 'ri', 'y', 'h', 
    297304            'd', 'e', 'g', 
    298             'n0', 'n3', 'sigma')[1,:].sum() 
    299         return L, z, p 
     305            'n0', 'n3', 'sigma') 
     306        return L, z 
    300307     
    301308    def foo(self): 
  • projects/AsynCluster/trunk/svpmc/sample.py

    r151 r154  
    6363        x[:,0] = K*W[I0] 
    6464        a = s.less(x[:,0], 1.0).nonzero()[0] 
    65         x = self.inline('x', 'a', 'b', b=s.setdiff1d(s.arange(0, K), a)) 
     65        self.inline('x', 'a', 'b', b=s.setdiff1d(s.arange(0, K), a)) 
    6666        V = s.rand(N) 
    6767        RI = s.random.randint(0, K, N) 
     
    106106        A reference to the updated array is returned. 
    107107        """ 
    108         return self.inline('x', 'p', 'm', 'wiggle') 
     108        self.inline('x', 'p', 'm', 'wiggle') 
     109        return self.x 
    109110 
    110111    def covarMatrix(self, correlations): 
     
    157158                "Must have a [%d x %d] cross-correlation matrix defined" \ 
    158159                % (n, n)) 
    159         return self.inline('y', 'x', 'r', y=s.empty_like(self.x)) 
     160        y = s.empty_like(self.x) 
     161        self.inline('y', 'x', 'r') 
     162        return y 
    160163         
    161164         
  • projects/AsynCluster/trunk/svpmc/weave.py

    r147 r154  
    8686        failing that, from my instance's namespace as C{self.<varname>}. 
    8787 
    88         A reference to the first variable is returned. 
     88        A reference to the result of the inline call, set inside the C code via 
     89        the variable I{return_val}, is returned. 
    8990        """ 
    9091        frame = inspect.currentframe() 
     
    107108            # Avoid cycle problems, per Python Library Reference 3.11.4 
    108109            del frame 
    109         inline( 
     110        return inline( 
    110111            self.code[methodName], 
    111112            args, extra_compile_args=['-w'], support_code=self.code['support']) 
    112         return locals()[args[0]] 
    113113 
    114114