image thumbnail
from cauchy by Peder Axensten
Cauchy cdf, pdf, inverse cdf, parameter fit, and random generator.

paxmle(pars, negloglike, varargin)
function [mlepars, output]= paxmle(pars, negloglike, varargin)

% USAGE: 
% [mlepars, output]= paxmle(pars, negloglike)
% [mlepars, output]= paxmle(pars, negloglike, lBounds)
% [mlepars, output]= paxmle(pars, negloglike, lBounds, uBounds)
% [mlepars, output]= paxmle(..., options)
% 
% Calculate the best parameter fit given the negative log-likelihood. 
% 
% The parameter(s) is/are estimated thru MLE, using Matlab optimization fminsearch (fmincon, 
%  if the Optimization Toolbox is available). 
% 
% NOTE: No confidence interval yet, I got to find the math for it first...
% 
% ARGUMENTS:
% - pars (non empty vector) The initial parameter, the starting value. 
% - negloglike is a function of the type [negL, negDL, negDDL]= negloglike(p), where
%   negL, negDL, and negDDL are the value, first derivate (Jacobian), and second derivate 
%   (Hessian) respectively for the (log-)likelihood function at p. If you don't want to
%   calculate the Jacobian and/or the Hessian, return NaN for these instead. They are only 
%   used when the Optimisation Toolbox is available. 
% - lBounds (default is -Inf), the lower bounds for mlepars.
% - uBounds (default is Inf), the upper bounds for mlepars.
% - options (string) Information ('info') or detailed information ('info2')
%   about execution. Generates a nice figure too!
% - mlepars is the maximum likelihood estimated parameter values, or NaNs if none was found. 
% - output (structure) is the 'output' structure of the optimization call with two additions:
%     .exitflag is the exitflag value returned by the optimization call. 
%     .call is the name of the called function, see its reference for the other fields.
% 
% EXAMPLE:
% [v, res]= paxmle([mean(x) std(x)], myfunhandle, 'info2');
% 
% Copyright (C) Peder Axensten <peder at axensten dot se>
% 
% HISTORY:
% Version 1.0, 2006-08-03.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	% Default values.
	options=	optimset( ...
					'Display', 		'off', ...
					'MaxIter', 		2000, ...
					'TolX', 		eps, ...
					'TolFun', 		0 ...
				);
	
	
	% Check the arguments
	argok=	all(all(isreal(pars))) && ~isempty(pars) && strcmp(class(negloglike), 'function_handle');
	pLen=	length(pars);							% Number of parameters.
	
	if((nargin > 2) && ischar(varargin{end}))		% Display execution information?
		dbg= 	true;
		switch(varargin{end})
			case 'info',	options= optimset(options, 'Display', 'final');
			case 'info2',	options= optimset(options, 'Display', 'iter');
			case '',		dbg=     false;
			otherwise,		argok=   false;
		end
		varargin=	{varargin{1:end-1}};
	else	dbg= false;
	end
	
	if(length(varargin) >= 1)						% Lower bounds?
		lBounds=	varargin{1};
		argok=		argok && all(all(isreal(lBounds))) && all(all(size(lBounds) == size(pars)));
	else
		lBounds=	repmat(-Inf, [1 pLen]);
	end
	if(length(varargin) >= 2)						% Upper bounds?
		uBounds=	varargin{2};
		argok=		argok && all(all(isreal(uBounds))) && all(all(size(uBounds) == size(pars)));
	else
		uBounds=	repmat( Inf, [1 pLen]);
	end
	if(~argok || (length(varargin) > 2))			% Argument error?
		error('Incorrect arguments, check ''help paxmle''.');
	end
	
	
	% Do we have the Jacobian ? The Hessian?. 
	[L, dL, ddL]=	negloglike(pars);
	if(~isnan(dL))
		options=	optimset(options, 'LargeScale', 'on', 'GradObj', 'on');
		if(~isnan(ddL))
			options=	optimset(options, 'Hessian', 'on');
		end
	end
	
	
	% Find parameters. 
	divzero=	warning('query', 'MATLAB:divideByZero');
	warning('off', 'MATLAB:divideByZero');
	if(exist('fmincon', 'file') == 2)	% Optimization Toolbox is available. 
		[mlepars,fval,exitflag,output]= fmincon(negloglike, pars, ...
						[], [], [], [], lBounds, uBounds, [], options);
		output.call=	'fmincon';
	else								% Standard Matlab. 
		[mlepars,fval,exitflag,output]= fminsearch(negloglike, pars, options);
		output.call=	'fminsearch';
	end
	warning(divzero.state, 'MATLAB:divideByZero');
	output.exitflag=	exitflag;
	
	
	% Diverged?
	if(exitflag <= 0),	mlepars= repmat(NaN, [1 pLen]);	end		% We did not find a solution...
	
	
	% Debug info.
	if(dbg)
		% Textual information. 
		value('ALGORITHM:', output.algorithm);
		value('Iterations:', 		output.iterations);
		value('Function calls:', 	output.funcCount);
		disp(' ');
		value('', '-loglike', '-Jacobian', 'parameter(s)');
		[l, dl]=	negloglike(pars);
		value('Initial value(s):', 	[l, sqrt(sum(dl.^2)), pars]);
		[l, dl]=	negloglike(mlepars);
		value('Best fit:',  		[l, sqrt(sum(dl.^2)), mlepars]);
		
		% Prepare for figure.
		st=		0.05;
		pmin=	max([lBounds; min([mlepars; pars; uBounds]) - 0.5 - st*3]);
		pmax=	min([uBounds; max([mlepars; pars; lBounds]) + 0.5 + st*3]);
		if(pLen == 1)		% Draw 2-d figure.
			mark=	{'MarkerFaceColor', 'r', 'MarkerSize', 8};
			xx=		linspace(pmin(1), pmax(1), 50);
			LL=		zeros(1, length(xx));
			for nx= 1:length(xx)
				LL(nx)=		negloglike(xx(nx));
			end
			plot(xx,      LL);
			hold on;
			plot(pars,    negloglike(pars),  	'^r', mark{:});
			plot(mlepars, negloglike(mlepars),	'vr', mark{:});
			xlabel('Parameter');	ylabel('negative log-likelihood');
		else				% Draw 3-d figure. 
			mark=	{'MarkerFaceColor', 'k', 'MarkerSize', 12};
			aa=		linspace(pmin(1), pmax(1), 50);
			bb=		linspace(pmin(2), pmax(2), 50);
			LL=		zeros(length(bb), length(aa));
			for na= 1:length(aa)
				for nb= 1:length(bb)
					LL(nb, na)=	negloglike([aa(na), bb(nb)]);
				end
			end
			[aa, bb]=	meshgrid(aa, bb);

			plot3(pars(1),    pars(2),    negloglike(pars),    '^k', mark{:});
			hold on
			plot3(mlepars(1), mlepars(2), negloglike(mlepars), 'vk', mark{:});
			meshz(aa, bb, LL);
			contour3(aa, bb, LL, 'LineSpec', 'k');
			shading interp;		colormap hsv;
			xlabel('Parameter 1');	ylabel('Parameter 2');	zlabel('negative log-likelihood');
		end
	end
end


function value(gs, varargin)
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% For debugging purposes. 
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	fprintf(1, '\n%-20s', gs);
	for i= 1:length(varargin)
		if(ischar(varargin{i})),	fprintf(1, '%15s',   varargin{i});	
		else						fprintf(1, '%15.6f', varargin{i});
		end
	end
end

Contact us at files@mathworks.com