[ADMB Users] SEPARABLE_FUNCTION

Richard Chandler richard.chandlers at gmail.com
Fri Mar 11 07:40:08 PST 2011


Thank you Hans and Dave. The tpl file below now works. Weihai Liu was
also kind enough to send me a suggestion, which is pasted in too.
Since Hans is one of the principal developers, I assume his
implementation is the preferred one.

Richard


// Based on Hans' suggestions

PARAMETER_SECTION

  init_bounded_number log_lambda(-20.0,20.0,1)
  init_bounded_number p0(-20.0,20.0,1)
  init_bounded_number p1(-20.0,20.0,1)

  init_bounded_number log_sigma(-3.0,3.0,2) // log of random effect SD
  random_effects_vector u(1,nG,2)

  objective_function_value nll

PROCEDURE_SECTION

  for(int id=1; id<=nG; id++) {
      nll_group(id, p0,p1,log_lambda,log_sigma,u(id));
      }


SEPARABLE_FUNCTION void nll_group(int id, const dvariable& p0,const
dvariable& p1,const dvariable& log_lambda, const dvariable& log_sigma,
const dvariable& u)
  dvar_vector p(1,R);
  dvar_vector f(1,S);
  dvar_vector g(1,S);
  dvariable sigma = exp(log_sigma);
  dvariable lambda = exp(log_lambda);

  nll += log_sigma + 0.5*square(u/sigma);

  int q=10*(id-1)+1;
  for(int i=q;i<=q+9;i++) {
      p(i) = 1.0/(1.0+exp(-1.0*(p0 + p1*x(i) + u)));
      for(int k=1;k<=S;k++) {
          f(k) = pow(lambda, N(k)) * exp(-1.0*lambda - gammln(N(k)+1));
          g(k) = 1.0;
          for(int j=1;j<=T;j++) {
              if(N(k)>=y(i,j))
                  g(k) *= exp(gammln(N(k)+1) - gammln(y(i,j)+1) -
                      gammln(N(k)-y(i,j)+1)) * pow(p(i), y(i,j)) *
                      pow(1.0-p(i), N(k)-y(i,j));
              else
                  g(k) =0.0;
              }
          }
      nll -= log(f*g);
  }






// based on Weihai's example

PARAMETER_SECTION

  init_bounded_number log_lambda(-20.0,20.0,1)
  init_bounded_number p0(-20.0,20.0,1)
  init_bounded_number p1(-20.0,20.0,1)

  init_bounded_number log_sigma(-3.0,3.0,2) // log of random effect SD
  random_effects_vector u(1,nG,2)

  objective_function_value nll


PROCEDURE_SECTION
  nll_group(p0,p1,log_lambda,log_sigma,u);



SEPARABLE_FUNCTION void nll_group(const dvariable& p0,const dvariable&
p1,const dvariable& log_lambda, const dvariable& log_sigma, const
dvar_vector& u)
  dvar_vector p(1,R);
  dvar_vector f(1,S);
  dvar_vector g(1,S);
  dvariable sigma = exp(log_sigma);
  dvariable lambda = exp(log_lambda);

//  nll = nG*log_sigma + 0.5*norm2(u/sigma);
  nll = nG*log_sigma + 0.5*norm2(u)/mfexp(2*log_sigma);


  for(int i=1;i<=R;i++) {
      int id = ID(i);
      p(i) = 1.0/(1.0+exp(-1.0*(p0 + p1*x(i) + u(id))));
      for(int k=1;k<=S;k++) {
          f(k) = pow(lambda, N(k)) * exp(-1.0*lambda -
gammln(N(k)+1)); //poisson
          g(k) = 1.0;
          for(int j=1;j<=T;j++) {
              if(N(k)>=y(i,j))
                  g(k) *= exp(gammln(N(k)+1) - gammln(y(i,j)+1) -
                      gammln(N(k)-y(i,j)+1)) * pow(p(i), y(i,j)) *
                      pow(1.0-p(i), N(k)-y(i,j));//binomial
              else
                  g(k) =0.;
              }
          }
      nll -= log(f*g + 1.e-20);
  }






On Fri, Mar 11, 2011 at 6:08 AM, H. Skaug <hskaug at gmail.com> wrote:
> Hi,
>
> Yes, it seems that your model is separable, but of type "4.1 The first example"
> in ADMBRE manual. Hence, you do not need the sparse matrix stuff.
> In your code you need to loop over the elements of "u" like in "4.1
> The first example"
> Your PROCEDURE_SECTION should basically consist of:
>
>  for(int id=1;id<=xxxxx;id++)
>   SEPARABLE_FUNCTION(u(id), + the rest of your arguments)
>
>
> Inside the SEPARABLE_FUNCTION you need to do all the calculations
> that involve u(id).
>
> If you do this you will be able to handle large models. Make sure
> that you get the same result on small examples with and with SEPARABLE_FUNCTION.
>
>
> Hans
>
> On Thu, Mar 10, 2011 at 2:54 PM, Richard Chandler
> <richard.chandlers at gmail.com> wrote:
>> Hi,
>>
>> I implemented a binomial-Poisson mixture model (Royle Biometrics 2004)
>> with random effects in ADMB (.tpl below). It works very well on small
>> simulated datasets; however, I run into memory issues when I try
>> complex variations of the model on large datasets. I have fiddled with
>> many of the command line options and the TOP_OF_MAIN_SECTION, but I
>> believe I need to use ADMB's sparse matrix capabilities via the
>> SEPARABLE_FUNCTION. My approach has been to start with something
>> simple:
>>
>> SEPARABLE_FUNCTION void nll_group(const dvariable& log_sigma, const
>> dvar_vector& u)
>>  nll = nG*log_sigma + 0.5*norm2(u)/mfexp(2*log_sigma);
>>
>> but this does not converge. I am new to ADMB and would greatly
>> appreciate it if someone could suggest a better way to use a
>> SEPARABLE_FUNCTION here. The RE manual is very helpful, but I must be
>> missing something. Also, I would appreciate any other suggestions for
>> improving the implementation of this model.
>>
>> Thanks for the great software.
>>
>> Richard
>>
>



More information about the Users mailing list