www.gusucode.com > mbctools 工具箱 matlab 源码程序 > mbctools/@modeldev/buildmodels.m

    function OK = buildmodels(mdev,mlist,varargin)
%BUILDMODELS build list of child models
%
% OK= buildmodels(mdev,mlist,Criteria)

%  Copyright 2000-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.


p= address(mdev);

if nargin<2
    m= model(mdev);
    s= statistics(mdev);
    nobs= s(1);
    % choose model template from dialog
    [mlist,OK]=xreg_modeltemplates('create',m,nobs);
    if ~OK
        return
    end
end

% Initalise display
DispObj= iMakeDispObj(mdev);
% Selection criteria
[Criteria,OK] = iChooseCriteria(mlist,DispObj,varargin{:});
% remove invalid models
[mlist,mdlsOK]= iCheckModels(mlist,DispObj);

if OK && mdlsOK
    
    % choose whether to build parallel or serial
    doPARFOR = mbcfoundation.DCTManager.isParpoolOpen();
    if doPARFOR
        fBuild = @iBuildParallel;
    else
        fBuild = @iBuildSerial;
    end


    N= length(mlist);
    DispObj= iCreateDisplay(DispObj,N+1);

    % prepare models for build
    mlist= iPrepareModels(mlist,mdev,Criteria);
    ExistingChildren = p.numChildren;
    % main build - either serial or parallel
    fBuild(p,mlist,DispObj);

    % display progress
    iDisplayProgress(DispObj,'Finished building models',length(mlist)+1)

    % choose best model
    iChooseBest(p,Criteria);

    % clean up progress display
    iDeleteProgress(DispObj,mdev)
    
    OK = p.numChildren>ExistingChildren;
    
else
    OK = false;
end



function stopped = iBuildSerial(p,mlist,DispObj)
%iBUILDSERIAL build models using ordinary for loop and display progress
%
% stopped = iBuildSerial(p,mlist,DispObj)

N = length(mlist);
stopped = false;
for i = 1:N;
    % prepare model for adding to tree
    mi = mlist{i};
    
    % build new child
    pch= modeldev(mi,p,false,false);

    % Display Progress
    iDisplayProgress(DispObj,...
        sprintf('Building model for %s/%s...',p.name,name(mi)),i);
    try
        % fit it
        fitmodel(pch.info);
        pch.name(name(mi));
        % clean up any temporary store in models
        pch.cleanup;
        % display new item on tree
        iDisplayTree(DispObj,pch)

        % delete any plot figures
        figs = findobj(allchild(0),'flat','Tag','mbcfitplot');
        if ~isempty(figs)
            delete(figs)
        end

    catch %#ok<CTCH>
        % model fit crashed so delete
        pch.delete;
    end
    drawnow
    if iStop(DispObj)
        stopped = true;
        break
    end
end


function stopped = iBuildParallel(p,mlist,DispObj)
%IBUILDPARALLEL build models using parfor - no display progress
%
% stopped = iBuildParallel(p,mlist,DispObj)

% can't stop 
stopped = false;
n = length(mlist);

[X,Y] = p.getdata;
% make data into double for size
X = double(X);
Y = double(Y);

% Display Progress
iDisplayProgress(DispObj,...
    sprintf('Building models for %s in parallel...',p.name),1);

% set up outputs
OK = false(1,n);
mout = cell(1,n);
Stats = cell(1,n);
% reorder on the assumption that models are of increasing complexity. This
% is reasonable for increasing number of centers for RBFs
index = [1:2:n,2:2:n];
mlist = mlist(index);
pp = gcp;
for i=1:n
    % fit model
    f(i) = parfeval(pp,@iFitModel,3,mlist{i},X,Y);
end

results = cell(1,3);
hasRun = false(1,n);
for i=1:n
    [idx,results{1:3}] = fetchNext(f);

    [mout{idx},OK(idx),Stats{idx}]= results{:};
    hasRun(idx) = true;
    if OK(idx)
        iDisplayProgress(DispObj,...
            sprintf('Building model for %s/%s...',p.name,name(mout{idx})),i);
    else
        iDisplayProgress(DispObj,...
            sprintf('Fit failed for %d...',idx),i);
    end
    if iStop(DispObj)
        stopped = true;
        break
    end
end

if stopped
    mout = mout(hasRun);
    OK = OK(hasRun);
    Stats = Stats(hasRun);
    index = index(hasRun);
    cancel(f);
end

% delete any plot figures
figs = findobj(allchild(0),'flat','Tag','mbcfitplot');
if ~isempty(figs)
    delete(figs)
end

% make modeldev and set up model - this needs to be done in the original
% order
[~,index] = sort(index);
for i=index
    if ~isempty(mout{i})
        % make child modeldev with fitted model
        pch= modeldev(mout{i},p,false,false);
        mdev = pch.info;
        mdev.Statistics = Stats{i};
        mdev = status(mdev,OK(i));
        % name node
        pch.name(name(mdev.Model));
        % display new item on tree
        iDisplayTree(DispObj,pch)
    end
end

function [m,OK,S] = iFitModel(m,X,Y)
%iFITMODEL fit model for parfor loop
%
% [m,OK,S] = iFitModel(m,X,Y)

try
    [m,OK,S]= fitmodel(m,X,Y);
    % reduce size of data 
    m = cleanup(m);
catch %#ok<CTCH>
    % set model to empty if fitmodel crashes so we can delete it
    m = [];
    S = [];
    OK = false;
end

function mlist= iPrepareModels(mlist,mdev,Criteria)
%IPREPAREMODELS prepare models for building
%
% mlist= iPrepareModels(mlist,p,Criteria)
%   resolve boxcox, reset model and make sure selection criteria is in
%   summary statistics

[~,Y,DataOK] = FitData(mdev);
m = model(mdev);
Yraw = double(Y(DataOK));
for i = 1:length(mlist)
    mi = mlist{i};
    % prepare model for adding to tree
    lam= get(mi,'boxcox');
    fopt= get(mi,'fitalg');
    mi = copymodel(m,mi);
    % Make sure selection criteria is present
    if ~ismember(Criteria, StatsList(mi))
        mi= addSummaryStats(mi,Criteria );
    end

    set(mi,'fitalg',fopt);
    % reset after copy model as rbf/reset requires this
    mi= reset(mi);
    % deal wirh box cox transform (this gets removed by copymodel!)
    if lam~=1
        set(mi,'boxcox',{lam,Yraw})
    else
        set(mi,'ytrans','');
    end

    mlist{i} = mi;
end



function [mlist,OK]= iCheckModels(mlist,DispObj)
%ICHECKMODELS check models before build to remove any invalid models
%
% [mlist,OK]= iCheckModels(mlist,DispObj)

% remove invalid models
mok= false(1,length(mlist));
BadModelList= '';
for i=1:length(mlist)
    if isstruct(mlist{i})
        % object didn't load properly
        mok(i)= false;
        BadModelList= sprintf('%s,<Invalid model>',BadModelList);
    else
        try
            mok(i)= checkmodel(mlist{i});
        catch %#ok<CTCH>
            mok(i)= false;
            BadModelList= sprintf('%s,%s',BadModelList,name(mlist{i}));
        end
    end
end
if ~all(mok)
    iDisplayMessage(DispObj,sprintf('Invalid models %s removed from template',BadModelList))
end
mlist= mlist(mok);
OK = any(mok);


function [Criteria,OK] = iChooseCriteria(mlist,DispObj,Criteria)
%ICHOOSECRITERIA choose selection criteria
%
% [Criteria,OK] = iChooseCriteria(mlist,Criteria)
OK = true;
% make an xregmulti to check selection criteria
mm= xregmulti('nfactors',nfactors(mlist{1}));
set(mm,'models',mlist);
if nargin<=2 
    % default selection criteria
    [~,List]=childstats(mm);
    if any(strcmp('AICc',List))
        Criteria= 'AICc';
    elseif any(strcmp('PRESS RMSE',List))
        Criteria= 'PRESS RMSE';
    else
        Criteria= 'RMSE';
    end
    if DispObj.GUIMode
        [Criteria,OK]= guiSelectCriteria(mm,Criteria);
        drawnow update
    end
else
    % check selection criteria is available
    [~,Chead]= childstats(mm);
    if ~any(strcmp(Criteria,Chead))
        Criteria= 'RMSE';
    end
end

function iChooseBest(p,Criteria)
%ICHOOSEBEST choose best model based on Criteria
%
% iChooseBest(p,Criteria)

FittedChildren= p.children(@status);
FittedChildren=find([FittedChildren{:}]~=0);
% choose best model based on Criteria
if ~isempty(FittedChildren)
    [S,Chead]= childstats(info(p));
    ind= find(strcmp(Criteria,Chead));
    if isempty(ind)
        % use RMSE by default
        Criteria= 'RMSE';
        ind= find(strcmp(Criteria,Chead));
    end
    % determine whether to minimize or maximize selection criteria
    mi = p.children(1,@model);
    [List,~,~,MinIsBest]= StatsList(mi{1});
    % select best model from fitted models
    if MinIsBest(strcmp(Chead{ind},List))
        [~,BestInd]=min(S(FittedChildren,ind));
    else
        [~,BestInd]=max(S(FittedChildren,ind));
    end
    %index of best accounting for unfitted models
    BestInd = FittedChildren(BestInd);
    if ~isempty(BestInd)
        % select best model if there is one
        p.BestModel(p.children(BestInd));
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Display progress
function DispObj= iMakeDispObj(mdev)

% Check whether running with model browser
DispObj.GUIMode =  isBrowserProject(mdev);


function DispObj= iCreateDisplay(DispObj,ProgressLength)

if DispObj.GUIMode && ProgressLength>1
    mbh= MBrowser;
    DispObj.mbh= mbh;
    DispObj.OldPtr= get(mbh.Figure,'Pointer');
    set(mbh.Figure,'Pointer','watch');
    % create waitbar

    
    hWB = xregGui.waitdlg('parent',mbh.Figure,'ShowStopButton',true);
    set(hWB.waitbar,'Min',1,'Max',ProgressLength);
    DispObj.hWB= hWB;
end


function stop = iStop(DispObj)

if DispObj.GUIMode
    drawnow update
    stop = DispObj.hWB.StopState;
else
    stop = false;
end

function iDisplayProgress(DispObj,msg,progress)

if DispObj.GUIMode
    hWB= DispObj.hWB;
    hWB.message= msg;
    if nargin>2
        hWB.Waitbar.Value= progress;
    end
    drawnow('expose');
end


function iDisplayTree(DispObj,pch)

if DispObj.GUIMode
    % add it to mbrowser tree
    DispObj.mbh.treeview(pch,'add');
end


function iDisplayMessage(DispObj,msg,Title)

if DispObj.GUIMode
    if nargin<3
        Title= 'Build Models';
    end
    h= msgbox(msg,Title,'modal');
    uiwait(h)
end

function iDeleteProgress(DispObj,mdev)

if DispObj.GUIMode
    mbh= DispObj.mbh;
    delete(DispObj.hWB);
    set(mbh.Figure,'Pointer',DispObj.OldPtr);
end