Changeset 200

Show
Ignore:
Timestamp:
05/27/08 16:46:38 (6 months ago)
Author:
edsuom
Message:

Integration over log-volatility simulations using Metropolis-within-Gibbs is looking most promising

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • projects/AsynCluster/trunk/doc/svpmc/example/svpmc.conf

    r199 r200  
    2727Variable    Value           Description 
    2828------------------------------------------------------------------------------- 
    29 D           5               Number of jump deviations in the D-kernel sim 
     29D           4               Number of jump deviations in the D-kernel sim 
    3030Ds          0.1             Starting jump deviation value 
    3131Df          0.2             Fractional value of each dev from prev (or start) 
    3232wiggle      0.5             Range +/- of uniform random walks on z for h sim 
    33 N1          10              Proposals on z for each importance-sampling of h 
    34 N2          20              Hybrid-Gibbs iterations for h sim 
     33Ni          50              Hybrid-Gibbs rounds for simulation of h 
     34 
    3535 
    3636 
     
    6868a           Distribution    Loc         Scale       a       b 
    6969------------------------------------------------------------------------------- 
    70 :           beta            0.00        0.005       2       5 
     70:           beta            0.00        0.002       2       3 
    7171 
    7272 
  • projects/AsynCluster/trunk/svpmc/model.c

    r199 r200  
    8686// ---------------------------------------------------------------------------- 
    8787 
    88 // Run evaluations until odds of error in selection between proposals null 
    89 // proposal on z will be less than 1/100. 
    90 #define MIN_DIFF 0.01 
    91  
    9288 
    9389// Model parameters 
     
    108104 
    109105 
    110 // A proposal sample 
     106// An evaluation sample 
    111107struct sample 
    112108{ 
     
    117113  // of h to this point 
    118114  double Lx; 
    119   // Multivariate normal proposal, which is just z for time-series samples 
    120   // after the first in each log-volatility computation 
     115  // Multivariate normal proposal, which is just z for the current evaluation, 
     116  // and for all time-series samples after the first in each log-volatility 
     117  // computation 
    121118  double *z; 
    122   // Multivariate log-volatility value based on the current proposal, or the 
     119  // Multivariate log-volatility value based on the current evaluation, or the 
    123120  // previous proposal to use this struct if the current proposal hasn't been 
    124121  // crunched yet 
     
    126123  // Scratchpad 1-D arrays of the same length as z, h 
    127124  double *x0, *x1; 
    128 }; 
    129  
    130  
    131 // A selection of a proposed log-volatility simulation 
    132 struct selection 
    133 { 
    134   int kp; 
    135   double Lp; 
    136125}; 
    137126 
     
    219208  // Inverse-scale the innovation by the square root of the volatilities in 
    220209  // preparation for decorrelation 
     210 
    221211  for(k=0; k<N; k++) 
    222     // TODO: Should we use a stripped-down version of exp here for speed? 
     212    // We could use a stripped-down version of exp here for speed; doing it 
     213    // with the stdlib exp function takes about 70 CPU cycles (20 nS) on an 
     214    // Intel QX9760 running at 3.8 GHz, though some of that is the unavoidable 
     215    // array lookups and products in the equation. 
    223216    SPA1(S, x0, k) = exp(-0.5 * SPA1(S, h, k)) * PA1(x, k); 
    224      
     217 
    225218  // Now decorrelate the equi-variance innovations in preparation for the 
    226219  // log-likelihood computation for this multivariate log-volatility proposal 
     
    232225 
    233226  S->Lxk = 0; 
    234    
     227 
    235228  // For each time series... 
    236229  for(k=0; k<N; k++) { 
     
    252245    S->Lxk -= 0.5 * SPA1(S, h, k); 
    253246  } 
     247  // Add the current log-likelihood to the accumulated log-likelihoods 
    254248  S->Lx += S->Lxk; 
    255 } 
    256  
    257  
    258 // Returns with zero only if the non-null proposals have converged close enough 
    259 // to the baseline value (the null proposal) to finish likelihood computation 
    260 int notCloseEnough(struct sample sp[], int n) 
    261 { 
    262   int k; 
    263   double L; 
    264   for(k=1; k<n; k++) { 
    265     L = sp[k].Lxk - sp[0].Lxk; 
    266     if(L > MIN_DIFF || L < -MIN_DIFF) 
    267       return 1; 
    268   } 
    269   return 0; 
    270 } 
    271  
    272  
    273 // Importance-samples one of the non-null proposals based on a weight computed 
    274 // from the log-density of z and the log-likelihood of the innovation given the 
    275 // proposal's log-volatility, conditional on the null proposal. 
    276 // 
    277 // Returns a struct with an integer index to the sampled proposal's struct and 
    278 // the log-probability of the proposal's having been selected. 
    279 struct selection \ 
    280 importanceSample(struct sample sp[], double Lz[], int n) 
    281 { 
    282   int k; 
    283   double val; 
    284   double Dp_sum = 0; 
    285   double Lp[n], Dp[n]; 
    286   double L_max = -HUGE_VAL; // Anything will be more positive 
    287   struct selection result; 
    288  
    289   // Log-densities densities are relative to the null-proposal, and with a 
    290   // maximum for normalization in selection 
    291   for(k=1; k<n; k++) { 
    292     val = sp[k].Lx + Lz[k] - sp[0].Lx - Lz[0]; 
    293     if(val > L_max) 
    294       L_max = val; 
    295     Lp[k] = val; 
    296   } 
    297  
    298   // Compute linear probability density for each proposal, relative to the 
    299   // maximum one 
    300   for(k=1; k<n; k++) { 
    301     val = exp(Lp[k] - L_max); 
    302     Dp[k] = val; 
    303     Dp_sum += val; 
    304   } 
    305    
    306   // Accept-reject sampling with uniform random proposal selection 
    307   do { 
    308     // Randomly select one of the proposals... 
    309     result.kp = (int) uniform(1, n); 
    310     // ...until the selected proposal is accepted, with probability 
    311     // proportional to its relative weight 
    312   } while(uniform(0, 1.0) > Dp[result.kp]); 
    313  
    314   // The probability density of the selected log-volatility proposal 
    315   result.Lp = log(Dp[result.kp] / Dp_sum); 
    316   return result; 
    317249} 
    318250 
     
    330262// w    Wiggle value for +/- proposals (float) 
    331263// ni   Number of hybrid-Gibbs iterations (int) 
    332 // np   Number of proposals to try per log-volatility simulation (int) 
    333264 
    334265//--- Model parameters, direct --- 
     
    342273// sc   Constants for multivariate normal PDF 
    343274 
    344 //--- Return values (tuple) --- 
    345 // 0    Lx: Log-likelihood of innovations given simulated log-volatilities 
    346 // 1    Lh: Log-likelihood of simulated log-volatilities 
    347  
     275//--- Return value (double float) --- 
     276// The linear likelihood P(x|w) of the innovations given the parameters, 
     277// integrated over the ni log-volatility simulations 
     278 
     279 
     280// Run evaluations until odds of error in selection between current and 
     281// proposed z will be less than 1/100. 
     282#define MIN_DIFF 0.01 
    348283 
    349284// The number of time series making up a single multivariate sample 
     
    352287const int Ns = Nx[1]; 
    353288 
    354 int ki, k0, k1, k2, k3; 
     289int ki, ke; 
     290int k0, k1, k2, k3; 
    355291double val; 
    356 double Lx = 0; 
    357 double Lh = 0; 
    358292 
    359293// Multivariate innovation for one current time-series sample 
    360294double *xk; 
    361 // The value of z and h for each proposal, at the first time-series sample of 
    362 // the evaluation interval 
    363 double zp[np], hp[np][Nt]; 
    364 // Log probability density of the value of z for each proposal 
    365 double Lz[np]; 
    366 // Log-likelihood of the innovation for the first time-series sample in 
    367 // proposal evalutions, for each proposal 
    368 double Lxk[np]; 
    369  
    370 // A struct for the result of the importance-sampling function 
    371 struct selection spSelection; 
    372 // A set of proposal sample structs 
    373 struct sample sp[np]; 
     295// The multivariate proposal on z 
     296double zp[Nt]; 
     297// The multivariate value of h for current and proposal evaluations, at the 
     298// first time-series sample of the evaluation interval 
     299double he[2][Nt]; 
     300// Log probability density of the value of z for current and proposal 
     301// evaluations, working values 
     302double Lzk[2]; 
     303// Log-likelihood of the innovation for the first time-series sample in current 
     304// and proposal evalutions, working values and accumulated for each iteration 
     305double Lxk[2], Lx[ni]; 
     306 
     307// A set of evaluation sample structs 
     308struct sample se[2]; 
    374309// A struct for the model parameters 
    375310struct parameters P; 
    376  
    377 // The scalar results go here 
    378 py::tuple result(2); 
    379311 
    380312// Generate parameter struct 
     
    384316// Initialize various arrays 
    385317xk = (double *) malloc(sizeof(double) * Nt); 
    386 for(k0=0; k0<np; k0++) { 
    387   sp[k0].z = (double *) malloc(sizeof(double) * Nt); 
    388   sp[k0].h = (double *) malloc(sizeof(double) * Nt); 
    389   sp[k0].x0 = (double *) malloc(sizeof(double) * Nt); 
    390   sp[k0].x1 = (double *) malloc(sizeof(double) * Nt); 
    391 
    392  
     318for(k0=0; k0<2; k0++) { 
     319  se[k0].z = (double *) malloc(sizeof(double) * Nt); 
     320  se[k0].h = (double *) malloc(sizeof(double) * Nt); 
     321  se[k0].x0 = (double *) malloc(sizeof(double) * Nt); 
     322  se[k0].x1 = (double *) malloc(sizeof(double) * Nt); 
     323
    393324 
    394325// For each iteration... 
    395326for(ki=0; ki<ni; ki++) { 
     327 
     328  // Initialize this iteration's accumulator 
     329  Lx[ki] = 0; 
    396330 
    397331  // The "previous" log-volatility of the first time-series sample is set to 
    398332  // the log-volatility offset plus a simulated, latent-parameter value. 
    399333  // TODO 
    400   for(k0=0; k0<np; k0++) { 
     334  for(k0=0; k0<2; k0++) { 
    401335    for(k1=0; k1<Nt; k1++) 
    402       PA1(sp[k0].h, k1) = D1(k1); 
     336      PA1(se[k0].h, k1) = D1(k1); 
    403337  } 
    404338 
     
    406340  for(k0=0; k0<Ns; k0++) { 
    407341     
    408     // Simulate np sets of h samples from separate proposals on z from the 
    409     // current time-series sample to some subsequent time-series sample at which 
    410     // the log-likelihood of the innovation for that sample becomes substantially 
    411     // the same for all proposals. 
    412  
     342    // Simulate two sets of h samples from the current z and a proposal on z, 
     343    // with a likelihood evaluation that starts from the current time-series 
     344    // sample to some subsequent time-series sample at which the log-likelihood 
     345    // of the innovation for that sample becomes substantially the same for the 
     346    // current and proposal value of z. 
     347   
    413348    k1 = k0; 
    414349   
    415     // Clear the log-likelihood accumulator of each proposal struct for the next 
    416     // proposal evalution 
    417     for(k2=0; k2<np; k2++) 
    418       sp[k2].Lx = 0; 
    419    
     350    // Clear the log-likelihood and normal log-density accumulators of each 
     351    // evaluation struct for the next pair of evaluations. 
     352    for(k2=0; k2<2; k2++) { 
     353      se[k2].Lx = 0; 
     354      Lzk[k2] = 0; 
     355      // Lxk[.] will be set to a value in se[.].Lx that has already been 
     356      // multivariate-accumulated, so it doesn't need clearing here 
     357    } 
     358     
    420359    do { 
    421360   
     
    424363        PA1(xk, k2) = X2(k2, k1); 
    425364       
    426       // For each proposal... 
    427       for(k2=0; k2<np; k2++) { 
     365      // For each evaluation... 
     366      for(k2=0; k2<2; k2++) { 
    428367   
    429368        // Set z... 
    430369        for(k3=0; k3<Nt; k3++) { 
    431370          val = Z2(k3, k1); 
    432           if(k1 == k0) { 
    433             // First time-series sample, use a proposal on z instead of z 
    434             // itself... 
    435             if(k2 != 0) 
    436               // ...but only actually change z if this isn't the null proposal 
     371          if(k1==k0) { 
     372            if(k2==1) { 
     373              // First time-series sample for the second evaluation, use a 
     374              // proposal on z instead of z itself 
    437375              val += uniform(-w, +w); 
    438             zp[k2] = val; 
    439             Lz[k2] = normLogDensity(val); 
     376              zp[k3] = val; 
     377            } 
     378            // Store the log-density of z for the first time-series sample to 
     379            // compare current vs. proposal 
     380            Lzk[k2] += normLogDensity(val); 
    440381          } 
    441           PA1(sp[k2].z, k3) = val; 
     382          PA1(se[k2].z, k3) = val; 
    442383        } 
    443384        // ...compute the multivariate log-volatility 
    444         logVol(&sp[k2], &P); 
     385        logVol(&se[k2], &P); 
    445386        // ...and the log-likelihood of the innovation for this time-series 
    446387        // sample, given the log-volatility 
    447         logLikelihood(&sp[k2], &P, xk); 
     388        logLikelihood(&se[k2], &P, xk); 
    448389         
    449390        // Save the first log-volatility and the log-likelihood based on it (and 
     
    452393        if(k1==k0) { 
    453394          for(k3=0; k3<Nt; k3++) 
    454             hp[k2][k3] = PA1(sp[k2].h, k3); 
    455           Lxk[k2] = sp[k2].Lx; 
     395            he[k2][k3] = PA1(se[k2].h, k3); 
     396          Lxk[k2] = se[k2].Lx; 
    456397        } 
    457398      } 
     
    459400      // Ready for the next time series sample, assuming there is one 
    460401      k1++; 
     402 
     403      // Continue only if difference in log-likelihood of the current 
     404      // time-series sample of the evaluations between current and proposed z 
     405      // is great enough to warrant doing so. 
     406      val = se[0].Lxk - se[1].Lxk; 
    461407     
    462     } while (k1<Ns && notCloseEnough(sp, np)); 
    463  
    464     // Importance sample proposal using pProb=exp(Lz+Lx) for each... 
    465     spSelection = importanceSample(sp, Lz, np); 
    466     // ...add the log-likelihood of the innovation given the selected 
    467     // log-volatility proposal to what will be the total log-likelihood of the 
    468     // innovations given the entire simulated h... 
    469     Lx += Lxk[spSelection.kp]
    470     // ...add the log-density of the selected log-volatility proposal to what 
    471     // will be the total log-density of the entire simulated h... 
    472     Lh += spSelection.Lp
    473     // ...and update the normal variate underlying the current time-series sample 
    474     // to that on which the selected log-volatility proposal was based. 
    475     for(k1=0; k1<Nt; k1++) 
    476       Z2(k1, k0) = zp[spSelection.kp]; 
    477    
    478     // Set the initial log-volatility of the proposals for the next time-series 
    479     // sample to the log-volatility of the selected proposal for this time-series 
    480     // sample. 
     408    } while (k1<Ns && (val > MIN_DIFF || val < -MIN_DIFF)); 
     409 
     410    // Metropolis-hastings selection of current or proposal using Lz+Lx for 
     411    // each evaluation 
     412    val = Lzk[1] + se[1].Lx  -  Lzk[0] - se[0].Lx; 
     413    if(val > 0 || log(uniform(0, 1)) < val) { 
     414      // Proposal accepted... 
     415      ke = 1
     416      // ...overwrite z for this sample with the proposal on z 
     417      for(k1=0; k1<Nt; k1++) 
     418        Z2(k1, k0) = zp[k1]
     419    } else { 
     420      // Proposal rejected 
     421      ke = 0; 
     422    } 
     423 
     424    // Set the initial log-volatility of the evaluations for the next 
     425    // time-series sample to the log-volatility of the selected evaluation for 
     426    // this time-series sample. 
    481427    for(k1=0; k1<Nt; k1++) { 
    482       val = hp[spSelection.kp][k1]; 
    483       for(k2=0; k2<np; k2++) 
    484         PA1(sp[k2].h, k1) = val; 
     428      val = he[ke][k1]; 
     429      for(k2=0; k2<2; k2++) 
     430        PA1(se[k2].h, k1) = val; 
    485431    } 
     432 
     433    // The joint probability of the innovation and the variates underlying the 
     434    // log-volatility simulation, conditional on the parameters, is equal to 
     435    // the likelihood of the innovation, conditional on the simulated 
     436    // variates and the parameters, times the probability of the 
     437    // simulated variates, conditional on the parameters: 
     438    // 
     439    // P(x,z|w) = P(x|z,w) * P(z|w) 
     440    // 
     441    // P(z|w) is conditional on w because of the correlation between sequential 
     442    // z values due to the VAR(1) in volatility shocks. Fortunately, the way 
     443    // that we've simulated z allows us to just evaluate P(z) using the joint 
     444    // normal distribution. 
     445 
     446    // Accumulate Log(P(xk,zk|w) = Lxk + Lzk) to eventually get Log(P(x,z|w) 
     447    Lx[ki] += Lxk[ke] + Lzk[ke]; 
    486448   
    487449    // Done with log-volatility draw for this time-series sample 
     
    494456// sample in the last iteration 
    495457for(k0=0; k0<Nt; k0++) 
    496   H1(k0) = PA1(sp[spSelection.kp].h, k0); 
     458  H1(k0) = PA1(se[ke].h, k0); 
    497459 
    498460// Free array memory 
    499461free(xk); 
    500 for(k0=0; k0<np; k0++) { 
    501     free(sp[k0].z); 
    502     free(sp[k0].h); 
    503     free(sp[k0].x0); 
    504     free(sp[k0].x1); 
    505 
    506  
    507 // The pair of results is Lx, the log-likelihood of each innovation given its 
    508 // simulated log-volatility and Lh, the total log-density of all of the 
    509 // simulated log-volatilities 
    510 result[0] = Lx / ni; 
    511 result[1] = Lh / ni; 
    512 return_val = result; 
     462for(k0=0; k0<2; k0++) { 
     463    free(se[k0].z); 
     464    free(se[k0].h); 
     465    free(se[k0].x0); 
     466    free(se[k0].x1); 
     467
     468 
     469// Compute the result, the integrated P(x|w) over the simulations on z 
     470 
     471// Compute the maximum log density // and save it to subtract from everybody 
     472// that the maximum log density is normalized to zero 
     473val = -HUGE_VAL; 
     474for(ki=0; ki<ni; ki++) { 
     475  if(Lx[ki] > val) 
     476    val = Lx[ki]; 
     477
     478// Accumulate the linearized normalized densities, borrowing Lzk[0] to do so 
     479Lzk[0] = 0; 
     480for(ki=0; ki<ni; ki++) 
     481  Lzk[0] += exp(Lx[ki] - val); 
     482// ...and return the denormalized, log mean of the linear densities 
     483return_val = log(Lzk[0]) + val - log(ni); 
  • projects/AsynCluster/trunk/svpmc/model.py

    r199 r200  
    129129                # Unpack string result from remote call 
    130130                result = list(pack.Unpacker(result)) 
    131             for k, name in enumerate(('Lx', 'Lh', 'z', 'h')): 
     131            for k, name in enumerate(('Lx', 'z', 'h')): 
    132132                setattr(paramContainer, name, result[k]) 
    133133            return paramContainer 
     
    184184      generator. 
    185185 
    186     @ivar N1: Number of log-volatility proposals to compute for the importance 
    187       sampling of each hybrid Gibbs step. For univariate, N1=10 appears most 
    188       cost-effective with wiggle=2.0. Scale for smaller wiggle and to account 
    189       for multivariate. 
    190  
    191     @ivar N2: Number of hybrid-Gibbs iterations per likelihood evaluation. For 
    192       univariate, N2=2 appears most cost-effective, but set to 4 anyays. Maybe 
    193       exploration of multivariate space needs more iterations. 
    194  
    195     """ 
    196     keyAttrs = {'y':None, 'wiggle':1.0, 'N1': 30, 'N2':10} 
     186    @ivar Ni: Number of hybrid Gibbs iterations per likelihood evaluation. 
     187     
     188    """ 
     189    keyAttrs = {'y':None, 'wiggle':1.0, 'Ni':30} 
    197190 
    198191    #--- Properties ----------------------------------------------------------- 
     
    260253        If a L{linalg.LinAlgError} is raised due to an invalid correlation 
    261254        matrix parameter, the method returns with no result. Otherwise, it 
    262         returns a tuple containing the following values reached at the end of 
    263         the log-volatility simulation: 
     255        returns a tuple containing the following: 
    264256         
    265             1. The log-likelihood of my observations given the simulated 
    266                log-volatility values. 
    267  
    268             2. The log-probability of the simulated log-volatilities. 
    269  
    270             3. The IID normal variates underlying the simulated 
    271                log-volatilities. 
    272  
    273             4. The multivariate log-volatility value for the last time-series 
    274                sample, useful for extrapolating from the fitted model. 
     257            1. The log-likelihood of my observations given the parameters, from 
     258               an integration of the join probability of the observations and 
     259               simulated log-volatilities over the simulation rounds. 
     260                
     261            2. The IID normal variates underlying the simulated 
     262               log-volatilities after the last simulation round. 
     263 
     264            3. The multivariate log-volatility value for the last time-series 
     265               sample after the last simulation round. (Useful for 
     266               extrapolating from the fitted model.) 
    275267         
    276268        The returned likelihood does not consider the prior probability of the 
     
    305297        sc[:,1] = s.log(s.sqrt(2*s.pi) * sc[:,0]) 
    306298 
    307         # Run the hybrid Gibbs rounds, returning the likelihood from the last 
    308         # one along with the state of the IID variate vector at that point. 
    309         Lx, Lh = self.inline( 
    310             'z', 'h', 'x', 
    311             'w', 'ni', 'np', 
     299        # Run the hybrid Gibbs rounds 
     300        Lx = self.inline( 
     301            'z', 'h', 'x', 'w', 'ni', 
    312302            'd', 'e', 'g', 'rz', 'ri', 'sc', 
    313             w=self.wiggle, np=self.N1+1, ni=self.N2
    314         return Lx, Lh, z, h 
     303            w=self.wiggle, ni=self.Ni
     304        return Lx, z, h 
  • projects/AsynCluster/trunk/svpmc/pmc.py

    r195 r200  
    198198        def weight(paramContainer): 
    199199            if s.isfinite(paramContainer.Lx): 
    200                 L = paramContainer.Lx + paramContainer.Lp \ 
    201                     - paramContainer.Lj - paramContainer.Lh 
     200                L = paramContainer.Lx + paramContainer.Lp - paramContainer.Lj 
    202201                info = " ".join([ 
    203202                    "%+12.2f" % (getattr(paramContainer, x),) 
    204                     for x in ('Lx', 'Lp', 'Lj', 'Lh')]) 
     203                    for x in ('Lx', 'Lp', 'Lj')]) 
    205204            else: 
    206205                info = "" 
  • projects/AsynCluster/trunk/svpmc/project.py

    r199 r200  
    112112        paramTitles, dimensions = self._setupParams() 
    113113        self.mgr = model.ModelManager( 
    114             self, tsData, wiggle=self.wiggle, N1=self.N1, N2=self.N2
     114            self, tsData, wiggle=self.wiggle, Ni=self.Ni
    115115        self._setupCDF( 
    116116            os.path.join(specDir, ncFileName), 
  • projects/AsynCluster/trunk/svpmc/test/test_model.py

    r199 r200  
    506506 
    507507 
    508 class Test_Model_importanceSample(BaseCase): 
    509     code = """ 
    510     int k; 
    511     const int n = NX[0]; 
    512     struct sample sp[n]; 
    513     double Lz[n]; 
    514     py::tuple result(2); 
    515     struct selection spSelection; 
    516  
    517     for(k=0; k<n; k++) { 
    518       sp[k].Lx = X1(k); 
    519       Lz[k] = Z1(k); 
    520     } 
    521     spSelection = importanceSample(sp, Lz, n); 
    522     result[0] = spSelection.kp; 
    523     result[1] = spSelection.Lp; 
    524     return_val = result; 
    525     """ 
    526  
    527     def _importanceSample(self, Lx_array, Lz_array=None): 
    528         if Lz_array is None: 
    529             Lz_array = s.zeros_like(Lx_array) 
    530         return self.inline(self.code, X=Lx_array, Z=Lz_array) 
    531  
    532     def test_basic(self): 
    533         N = 8 
    534         N_iter = 1000 
    535         Lx_array = s.zeros(N) 
    536         I = [self._importanceSample(Lx_array)[0] for k in xrange(N_iter)] 
    537         for k in xrange(N): 
    538             self.failUnless(k in I) 
    539  
    540     def _check(self, z0, wiggle): 
    541         N = 20 
    542         N_iter = 1000 
    543         distObj = stats.distributions.truncnorm(z0-wiggle, z0+wiggle) 
    544         X = 2*wiggle*(s.rand(N_iter, N) - 0.5) + z0 
    545         Y = s.empty(N_iter) 
    546         Lp = s.empty(N_iter) 
    547         for k, Xk in enumerate(X): 
    548             Lx_array = s.log(distObj.pdf(Xk)) 
    549             kp, Lpk = self._importanceSample(Lx_array) 
    550             Y[k] = Xk[kp] 
    551             Lp[k] = Lpk 
    552         if VERBOSE: 
    553             I = Y.argsort() 
    554             sp = self.fig.add_subplot(111) 
    555             sp.plot(Y, s.exp(Lp), '.', Y[I], s.pi/N*distObj.pdf(Y[I])) 
    556         self.failUnlessNormal(Y) 
    557  
    558     def test_full(self): 
    559         return self._check(0, 4.0) 
    560  
    561     def test_closePortion(self): 
    562         return self._check(1.5, 1.0) 
    563  
    564     def test_farPortion(self): 
    565         return self._check(2.5, 0.5) 
    566  
    567  
    568508class Test_Model_likelihood(BaseCase): 
    569509    corr = 0.0 
     
    602542        return iv, h, x 
    603543 
    604     def _inlineVars(self, wiggle, eValue, N1, N2=1): 
     544    def _inlineVars(self, wiggle, eValue, Ni): 
    605545        return { 
    606546            'h':s.empty(1), 
    607547            'sc':s.array([1, s.log(s.sqrt(2*s.pi))]), 
    608548            'w':wiggle, 
    609             'np':N1+1, 
    610             'ni':N2, 
     549            'ni':Ni, 
    611550            'd':s.array([0.0]), 
    612551            'e':s.array([[float(eValue)]]), 
     
    616555            } 
    617556     
    618     def _modelAndParamFactory(self, wiggle, N1, N2, **kw): 
     557    def _modelAndParamFactory(self, wiggle, Ni, **kw): 
    619558        """ 
    620559        Returns a parameter container populated from my I{params} dict, 
     
    632571                s.array(kw.get(name, self.params[name]), dtype='d')) 
    633572        # Return the parameter container along with a model to be tested 
    634         modelObj = model.Model(N1=N1, N2=N2, wiggle=wiggle) 
     573        modelObj = model.Model(Ni=Ni, wiggle=wiggle) 
    635574        modelObj.paramNames = util.PARAM_NAMES 
    636575        return pc, modelObj 
     
    650589        """ 
    651590        Runs C code for L{model.Model.likelihood} independent of the method 
    652         itself
     591        itself, repeating the run I{Nr} times with different simulated data
    653592        """ 
    654593        z = s.zeros((1, Ns)) 
     
    666605        wiggle = 0.1 
    667606        eValue = 0.90 
    668         Ns, N1, N2 = 10, 5, 2
    669         inlineVars = self._inlineVars(wiggle, eValue, N1, N2
    670         inlineVars.update({'x':2*s.ones((1, Ns)), 'z':s.zeros((1, Ns))}) 
     607        Ns, Nr = 6, 5
     608        inlineVars = self._inlineVars(wiggle, eValue, 1
     609        inlineVars.update({'x':2*s.ones((1,Ns)), 'z':s.zeros((1, Ns))}) 
    671610        modelObj = model.Model() 
    672         print "\n  k      Lx       Lh     Simulated Volatility Shocks" 
     611        print "\n  k      Lx       Simulated Volatility Shocks" 
    673612        print "-"*100 
    674         for k in xrange(N2): 
    675             Lx, Lh = modelObj.inlineDirect( 
     613        for k in xrange(Nr): 
     614            Lx = modelObj.inlineDirect( 
    676615                modelObj.code['likelihood'], **inlineVars) 
    677616            zLine = "   ".join(["%+4.2f" % xx for xx in inlineVars['z'][0,:]]) 
    678             print "%3d: %+6.1f  %+7.1f%s%s" % (k, Lx, Lh, " "*5, zLine) 
    679  
     617            print "%3d: %+6.1f  %s%s" % (k, Lx, " "*5, zLine) 
     618     
    680619    def _simRounds(self, Nr, Ns, inlineVars, name, values): 
    681620        fig = self.fig 
    682621        bins = s.linspace(0.65, 0.95, 20) 
    683622        for k, value in enumerate(values): 
    684             print k, value 
    685623            inlineVars[name] = value 
    686624            correlations = [] 
     
    694632            sp.set_title("%s=%d" % (name, value)) 
    695633 
    696     def test_optimize_N1(self): 
    697         # Empirically, it looks like np=10 is best. Going to np=20 barely gives 
    698         # any improvement, and obviously doubles the amount of computation 
    699         # time. Dropping to np=5 is significantly worse. 
    700         Nr = 500 
     634 
     635    def test_optimize_Ni(self): 
     636        """ 
     637        With univariate, Ni=20 is significantly better than Ni=10, but not 
     638        significantly worse than Ni=40. Tested with wiggles of 0.5 and 1.0, and 
     639        eValue=0.95. 
     640        """ 
     641        Nr = 1000 
    701642        wiggle = 0.5 
    702643        eValue = 0.95 
    703         Ns, N2 = 500, 10 
    704         inlineVars = self._inlineVars(wiggle, eValue, 1, N2) 
    705         self._simRounds(Nr, Ns, inlineVars, 'np', (2,5,10,20)) 
    706  
    707     def test_optimize_N2(self): 
    708         # Empirically, it looks like ni=20 is best. It's noticeably better than 
    709         # ni=10 (though not dramatically so), but going to ni=40 doesn't show 
    710         # any improvement. 
    711         Nr = 500 
    712         wiggle = 0.5 
    713         eValue = 0.95 
    714         Ns, N1 = 500, 10 
    715         inlineVars = self._inlineVars(wiggle, eValue, N1, 1) 
     644        Ns = 1000 
     645        inlineVars = self._inlineVars(wiggle, eValue, 1) 
    716646        self._simRounds(Nr, Ns, inlineVars, 'ni', (5,10,20,40)) 
    717647     
     
    719649        wiggle = 0.5 
    720650        eValue = 0.97 
    721         Ns, N1, N2 = 200, 10, 20 
    722         inlineVars = self._inlineVars(wiggle, eValue, N1, N2
     651        Ns, Ni = 200, 20 
     652        inlineVars = self._inlineVars(wiggle, eValue, Ni
    723653        for hReal, hSim in self._likelihood(Ns, 1, inlineVars): 
    724654            self._plot((hReal, hSim)) 
     
    727657        wiggle = 0.5 
    728658        eValue = 0.97 
    729         Ns, N1, N2 = 1000, 10, 20 
     659        Ns, Ni = 1000, 20 
    730660        iv, h, x = self._simData(Ns, eValue) 
    731         pc, modelObj = self._modelAndParamFactory(wiggle, N1, N2, e=[[eValue]]) 
     661        pc, modelObj = self._modelAndParamFactory(wiggle, Ni, e=[[eValue]]) 
    732662        pc.z = s.zeros((1, Ns)) 
    733663        modelObj.y = self._x_to_y(x) 
    734         Lx, Lh, z, hn = modelObj.likelihood(pc) 
     664        Lx, z, hn = modelObj.likelihood(pc) 
    735665        self._plot(x, (iv[1,:], z[0,:]), (h, self._z_to_h(z[0,:], eValue)))