function params = annealit(initparams, type) %annealit: a simple annealing routine %Annealing is based on a simple idea of jumping around a local parameter space looking for the minima %A proposed parameter set is accepted with probability exp(-(energy_old_params - energy_new_params)/temperature) the 'energy' (in this example energy = neg log likelihood) % The effect is that if energy_new is lower then the new param set is accepted but if % energy_new is higher it accepted with a probability that depends on how much higher it is % Temperature affects how this probability depends on the energy difference. % The idea is to slowly lower the temperature to get to the lowest energy: voila, simulated annealing % Surprisingly this simple little idea often works %initparams is composed of initparams.free and initparams.fixed; it's a vector %fittomodel is some model that is called with params and returns -log(L(data|params)) %iter is the number of annealing calls to make if(nargin == 1) type = 2; end iter=10000; limunif = .1; %10% up or down %T is the temperature; a somewhat vague concept with basically indicates how much the annealing jumps around T = 10; %initialize things energy_old=fittomodel(initparams); param=initparams; srecord = zeros(iter,1); %just a holding bin %run iter iterations of the annealing routine for(j = 1:iter) %in this routine, I go through the free params one by one %one can randomly pick a completely new set, but then it is quite unlikely that one %will choose a new set with lower energy for(i = 1:length(params.free)) proposed_params=params; proposed_params.free=params.free; switch type %different ways you can choose new params; I like #2 case 1 proposed_params.free(i)=unifrnd( (1-limunif)*params.free(i),(1+limunif)*params.free(i) ); case 2 proposed_params.free(i)=unifrnd( -limunif,limunif )+params.free(i); otherwise display('type must be 1 or 2'); break end energy_new=fittomodel(proposed_params); %switch probability swprob = unifrnd(0,1); ener = exp(-(energy_new - energy_old)/T); if(swprob < ener) %accept params.free = proposed_params.free; energy_old = energy_new; end end srecord(j) = fittomodel(params); disp(srecord(j)); if(mod(j,100)==0) display(['iter = ' num2str(j) ' T = ' num2str(T)]); display('Now lower T slowly to converge to global minima'); display('Yes, manually do this by typing T = y; y being something lower than Ts current value'); keyboard; end end plot(srecord) %this will help you see if the annealing is working