function net = demo_iris(netCont)
% Trying the codes on the Iris data, which is a bit of a classic.
% This is quite an easy one, with very fast training and good result except
% for a couple of tricky flowers that are very hard to classify.
%
% This will print out a so-called confusion matrix after each few steps of
% training. From there you will see how the MLP gets things first into
% wrong classes, and then, first fast and later rather one-by-one, the
% items fall to their true classes. Except for the painfully tricky ones.

% For training we need input vectors and corresponding target vectors.
DATADIR = 'data';
fname = fullfile(DATADIR,'iris.data');
[vectors,labels,classnames] = loadLabeledData(fname,5);

% Encode labels as binary vectors:
prototypes = -1 + 2*eye(3);
labels = prototypes(:,labels);

% There can be some order in a data file, like in the iris. First thing to
% do is to make a random (or better) permutation before we apply methods, 
% or split the data set. Here's a random one:
rand('state', 123);
p = randperm(size(vectors,2));
vectors = vectors(:,p);
labels = labels(:,p);

% Let's split the data for training and testing (50%/50% for the demo):
nt = floor(.5*size(vectors,2));
input   = vectors(:,1:nt);
target  =  labels(:,1:nt);
testx   = vectors(:,nt+1:end);
trueOut =  labels(:,nt+1:end);

% Scale to [-1,1]:
[input, traA, traB] = datatool_scale(input);

% In principle, testing data is "unforeseen", so we can only scale it based
% on the knowledge gathered from the training set:
testx = datatool_scale(testx,traA,traB);

%disp(input(:,1:4)); disp(target(:,1:4)); disp(testx(:,1:4)); disp(trueOut(:,1:4))


% Pick random initial weights, and optimize from there:
net = simple_mlp_create([size(input,1) 6 5 size(target,1)]);

if nargin==1, net = netCont; end;

uFunc = @simple_mlp_evalMSErVecWrap;

atOnce = 10;
for s = 1:100

  uPar.net = net;
  uPar.inputs = input;
  uPar.targets = target;

  x = simple_mlp_cell2vec(net.W);
  x = simple_mlp_optimGD(x, uFunc, uPar, 0.05, atOnce, 0, 1e-6);
%  x = simple_mlp_optimCGP(x, uFunc, uPar, 1, atOnce, 0, 1e-6);
  net.W = simple_mlp_vec2cell(x, net.nneur);

  % Evaluate and print accuracy measures.
  f = simple_mlp_evalMSEr(net, input, target);

  trainOut = simple_mlp_evalMSEr(net, input, 'feed');
  trainOut = class_compete(trainOut);
  trainRate = classif_rate(trainOut, target);
  
  testOut = simple_mlp_evalMSEr(net, testx, 'feed');
  testOut = class_compete(testOut);
  rate = classif_rate(testOut, trueOut);
  
  commentary = sprintf('Iter %d: Cost=%f, TrainRate=%f TestRate=%f', ...
		       s*atOnce, f, trainRate, rate);
  disp(commentary);
  
  confusion_matrix(testOut, trueOut);

  pause(0.1);
end
