ghiath
ghiath

Reputation: 159

How to write a "classregtree" object on a file?

Is there any way to save a classregtree object to a file using MATLAB so that I can read the file from a java app?

Ideally I would like to save from matlab to an XML file.

Upvotes: 1

Views: 186

Answers (2)

m.s.
m.s.

Reputation: 16334

The classregtreeobject can be displayed in text form using disp(t). The logic behind that function is located atMATLAB/R201Xx/toolbox/stats/stats/@classregtree/disp.m. In order to programmatically save this output to a file, some modifications need to be applied to the function. The following code added the ability to save the text form to a text file, which you can then parse in Java:

function save_classregtree(t, filename)

fileId = fopen(filename, 'w');

% Get some information about the whole tree
maxnode = numel(t.node);
nd = 1 + floor(log10(maxnode)); % number of digits for node number
varnames = names(t);
if isempty(varnames)
    numCell = textscan(sprintf('%d\n',1:t.npred),'%s\n');
    varnames = strcat('x',numCell{1});
end
isregression = isequal(t.method,'regression');
if isregression
    fprintf(fileId, getString(message('stats:classregtree:disp:DecisionTreeForRegression')));
else
    fprintf(fileId, getString(message('stats:classregtree:disp:DecisionTreeForClassification')));
end

% Display information about each node
for j=1:maxnode
    if any(t.children(j))
        % branch node
        vnum = t.var(j);
        vname = varnames{abs(vnum)};
        cut = t.cut{j};
        kids = t.children(j);
        if     strcmp(type(t),'regression')
            Yfit = t.class(j);
            Yfit = num2str(Yfit,'%g');
        elseif strcmp(type(t),'classification')
            Yfit = t.classname(t.class(j));
        end
        if vnum>0        % continuous predictor "<" condition
            condleft = sprintf('%s<%g',vname,cut);
            condright = sprintf('%s>=%g',vname,cut);
            fprintf(fileId, '%*d  %s\n',nd,j,getString(message('stats:classregtree:disp:TreeBranch',...
                condleft,kids(1),condright,kids(2),char(Yfit))));
        else             % categorical predictor, membership condition
            cats = cut{1};
            if isscalar(cats)
                condleft = sprintf('%s=%g',vname,cats);
            else
                set = deblank(num2str(cats,'%g '));
                condleft = sprintf('%s %s {%s}',vname,getString(message('stats:classregtree:disp:ElementInSet')),set);
            end
            cats = cut{2};
            if isscalar(cats)
                condright = sprintf('%s=%g',vname,cats);
            else
                set = deblank(num2str(cats,'%g '));
                condright = sprintf('%s %s {%s}',vname,getString(message('stats:classregtree:disp:ElementInSet')),set);
            end
            fprintf(fileId, '%*d  %s\n',nd,j,getString(message('stats:classregtree:disp:TreeBranch',...
                condleft,kids(1),condright,kids(2),Yfit)));
        end
    else
        % terminal node, display fit (regression) or class assignment
        if isregression
            fprintf(fileId, sprintf('%s  %s %s\n','%*d',getString(message('stats:classregtree:disp:FittedResponse')),'%g'),nd,j,t.class(j));
        else
            fprintf(fileId, sprintf('%s  %s %s\n','%*d',getString(message('stats:classregtree:disp:PredictedClass')),'%s'),nd,j,char(t.classname(t.class(j))));
        end
    end

fclose(fileId);

end

You could of course also directly build XML in Matlab while iterating over the children. The following recursive function gives you a hint on how you could implement that:

function [] = build_xml(t, filename)
children = t.children(1);
xml = '<classregtree>';
xml = [xml, rec(t,children(1))];
xml = [xml, rec(t,children(2))];
xml = [xml, '</classregtree>'];

fileId = fopen(filename, 'w+t', 'n');
fwrite(fileId, xml, 'char');
fclose(fileId);
end

function [xml] = rec(t, child)
xml = ['<child id="', num2str(child), '">'];
children = t.children(child);

if any(children)    
    if children(1)
        xml = [xml, rec(t,children(1))];
    end
    if children(2)
        xml = [xml, rec(t,children(2))];
    end
end

xml = [xml, '</child>'];


end

Upvotes: 2

xenoclast
xenoclast

Reputation: 1635

The best I could manage was to export the split definitions and reimplement the tree from those:

classificationtree.view

will show you a text version of the decision tree, if your object is called classificationtree.

It comes out in if-elseif-else-goto pseudocode that doesn't take much to turn into your language of choice: macros or some kind of string processing could be useful if you have to change the training data a lot. It's probably the most useful form they could have chosen.

If you apply meaningful names to the input variables (by setting the PredictorNames property) this will help - make these names the same as the variable names in your java program and that's one less set of transcriptions you have to do.

Upvotes: 0

Related Questions