Code covered by the BSD License  

Highlights from
Fuzzy ARTMAP

image thumbnail
from Fuzzy ARTMAP by Massimiliano Versace
This package contains an implementation of Fuzzy ARTMAP.

fuzzyARTMAP_examples.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This is an implementation of an ARTMAP variant,
% as described in:
% Gaddam, C. S. (2007).
% Feature Selection via transmitter depletion in ARTMAP. Online Document, xx(x) xxx-xxx.
% Boston, MA: Boston University.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Programmed by Chaitanya Sai (August 2007-08)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The notation follows the article's notation,
% as does the headers for each step of the
% algorithm

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% close all;


if ~exist('dataStruct_biasedART','var')
    load fuzzyARTbenchmarks
    load dataset_descriptions
    disp('Finished loading datasets')
end


%%%%%%%%DATASETS%%%%%%%%%%%%%
%
%     1'six_point_test'
%     2'Stripes_Sparse'
%     3'Stripes_Dense'
%     4'CIS_Sparse'
%     5'CIS_Dense'
%     6'Checkerboard_Sparse'
%     7'Checkerboard_Dense'
%     8'Binary_five'
%     9'Test on Stripe 3 Capped'
%     10'Test on Stripe 2 Capped'
%     11'Test on Stripe 1 Capped'
%     12'Test on Stripe 0 Capped'
%     13'Genre prediction'
%%%%%%%%DATASETS%%%%%%%%%%%%%


disp({dataset_strings.string_val}')
%dataSetNum=input('Input dataset?');

if (init_vals.datasrc==1)
    dataSetNum=4;
elseif (init_vals.datasrc==2)
    dataSetNum=5;
elseif (init_vals.datasrc==3)
    dataSetNum=2;
elseif (init_vals.datasrc==4)
    dataSetNum=3;
elseif (init_vals.datasrc==5)
    dataSetNum=6;
elseif (init_vals.datasrc==6)
    dataSetNum=7;
elseif (init_vals.datasrc==7)
    dataSetNum=9;
elseif (init_vals.datasrc==8)
    dataSetNum=10;
elseif (init_vals.datasrc==9)
    dataSetNum=11;
elseif (init_vals.datasrc==10)
    dataSetNum=12;
elseif (init_vals.datasrc==11)
    dataSetNum=13;
end

%lambda_Attention=input('lambda Value (0 -> fuzzy ARTMAP)?');

lambda_Attention=0;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

try
    dataStruct_fuzzyART(dataSetNum).test_output=dataStruct_fuzzyART(dataSetNum).test_output(:);
catch
    disp('Test Output Not Available')
end


inputNet = struct('M', {[]}, ... % Number of features
    'TestOnly', {0}, ... % Train & Test or Test only? unless specified otherwise
    'test_fast', {1}, ... % Use fast tester unless specified otherwise
    'compute_overlap', {0}, ... % Indirectly measure overlap by looking at how many nodes overlap with a test_point
    'C', {0}, ... % Number of committed coding nodes (paper says set to 0, but harder to Matlab)
    'plotSteps',{0}, ... % % Iterate through individual learning steps
    'NodeList', {[]}, ... % List of node associated with each input
    'maxNumCategories', {100}, ...
    'numClasses', {[]}, ... % The total number of classes
    'w', {[]}, ... % coding node weight vector
    'W', {[]}, ... % output class weight vector
    'rho_bar', {0}, ... % rho_bar, the baseline vigilance. baseline=0 maximizes code compression
    'rho', {0.0}, ... % vigilance
    'alpha', {.1}, ... % Signal Rule Parameter
    'alphaTrain',{[]},... % Store when reverting alpha value in TESTING
    'beta', {1.0}, ...  % Learning fraction
    'gamma',{.000001},... % fraction additive in numerator and denominator of matching signal
    'epsilon', {-.00001}, ... % Match Tracking (codes inconsistent cases)
    'base_vigilance', {0.0}, ... % Baseline vigilance
    'p', {1.0}, ... % CAM rule power
    'dataSubsets', {1}, ... % 4-fold cross-validation
    'votes', {5}, ... % Number of voting systems
    'learningRate', {1.0}, ...
    'win_sequence',{[]},...
    'act_sequence',{[]},...
    'search_cycles', {0},... % Total number of search cycles during training
    'lambda_Attention',{[]},...
    'dataStore',{[]},... % Store data if using structs as inputs
    'numEpochs',{1},...%Number of times to present input
    'model_num',{[]},... % Depletion Model Number
    'type_depletion',{4},... %Options are 0 1 2 3 4
    'deplete_fast',{[]},...
    'learn_trail',{[]},...
    'learn_description',{''},...
    'short_learn_descript',{''},...
    'uncommitted_fail',{0},...
    'NI_fail',{[]},...
    'NI_fail_addNode',{[]},...
    'node_created',{[]},...
    'start_conservative',{[]},...
    'ovlp_net',{[]},...
    'A_dep_dist',{[]},...
    'e_mod_dist',{[]},...
    'e_realLow',{0},...
    'e_zero',{0},...
    'diffE_count',{[]},...
    'perc_error',{[]},... % percentage error added to labels in training
    'var_error_features',{[]},... % variance of error added to features in training
    'testAccuracy',{[]}); % Attention gain parameter



% inputNet.lambda_Attention=0.5;

inputNet.lambda_Attention=lambda_Attention;
inputNet.deplete_fast = 0;  %TURN OFF (=0) IF DEPLETING USING ITERATIVE VERSION
inputNet.start_conservative =0;
inputNet.DEFAULT_RETEST=1;

%inputNet.alpha=10^(-8);
inputNet.alpha=init_vals.alpha;

%inputNet.beta=1;
inputNet.beta=init_vals.beta;


%inputNet.gamma=0.0000001;
inputNet.gamma=init_vals.gamma;

%inputNet.rho_bar=0;
inputNet.rho_bar=init_vals.rho;


%inputNet.plotSteps=0;
inputNet.plotSteps=init_vals.plot_steps;

inputNet.model_num=32;

%Train for number of epochs
%inputNet.numEpochs=1;
inputNet.numEpochs=init_vals.epochs;

%%%Inject label errors into dataset | e.g perc_error = 10 implies 10% of
%%%training data have erroneous class labels during training
perc_error=0;
inputNet.perc_error=perc_error;

%%%Inject feature noise into dataset | e.g var_error_features = 10 implies 10% of
%%%training data have noise added to input features
var_error_features=0;
inputNet.var_error_features=var_error_features;

inputNet.compute_overlap=1;

if (dataSetNum==13)
    %Matrix manipulation becomes too memory intensive for movie genres
    %benchmark
    inputNuet.test_fast=0;
end


if (inputNet.perc_error~=0)
    disp('Adding error in training set!');
elseif (inputNet.var_error_features~=0)
    disp('Adding feature error in training set!');
end
%%%%%%%%%%%%%%%%%%%
%Create uniform plot grid%%
%%%%%%%%%%%%%%%%%%%



if ismember(dataSetNum,[1 2 3 4 5 6 7])

    if (perc_error>0)
        orig_dataset_labels=dataStruct_fuzzyART(dataSetNum).training_output;
        dataStruct_fuzzyART(dataSetNum).training_output=addClassError(dataStruct_fuzzyART(dataSetNum).training_output,inputNet.perc_error);
        temp_labels_noise=dataStruct_fuzzyART(dataSetNum).training_output;
    elseif (var_error_features>0)
        orig_dataset_features=dataStruct_fuzzyART(dataSetNum).training_input;
        dataStruct_fuzzyART(dataSetNum).training_input=max(min(dataStruct_fuzzyART(dataSetNum).training_input+randn(size(dataStruct_fuzzyART(dataSetNum).training_input))*var_error_features,1),0);
        temp_features_noise=dataStruct_fuzzyART(dataSetNum).training_input;
    end
    if ~exist('dataTestUnif','var')
        load ARTMAP_data_test dataTestUnif dataTestOutUnif test_x test_y
    end
    dataStruct_fuzzyART(dataSetNum).test_input=dataTestUnif;
    if dataSetNum>1
        dataStruct_fuzzyART(dataSetNum).test_output=dataTestOutUnif{floor(dataSetNum/2)}';
    end
end






[a,b,c]=Default_ARTMAP(dataStruct_fuzzyART(dataSetNum),inputNet);
if ismember(dataSetNum,[1 2 3 4 5 6 7])
    if (perc_error>0)
        inputNet.lambda_Attention=0;
        [a_zero,b_zero,c_zero]=Default_ARTMAP(dataStruct_fuzzyART(dataSetNum),inputNet);
        disp('Same training order lambda = 0')
        disp(sum(a_zero==dataStruct_fuzzyART(dataSetNum).test_output)*100/length(a_zero));
        labels_switch_positions=find(orig_dataset_labels~=temp_labels_noise);
        disp(intersect(labels_switch_positions,c.NI_fail))
        dataStruct_fuzzyART(dataSetNum).training_output=orig_dataset_labels;
    elseif (var_error_features>0)
        dataStruct_fuzzyART(dataSetNum).training_input=orig_dataset_features;
    end
end
if (ismember(inputNet.model_num,[31 2^c.M]) && (inputNet.deplete_fast==1) && (inputNet.lambda_Attention==1))
    c.lambda_Attention='\infty';
end



if (c.M==2) && (inputNet.plotSteps==0)

    a=a(:);

    if dataSetNum~=1
        colormap([1 .4 .4; 1 .8 .8;.8 .8 1; .4 .4 1])

        imagesc(test_x(:),test_y(:),(reshape(a+(a~=dataStruct_fuzzyART(dataSetNum).test_output).*((a==2)-(a==1)),length(test_x),length(test_x))));
        set(gca,'ydir','normal')
        hold on

    else

        colormap([1 .7 .7;.7 .7 1])
        imagesc(test_x(:),test_y(:),(reshape(a,length(test_x),length(test_x))));
        set(gca,'ydir','normal')
        hold on

    end
    drawRectsArtmap;

    axis equal
    axis tight
    axis([-.1 1.1 -.1 1.1]);
    %     title(['fuzzy ARTMAP: feature selection in ART search cycle; Type (One Epoch)'],'fontsize',12);
    %      ylabel(['\lambda = ' num2str(c.lambda_Attention,3)],'fontsize',12)
    if dataSetNum~=1
        xlabel(['Accuracy : ', num2str(sum(dataStruct_fuzzyART(dataSetNum).test_output==a)*100/length(dataStruct_fuzzyART(dataSetNum).test_output),3),'%, Committed Nodes: ',num2str(c.C), ......
            ],'fontsize',12);
    end


    if (perc_error>0)
        figure(2)
        if dataSetNum~=1

            colormap([1 .4 .4; 1 .8 .8;.8 .8 1; .4 .4 1])


            a_test=dataStruct_fuzzyART(dataSetNum).test_output;
            colormap([1 .8 .8;.8 .8 1])
            imagesc(test_x(:),test_y(:),(reshape(a_test+(a_test~=dataStruct_fuzzyART(dataSetNum).test_output).*((a_test==2)-(a_test==1)),length(test_x),length(test_x))));
            set(gca,'ydir','normal')
            hold on

        else

            colormap([1 .7 .7;.7 .7 1])
            imagesc(test_x(:),test_y(:),(reshape(a,length(test_x),length(test_x))));
            set(gca,'ydir','normal')
            hold on

        end
        for i=1:size(c_zero.w,2)
            if (sum(c_zero.w(:,i))==2)
                rect_created=[(min(c_zero.w(1,i),1-c_zero.w(3,i))) (min(c_zero.w(2,i),1-c_zero.w(4,i))) abs(1-c_zero.w(3,i)-c_zero.w(1,i))+.01 abs(1-c_zero.w(4,i)-c_zero.w(2,i))+.01];

                %IF RESCALING
                %rect_created=[(min((9*c.w(1,i)-4),1-(9*c.w(3,i)-4))) (min((9*c.w(2,i)-4),1-(9*c.w(4,i)-4))) abs(1-(9*c.w(3,i)-4)-(9*c.w(1,i)-4))+.01 abs(1-(9*c.w(4,i)-4)-(9*c.w(2,i)-4))+.01];

                if c_zero.W(i,1)==0
                    rectangle('Position',rect_created,'EdgeColor',[0 0 1],'LineWidth',1.5)
                    hold on
                    %text((rect_created(1)+rect_created(3)/2),(rect_created(2)+rect_created(4)/2),'\beta')
                else
                    rectangle('Position',rect_created,'EdgeColor',[1 0 0],'LineWidth',1.5)
                    hold on
                    %text((rect_created(1)+rect_created(3)/2),(rect_created(2)+rect_created(4)/2),'\alpha')
                end
            end
        end

        axis equal
        axis tight
        axis([-.1 1.1 -.1 1.1]);
        %         title(['fuzzy ARTMAP: feature selection in ART search cycle; Type ' num2str(c_zero.model_num) ' (One Epoch)'],'fontsize',12);
        %         ylabel(['\lambda = ' num2str(c_zero.lambda_Attention,3)],'fontsize',12)
        %         if dataSetNum~=1
        %             xlabel(['Accuracy% : ', num2str(sum(dataStruct_fuzzyART(dataSetNum).test_output==a_zero)*100/length(dataStruct_fuzzyART(dataSetNum).test_output),3),', C Nodes: ',num2str(c_zero.C), ...
        %                 ', \alpha: ',num2str(c_zero.alpha)......
        %                 ', Training Pts : ',num2str(length(dataStruct_fuzzyART(dataSetNum).training_input))...
        %                 ', U Fail : ',num2str(c_zero.uncommitted_fail) ', NIT fail : ',num2str(length(c_zero.NI_fail))],'fontsize',12);
        %         end
    end


    try
        depleted_count=0;
        for i=1:length(c.learn_trail)
            if ~isempty(c.learn_trail(dataSetNum).MT_nodes)
                depleted_count=depleted_count+1;
                depleted_sample(depleted_count)=i;
                depleted_num(depleted_count)=length(c.learn_trail(dataSetNum).MT_nodes);
                depleted_A(depleted_count,:)=c.learn_trail(dataSetNum).MT_Adash_after{end};
            end
        end
        depleted_sample=depleted_sample(:);
        depleted_num=depleted_num(:);
        min(sum(depleted_A,2))
    catch
        disp('Trail Not Available');
    end


elseif ismember(c.M,6)

    inputNet.lambda_Attention=0;

    num_mapping=c.W*[1 2]';
    max_vals=(b==repmat(max(b,[],2),1,3));
    ties=(mod(max_vals*(2*num_mapping+1),2)==0);


    inputNet.gamma=0.01;

    [a_nodep,b_nodep,c_nodep]=Default_ARTMAP(dataStruct_fuzzyART(dataSetNum),inputNet);
    test_out=num2str(dataStruct_fuzzyART(dataSetNum).test_input');
    test_out=test_out(:,1:3:size(test_out,2));
    num_mapping=c_nodep.W*[1 2]';
    max_vals=(b_nodep==repmat(max(b_nodep,[],2),1,3));
    ties_nodep=(mod(max_vals*(2*num_mapping+1),2)==0);
    show_val={'+','-','T'};
    a_with_ties=a.*(~ties)+3*ties;
    a_nodep_with_ties=a_nodep.*(~ties_nodep)+3*ties_nodep;

    [strvcat(num2str(round(b_nodep*1000)/1000,'%1.3f\t')) ...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        [show_val{a_nodep_with_ties}]'...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        [show_val{a_with_ties}]'...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        strvcat(num2str(round(b*1000)/1000,'%1.3f\t')) ...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        repmat(' ',2^(c.M),1)...
        strvcat(test_out)]


    disp('Not Displaying Outputs: More than 2 input dimensions')

    disp('Total number of differences: Depletion versus no depletion')

    sum(a~=a_nodep)

elseif c.M==41

    disp('Finished running Boston dataset simulation')

    if dataSetNum<13
        title_boston=['Boston dataset ' num2str(dataSetNum-8) ' (uncapped)  \lambda=' num2str(c.lambda_Attention,2)];
    end

    [conf_nonnorm,conf_norm,avg_acc]= confMatrixPlot(dataStruct_fuzzyART(dataSetNum).test_output(:),a(:),c,dataStruct_fuzzyART(dataSetNum).labels,title_boston);


elseif strcmp(dataStruct_fuzzyART(dataSetNum).description,'movie_genres')
    b_mean=mean(b,1);
    b_std=std(b,1);
    b_new=(b-repmat(b_mean,length(dataStruct_fuzzyART(dataSetNum).test_output),1))./repmat(b_std,length(dataStruct_fuzzyART(dataSetNum).test_output),1);
    top_node_num=round(c.C*.02);
    dum=sort(b_new,2,'descend');
    y_rect=b_new.*(b_new>repmat(mean(b_new,2),1,c.C)).*(b_new>repmat(dum(:,top_node_num),1,c.C));
    sigma = c.W'*y_rect';
    sigma_mean=mean(sigma,2);
    sigma_std=std(sigma',1)';
    sigma_new=(sigma-repmat(sigma_mean,1,length(dataStruct_fuzzyART(dataSetNum).test_output)))./repmat(sigma_std,1,length(dataStruct_fuzzyART(dataSetNum).test_output));
    [dum,classes]=max(sigma,[],1);

    [conf_nonnorm,conf_norm,avg_acc]= confMatrixPlot(dataStruct_fuzzyART(dataSetNum).test_output(:),classes,c,dataStruct_fuzzyART(dataSetNum).labels,'');
end

disp('Output class predictions are stored in variable ''a''.');
disp('Distributed output predictions are stored in ''b''.');
disp('The ARTMAP network details are stored in ''c''');

Contact us at files@mathworks.com