Mercurial > hg > ltpda
diff m-toolbox/classes/+utils/@math/mhsample_td.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/+utils/@math/mhsample_td.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,168 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Metropolis algorithm +% +% M Nofrarias 15-06-09 +% +% $Id: mhsample_td.m,v 1.1 2010/11/26 13:48:48 luigi Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +function smpl = mhsample_td(model,in,out,cov,number,limit,parnames,Tc,xi,xo,search,jumps,parplot,dbg_info,inNames,outNames,Noise,cutbefore,cutafter) + + import utils.const.* + + % compute mean and range + mn = mean(limit); + range = diff(limit); + % initialize + acc = []; + nacc = 1; + nrej = 1; + loop = 0; + oldacc = 0; + oldrej = 0; + chgsc = 0; + nparnames = length(parnames); + + + % switch depending on model class (initial likelihood) + switch class(model) + case 'matrix' +% loglk1 = utils.math.loglikehood_matrix(xo,in,out,nse,model,parnames); +% loglk1 = utils.math.loglikehood_matrix(xo,in,out,nse,model,parnames,inModel,outModel); + case 'smodel' +% loglk1 = utils.math.loglikehood(xo,in,out,nse,model,parnames); + case 'ssm' + loglk1 = utils.math.loglikehood_ssm_td(xo,in,out,parnames,model,inNames,outNames,Noise,'cutbefore',cutbefore,'cutafter',cutafter); + otherwise + error('### Model must be either from the ''smodel'' or the ''ssm'' class. Please check the inputs') + end + + % accept the first sample if no search active + if ~search + smpl(1,:) = xo; + nacc = 1; + else + smpl = []; + nacc = 0; + end + nrej = 0; + + utils.helper.msg(msg.IMPORTANT, 'Starting Monte Carlo sampling', mfilename('class'), mfilename); + + + hjump = 0; + % main loop + while(nacc<number) + % jumping criterion during search phase + % - 2-sigma by default + % - 10-sigma jumps at mod(10) samples + % - 100-sigma jumps at mod(25) samples + % - 1000-sigma jumps at mod(100) samples + if search + if nacc <= Tc(1) + if(mod(nacc,10) == 0 && mod(nacc,25) ~= 0 && mod(nacc,100) ~= 0 && hjump ~= 1) + hjump = 1; + xn = mvnrnd(xo,jumps(2)^2*cov); + elseif(mod(nacc,25) == 0 && mod(nacc,100) ~= 0 && hjump ~= 1) + hjump = 1; + xn = mvnrnd(xo,jumps(3)^2*cov); + elseif(mod(nacc,100) == 0 && hjump ~= 1) + hjump = 1; + xn = mvnrnd(xo,jumps(4)^2*cov); + % xn = xo + range/2+rand(size(xo)); + else + hjump = 0; + xn = mvnrnd(xo,jumps(1)^2*cov); + end + else + xn = mvnrnd(xo,cov); + end + else + xn = mvnrnd(xo,cov); + end + + % check if out of limits + if( any(xn < limit(1,:)) || any(xn > limit(2,:))) + logprior = inf; + loglk2 = inf; + betta = inf; + else + % compute annealing + if ~isempty(Tc) + if nacc <= Tc(1) + betta = 1/2 * 10^(-xi*(1-Tc(1)/Tc(2))); + elseif Tc(1) < nacc && nacc <= Tc(2) + betta = 1/2 * 10^(-xi*(1-nacc/Tc(2))); + else + betta = 1/2; + end + else + betta = 1/2; + end + % switch depending on model class (new likelihood) + switch class(model) + case 'matrix' +% loglk2 = utils.math.loglikehood_matrix(xn,in,out,nse,model,parnames,inModel,outModel); + case 'smodel' +% loglk2 = utils.math.loglikehood(xn,in,out,nse,model,parnames); + case 'ssm' + loglk2 = utils.math.loglikehood_ssm_td(xn,in,out,parnames,model,inNames,outNames,Noise,'cutbefore',cutbefore,'cutafter',cutafter); + otherwise + error('### Model must be either from the ''smodel'' or the ''ssm'' class. Please check the inputs') + end + end + + % likelihood ratio + logr = betta*(loglk2 - loglk1) ; + % decide if sample is accepted or not + if logr < 0 + xo = xn; + nacc = nacc+1; + smpl(nacc,:) = xn; + loglk1 =loglk2; + if dbg_info + utils.helper.msg(msg.IMPORTANT, sprintf('acc.\t loglik: %d -> %d betta: %d ratio: %d',loglk1,loglk2,betta,logr), mfilename('class'), mfilename); + end + elseif rand(1) > (1 - exp(-logr)) + xo = xn; + nacc = nacc+1; + smpl(nacc,:) = xn; + loglk1 =loglk2; + if dbg_info + utils.helper.msg(msg.IMPORTANT, sprintf('acc.\t loglik: %d -> %d betta: %d ratio: %d',loglk1,loglk2,betta,logr), mfilename('class'), mfilename); + end + else + nrej = nrej+1; + if dbg_info + utils.helper.msg(msg.IMPORTANT, sprintf('rej.\t loglik: %d -> %d betta: %d ratio: %d',loglk1,loglk2,betta,logr), mfilename('class'), mfilename); + end + end + + % display and save + if(mod(nacc,100) == 0 && nacc ~= oldacc) + updacc = nacc-oldacc; + updrej = nrej-oldrej; + ratio(nacc/10,:) = updacc/(updacc+updrej); + utils.helper.msg(msg.IMPORTANT, sprintf('accepted: %d rejected : %d acc. rate: %4.2f',nacc,updrej,ratio(end)), mfilename('class'), mfilename); + for i = 1:numel(parnames) + fprintf('### Parameters: %s = %d \n',parnames{i},xn(i)) + end + oldacc = nacc; + oldrej = nrej; + save('chain.txt','smpl','-ASCII') + save('acceptance.txt','ratio','-ASCII') + end + + % plot + if ((mod(nacc,100) == 0) && (nacc ~= 0) && ~isempty(parplot)) + for i = 1:numel(parplot) + figure(parplot(i)) + plot(smpl(:,parplot(i))) + end + end + + end +end