Changeset 186

Show
Ignore:
Timestamp:
05/20/08 15:42:21 (7 months ago)
Author:
edsuom
Message:

Working on putting the likelihood method together, finally

Files:

Legend:

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

    r185 r186  
    122122 
    123123 
    124 // A selection of a proposal sample 
     124// A selection of a proposed log-volatility simulation 
    125125struct selection 
    126126{ 
    127127  int kp; 
    128   double Lp
     128  double Lh
    129129}; 
    130130 
     
    213213  // preparation for decorrelation 
    214214  for(k=0; k<N; k++) 
     215    // TODO: Should we use a stripped-down version of exp here for speed? 
    215216    SPA1(S, x0, k) = exp(-0.5 * SPA1(S, h, k)) * PA1(x, k); 
    216217     
     
    247248// Returns with zero only if the post-first proposals are close enough to 
    248249// finish likelihood computation 
    249 int notCloseEnough(struct sample *sp[][2], int n) 
     250int notCloseEnough(struct sample sp[][2], int n) 
    250251{ 
    251252  int k; 
     
    254255  double Lmax = -HUGE_VAL;   // Anything will be more positive 
    255256  for(k=0; k<n; k++) { 
    256     L = sp[k][1]->Lx; 
     257    L = sp[k][1].Lx; 
    257258    if(L < Lmin) 
    258259      Lmin = L; 
     
    271272// the log-probability of the proposal's having been selected. 
    272273struct selection \ 
    273 importanceSample(struct sample *sp[][2], double Lz[], int n) 
     274importanceSample(struct sample sp[][2], double Lz[], int n) 
    274275{ 
    275276  int k, kpMax; 
    276277  double val; 
    277   double pSum = 0
     278  double Dp[n]
    278279  double pMax = -HUGE_VAL;  // Anything will be more positive 
    279   double Dp[n]; 
    280280  struct selection result; 
    281281 
    282   // Compute linear probability density for each proposal 
     282  // Compute linear probability density for each proposal and their maximum 
    283283  for(k=0; k<n; k++) { 
    284     val = exp(sp[k][1]->Lx + Lz[k]); 
     284    val = exp(sp[k][1].Lx + Lz[k]); 
    285285    Dp[k] = val; 
    286     pSum += val; 
    287286    if(val > pMax) { 
    288287      pMax = val; 
     
    299298  } while(result.kp != kpMax && uniform(0, pMax) > Dp[result.kp]); 
    300299 
    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]); 
    303303  return result; 
    304304} 
     
    342342double val; 
    343343double Lx = 0; 
    344 double Lp = 0; 
     344double Lh = 0; 
    345345 
    346346// Multivariate innovation for one current time-series sample 
     
    348348// Log probability density of each proposal on z 
    349349double Lz[n]; 
    350 // Linear probability density of each log-volatility proposal 
    351 double Dp[n]; 
    352350 
    353351// A struct for the result of the importance-sampling function 
     
    373371  for(k1=0; k1<2; k1++) { 
    374372    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; 
    379381} 
    380382 
     
    389391  for(k2=0; k2<n; k2++) 
    390392    Lz[k2] = 0; 
    391    
     393 
    392394  do { 
    393395 
     
    405407          Lz[k2] += normLogDensity(val); 
    406408        } 
    407         SPA1(sp[k2][notFirst], z, k3) = val; 
     409        PA1(sp[k2][notFirst].z, k3) = val; 
    408410      } 
    409411    } 
     
    426428      for(k2=0; k2<n; k2++) { 
    427429        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); 
    429431      } 
    430432    } 
     
    432434  } while (k1==k0+1 || (k1<Ns && notCloseEnough(sp, n))); 
    433435 
    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. 
    437443  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   
    440446  // Set the initial log-volatility of the proposals for the next time-series 
    441447  // sample to the log-volatility of the selected proposal for this time-series 
    442448  // 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; 
    447453  } 
    448454 
     
    453459// sample 
    454460for(k0=0; k0<Nt; k0++) 
    455   H1(k0) = SPA1(sp[kp][1], h, k0); 
     461  H1(k0) = PA1(sp[kp][1].h, k0); 
    456462 
    457463// Free array memory 
     
    459465for(k0=0; k0<n; k0++) { 
    460466  for(k1=0; k1<2; k1++) { 
     467    free(sp[k0][k1].z); 
    461468    free(sp[k0][k1].h); 
    462469    free(sp[k0][k1].x0); 
     
    465472} 
    466473 
    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... 
     476for(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 
     479result[0] = Lx; 
     480result[1] = Lh; 
    472481return_val = result; 
  • projects/AsynCluster/trunk/svpmc/model.py

    r184 r186  
    276276        # ...including the latent parameter of IID normal variates 
    277277        z = paramContainer.z.copy() 
     278        print self.fs, self.fr 
    278279 
    279280        # Set up arary variables for the inline call, including innovations as 
     
    293294            return 
    294295        # ...scaling constants for multivariate normal pdf 
     296        sc = s.empty((self.p, 2)) 
    295297        sc[:,0] = s.sqrt(1 - self.g**2) 
    296298        sc[:,1] = s.log(s.sqrt(2*s.pi) * sc[:,0]) 
     
    299301        # one along with the state of the IID variate vector at that point. 
    300302        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): 
    303306            result = self.inline( 
    304307                'z', 'h', 'x', 'w', 'n', 'd', 'e', 'g', 'rz', 'ri', 'sc', 
    305308                w=self.wiggle, n=self.N1) 
     309            print "\n", k, result 
     310            print z[0,:] 
    306311            Lx += result[0] 
    307             Lp += result[1] 
    308         return Lx, Lp, z, h 
     312            Lh += result[1] 
     313        return Lx, Lh, z, h 
  • projects/AsynCluster/trunk/svpmc/test/test_model.py

    r185 r186  
    2727from twisted.spread import pb 
    2828from asynqueue import ThreadQueue 
    29 from twisted_goodies.pybywire import pack, params 
    30  
    31 import model, tseries 
     29from twisted_goodies.pybywire import pack 
     30from twisted_goodies.pybywire.params import Parameterized 
     31 
     32import params, model 
    3233import util 
    3334 
     
    4041 
    4142 
    42 class Mock_Model(params.Parameterized, util.Mock): 
     43class Mock_Model(Parameterized, util.Mock): 
    4344    drift = 1.5 
    4445    p, n = 8, 937 
     
    109110            self.nextCall(Mock_Client.calls) 
    110111            self.nextCall( 
    111                 'registerClasses', params.Parameterized.registry) 
     112                'registerClasses', Parameterized.registry) 
    112113            self.nextCall( 
    113114                'update', ('newModel', self.model)) 
     
    144145        } 
    145146 
    146     def modelFactory(self, **kw): 
    147         """ 
    148         Instantiate a model to be tested and set its parameters 
    149         """ 
    150         kw['paramNames'] = util.PARAM_NAMES 
    151         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.y 
    159             else: 
    160                 kw['y'] = s.zeros((len(kw['fs']), self.N)) 
    161         return model.Model(**kw) 
    162  
    163147    def inline(self, code, **kw): 
    164148        """ 
    165149        Do an inline call with the model's Weaver API and support code. 
    166150        """ 
    167         return self.modelFactory().inlineDirect(textwrap.dedent(code), **kw) 
     151        return model.Model().inlineDirect(textwrap.dedent(code), **kw) 
    168152     
    169153    def _covarMatrix(self, cs, cr): 
     
    313297                "Generated array \n%s\n != \n%s" % (y, x)) 
    314298 
    315         modelObj = self.modelFactory() 
     299        modelObj = model.Model() 
    316300        tryCoeffs([1.0], [], [[1.0]]) 
    317301        tryCoeffs([1.0, 1.0], [0.2], [[1.0, 0.2], [0.2, 1.0]]) 
     
    523507 
    524508class Test_Model_spArray(BaseCase): 
    525     code = """ 
     509    codeBase = """ 
    526510    int k; 
    527     const int n = NL[0]; 
    528     struct selection spSelection; 
     511    const int n = NX[0]; 
    529512    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 + """ 
    530522    double Lz[n]; 
    531523    py::tuple result(2); 
    532      
    533     for(k=0; k<n; k++) { 
     524    struct selection spSelection; 
     525    for(k=0; k<n; k++) 
    534526      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
    539531    """ 
    540532 
     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 
    541574 
    542575class Test_Model_likelihood(BaseCase): 
    543     N = 1000 
     576    N = 6 
    544577    corr = 0.0 
    545578    params = { 
    546579        'a': [0], 
    547580        'b': [[0]], 
    548         'cs': [1.0], 
    549581        'cr': [], 
    550582        'd': [0], 
     
    555587        } 
    556588 
    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 
    560603        self.iv = random.multivariate_normal( 
    561604            [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) 
    582624        if VERBOSE: 
    583625            fig = self.fig 
    584             vectors = (self.x[0,:], (self.h, h[0,:])) 
     626            vectors = (self.x, (self.h, h)) 
    585627            for k, vector in enumerate(vectors): 
    586                 spNumber = 100*(len(vectors)+1) + k + 11 
     628                spNumber = 100*len(vectors) + k + 11 
    587629                sp = fig.add_subplot(spNumber) 
    588630                if not isinstance(vector, (tuple, list)): 
     
    590632                for v in vector: 
    591633                    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) 
    594635         
    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]]) 
    599638         
    600639    def test_hybridGibbs_lowCorrelation(self):