Code covered by the BSD License  

Highlights from
Greyboxeval - Model quality evaluation

image thumbnail
from Greyboxeval - Model quality evaluation by Bill Whiten
For models residues=model(data,parameters) with data sets at different experimental conditions

[A,info]=greyboxbuild(condfn,resfn,data,vndata,optn)
function [A,info]=greyboxbuild(condfn,resfn,data,vndata,optn)
% greyboxbuild  Greybox build an improved model
%  2012-01-24  Matlab8  Copyright (c) 2013, W J Whiten  BSD License
%
% [pr,rmse1,rmse2,info]=greyboxbuild(resfn,condfn,data,vndata,optn)
%  condfn  Condition function  
%           [c,pscale,pbase,pvalue]=condfn(data,idata)
%            data  User supplied data in any form
%            idata Data set number
%            c      Experimental condition column vector: data set idata
%            pscale Vector of scale (ie typical nonzero size) values 
%                    for parameters (optional if optn.Amat given)
%            pbase  Vector of base values for parameters (optional:
%                    default zero)
%  resfn   Residue calculation  [r,dr]=resfn(data,idata,p)
%            data  User supplied data in any form
%            idata Data set number
%            p     Parameter values
%            r     Column vector of residues for data set nbr idata
%            dr    Derivatives of r wrt p (ith column wrt p(i)) (optional)
%  data    Data for use in resfn & condfn (possibly a struct)
%  vndata  Vector of selected data set indices (typically 1:ndata)
%  optn    Optional additional information:
%           .Amat  Initial value for A matrix
%           .Acode Code value for use of each A matrix element
%                   0 do not use, 1 always use, 2 select
%           .mres  Estimate of total number of residuals
%           .reg   Ratio of largest eigenvalue for reject in linfitreg
%           .maxitr1 Maximum iterations for outer loop
%           .maxitr2 Maximum iterations for inner loop
%           .print   0 not printing, 1 final result, 2 partial results
%           .conv    Test level for convergence
%           .linfit  Function to use for linear fitting (default
%           .linoptn Struct options for linear fitting
%              .reg   Ratio of largest eigenvalue for reject in linfit
%              .tval  t ratio for rejection in linfitreg
%
%  pr      Estimated probability of reduction using random data
%  rmse0   Root mean squared error of unadjusted model
%  rmse2   Root mean squared error of adjusted model
%  info    Struct giving:
%           .Amat  Calculated A matrix value 
%           .Acode Matrix code for terms in A matrix (>0 use term)
%           .reg   Regularisation fraction for rejection of eigenvalues
%           .nreg  Number of eigenvectors used in regression
%           .ncond Number of condition terms
%           .npar  Number of parameters
%           .nres  Toal number of residuals
%           .conv  0 did not converge, 1 normal convergence,
%                   2 unable to improve current estimate.

% default option values
if(nargin<5)
    optn=struct();
end
optn0=struct('Amat',[],'Acode',[],'nres',1000,  ...
    'conv',1e-10,'maxitr1',50,'maxitr2',20,'print',2,  ...
    'linfit',@linfitregvar,'linoptn',struct());
optn=optndfts(optn,optn0);
A=optn.Amat;
Acode=optn.Acode;
linoptn=optn.linoptn;

optncore=selectfields(optn,'Amat','Acode','nres');

if(optn.print>0)
    fprintf('\nIter #   RMS error   Inner loop #\n')
end
indconv=0;
for i=1:optn.maxitr1
    optncore.Amat=A;
    [X,y,r1,info]=greyboxcore(condfn,resfn,data,vndata,optncore);
    
    if(optn.print>1 && i==1)
        fprintf('%4i %#15.9g\n',0,rms(r1))
    end
    
    if(i==1)
        ssq0=r1'*r1;
        if(isempty(optn.Acode))
            Acode=2*ones(info.npar,info.ncond);
        end
        
        linoptn.sel=Acode(Acode>0);

    end
    
    % solve for result matrix, default linfitregvar
    [a2,vm,sel,infolf]=optn.linfit(X,y,linoptn);
    a1=zeros(size(X,2),1);
    a1(sel)=a2;

    % form new A matrix
    if(isempty(A))
        A=zeros(info.npar,info.ncond);
    end
    A(Acode>0)=a1;

    if(optn.maxitr1>1)
        
        for j=1:optn.maxitr2
            r2=zeros(info.nres,1);
            k1=0;
            for kk=1:length(vndata)
                k=vndata(kk);
                
                par=parcalc(condfn,data,k,A);
                r2a=resfn(data,k,par);
                k1a=k1+1;
                k1=k1+numel(r2a);
                r2(k1a:k1)=r2a(:);
            end
            
            r12=(r1+r2)'*(r1-r2);
            if(abs(r12)/sum((abs(r1)+abs(r2)).^2)<optn.conv)
                indconv=1;
                break
            end
            
            if(optn.maxitr1==1)
                break
            end
            
            if(r12<0 && ~isempty(optn.Amat))
                A=(optn.Amat+A)/2;
            else
                break
            end
            
        end
        
        if(j==optn.maxitr2)
            indconv=2;
            break
        end
        
        if(indconv>0)
            break
        end
    
        if(optn.print>1)
            fprintf('%4i %#15.9g %4i\n',i,rms(r2),j)
        end
        
    elseif(optn.maxitr1==1)
        % if not iterating use predicted new residues
        r2=X*a1-y;
        j=0;
    end
    
    optn.Amat=A;
end

ssq2=r2'*r2;

% calculate output values
rx=1-ssq2/ssq0;
rx(rx<0)=0;
nreg=infolf.nreg;
pr=betainc(rx,nreg/2,(info.nres-nreg)/2,'upper');

rmse0=sqrt(ssq0/info.nres);
rmse2=sqrt(ssq2/info.nres);

info.indconv=indconv;
t=find(Acode>0);
info.sel=t(sel);
info.Acode=Acode;
info.vm=vm;
info.itr1=i;
info.nreg=nreg;
info.rmse0=rmse0;
info.rmse2=rmse2;

if(optn.print>0)
    fprintf('%4i %#15.9g %4i\n',i,rms(r2),j)
    fprintf('Test percent  %#9.3g\n',pr)
end
if(indconv~=1 && optn.maxitr1~=1)
    warning('greyboxeval  Did not converge')
end

return
end

Contact us