annotate toolboxes/FullBNT-1.0.7/netlab3.3/metrop.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
rev   line source
wolffd@0 1 function [samples, energies, diagn] = metrop(f, x, options, gradf, varargin)
wolffd@0 2 %METROP Markov Chain Monte Carlo sampling with Metropolis algorithm.
wolffd@0 3 %
wolffd@0 4 % Description
wolffd@0 5 % SAMPLES = METROP(F, X, OPTIONS) uses the Metropolis algorithm to
wolffd@0 6 % sample from the distribution P ~ EXP(-F), where F is the first
wolffd@0 7 % argument to METROP. The Markov chain starts at the point X and each
wolffd@0 8 % candidate state is picked from a Gaussian proposal distribution and
wolffd@0 9 % accepted or rejected according to the Metropolis criterion.
wolffd@0 10 %
wolffd@0 11 % SAMPLES = METROP(F, X, OPTIONS, [], P1, P2, ...) allows additional
wolffd@0 12 % arguments to be passed to F(). The fourth argument is ignored, but
wolffd@0 13 % is included for compatibility with HMC and the optimisers.
wolffd@0 14 %
wolffd@0 15 % [SAMPLES, ENERGIES, DIAGN] = METROP(F, X, OPTIONS) also returns a log
wolffd@0 16 % of the energy values (i.e. negative log probabilities) for the
wolffd@0 17 % samples in ENERGIES and DIAGN, a structure containing diagnostic
wolffd@0 18 % information (position and acceptance threshold) for each step of the
wolffd@0 19 % chain in DIAGN.POS and DIAGN.ACC respectively. All candidate states
wolffd@0 20 % (including rejected ones) are stored in DIAGN.POS.
wolffd@0 21 %
wolffd@0 22 % S = METROP('STATE') returns a state structure that contains the state
wolffd@0 23 % of the two random number generators RAND and RANDN. These are
wolffd@0 24 % contained in fields randstate, randnstate.
wolffd@0 25 %
wolffd@0 26 % METROP('STATE', S) resets the state to S. If S is an integer, then
wolffd@0 27 % it is passed to RAND and RANDN. If S is a structure returned by
wolffd@0 28 % METROP('STATE') then it resets the generator to exactly the same
wolffd@0 29 % state.
wolffd@0 30 %
wolffd@0 31 % The optional parameters in the OPTIONS vector have the following
wolffd@0 32 % interpretations.
wolffd@0 33 %
wolffd@0 34 % OPTIONS(1) is set to 1 to display the energy values and rejection
wolffd@0 35 % threshold at each step of the Markov chain. If the value is 2, then
wolffd@0 36 % the position vectors at each step are also displayed.
wolffd@0 37 %
wolffd@0 38 % OPTIONS(14) is the number of samples retained from the Markov chain;
wolffd@0 39 % default 100.
wolffd@0 40 %
wolffd@0 41 % OPTIONS(15) is the number of samples omitted from the start of the
wolffd@0 42 % chain; default 0.
wolffd@0 43 %
wolffd@0 44 % OPTIONS(18) is the variance of the proposal distribution; default 1.
wolffd@0 45 %
wolffd@0 46 % See also
wolffd@0 47 % HMC
wolffd@0 48 %
wolffd@0 49
wolffd@0 50 % Copyright (c) Ian T Nabney (1996-2001)
wolffd@0 51
wolffd@0 52 if nargin <= 2
wolffd@0 53 if ~strcmp(f, 'state')
wolffd@0 54 error('Unknown argument to metrop');
wolffd@0 55 end
wolffd@0 56 switch nargin
wolffd@0 57 case 1
wolffd@0 58 % Return state of sampler
wolffd@0 59 samples = get_state(f); % Function defined in this module
wolffd@0 60 return;
wolffd@0 61 case 2
wolffd@0 62 % Set the state of the sampler
wolffd@0 63 set_state(f, x); % Function defined in this module
wolffd@0 64 return;
wolffd@0 65 end
wolffd@0 66 end
wolffd@0 67
wolffd@0 68 if 0
wolffd@0 69 seed = 42;
wolffd@0 70 randn('state', seed);
wolffd@0 71 rand('state', seed)
wolffd@0 72 end
wolffd@0 73
wolffd@0 74 display = options(1);
wolffd@0 75 if options(14) > 0
wolffd@0 76 nsamples = options(14);
wolffd@0 77 else
wolffd@0 78 nsamples = 100;
wolffd@0 79 end
wolffd@0 80 if options(15) >= 0
wolffd@0 81 nomit = options(15);
wolffd@0 82 else
wolffd@0 83 nomit = 0;
wolffd@0 84 end
wolffd@0 85 if options(18) > 0.0
wolffd@0 86 std_dev = sqrt(options(18));
wolffd@0 87 else
wolffd@0 88 std_dev = 1.0; % default
wolffd@0 89 end
wolffd@0 90 nparams = length(x);
wolffd@0 91
wolffd@0 92 % Set up string for evaluating potential function.
wolffd@0 93 f = fcnchk(f, length(varargin));
wolffd@0 94
wolffd@0 95 samples = zeros(nsamples, nparams); % Matrix of returned samples.
wolffd@0 96 if nargout >= 2
wolffd@0 97 en_save = 1;
wolffd@0 98 energies = zeros(nsamples, 1);
wolffd@0 99 else
wolffd@0 100 en_save = 0;
wolffd@0 101 end
wolffd@0 102 if nargout >= 3
wolffd@0 103 diagnostics = 1;
wolffd@0 104 diagn_pos = zeros(nsamples, nparams);
wolffd@0 105 diagn_acc = zeros(nsamples, 1);
wolffd@0 106 else
wolffd@0 107 diagnostics = 0;
wolffd@0 108 end
wolffd@0 109
wolffd@0 110 % Main loop.
wolffd@0 111 n = - nomit + 1;
wolffd@0 112 Eold = feval(f, x, varargin{:}); % Evaluate starting energy.
wolffd@0 113 nreject = 0; % Initialise count of rejected states.
wolffd@0 114 while n <= nsamples
wolffd@0 115
wolffd@0 116 xold = x;
wolffd@0 117 % Sample a new point from the proposal distribution
wolffd@0 118 x = xold + randn(1, nparams)*std_dev;
wolffd@0 119 %fprintf('netlab propose: xold = %5.3f,%5.3f, xnew = %5.3f,%5.3f\n',...
wolffd@0 120 % xold(1), xold(2), x(1), x(2));
wolffd@0 121
wolffd@0 122 % Now apply Metropolis algorithm.
wolffd@0 123 Enew = feval(f, x, varargin{:}); % Evaluate new energy.
wolffd@0 124 a = exp(Eold - Enew); % Acceptance threshold.
wolffd@0 125 if (diagnostics & n > 0)
wolffd@0 126 diagn_pos(n,:) = x;
wolffd@0 127 diagn_acc(n,:) = a;
wolffd@0 128 end
wolffd@0 129 if (display > 1)
wolffd@0 130 fprintf(1, 'New position is\n');
wolffd@0 131 disp(x);
wolffd@0 132 end
wolffd@0 133
wolffd@0 134 r = rand(1);
wolffd@0 135 %fprintf('netlab: n=%d, a=%f/%f=%5.3f (%5.3f), r=%5.3f\n',...
wolffd@0 136 % n, exp(-Enew), exp(-Eold), a, exp(-Enew)/exp(-Eold), r);
wolffd@0 137 if a > r % Accept the new state.
wolffd@0 138 Eold = Enew;
wolffd@0 139 if (display > 0)
wolffd@0 140 fprintf(1, 'Finished step %4d Threshold: %g\n', n, a);
wolffd@0 141 end
wolffd@0 142 else % Reject the new state
wolffd@0 143 if n > 0
wolffd@0 144 nreject = nreject + 1;
wolffd@0 145 end
wolffd@0 146 x = xold; % Reset position
wolffd@0 147 if (display > 0)
wolffd@0 148 fprintf(1, ' Sample rejected %4d. Threshold: %g\n', n, a);
wolffd@0 149 end
wolffd@0 150 end
wolffd@0 151 if n > 0
wolffd@0 152 samples(n,:) = x; % Store sample.
wolffd@0 153 if en_save
wolffd@0 154 energies(n) = Eold; % Store energy.
wolffd@0 155 end
wolffd@0 156 end
wolffd@0 157 n = n + 1;
wolffd@0 158 end
wolffd@0 159
wolffd@0 160 if (display > 0)
wolffd@0 161 fprintf(1, '\nFraction of samples rejected: %g\n', ...
wolffd@0 162 nreject/(nsamples));
wolffd@0 163 end
wolffd@0 164
wolffd@0 165 if diagnostics
wolffd@0 166 diagn.pos = diagn_pos;
wolffd@0 167 diagn.acc = diagn_acc;
wolffd@0 168 end
wolffd@0 169
wolffd@0 170 % Return complete state of the sampler.
wolffd@0 171 function state = get_state(f)
wolffd@0 172
wolffd@0 173 state.randstate = rand('state');
wolffd@0 174 state.randnstate = randn('state');
wolffd@0 175 return
wolffd@0 176
wolffd@0 177 % Set state of sampler, either from full state, or with an integer
wolffd@0 178 function set_state(f, x)
wolffd@0 179
wolffd@0 180 if isnumeric(x)
wolffd@0 181 rand('state', x);
wolffd@0 182 randn('state', x);
wolffd@0 183 else
wolffd@0 184 if ~isstruct(x)
wolffd@0 185 error('Second argument to metrop must be number or state structure');
wolffd@0 186 end
wolffd@0 187 if (~isfield(x, 'randstate') | ~isfield(x, 'randnstate'))
wolffd@0 188 error('Second argument to metrop must contain correct fields')
wolffd@0 189 end
wolffd@0 190 rand('state', x.randstate);
wolffd@0 191 randn('state', x.randnstate);
wolffd@0 192 end
wolffd@0 193 return