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

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