function demo_mmgauss(action,hfigure,varargin)
% DEMO_MMGAUSS Demo on minimax estimation for Gaussian.
%
% Synopsis:
% demo_mmgauss
%
% Description:
% demo_mmgauss demonstrates the minimax estimation algorithm
% [SH10] for bivariate Gaussian distribution. The training data
% is supposed to contain samples which well describing the
% probability distribution function (pdf), i.e., which have
% high value of pdf. The samples do not have to be i.i.d. in
% contrast to the ML estimation.
%
% The estimated model is visualized as an ellipsoid:
% shape is influenced by the covariance matrix and the center
% corresponds to the mean vector.
% The lower (red) and upper (blue) bound on the optimal value
% of the optimized minimax criterion is displayed at the bottom
% part of the window.
%
% Control:
% Epsilon - Stopping condition. The algorithm stops if the
% difference between lower and the upper bound
% is less then the epsilon.
%
% Iterations - Number of iterations after which the model
% is re-displayed.
%
% FIG2EPS - Exports figure to the PostScript file.
% Load data - Loads input data sample from file.
% Create data - Invokes program for creating data sample.
% Reset - Resets the demo.
% Play - Runs the algorithm.
% Stop - Stops the running algorithm.
% Step - Performs one iteration of the algorithm.
% Info - Invokes the info box.
% Close - Closes the program.
%
% See also MMGAUSS.
%
% About: Statistical Pattern Recognition Toolbox
% (C) 1999-2003, Written by Vojtech Franc and Vaclav Hlavac
% <a href="http://www.cvut.cz">Czech Technical University Prague</a>
% <a href="http://www.feld.cvut.cz">Faculty of Electrical Engineering</a>
% <a href="http://cmp.felk.cvut.cz">Center for Machine Perception</a>
% Modifications:
% 2-may-2004, VF
% 19-sep-2003, VF
% 3-mar-2003, VF
% 11-june-2001, V.Franc, comments added.
% 24. 6.00 V. Hlavac, comments polished.
BORDER=0.25;
CENTERSIZE=10;
LINE_WIDTH=1;
AXIST_ADD=10;
DATA_IDENT='Finite sets, Enumeration';
if nargin < 1,
action = 'initialize';
end
switch lower(action)
case 'initialize'
left=0.2;
width=0.6;
bottom=0.1;
height=0.8;
hfigure=figure('Name','Minimax learning', ...
'Visible','off',...
'NumberTitle','off', ...
'Units','normalized', ...
'Position',[left bottom width height],...
'tag','Demo_mmgauss',...
'doublebuffer','on',...
'backingstore','off');
left=0.1;
width=0.65;
bottom=0.1;
height=0.28;
haprob=axes(...
'Units','normalized', ...
'NextPlot','add',...
'Position',[left bottom width height]);
title('blue - log p(x), red - \Sigma \alpha(x) log p(x)',...
'Parent',haprob,...
'VerticalAlignment','bottom',...
'Units','normalized',...
'HorizontalAlignment','left',...
'Position',[0 1 0]);
htxsteps=xlabel('step number');
height=0.45;
bottom=0.5;
haset=axes(...
'Units','normalized', ...
'NextPlot','add',...
'Position',[left bottom width height]);
ylabel('feature y');
xlabel('feature x');
width=0.1;
left=0.75-width;
bottom=0.95;
height=0.04;
hbtclose = uicontrol(...
'Units','Normalized', ...
'Callback','fig2eps(gcf)',...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','FIG2EPS');
left=0.8;
bottom=0.05;
height=0.05;
width=0.15;
hbtclose = uicontrol(...
'Units','Normalized', ...
'Callback','close(gcf)',...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Close');
bottom=bottom+1.5*height;
hbtinfo = uicontrol(...
'Units','Normalized', ...
'Callback','demo_mmgauss(''info'',gcf)',...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Info');
bottom=bottom+1.5*height;
hbtstep = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Step', ...
'Interruptible','off',...
'Callback','demo_mmgauss(''step'',gcf)');
bottom=bottom+height;
hbtstop = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Stop', ...
'Callback','set(gcbo,''UserData'',1)',...
'Enable','off');
bottom=bottom+height;
hbtplay = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Play', ...
'Callback','demo_mmgauss(''play'',gcf)');
bottom=bottom+height;
hbtreset = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Reset', ...
'Callback','demo_mmgauss(''reset'',gcf)');
bottom=bottom+1.5*height;
hbtcreat = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Create data', ...
'Callback','demo_mmgauss(''creatdata'',gcf)');
bottom=bottom+1*height;
hbtload = uicontrol(...
'Units','Normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'String','Load data', ...
'Callback','demo_mmgauss(''getfile'',gcf)');
bottom=0.95-height;
htxeps=uicontrol( ...
'Style','text', ...
'Units','normalized', ...
'Position',[left bottom width 0.9*height], ...
'String','epsilon');
bottom=bottom-height;
hedeps = uicontrol(...
'Units','normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'Style','edit',...
'String','0.1');
bottom=bottom-1.5*height;
htxiter=uicontrol( ...
'Style','text', ...
'Units','normalized', ...
'Position',[left bottom width 0.9*height], ...
'String','Iterations');
bottom=bottom-height;
hediter = uicontrol(...
'Units','normalized', ...
'ListboxTop',0, ...
'Position',[left bottom width height], ...
'Style','edit',...
'String','1');
htitle1=title('No data loaded',...
'Parent',haset,...
'VerticalAlignment','bottom',...
'HorizontalAlignment','left',...
'Units','normalized',...
'Position',[0 1 0]);
handlers=struct(...
'ellipse',struct('handler',-1,'center',-1,'mi',[],'sigma',[],'t',0,'N',[]),...
'plot1',struct('handler',-1,'topps',[],'axist',0,'time',[]),...
'plot2',struct('handler',-1,'minps',[]),...
'title1',htitle1,...
'btstep',hbtstep,...
'btstop',hbtstop,...
'btclose',hbtclose,...
'btplay',hbtplay,...
'btreset',hbtreset,...
'btinfo',hbtinfo,...
'btload',hbtload,...
'btcreat',hbtcreat,...
'txsteps',htxsteps,...
'txeps',htxeps,...
'txiter',htxiter,...
'aset',haset,...
'aprob',haprob,...
'editer',hediter,...
'edeps',hedeps);
set(hfigure,'UserData',handlers)
demo_mmgauss('reset',hfigure);
set(hfigure,'Visible','on');
drawnow;
case 'play'
h=get(hfigure,'UserData');
sets=get(h.aset,'UserData');
if isempty(sets)==1,
return;
end
set([h.editer,h.edeps,h.btstep,h.btclose,h.btplay,...
h.btreset,h.btinfo,h.btload,h.btcreat,h.txeps,h.txiter],...
'Enable','off');
set(h.btstop,'Enable','on');
iter=str2num(get(h.editer,'String'));
epsilon=str2num(get(h.edeps,'String'));
set(h.btstop,'UserData',0);
if h.ellipse.t==0 & iter > 1,
options.eps = epsilon;
options.tmax = 1;
model=mmgauss(sets.X,options);
mi = model.Mean;
sigma = model.Cov;
minp = model.lower_bound(end);
topp = model.upper_bound(end);
solution = model.exitflag;
h.plot1.time=[1];
h.plot2.minps=[minp];
h.plot1.topps=[topp];
end
play=1;
while play==1 & get(h.btstop,'UserData')==0,
options.tmax = iter+h.ellipse.t;
options.eps = epsilon;
if h.ellipse.t == 0,
model=mmgauss(sets.X,options);
else
init_model.t = h.ellipse.t;
init_model.Alpha = h.ellipse.N;
model=mmgauss(sets.X,options,init_model);
end
mi= model.Mean;
sigma = model.Cov;
solution = model.exitflag;
minp = model.lower_bound(end);
topp = model.upper_bound(end);
h.ellipse.N = model.Alpha;
h.ellipse.t = model.t;
text=sprintf('iteration t=%d ',h.ellipse.t);
if solution==1,
text=strcat(text,', algorithm has converged.');
play=0;
else
h.plot1.time=[h.plot1.time,h.ellipse.t];
h.plot2.minps=[h.plot2.minps,minp];
h.plot1.topps=[h.plot1.topps,topp];
if h.ellipse.t > h.plot1.axist,
h.plot1.axist=h.ellipse.t+iter*AXIST_ADD;
set(h.aprob,'XLim',[1 h.plot1.axist]);
end
set(h.plot2.handler,'XData',h.plot1.time,'YData',h.plot2.minps,'Visible','on');
set(h.plot1.handler,'XData',h.plot1.time,'YData',h.plot1.topps,'Visible','on');
set(h.ellipse.center,'XData',mi(1),'YData',mi(2),'Visible','on');
r=sqrt(max(mahalan(sets.X,mi,sigma)));
[x,y]=ellips(mi,inv(sigma),r,40);
set(h.ellipse.handler,'XData',x,'YData',y,'Visible','on');
end
set(h.txsteps,'String',text);
set(hfigure,'UserData',h);
drawnow;
end
set([h.edeps,h.editer,h.btstep,h.btclose,h.btplay,...
h.btreset,h.btinfo,h.btload,h.btcreat,h.txeps,h.txiter],...
'Enable','on');
set(h.btstop,'Enable','off');
case 'step'
h=get(hfigure,'UserData');
sets=get(h.aset,'UserData');
if isempty(sets)==1,
return;
end
iter=str2num(get(h.editer,'String'));
epsilon=str2num(get(h.edeps,'String'));
if h.ellipse.t==0 & iter > 1,
options.eps = epsilon;
options.tmax = 1;
model=mmgauss(sets.X,options);
mi = model.Mean;
sigma = model.Cov;
minp = model.lower_bound(end);
topp = model.upper_bound(end);
solution = model.exitflag;
h.plot1.time=[1];
h.plot2.minps=[minp];
h.plot1.topps=[topp];
end
options.tmax = iter+h.ellipse.t;
options.eps = epsilon;
if h.ellipse.t == 0,
model=mmgauss(sets.X,options);
else
init_model.t = h.ellipse.t;
init_model.Alpha = h.ellipse.N;
model=mmgauss(sets.X,options,init_model);
end
mi= model.Mean;
sigma = model.Cov;
solution = model.exitflag;
minp = model.lower_bound(end);
topp = model.upper_bound(end);
h.ellipse.N = model.Alpha;
h.ellipse.t = model.t;
text=sprintf('iteration t=%d ',h.ellipse.t);
if solution==1,
text=strcat(text,',solution was found.');
else
h.plot1.time=[h.plot1.time,h.ellipse.t];
h.plot2.minps=[h.plot2.minps,minp];
h.plot1.topps=[h.plot1.topps,topp];
if h.ellipse.t > h.plot1.axist,
h.plot1.axist=h.ellipse.t+iter*AXIST_ADD;
set(h.aprob,'XLim',[1 h.plot1.axist]);
end
set(h.plot2.handler,'XData',h.plot1.time,'YData',h.plot2.minps,'Visible','on');
set(h.plot1.handler,'XData',h.plot1.time,'YData',h.plot1.topps,'Visible','on');
set(h.ellipse.center,'XData',mi(1),'YData',mi(2),'Visible','on');
r=sqrt(max(mahalan(sets.X,mi,sigma)));
[x,y]=ellips(mi,inv(sigma),r,40);
set(h.ellipse.handler,'XData',x,'YData',y,'Visible','on');
end
set(h.txsteps,'String',text);
drawnow;
set(hfigure,'UserData',h);
case 'redraw'
h=get(hfigure,'UserData');
sets=get(h.aset,'UserData');
if isempty(sets)==1,
return;
end
axes(h.aset);
set(get(h.aset,'Children'),'EraseMode','normal');
clrchild(h.aset);
h.ellipse.handler=plot([0],[0],...
'Parent',h.aset,'LineWidth',LINE_WIDTH,...
'EraseMode','xor','Color','r','Visible','off');
h.ellipse.center=line(0,0,'Marker','+',...
'EraseMode','xor','Color','r','MarkerSize',CENTERSIZE,'Visible','off');
win=cmpwin(min(sets.X'),max(sets.X'),BORDER,BORDER);
setaxis(h.aset,win);
axes(h.aset);
ppatterns(sets.X);
set(hfigure,'UserData',h);
case 'getfile'
h=get(hfigure,'UserData');
[name,path]=uigetfile('*.mat','Open file');
if name~=0,
file.pathname=strcat(path,name);
file.path=path;
file.name=name;
if check2ddata(file.pathname),
set(h.btload,'UserData',file);
demo_mmgauss('loadsets',hfigure);
else
errordlg('This file does not contain required data.','Bad file','modal');
end
end
case 'loadsets'
h=get(hfigure,'UserData');
file=get(h.btload,'UserData');
sets=load(file.pathname);
sets.I = sets.y;
sets.K = size(sets.X,2);
sets.N = 2;
set(h.aset,'UserData',sets);
demo_mmgauss('reset',hfigure);
demo_mmgauss('redraw',hfigure);
drawnow;
case 'reset'
h=get(hfigure,'UserData');
file=get(h.btload,'UserData');
sets=get(h.aset,'UserData');
h.ellipse.mi=[];
h.ellipse.sigma=[];
h.ellipse.t=0;
h.ellipse.N=[];
h.plot1.topps=[];
h.plot2.minps=[];
h.plot1.time=[];
h.plot1.axist=0;
text=sprintf('iteration t=0 ');
set(h.txsteps,'String',text);
if h.ellipse.handler==-1,
h.ellipse.handler=plot([0],[0],...
'Parent',h.aset,'LineWidth',LINE_WIDTH,...
'EraseMode','xor','Color','k','Visible','off');
h.ellipse.center=line(0,0,'Marker','x',...
'EraseMode','xor','Color','k','MarkerSize',CENTERSIZE,'Visible','off');
else
set(h.ellipse.handler,'Visible','off');
set(h.ellipse.center,'Visible','off');
end
axes(h.aprob);
cla;
axis auto;
h.plot1.handler=plot([0],[0],'b','Parent',h.aprob,...
'EraseMode','background','Visible','off');
h.plot2.handler=plot([0],[0],'r','Parent',h.aprob,...
'EraseMode','background','Visible','off');
set(hfigure,'UserData',h);
axes(h.aset);
if isempty(sets)==0,
set(h.title1,'String',sprintf('Data file: %s, %d vectors',...
file.name,sum(sets.K)));
else
set(h.title1,'String','No data loaded');
pos=get(h.aset,'Position');
fsize=min(pos(3),pos(4))/8;
axis([-1 1 -1 1]);
builtin('text',0,0,'Press ''Load data'' button.',...
'HorizontalAlignment','center',...
'FontUnits','normalized',...
'Clipping','on',...
'FontSize',fsize);
builtin('text',0,-fsize*2,...
'Load sample data from ../toolboxroot/data/mm\_samples/ ',...
'HorizontalAlignment','center',...
'FontUnits','normalized',...
'Clipping','on',...
'FontSize',fsize*0.65);
end
drawnow;
case 'creatdata'
createdata('finite',1,'demo_mmgauss','created',hfigure);
case 'created'
figure(hfigure);
h=get(hfigure,'UserData');
path=varargin{1};
name=varargin{2};
pathname=strcat(path,name);
if check2ddata(pathname),
file.pathname=pathname;
file.path=path;
file.name=name;
set(h.btload,'UserData',file);
demo_mmgauss('loadsets',hfigure);
else
errordlg('This file does not contain required data.','Bad file','modal');
end
case 'info'
helpwin(mfilename);
end
function []=clrchild(handle)
delete(get(handle,'Children'));
return;
function [win]=cmpwin(mins,maxs,xborder,yborder)
dx=max( (maxs(1)-mins(1)), 1 )*xborder;
dy=max( (maxs(2)-mins(2)), 1 )*yborder;
x1=(mins(1)-dx);
x2=(maxs(1)+dx);
y1=(mins(2)-dy);
y2=(maxs(2)+dx);
win=[x1 x2 y1 y2];
return;
function []=setaxis(handle,rect)
set(handle,'XLim',rect(1:2));
set(handle,'YLim',rect(3:4));
if size(rect,2)>=6,
set(handle,'ZLim',rect(5:6));
end
return;