Main Page | Report this Page
 
   
Science Forum Index  »  Statistics - Math Forum  »  Gamma distribution & Markov chain Monte Carlo...
Page 1 of 1    
Author Message
Maniaoh...
Posted: Wed Jul 16, 2008 8:23 pm
Guest
Hi guys,

I code a small piece to generate variates from Gamma distribution with
Markov chain Monte Carlo as shown below. The appeared results,
however, using 'hist(vari)' command does not looks like it follows
Gamma distribution at all. (I compare it with 'gamrnd' provided in
Matlab.) None of Metropolis - Hastings or Metropolis method works.
Please kindly provide me some hints about this problem, I'm totally
lost.

Thanks in advance. Any comment is highly appreciated.
Iaoh.

--------------------

clear all

% number of iterations
n = 5000;
% burn-in rounds
burnin = 2000;
% preallocate the array
vari = zeros(1, n);

str = 'x^(a - 1)*exp(-b*x)'; % gamma distribution
gamDist = inline(str, 'x', 'a', 'b');
a = 1;
b = 1;

str = 'exp(-0.5*((x-mu)/sig)^2)';
norm = inline(str, 'x', 'mu', 'sig');
sig = 1;

vari(1) = randn(1); % initial value
for index = 2:n
% normal distribution is used as proposal distribution
y = vari(index - 1) + randn(1)*sig;
% draw u from normal distribution
u = randn(1);
% calculate accepting factor alpha
% by Metropolis - Hastings method
alpha = min(1, (gamDist(y, a, b))*norm(vari(index - 1), y,
sig)/...
((gamDist(vari(index - 1), a, b))*norm(y, vari(index -
1), sig)));
% by Metropolis-only method
% alpha = min(1, (gamDist(y, a, b))/(gamDist(vari(index - 1), a,
b)));
if u <= alpha
vari(index) = y;
else
vari(index) = vari(index - 1);
end
end

% remove burn-in elements
vari = vari(burnin:n);
hist(vari);
Maniaoh...
Posted: Thu Jul 17, 2008 6:59 am
Guest
Thank you very much for your comment. The reason I use MCMC is just
for testing and I believe you are completely right about other faster
methods.

Based on your comment, I assume that my code is right (if w/o burn-in)
but I'm still in serious doubt. I removed the burn-in steps as you say
but the problem remains the same, even when I tried to run for several
times. In addition, all variable values are smaller than zero, none is
bigger.

Can you please skim through my code and see if there are some
mistakes?

Thank you very much,
Iaoh.

Quote:

The Gamma distribution is log concave if the shape parameter is
at least one; the log Gamma distribution for any value of
the parameter. If the parameter is at least 1/3, the cube
root of a Gamma random variable is "dominated" by the normal
density fitting it at the mode; this is the Wilson-Hilferty
transformation.  Acceptance rejection methods are quick.

MKMC does not give independent Gamma random variables; this
does with no "burn in".

...
Posted: Thu Jul 17, 2008 10:09 am
Guest
On Jul 17, 1:23 am, Maniaoh <n.hoai... at (no spam) gmail.com> wrote:

Quote:
Matlab.) None of Metropolis - Hastings or Metropolis method works.
Please kindly provide me some hints about this problem, I'm totally
lost.

Some comments. Take them as you will...

Quote:
vari(1) = randn(1); % initial value

If you're trying to sample gamma variates, make sure you start your
chain with a value > 0. Sampling from the standard normal could give
you a negative value which causes the MCMC to blow up since the
density of a gamma < 0 is 0

Quote:
for index = 2:n
        % normal distribution is used as proposal distribution
        y = vari(index - 1) + randn(1)*sig;

Ok, your proposal distribution is

p(x* | x) = N( x, sig^2 )

Quote:
% draw u from normal distribution
u = randn(1);

This is wrong. Draw u from a *Uniform* distribution on [0, 1]

Quote:
        % calculate accepting factor alpha
        % by Metropolis - Hastings method
        alpha = min(1, (gamDist(y, a, b))*norm(vari(index - 1), y,
sig)/...
                ((gamDist(vari(index - 1), a, b))*norm(y, vari(index -
1), sig)));

This looks ok, but you might want to compute each term for clarity
just is case there's something subtle, e.g.

x = vari(index - 1);
p_y = gamDist(y, a, b);
p_x = gamDist(x, a, b);
q_y_x = norm(y, x, sig);
q_x_y = norm(x, y, sig);

alpha = (p_y * q_x_y) / (p_x * q_y_x);

Quote:
        % by Metropolis-only method
%       alpha = min(1, (gamDist(y, a, b))/(gamDist(vari(index - 1), a,
b)));

Again, looks ok....

Quote:
        if u <= alpha
                vari(index) = y;
        else
                vari(index) = vari(index - 1);
        end

This is OK as long as you fix how you draw u. Add in some warning()
or error() statements to catch any case where you get bad values, e.g.
Infinite or NaN likelihood and likelihood ratios or if alpha < 0 or if
y every becomes negative.

-Lucas
Herman Rubin...
Posted: Thu Jul 17, 2008 10:32 am
Guest
In article <63de0933-cb20-47b5-b93c-9688c943bb19 at (no spam) 56g2000hsm.googlegroups.com>,
Maniaoh <n.hoainam at (no spam) gmail.com> wrote:
Quote:
Hi guys,

<I code a small piece to generate variates from Gamma distribution with
<Markov chain Monte Carlo as shown below. The appeared results,
<however, using 'hist(vari)' command does not looks like it follows
<Gamma distribution at all. (I compare it with 'gamrnd' provided in
<Matlab.) None of Metropolis - Hastings or Metropolis method works.
<Please kindly provide me some hints about this problem, I'm totally
<lost.

Quote:
Thanks in advance. Any comment is highly appreciated.
Iaoh.

The Gamma distribution is log concave if the shape parameter is
at least one; the log Gamma distribution for any value of
the parameter. If the parameter is at least 1/3, the cube
root of a Gamma random variable is "dominated" by the normal
density fitting it at the mode; this is the Wilson-Hilferty
transformation. Acceptance rejection methods are quick.

MKMC does not give independent Gamma random variables; this
does with no "burn in".

Quote:
--------------------

clear all

% number of iterations
n = 5000;
% burn-in rounds
burnin = 2000;
% preallocate the array
vari = zeros(1, n);

str = 'x^(a - 1)*exp(-b*x)'; % gamma distribution
gamDist = inline(str, 'x', 'a', 'b');
a = 1;
b = 1;

str = 'exp(-0.5*((x-mu)/sig)^2)';
norm = inline(str, 'x', 'mu', 'sig');
sig = 1;

vari(1) = randn(1); % initial value
for index = 2:n
% normal distribution is used as proposal distribution
y = vari(index - 1) + randn(1)*sig;
% draw u from normal distribution
u = randn(1);
% calculate accepting factor alpha
% by Metropolis - Hastings method
alpha = min(1, (gamDist(y, a, b))*norm(vari(index - 1), y,
sig)/...
((gamDist(vari(index - 1), a, b))*norm(y, vari(index -
1), sig)));
% by Metropolis-only method
% alpha = min(1, (gamDist(y, a, b))/(gamDist(vari(index - 1), a,
b)));
if u <= alpha
vari(index) = y;
else
vari(index) = vari(index - 1);
end
end

% remove burn-in elements
vari = vari(burnin:n);
hist(vari);


--
This address is for information only. I do not claim that these views
are those of the Statistics Department or of Purdue University.
Herman Rubin, Department of Statistics, Purdue University
hrubin at (no spam) stat.purdue.edu Phone: (765)494-6054 FAX: (765)494-0558
Maniaoh...
Posted: Thu Jul 17, 2008 7:47 pm
Guest
Hi Lucas,

Thank you very much. I was able to code it right. Use of normal
distribution sometimes create value < 0 that causes terrible pain. I
also did add a guard to check it and change the way I draw u.

Thanks again.

On Jul 18, 5:09 am, lscha... at (no spam) d.umn.edu wrote:
Quote:
On Jul 17, 1:23 am, Maniaoh <n.hoai... at (no spam) gmail.com> wrote:

Matlab.) None of Metropolis - Hastings or Metropolis method works.
Please kindly provide me some hints about this problem, I'm totally
lost.

Some comments. Take them as you will...

vari(1) = randn(1); % initial value

If you're trying to sample gamma variates, make sure you start your
chain with a value > 0. Sampling from the standard normal could give
you a negative value which causes the MCMC to blow up since the
density of a gamma < 0 is 0

for index = 2:n
% normal distribution is used as proposal distribution
y = vari(index - 1) + randn(1)*sig;

Ok, your proposal distribution is

p(x* | x) = N( x, sig^2 )

% draw u from normal distribution
u = randn(1);

This is wrong. Draw u from a *Uniform* distribution on [0, 1]

% calculate accepting factor alpha
% by Metropolis - Hastings method
alpha = min(1, (gamDist(y, a, b))*norm(vari(index - 1), y,
sig)/...
((gamDist(vari(index - 1), a, b))*norm(y, vari(index -
1), sig)));

This looks ok, but you might want to compute each term for clarity
just is case there's something subtle, e.g.

x = vari(index - 1);
p_y = gamDist(y, a, b);
p_x = gamDist(x, a, b);
q_y_x = norm(y, x, sig);
q_x_y = norm(x, y, sig);

alpha = (p_y * q_x_y) / (p_x * q_y_x);

% by Metropolis-only method
% alpha = min(1, (gamDist(y, a, b))/(gamDist(vari(index - 1), a,
b)));

Again, looks ok....

if u <= alpha
vari(index) = y;
else
vari(index) = vari(index - 1);
end

This is OK as long as you fix how you draw u. Add in some warning()
or error() statements to catch any case where you get bad values, e.g.
Infinite or NaN likelihood and likelihood ratios or if alpha < 0 or if
y every becomes negative.

-Lucas
...
Posted: Thu Jul 17, 2008 8:30 pm
Guest
On Jul 18, 12:47 am, Maniaoh <n.hoai... at (no spam) gmail.com> wrote:
Quote:
Hi Lucas,

Thank you very much. I was able to code it right. Use of normal
distribution sometimes create value < 0 that causes terrible pain. I
also did add a guard to check it and change the way I draw u.

Just to be clear, there's nothing wrong with your Normal proposal
generating values, y, less than zero. The gamma density, gamDist(y,
a, b), should return zero for negative arguments. Since this factor
is in the numerator of the acceptance ratio, alpha becomes zero and
the the negative value will never be accepted.

It sounds like you may have "fixed" your code by preventing the
proposal distribution from proposing negative numbers. If you did this
by adding a loop like

% normal distribution is used as proposal distribution
y = vari(index - 1) + randn(1)*sig;
while y < 0,
y = vari(index - 1) + randn(1)*sig;
end

then you have *changed your proposal distribution* from a Normal to a
truncated Normal distribution and your acceptance ratio calculation is
no longer correct. In fact, you would have to use only Metropolis-
Hastings since this proposal is not symmetric and the Metropolis
algorithm no longer applies.

It's very easy to invalidate a sampling algorithm by making "obvious"
changes.

-Lucas
Maniaoh...
Posted: Thu Jul 17, 2008 9:59 pm
Guest
Hi Lucas,

Just as you say, a proposal of normal distribution does nothing
harmful to the target distribution if it generates value less than
zero. It can be confirmed through explicit expression of alpha.
Nevertheless, when I allow normal distribution to generate less-than-
zero values, the target distribution does not seem right. When I draw
histogram, on the negative side of axis, some values of y (target) are
generated.

You exactly state what I did, even the code Smile, I took a guard and
therefore the proposal normal distribution became a truncated one. In
this case, the result is better, i.e., histogram. Do you have any
comment on this?

One more thing about choice of MH or M-only method. Just in prior of
receiving your kind final message, I removed M-only from my code.

Iaoh.
On Jul 18, 3:30 pm, lscha... at (no spam) d.umn.edu wrote:
Quote:
On Jul 18, 12:47 am, Maniaoh <n.hoai... at (no spam) gmail.com> wrote:

Hi Lucas,

Thank you very much. I was able to code it right. Use of normal
distribution sometimes create value < 0 that causes terrible pain. I
also did add a guard to check it and change the way I draw u.

Just to be clear, there's nothing wrong with your Normal proposal
generating values, y, less than zero. The gamma density, gamDist(y,
a, b), should return zero for negative arguments. Since this factor
is in the numerator of the acceptance ratio, alpha becomes zero and
the the negative value will never be accepted.

It sounds like you may have "fixed" your code by preventing the
proposal distribution from proposing negative numbers. If you did this
by adding a loop like

% normal distribution is used as proposal distribution
y = vari(index - 1) + randn(1)*sig;
while y < 0,
y = vari(index - 1) + randn(1)*sig;
end

then you have *changed your proposal distribution* from a Normal to a
truncated Normal distribution and your acceptance ratio calculation is
no longer correct. In fact, you would have to use only Metropolis-
Hastings since this proposal is not symmetric and the Metropolis
algorithm no longer applies.

It's very easy to invalidate a sampling algorithm by making "obvious"
changes.

-Lucas
...
Posted: Fri Jul 18, 2008 6:23 am
Guest
On Jul 18, 2:59 am, Maniaoh <n.hoai... at (no spam) gmail.com> wrote:
Quote:
Hi Lucas,

Just as you say, a proposal of normal distribution does nothing
harmful to the target distribution if it generates value less than
zero. It can be confirmed through explicit expression of alpha.
Nevertheless, when I allow normal distribution to generate less-than-
zero values, the target distribution does not seem right. When I draw
histogram, on the negative side of axis, some values of y (target) are
generated.

You exactly state what I did, even the code Smile, I took a guard and
therefore the proposal normal distribution became a truncated one. In
this case, the result is better, i.e., histogram. Do you have any
comment on this?

If you are still seeing negative values of y then there is something
wrong in your code. I'm sure truncating y to be positive does improve
the histograms, but that doesn't mean it's correct. :)

I implemented your code myself as follows. It appears to work fine --
no negative y values and a histogram of 10,000 samples is a pretty
good looking gamma. Use this as a reference to check your own code.

function s = gamma_mcmc(n)

s = zeros(1,n);

gampdf = at (no spam) (x,a,b) x.^(a-1) * exp(-b*x) .* (x>=0);
normpdf = at (no spam) (x,mu,sig) exp(-0.5*((x-mu)/sig).^2);

a = 1;
b = 1;
sig = 1;

% Initialize chain at the mean of the gamma distribution
x = a * b;

for i = 1:n,

% Generate a proposal from a normal distribution
x_star = x + sig .* randn;

% Calculate the M-H acceptance
q_x_given_x_star = normpdf( x, x_star, sig );
q_x_star_given_x = normpdf( x_star, x, sig );
p_x = gampdf( x, a, b );
p_x_star = gampdf( x_star, a, b );

alpha = (p_x_star * q_x_given_x_star) / (p_x * q_x_star_given_x );

if rand <= alpha
x = x_star;
end

s(i) = x;
end
 
Page 1 of 1       All times are GMT - 5 Hours
The time now is Tue Oct 07, 2008 10:36 pm