Mercurial > hg > ltpda
diff m-toolbox/classes/+utils/@math/loglikelihood_ssm.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/+utils/@math/loglikelihood_ssm.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,261 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Compute log-likelihood for SSM objects +% +% M Nofrarias 15-06-09 +% +% $Id: loglikelihood_ssm.m,v 1.3 2011/11/16 08:52:49 nikos Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [loglk snr]= loglikelihood_ssm(xn,in,out,noise,model,params,inNames,outNames, spl, Amats, Bmats, Cmats, Dmats) + + loglk = 0; + snr = 0; + switch class(in) + case 'ao' + % parameters + fs = noise(1).fs; + N = length(noise(1).y); + + if (numel(in) == 1 && numel(out) == 1) + xn = double(xn); + + spl = plist('set', 'for bode', ... + 'outputs', outNames, ... + 'inputs', inNames, ... + 'reorganize', false,... + 'f', in(1).x); + + eval = copy(model,1); + + % set parameter values + eval.doSetParameters(params, xn); + + % make numeric + eval.doSubsParameters(params, true); + + % do bode + h11 = bode(eval, spl, 'internal'); + + f = in.x; + % spectra to variance + C11 = (N*fs/2)*noise(1).y; + + % compute elements of inverse cross-spectrum matrix + InvS11 = 1./C11; + + % compute log-likelihood terms first, all at once does not cancel the + % imag part when multiplying x.*conj(x) + v1v1 = conj(out(1).y - h11.y.*in(1).y).*(out(1).y - h11.y.*in(1).y); + + tmplt = h11.*in(1).y; + + %computing SNR + snrexp = utils.math.stnr(tmplt,0,out(1).y,0,InvS11,0,0,0); + + snr = snr + 20*log10(snrexp); + + log1exp = sum(InvS11.*v1v1); + + loglk = loglk + log1exp; + + elseif (numel(in) == 2 && numel(out) == 2) + + f = in(1).x; + + xn = double(xn); + + spl = plist('set', 'for bode', ... + 'outputs', outNames, ... + 'inputs', inNames, ... + 'reorganize', false,... + 'f', in(1).x); + + eval = copy(model,1); + + % set parameter values + eval.doSetParameters(params, xn); + + % make numeric + eval.doSubsParameters(params); + + % do bode + h = bode(eval, spl, 'internal'); + h11 = h(1); + h12 = h(2); + h21 = h(3); + h22 = h(4); + + % spectra to variance + C11 = (N*fs/2)*noise(1).y; + C22 = (N*fs/2)*noise(2).y; + C12 = (N*fs/2)*noise(3).y; + C21 = (N*fs/2)*noise(4).y; + + % compute elements of inverse cross-spectrum matrix + InvS11 = (C22./(C11.*C22 - C12.*C21)); + InvS22 = (C11./(C11.*C22 - C12.*C21)); + InvS12 = (C21./(C11.*C22 - C12.*C21)); + InvS21 = (C12./(C11.*C22 - C12.*C21)); + + % compute log-likelihood terms first, all at once does not cancel the + % imag part when multiplying x.*conj(x) + v1v1 = conj(out(1).y - h11.y.*in(1).y - h12.y.*in(2).y).*(out(1).y - h11.y.*in(1).y - h12.y.*in(2).y); + v2v2 = conj(out(2).y - h21.y.*in(1).y - h22.y.*in(2).y).*(out(2).y - h21.y.*in(1).y - h22.y.*in(2).y); + v1v2 = conj(out(1).y - h11.y.*in(1).y - h12.y.*in(2).y).*(out(2).y - h21.y.*in(1).y - h22.y.*in(2).y); + v2v1 = conj(out(2).y - h21.y.*in(1).y - h22.y.*in(2).y).*(out(1).y - h11.y.*in(1).y - h12.y.*in(2).y); + + tmplt1 = h11.*in(1).y + h12.*in(2).y; + tmplt2 = h21.*in(1).y + h22.*in(2).y; + + %computing SNR + snrexp = utils.math.stnr(tmplt1,tmplt2,out(1).y,out(2).y,InvS11,InvS22,InvS12,InvS21); + + snr = snr + 20*log10(snrexp); + + log1exp = sum(InvS11.*v1v1 + InvS22.*v2v2 - InvS12.*v1v2 - InvS21.*v2v1); + + loglk = loglk + log1exp; + + else + error('This method is only implemented for 1 input / 1 output model or for 2 inputs / 2 outputs models'); + end + + case 'matrix' + % parameters + + fs = in(1).objs(1).fs; + + % num. experiments + nexp = numel(in); + + noutChannels = numel(out(1).objs); + + N = length(noise(1).objs(1).y); + + loglk = 0; + for nnn = 1:nexp + + if ((numel(in(1).objs) == 1) && numel(out(1).objs) == 1) + + freqs = in(nnn).objs(1).data.getX; + + xn = double(xn); + + spl = plist('set', 'for bode', ... + 'outputs', outNames, ... + 'inputs', inNames, ... + 'reorganize', false,... + 'f', freqs); + + + eval = copy(model(nnn),1); + + % set parameter values + eval.doSetParameters(params, xn); + + % make numeric + eval.doSubsParameters(params, true); + + % do bode + h(:,1) = bode(eval, spl, 'internal'); + + for j = 1:noutChannels^2 + % spectra to variance + % (N*fs/2)* this multiplication is done now in mcmc + C(:,j) = noise(nnn).objs(j).data.getY; + end + + % compute elements of inverse cross-spectrum matrix + InvS11 = 1./C(:,1); + + + % compute log-likelihood terms first, all at once does not cancel the + % imag part when multiplying x.*conj(x) + in1 = in(nnn).objs(1).data.getY; + out1 = out(nnn).objs(1).data.getY; + + % matrix index convention: H(1,1)->h(1) H(2,1)->h(2) H(1,2)->h(3) H(2,2)->h(4) + v1v1 = conj(out1 - h.getObjectAtIndex(1,1).y.*in1).*(out1 - h.getObjectAtIndex(1,1).y.*in1); + + tmplt = h.getObjectAtIndex(1,1).y.*in1; + + %computing SNR + snrexp = utils.math.stnr(tmplt,0,out1,0,InvS11,0,0,0); + + snr = snr + 20*log10(snrexp); + + log1exp = sum(InvS11.*v1v1); + + loglk = loglk + log1exp; + + elseif ((numel(in(1).objs) == 2) && numel(out(1).objs) == 2) + + freqs = in(nnn).objs(1).data.getX; + + xn = double(xn); + + spl.pset('f', freqs); + + eval = model(nnn); + eval.setA(Amats); + eval.setB(Bmats); + eval.setC(Cmats); + eval.setD(Dmats); + + % set parameter values + eval.doSetParameters(params, xn); + + % make numeric + eval.doSubsParameters(params, true); + + % do bode + [h1 h2 h3 h4] = bode(eval, spl); + + for j = 1:noutChannels^2 + % spectra to variance + % (N*fs/2)* this multiplication is done now in mcmc + C(:,j) = noise(nnn).objs(j).data.getY; + end + + % compute elements of inverse cross-spectrum matrix + detm = (C(:,1).*C(:,4) - C(:,2).*C(:,3)); + InvS11 = C(:,4)./detm; %1 4 + InvS22 = C(:,1)./detm; %4 1 + InvS12 = C(:,2)./detm; %2 2 + InvS21 = C(:,3)./detm; %3 3 + + % compute log-likelihood terms first, all at once does not cancel the + % imag part when multiplying x.*conj(x) + in1 = in(nnn).objs(1).data.getY; + in2 = in(nnn).objs(2).data.getY; + out1 = out(nnn).objs(1).data.getY; + out2 = out(nnn).objs(2).data.getY; + + % matrix index convention: H(1,1)->h(1) H(2,1)->h(2) H(1,2)->h(3) H(2,2)->h(4) + v1v1 = conj(out1 - h1.*in1 - h3.*in2).*(out1 - h1.*in1 - h3.*in2); + v2v2 = conj(out2 - h2.*in1 - h4.*in2).*(out2 - h2.*in1 - h4.*in2); + v1v2 = conj(out1 - h1.*in1 - h3.*in2).*(out2 - h2.*in1 - h4.*in2); + v2v1 = conj(out2 - h2.*in1 - h4.*in2).*(out1 - h1.*in1 - h3.*in2); + + tmplt1 = h1.*in1 + h3.*in2; + tmplt2 = h2.*in1 + h4.*in2; + + %computing SNR + snrexp = utils.math.stnr(tmplt1,tmplt2,out1,out2,InvS11,InvS22,InvS12,InvS21); + + snr = snr + 20*log10(snrexp); + + log1exp = sum(InvS11.*v1v1 + InvS22.*v2v2 - InvS12.*v1v2 - InvS21.*v2v1); + + loglk = loglk + log1exp; + else + error('This method is only implemented for 1 input / 1 output model or for 2 inputs / 2 outputs models'); + end + + + + end + end +end +