spm_fmin.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. function [P,F] = spm_fmin(fun,Q,C,varargin)
  2. % Objective function minimisation
  3. % FORMAT [P,F] = spm_fmin('fun',P,C,varargin)
  4. %
  5. % fun - function or inline function f - fun(P,varargin)
  6. % P - free parameters (prior mean)
  7. % C - prior covariance
  8. %
  9. % P - optimised parameters
  10. % f - optimised value of fun(P)
  11. %
  12. %--------------------------------------------------------------------------
  13. % spm_fmin is a slow but robust function minimiser that uses a stochastic
  14. % sampling of the objective function to be minimised (supplemented by a line
  15. % search along the principal eigenvariate at the current sampling density.
  16. % The sampling density is approximated with a Gaussian (first and second
  17. % order moments) using that the sampling density is:
  18. %
  19. % p(P) = (1/Z)*exp(-fun(P)/T)
  20. %
  21. % where the temperature; T is the sample standard deviation of the sampled
  22. % objective function.
  23. %__________________________________________________________________________
  24. % Copyright (C) 2005-2013 Wellcome Trust Centre for Neuroimaging
  25. % Karl Friston
  26. % $Id: spm_fmin.m 6801 2016-05-29 19:18:06Z karl $
  27. % stochastic search
  28. %--------------------------------------------------------------------------
  29. P = spm_vec(Q);
  30. pmin = P;
  31. n = length(P); % number of parameters
  32. try
  33. C; % prior covariance
  34. catch
  35. C = speye(n,n);
  36. end
  37. C = C + speye(n,n)*exp(-16);
  38. % Optimise sampling distribution iteratively
  39. %==========================================================================
  40. spm_figure('GetWin','FMIN');
  41. for k = 1:8
  42. % report - current sample density
  43. %----------------------------------------------------------------------
  44. p1 = linspace(-3*sqrt(C(1,1)),3*sqrt(C(2,2)),64);
  45. p2 = linspace(-3*sqrt(C(2,2)),3*sqrt(C(2,2)),64);
  46. iC = inv(C(1:2,1:2));
  47. for i = 1:64
  48. for j = 1:64
  49. d(i,j) = exp(-[p1(i) p2(j)]*iC*[p1(i) p2(j)]'/2);
  50. end
  51. end
  52. subplot(3,2,1)
  53. imagesc(p2 + P(2),p1 + P(1),d)
  54. xlabel('2nd parameter','FontSize',12)
  55. ylabel('1st parameter','FontSize',12)
  56. title(sprintf('iteration %i',k - 1),'FontSize',16)
  57. axis square xy
  58. % sample objective function using N(P,C)
  59. %----------------------------------------------------------------------
  60. if k == 1
  61. N = 256; % number of samples
  62. else
  63. N = 32;
  64. end
  65. p = P*ones(1,N) + spm_sqrtm(C)*randn(n,N);
  66. p(:,1) = pmin;
  67. F = sparse(N,1);
  68. for i = 1:N
  69. F(i) = feval(fun,spm_unvec(p(:,i),Q),varargin{:});
  70. end
  71. [m,i] = min(F);
  72. pmin = p(:,i);
  73. % supplement with line search along principal eigenvector
  74. %----------------------------------------------------------------------
  75. [U,S] = spm_svd(C);
  76. U = U(:,1);
  77. S = S(1);
  78. x = linspace(-3*sqrt(S),3*sqrt(S),16 + 1);
  79. for i = 1:(16 + 1)
  80. p(:,end + 1) = pmin + U*x(i);
  81. F(end + 1,1) = feval(fun,spm_unvec(p(:,end),Q),varargin{:});
  82. end
  83. [m,i] = min(F);
  84. pmin = p(:,i);
  85. M(k) = m;
  86. R(:,k) = pmin;
  87. % plot objective function along eigenvariate and sampled values
  88. %----------------------------------------------------------------------
  89. subplot(3,2,3)
  90. plot(x,F(end - 16:end),'.')
  91. xlabel('first eigenvariate','FontSize',12)
  92. title('objective function','FontSize',16)
  93. axis square
  94. subplot(3,2,5)
  95. plot(sort(F))
  96. xlabel('sample','FontSize',12)
  97. title('ranked samples','FontSize',16)
  98. axis square
  99. % Laplace approximation: p(P)
  100. %======================================================================
  101. % temperature
  102. %----------------------------------------------------------------------
  103. T = sqrt(2)*std(F);
  104. % mean (P)
  105. %----------------------------------------------------------------------
  106. q = exp(-(F - mean(F))/T);
  107. q = q/sum(q);
  108. P = p*q;
  109. % dispersion
  110. %----------------------------------------------------------------------
  111. for i = 1:n
  112. for j = 1:n
  113. C(i,j) = ((p(i,:) - P(i)).*(p(j,:) - P(j)))*q;
  114. end
  115. end
  116. % report - updated sampling density
  117. %----------------------------------------------------------------------
  118. subplot(3,2,2)
  119. iC = inv(C(1:2,1:2));
  120. for i = 1:64
  121. for j = 1:64
  122. d(i,j) = exp(-[p1(i) p2(j)]*iC*[p1(i) p2(j)]'/2);
  123. end
  124. end
  125. imagesc(p2 + P(2),p1 + P(1),d)
  126. title(sprintf('iteration %i',k),'FontSize',16)
  127. axis square xy
  128. % superimpose line search and plot means and min(F)
  129. %----------------------------------------------------------------------
  130. subplot(3,2,1),hold on
  131. plot(p(2,end - 16:end),p(1,end - 16:end),'r'), hold off
  132. subplot(3,2,2),hold on
  133. plot(p(2,end - 16:end),p(1,end - 16:end),'r'), hold off
  134. subplot(3,2,4)
  135. plot(R')
  136. xlabel('iteration','FontSize',12)
  137. title('parameter values','FontSize',16)
  138. axis square
  139. subplot(3,2,6)
  140. bar(M)
  141. xlabel('iteration','FontSize',12)
  142. title('minimum','FontSize',16)
  143. axis square
  144. drawnow
  145. end
  146. % minimiser
  147. %--------------------------------------------------------------------------
  148. P = spm_unvec(pmin,Q);