changeset 11:0e0f2805ef9c

Added new mechanism for checking Markov chains for uniqueness of stationary distribution; new supporting files and new parameters to mt_init (see CHANGES). Some functions require greater Matlab library, not included.
author samer
date Sun, 26 Feb 2012 23:11:10 +0000
parents bce0bd672b47
children e9b425233168
files CHANGES mt_init.m mt_resample.m mt_show_transmat.m private/addkbcallback.m private/mc_fixpt.m private/mc_global_info.m private/mc_global_info1.m private/randnat.m private/sample_transmat_hdp.m
diffstat 10 files changed, 235 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CHANGES	Sun Feb 26 23:11:10 2012 +0000
@@ -0,0 +1,17 @@
+Changed transition matrix sampling procedure to try to avoid Markov chains
+with mupltiple stationary distributions (fixed points).
+To this end:
+* mc_fixpt has a tolerance parameter - all eigenvalues within this much of
+  1 are considered fixed points.
+* mc_global_info1 (replaces mc_global_info) now checks that transition matrix
+  has only one fixed point and returns a flag if this is the case
+* sampling logic is in mt_resample - transition matrices not passing uniqueness
+  test are either resampled (method 1) or perturbed (method 2)
+* mt_init has new parameters, ErgMethod to select conditioning method and
+  tolerance to pass to mc_fixpt.
+
+
+Other changes 
+* Information measures are now displayed in bits, not nats.
+* Clicking on the title bar of a displayed transition matrix now displays
+  information about its eigenvalues and eigenvectors (mt_show_transmat.m).
--- a/mt_init.m	Wed Feb 22 21:24:44 2012 +0000
+++ b/mt_init.m	Sun Feb 26 23:11:10 2012 +0000
@@ -18,12 +18,19 @@
 %
 % The figure for scatter plots is fixed to figure 50 for now.
 
-function Sys=mt_init(A0,B0,A1,B1,L,Shuffle)
-	Sys.sample_transmats = @(k)sample_transmat_hdp(A0,B0,A1,B1,k,L);
+function Sys=mt_init(A0,B0,A1,B1,L,Shuffle,ErgMethod,Tol)
+	if nargin<7, ErgMethod=1; end
+	if nargin<6, Shuffle=0; end
+	if nargin<8, Tol=0.001; end
+	Sys.sample_transmats = @(k,l)sample_transmat_hdp(A0,B0,A1,B1,k,l);
 	Sys.transmats = {};
 	Sys.info      = {};
 	Sys.refpoints = [0,0;1,0;0,1]';
 	Sys.fig       = 50;
 	Sys.shuffle   = Shuffle;
+	Sys.ergmeth   = ErgMethod;
+	Sys.L         = L;
+	Sys.tol       = Tol;
 	Sys = mt_calibrate(Sys);
 end
+
--- a/mt_resample.m	Wed Feb 22 21:24:44 2012 +0000
+++ b/mt_resample.m	Sun Feb 26 23:11:10 2012 +0000
@@ -10,11 +10,42 @@
 % mt_init.
 
 function Sys=mt_resample(Sys,K)
-	[TT, II] = Sys.sample_transmats(K);
-	figure(Sys.fig); % 'name','info space'); 
+	figure(Sys.fig); 
+	cla;
+
+
+	L=Sys.L;
+	tol=Sys.tol;
+	II=zeros(L,3);
+	ok=zeros(1,L);
+
+	title(sprintf('sampling %d transition matrices...',L)); drawnow;
+	TT=Sys.sample_transmats(K,L);
+	title(sprintf('checking (tolerance=%f)...',tol)); drawnow;
+	for i=1:L, [II(i,:),ok(i)]=mc_global_info(TT(:,:,i)); end
+	todo=find(~ok);
+
+	if Sys.ergmeth==1
+		while ~isempty(todo)
+			title(sprintf('resampling %d nonergodic transition matrices...',length(todo)));
+			drawnow;
+			TT(:,:,todo)=Sys.sample_transmats(K,length(todo));
+			for i=todo, [II(i,:),ok(i)]=mc_global_info1(TT(:,:,i),tol); end
+			todo=find(~ok);
+		end
+	else
+		while ~isempty(todo)
+			title(sprintf('perturbing %d nonergodic transition matrices...',length(todo)));
+			drawnow;
+			for i=todo, j=randnat(K); TT(:,j,i)=stoch(TT(:,j,i)+0.1); end
+			for i=todo, [II(i,:),ok(i)]=mc_global_info1(TT(:,:,i),tol); end
+			todo=find(~ok);
+		end
+	end
+
 	Sys.transmats{K} = TT;
 	Sys.info{K}      = II;
-	Sys.hScat{K}     = scatc(II,II(:,3),16); 
+	Sys.hScat{K}     = scatc(II/log(2),II(:,3)/log(2),16); 
 	axis on; box on; grid off; 
 	lc=[0.4,0.4,0.4];
 	set(gca,'Color','none');
@@ -26,3 +57,7 @@
 	zlabel('pred-info rate');
 	rotate3d on;
 end
+
+
+
+
--- a/mt_show_transmat.m	Wed Feb 22 21:24:44 2012 +0000
+++ b/mt_show_transmat.m	Sun Feb 26 23:11:10 2012 +0000
@@ -4,11 +4,27 @@
 %    natural ~'voice id'
 %    [[K,K]] ~'transition matrix'
 % -> action void.
+%
+% Also displays global information measures in bits in the title.
 
 function mt_show_transmat(Id,T,I)
 	figure(Id); 
 	imagesc(T,[0,1]); 
 	axis xy;
 	if nargin<3, I=mc_global_info(T); end
-	title(sprintf('H=%.2f, R=%.2f, PI=%.2f',I(1),I(2),I(3)));
+	I=I/log(2); % convert to bits
+	htit=title(sprintf('H=%.2f, R=%.2f, PI=%.2f',I(1),I(2),I(3)));
+	addkbcallback(gcf);
+	addkbcallback(gcf,@(k)show_eigs(Id,T));
+	set(htit,'ButtonDownFcn',@(a,b)show_eigs(Id,T));
 end
+
+function show_eigs(Id,T) 
+	figure(40);
+	[V,D]=eig(T); d=diag(D);
+	k=find(abs(d-1)<0.001);
+	subplot(3,1,1); plot_cvec(diag(D)); 
+	title(sprintf('%d: eigenvalues %s',Id,mat2str(d(k))));
+	subplot(3,1,2); plot_cvec(sum(V)); title('sum eigenvectors');%ylim([-1,1]);
+	subplot(3,1,3); plotseq(@plot_cvec,window(V)); title('eigenvector');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/private/addkbcallback.m	Sun Feb 26 23:11:10 2012 +0000
@@ -0,0 +1,19 @@
+function addkbcallback(fig,handler)
+% addkbcallback - Add keypress handler to figure or remove all handlers
+
+	if nargin>1,
+		cb=get(fig,'KeypressFcn');
+		if isempty(cb)
+			set(fig,'KeypressFcn',{@kpcb,{handler}});
+		else
+			set(fig,'KeypressFcn',{cb{1},[cb{2},{handler}]});
+		end
+	else
+		set(fig,'KeypressFcn',[]);
+	end
+end
+
+function kpcb(a,b,handlers), 
+	for i=1:length(handlers), h=handlers{i}; h(b); end; 
+end
+
--- a/private/mc_fixpt.m	Wed Feb 22 21:24:44 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-function p=mc_fixpt(Pt)
-% mc_fixpt - fixed point of Markov chain (stationary state distribution)
-%
-% mc_fixpt :: [[K,K]]~'transition matrix'-> [[K]].
-
-
-% for ergodic HMM we want to get stationary distribution 
-% use eigenvalues of transition matrix.
-[V,D]=eig(Pt);
-
-% one of the eigenvalues should be 1
-[dummy,k]=max(-abs(diag(D)-1));
-
-% check that it is really close
-if abs(D(k,k)-1)>0.001
-	disp('mc_fixpt: failed to find eigenvalue of 1 in ');
-	disp(Pt)
-	error('mc_fixpt:noeig','failed to find eigenvalue of 1');
-end
-
-% get eigenvector and flip it over if all negative
-v=V(:,k); if sum(v)<0, v=-v; end
-
-if ~isreal(v)
-	disp('mc_fixpt: discarding complex parts of eigenvector'); 
-	v=real(v);
-end
-if any(v<0)
-	%fprintf('mc_fixpt: discarding negative parts of eigenvector: %s\n',mat2str(v(v<0))); 
-	v=max(0,v);
-end
-
-% final normalisation
-p=v/sum(v);
--- a/private/mc_global_info.m	Wed Feb 22 21:24:44 2012 +0000
+++ b/private/mc_global_info.m	Sun Feb 26 23:11:10 2012 +0000
@@ -1,4 +1,4 @@
-function Info=mc_global_info(T,pz)
+function [Info,ergodic]=mc_global_info(T,pz)
 % mc_global_info - Three global information measures about stationary MC
 %
 % mc_global_info :: [[N,N]] ~'transmat' -> [[3]].
@@ -6,7 +6,7 @@
 % mc_global_info :: 
 %    [[N,N]] ~'transmat',
 %    [[N]] ~'stationary distribution if already known'
-% -> [[3]].
+% -> [[3]],bool.
 %
 % The three measures in order are
 %    Entropy rate H(X|Z)
@@ -16,34 +16,42 @@
 
 
 n=size(T,1);
-if nargin<2, pz=mc_fixpt(T); end
-TlogT=T.*slog(T);
-HXZ=-sum(TlogT,1)*pz;
+if nargin<2, pz=mc_fixpt(T,0.001); end
 
-pxz=T; % p(x|z)
-pyxz=repmat(T,[1,1,n]).*repmat(shiftdim(T,-1),[n,1,1]); % p(y,x|z)
-pyz=sum(pyxz,2); % p(y|z)
-pyz(pyz==0)=realmin;
-pxyz=permute(pyxz./repmat(pyz,[1,n,1]),[2,1,3]); % p(x|y,z)
+ergodic=(size(pz,2)==1);
+if ergodic && all(isfinite(pz))
 
-HXYz=-shiftdim(sum(sum(permute(pyxz,[2,1,3]).*slog(pxyz),1),2),2); % H(X|Y,z)
-IXYZ=(-HXYz' - sum(pxz.*slog(pxz)))*pz;
+	TlogT=T.*slog(T);
+	HXZ=-sum(TlogT,1)*pz;
 
-IXZ=max(0,(sum(TlogT)-slog(pz)')*pz); 
+	pxz=T; % p(x|z)
+	pyxz=repmat(T,[1,1,n]).*repmat(shiftdim(T,-1),[n,1,1]); % p(y,x|z)
+	pyz=sum(pyxz,2); % p(y|z)
+	pyz(pyz==0)=realmin;
+	pxyz=permute(pyxz./repmat(pyz,[1,n,1]),[2,1,3]); % p(x|y,z)
 
+	HXYz=-shiftdim(sum(sum(permute(pyxz,[2,1,3]).*slog(pxyz),1),2),2); % H(X|Y,z)
+	IXYZ=(-HXYz' - sum(pxz.*slog(pxz)))*pz;
 
-Info=[HXZ;IXZ;IXYZ];
-if any(~isreal(Info))
-	disp('unreal information');
-	keyboard
-elseif any(Info<0)
-	if any(Info<-eps)
-		disp('negative information');
-		disp(Info);
-		keyboard
-	else
-		Info=max(0,Info);
+	IXZ=max(0,(sum(TlogT)-slog(pz)')*pz); 
+
+
+	Info=[HXZ;IXZ;IXYZ];
+	if any(~isreal(Info))
+		disp('unreal information');
+		ergodic=0;
+	elseif any(Info<0)
+		if any(Info<-eps)
+			disp('negative information');
+			disp(pz');
+			disp(Info');
+			ergodic=0;
+		else
+			Info=max(0,Info);
+		end
 	end
+else
+	Info=[0;0;0];
 end
 
 function y=slog(x)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/private/mc_global_info1.m	Sun Feb 26 23:11:10 2012 +0000
@@ -0,0 +1,82 @@
+function [Info,ergodic]=mc_global_info1(T,tol)
+% mc_global_info1 - Three global information measures about stationary MC
+%
+% mc_global_info1 :: 
+%    [[N,N]] ~'transmat',
+%    nonneg  ~'tolerance for fixed point check'
+% -> [[3]],bool.
+%
+% The three measures in order are
+%    Entropy rate H(X|Z)
+%    Redundancy I(X,Z)
+%    Predictive information rate I(X,Y|Z)
+% All in NATS, not bits.
+
+
+n=size(T,1);
+pz=mc_fixpt(T,tol); 
+ergodic=(size(pz,2)==1);
+if ergodic && all(isfinite(pz))
+
+	TlogT=T.*slog(T);
+	HXZ=-sum(TlogT,1)*pz;
+
+	pxz=T; % p(x|z)
+	pyxz=repmat(T,[1,1,n]).*repmat(shiftdim(T,-1),[n,1,1]); % p(y,x|z)
+	pyz=sum(pyxz,2); % p(y|z)
+	pyz(pyz==0)=realmin;
+	pxyz=permute(pyxz./repmat(pyz,[1,n,1]),[2,1,3]); % p(x|y,z)
+
+	HXYz=-shiftdim(sum(sum(permute(pyxz,[2,1,3]).*slog(pxyz),1),2),2); % H(X|Y,z)
+	IXYZ=(-HXYz' - sum(pxz.*slog(pxz)))*pz;
+
+	IXZ=max(0,(sum(TlogT)-slog(pz)')*pz); 
+
+
+	Info=[HXZ;IXZ;IXYZ];
+	if any(~isreal(Info))
+		disp('unreal information');
+		ergodic=0;
+	elseif any(Info<0)
+		if any(Info<-eps)
+			disp('negative information');
+			disp(pz');
+			disp(Info');
+			ergodic=0;
+		else
+			Info=max(0,Info);
+		end
+	end
+else
+	Info=[0;0;0];
+end
+
+function y=slog(x)
+% slog - safe log, x<=0 => slog(x)=0
+%
+% slog :: real -> real.
+
+	x(x<=0)=1;
+	y=log(x);
+
+% mc_fixpt - fixed point(s) of Markov chain (stationary state distribution)
+%
+% mc_fixpt :: [[K,K]]~'transition matrix'-> [[K,L]].
+function p=mc_fixpt(Pt,tol)
+	% use eigenvalues of transition matrix.
+	[V,D]=eig(Pt);
+
+	% find eigenvalues near 1 to within tolerance
+	k=find(abs(diag(D)-1)<tol);
+	
+	Vk=V(:,k);
+	%sumk=sum(V(:,k));
+	%Vk=V(:,k)*diag(1./sumk); % normalise to unit sum
+	%poss=abs(sumk)>0; % find those with non-zero sum
+	%Vk=V(:,k(poss))*diag(1./sumk(poss)); % normalise to unit sum
+	%p=Vk(:,all(Vk >= -eps)); % eigs with all positive components to within eps.
+
+	%p=max(0,real(Vk*diag(1./sum(Vk))));
+	p=real(Vk*diag(1./sum(Vk)));
+	p(abs(p)<tol/10)=0;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/private/randnat.m	Sun Feb 26 23:11:10 2012 +0000
@@ -0,0 +1,18 @@
+function X=randnat(M,varargin)
+% randnat - Draw Random natural numbers from uniform distribution
+%
+% randnat :: 
+%    M:natural   ~'maximum value', 
+%    D:[[1,E]]   ~'size of E-dimensional array'
+% -> [[D]->[M]] ~'size D array of numbers in 1..M'.
+%
+% The size is specified as in the RAND function, except that if
+% only one dimension is given, we create a vector, not a square
+% matrix, eg
+%
+% randnat(10,3) :: [[3,3]->[10]].
+% randnat(20,2,5,7) :: [[2,5,7]->[20]].
+% randnat(20,5) :: [[5,1]->[20]].
+
+X=1+floor(M*rand(tosize(varargin{:})));
+
--- a/private/sample_transmat_hdp.m	Wed Feb 22 21:24:44 2012 +0000
+++ b/private/sample_transmat_hdp.m	Sun Feb 26 23:11:10 2012 +0000
@@ -1,4 +1,4 @@
-function [T,I]=sample_transmat_hdp(A0,B0,A1,B1,K,L,T0)
+function T=sample_transmat_hdp(A0,B0,A1,B1,K,L,T0)
 % sample_transmat_hdp - Sample 1st order Markov transition matrix using HDP
 %
 % sample_transmat_hdp ::
@@ -8,8 +8,7 @@
 %    nonneg ~'Scale parameter for sub Dirichlet Gamma prior',
 %    natural ~'size of alphabet',
 %    natural ~'num of transition matrices to produce',
-% -> [[K,K,L]] ~ 'lots of transition matrices',
-%    [[L,3]]   ~ 'entropy rate, redundancy, and predinfo rate for all'.
+% -> [[K,K,L]] ~ 'lots of transition matrices'.
 %
 % An extra optional argument of type [[K,K]] can be added, which
 % is used as a sort of bias for the sampled matrices.
@@ -26,14 +25,7 @@
 	T=sample_dir(repmat(Alpha1,[K,K,1]).*HT);
 
 	if any(sum(H0)<0.99)
-		disp('normalisation problem in H')
-		keyboard
-	end
-	if nargout>=2
-		I=zeros(K,3);
-		for i=1:L
-			I(i,:)=mc_global_info(T(:,:,i));
-		end
+		error('normalisation problem in H')
 	end
 end