function slide=demolin5
% This is a slideshow file for use with playshow.m and makeshow.m
% To see it run, type 'playshow demolin5', 

% Copyright 1992-2000 The MathWorks, Inc.
% $Revision: 1.9 $  $Date: 2000/06/15 04:17:48 $

if nargout<1,
  playshow demolin5
else
  %========== Slide 1 ==========

  slide(1).code={
   'slideData=nnslides(''start'',slideData,''Underdetermined Problem'');' };
  slide(1).text={
   'NEWLIN - Creates a linear layer.',
   'TRAIN  - Trains a neural network.',
   'SIM  - Simulates a neural network.',
   '',
   'Using the above functions a linear neuron is trained to find a non-unique solution to an undetermined problem..'};

  %========== Slide 2 ==========

  slide(2).code={
   'slideData=nnslides(''blank'',slideData);',
   'P = [+1.0];',
   ' T = [+0.5];' };
  slide(2).text={
   'P defines one 1-element input patterns (column vectors):',
   '>> P = [+1.0];',
   'T defines an associated 1-element target (column vectors):',
   '>> T = [+0.5];',
   'Note that there are infinite values of W and B such that the expression W*P+B = T is true.  Problems with multiple solutions are called underdetermined.',
   ''};

  %========== Slide 3 ==========

  slide(3).code={
   'slideData=nnslides(''axes'',slideData);',
   'slideData=nnslides(''wipeaxes'',slideData'');',
   'w_range = -1:0.2:1;  b_range = -1:0.2:1;',
   'ES = errsurf(P,T,w_range,b_range,''purelin'');',
   'plotes(w_range,b_range,ES);',
   '' };
  slide(3).text={
   'ERRSURF calculates errors for a neuron with a range of possible weight and bias values.  PLOTES plots this error surface with a contour plot underneath.',
   '>> w_range =-2:0.4:2;  b_range = -2:0.4:2;',
   '>> ES = errsurf(P,T,w_range,b_range,''purelin'');',
   '>> plotes(w_range,b_range,ES);',
   'The bottom of the valley in the error surface corresponds to the infinite solutions to this problem.',
   '',
   '',
   ''};

  %========== Slide 4 ==========

  slide(4).code={
   'slideData=nnslides(''blank'',slideData);',
   'maxlr=maxlinlr(P,''bias'');',
   'net=newlin([-2 2],1,[0],maxlr);' };
  slide(4).text={
   'MAXLINLR finds the fastest stable learning rate for training a linear network.',
   '>> maxlr=maxlinlr(P,''bias'');',
   'NEWLIN creates a linear neuron.',
   '>> net=newlin([-2 2],1,[0],maxlr);',
   'NEWLIN takes these arguments: 1) Rx2 matrix of min and max values for R input elements, 2) Number of elements in the output vector, 3) Input delay vector, and 4) Learning rate.'};

  %========== Slide 5 ==========

  slide(5).code={
   'slideData=nnslides(''wipeaxes'',slideData);',
   'slideData=nnslides(''axes'',slideData);',
   'plotes(w_range,b_range,ES);',
   ' net.trainParam.goal=1e-10;' };
  slide(5).text={
   'Override the default training parameters by setting the performance goal.',
   '>> net.trainParam.goal=1e-10;',
   'Use PLOTES to replot the error surface:',
   '>> plotes(w_range,b_range,ES);'};

  %========== Slide 6 ==========

  slide(6).code={
   'slideData=nnslides(''lock'',slideData);',
   'slideData=nnslides(''axes'',slideData);',
   'slideData=nnslides(''wipeaxes'',slideData);',
   'ES = errsurf(P,T,w_range,b_range,''purelin'');',
   'plotes(w_range,b_range,ES);',
   'subplot(1,2,2);',
   'h = text(sum(get(gca,''xlim''))*0.5,sum(get(gca,''ylim''))*0.5,''* Click On Me *'');',
   'set(h,''horizontal'',''center'', ''fontweight'',''bold'');',
   '[net.IW{1,1} net.b{1}]=ginput(1);',
   'delete(h);',
   '[slideData,net,tr]=nnslides(''trainlin'',slideData,net,P,T);',
   'slideData=nnslides(''unlock'',slideData);' };
  slide(6).text={
   'Override the randomly generated weight and bias by getting a mouse click on the Error Contour Plot with GINPUT:',
   '>> subplot(1,2,2);  [net.IW{1,1} net.b{1}] = ginput(1);',
   'To show the path of the training we will train only one epoch at a time and call PLOTEP every epoch (code not shown here).',
   '>> [net,tr] = train(net,P,T);',
   'The plot shows a history of the training.  Each dot represents an epoch and the blue lines show each change made by the learning rule (Widrow-Hoff by default).',
   ''};

  %========== Slide 7 ==========

  slide(7).code={
   'solvednet = newlind(P,T);',
   'hold on;',
   'plot(solvednet.IW{1,1},solvednet.b{1},''ro'')',
   'hold off;' };
  slide(7).text={
   'Here we plot the NEWLIND solution.',
   '>> solvednet = newlind(P,T);',
   '>> hold on;',
   '>> plot(solvednet.IW{1,1},solvednet.b{1},''ro'')',
   'Note that the TRAIN (white dot) and SOLVELIN (red circle) solutions are not the same.  In fact, TRAINWH will return a different solution for different initial conditions, while SOLVELIN will always return the same solution.'};

  %========== Slide 8 ==========

  slide(8).code={
   'slideData=nnslides(''axes'',slideData);',
   'subplot(1,2,1);',
   'hold off;',
   'plotperf(tr,net.trainParam.goal);' };
  slide(8).text={
   'The train function outputs the trained network and a history of the training performance (tr).  Here the errors are plotted with respect to training epochs:',
   '>> plotperf(tr,net.trainParam.goal);',
   'Once the error reaches the goal, an adequate solution for W and B has been found.  However, because the problem is underdetermined, this solution is not unique.',
   ''};

  %========== Slide 9 ==========

  slide(9).code={
   'p = 1.0;',
   'a = sim(net,p);',
   'slideData=nnslides(''text'',slideData,[''a = '' num2str(a)]);' };
  slide(9).text={
   'We can now test the associator with one of the original inputs, 1.0, and see if it returns the target, 0.5.',
   '>> p = 1.0;',
   '>> a = sim(net,p);',
   '(see above for result)',
   'The result is very close to 0.5.  The error can be reduced further, if required, by continued training with TRAINWH using a smaller error goal.'};
end