%% This is a demo of a 2-dimensional learning problem, illustrating
%% steepest descent with and without momentum. The error surface is defined by 
%% E = w1^2 + 0.1 w2^2, and the weight gradient vector is therefore always
%% grad = [2 * w1, 0.2 * w2]
%% The minimum error is reached when W = [0,0]

%% To run demo, load this file into matlab. 

more off
%%% draw a contour map of the error surface
clf
[x,y] = meshgrid(-5:.2:5, -5:.2:5);
errorSurface = x.^2 + 0.1 * y.^2 ;
contour(x,y,errorSurface,15);
hold on;
%%% initialize parameters
nOutputs = 1;
nInputs = 2;

for momentum = 0:1,
   outputWeights =  [1,5];
   if momentum == 1
      epsilon = 0.9;
      alpha = 0.3;
      nIters = 10;
   else 
      epsilon = 0.8;
      alpha = 0.0;
      nIters = 20;
   end
   
   lastWeightChange = zeros(size(outputWeights));
   weightHistory = zeros(nInputs,nIters);
   %%% update the weights for nIters iterations of steepest descent
   for i = 1:nIters,
     weightHistory(:,i) = outputWeights';  
     error = outputWeights(1,1)^2 + 0.1 * outputWeights(1,2)^2;
     outputWGrad = [2 * outputWeights(1,1), 0.2 * outputWeights(1,2)];
     weightChange = -1.0 * epsilon * outputWGrad + alpha * lastWeightChange;
     outputWeights = outputWeights + weightChange;
     lastWeightChange = weightChange;
     fprintf(1,'iter=%d, momentum=%d, E=%f, |G|=%f\n', ...
                i,momentum,error,norm(outputWGrad));
   end
   %% plot the weight vector over the nIters learning iterations
   if momentum == 0
     plot(weightHistory(1,:),weightHistory(2,:),'b')
     plot(weightHistory(1,:),weightHistory(2,:),'*b')
     fprintf(1,'press any key to run demo again, this time with momentum\n');
     pause;
   else 
     plot(weightHistory(1,:),weightHistory(2,:),'r')
     plot(weightHistory(1,:),weightHistory(2,:),'*r')
   end
end
