%% matlab_demo_04.m
%%
%% CSS 581, Introduction to Machine Learning, Winter 2014
%% Computing & Software Systems, University of Washington Bothell
%% written by J. Jeffry Howbert, 2012-01-20

%% TIP: to execute a line or block of code, highlight the code, then
%%      press F9
%% TIP: to comment a line or block of code, highlight the code, then ctrl-R
%% TIP: to uncomment a line or block of code, highlight the code, then ctrl-T

%% Part A
clear all;
close all;
load fisheriris;
tr = classregtree( meas, species, 'names', {'SL' 'SW' 'PL' 'PW'} );
view( tr );
% in tree viewer:
%   - look at various nodes in different display modes
%   - look at different pruning levels
pred = eval( tr, meas );
format compact;
disp( species' );   % cell array of strings
disp( pred' );      % cell array of strings
disp( strcmp( species, pred )' );
disp( sum( strcmp( species, pred )' ) );
disp( [ 'correct predictions :   ', num2str( sum( strcmp( species, pred ) ) ), ' / ', num2str( length( species ) ) ] ); 
fprintf( 1, 'correct predictions :   %d / %d\n', sum( strcmp( species, pred ) ), length( species ) ); 

% review:
%   - Help entry on classregtree
%   - 'Name', 'value' syntax for arguments
%   - eval
%   - cell arrays
%   - strcmp
%   - num2str
%   - fprintf

%% Part B
% one approach to randomly selecting a subset of records from a dataset
randSeed = 1;
stream = RandStream( 'mt19937ar', 'seed', randSeed );
RandStream.setGlobalStream( stream );

disp( randperm( 6 ) );      % random permutation of numbers 1 : 6
disp( randperm( 6 ) );      % different random permutation of numbers 1 : 6
disp( randperm( 6 ) );      % yet another random permutation of numbers 1 : 6

randSeed = 1;
stream = RandStream( 'mt19937ar', 'seed', randSeed );
RandStream.setGlobalStream( stream );

% randomly select 100 of 150 fisher iris records for training set, use
%   other 50 as test set
nInst = size( meas, 1 );    % number of instances (records) in fisheriris
rp = randperm( nInst );
disp( rp );

nTrain = 100;
trainData = meas( rp( 1 : nTrain ), : );
trainLabel = species( rp( 1 : nTrain ) );
testData = meas( rp( nTrain + 1 : nInst ), : );
testLabel = species( rp( nTrain + 1 : nInst ) );

% look at contents of trainData, trainLabel, testData, testLabel in
%   Variable Editor

randSeed = 1;
stream = RandStream( 'mt19937ar', 'seed', randSeed );
RandStream.setGlobalStream( stream );

% best to be explicit with model parameter settings, even when using defaults
minparent = 10;     % default value = 10
minleaf = 1;        % default value = 1
tr = classregtree( trainData, trainLabel, 'names', {'SL' 'SW' 'PL' 'PW'}, ...
    'method', 'classification', 'minparent', minparent, 'minleaf', minleaf );
% view( tr );
nPruneLevel = max( prunelist( tr ) );
disp( nPruneLevel );
pruneLevel = 0;     % default value = 0
trainPred = eval( tr, trainData, pruneLevel );
fprintf( 1, 'correct predictions on training set :   %d / %d\n', sum( strcmp( trainLabel, trainPred ) ), length( trainLabel ) ); 
[ mat, order ] = confusionmat( trainLabel, trainPred );
disp( ' ' );
disp( order' );
disp( mat );
testPred = eval( tr, testData, pruneLevel );
fprintf( 1, 'correct predictions on test set     :   %d / %d\n', sum( strcmp( testLabel, testPred ) ), length( testLabel ) ); 
[ mat, order ] = confusionmat( testLabel, testPred, 'order', order );
disp( ' ' );
disp( order' );
disp( mat );

% for confusionmat, first arg should be known labels, second arg predicted labels

%% Part C
clear all;
close all;
load mnistabridged;
for ix = 1 : 50
    figure( mod( ix, 10 ) + 1 );
    imagesc( reshape( train( ix, : ), 28, 28 ) );
    colormap( gray );
    pause;
end

trainData = double( train );
testData = double( test );
trainLabel = double( trainlabels );
testLabel = double( testlabels );
nTrain = length( trainlabels );
nTest = length( testlabels );

minparent = 10;     % default value = 10
minleaf = 1;        % default value = 1
tr = classregtree( trainData, trainLabel, 'method', 'classification', ...
    'minparent', minparent, 'minleaf', minleaf );
view( tr );
trainPred = eval( tr, trainData );
testPred = eval( tr, testData );
trainPred = cellfun( @str2num, trainPred );     % convert cell array of strings to vector of integers
testPred = cellfun( @str2num, testPred );       % convert cell array of strings to vector of integers

nTrainCorrect = sum( trainLabel == trainPred );
nTestCorrect = sum( testLabel == testPred );
fprintf( 1, 'correct predictions on training set :   %d / %d,  %5.2f%%\n', ...
    nTrainCorrect, nTrain, 100 * nTrainCorrect / nTrain );
[ mat, order ] = confusionmat( trainLabel, trainPred );
disp( ' ' );
disp( order' );
disp( mat );
fprintf( 1, 'correct predictions on test set     :   %d / %d,  %5.2f%%\n', ...
    nTestCorrect, nTest, 100 * nTestCorrect / nTest );
[ mat, order ] = confusionmat( testLabel, testPred, 'order', order );
disp( ' ' );
disp( order' );
disp( mat );

bar3( mat )
set( gca, 'XTickLabel', { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' } );
set( gca, 'YTickLabel', { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' } );

maxPruneLevel = max( prunelist( tr ) );
for pr = 0: 20 % maxPruneLevel
    trainPred = eval( tr, trainData, pr );
    testPred = eval( tr, testData, pr );
    trainPred = cellfun( @str2num, trainPred );
    testPred = cellfun( @str2num, testPred );
    nTrainCorrect = sum( trainLabel == trainPred );
    nTestCorrect = sum( testLabel == testPred );
    fprintf( 1, 'prune level: %d   training: %5.2f%%   test: %5.2f%%\n', ...
        pr, 100 * nTrainCorrect / nTrain, 100 * nTestCorrect / nTest );
end

hist( double( trainLabel ), 10 );
hist( double( testLabel ), 10 );

