annotate notes/hnmf.m @ 116:91bb029a847a timing

Reorder the calculations to match the series of vector operations in the most recent bqvec code, just in case it's the order of vector calculations that is saving the time rather than the avoidance of std::vector
author Chris Cannam
date Wed, 07 May 2014 09:57:19 +0100
parents f1f8c84339d0
children
rev   line source
Chris@16 1 function [w,h,z,xa] = hnmf( x, K, R, iter, sh, sz, w, h, pl, lh, lz)
Chris@16 2 % function [w,h,z,xa] = hnmf( x, K, R, iter, sh, sz, w, h, pl, lh, lz)
Chris@16 3 %
Chris@16 4 % Perform Multi-source NMF
Chris@16 5 %
Chris@16 6 % Inputs:
Chris@16 7 % x input distribution
Chris@16 8 % K number of components
Chris@16 9 % R number of sources
Chris@16 10 % iter number of EM iterations [default = 100]
Chris@16 11 % sh sparsity of h
Chris@16 12 % sz sparsity of z
Chris@16 13 % w initial value of w
Chris@16 14 % h initial value of h
Chris@16 15 % pl plot flag
Chris@16 16 % lh update h flag
Chris@16 17 % lz update z flag
Chris@16 18 %
Chris@16 19 % Outputs:
Chris@16 20 % w spectral bases
Chris@16 21 % h component activation
Chris@16 22 % z source activation per component
Chris@16 23 % xa approximation of input
Chris@16 24 %
Chris@16 25 % Emmanouil Benetos 2011
Chris@16 26
Chris@16 27
Chris@16 28 % Get sizes
Chris@16 29 [M,N] = size( x);
Chris@16 30 sumx = sum(x);
Chris@16 31
Chris@16 32 % Default training iterations
Chris@16 33 if ~exist( 'iter')
Chris@16 34 iter = 100;
Chris@16 35 end
Chris@16 36
Chris@16 37 % Default plot flag
Chris@16 38 if ~exist( 'pl')
Chris@16 39 pl = 1;
Chris@16 40 end
Chris@16 41
Chris@16 42 % Initialize
Chris@16 43 if ~exist( 'w') || isempty( w)
Chris@16 44 w = rand( M, R, K);
Chris@16 45 end
Chris@16 46 for r=1:R
Chris@16 47 for k=1:K
Chris@16 48 w(:,k,r) = w(:,k,r) ./ sum(w(:,k,r));
Chris@16 49 end;
Chris@16 50 end;
Chris@16 51 if ~exist( 'h') || isempty( h)
Chris@16 52 h = rand( K, N);
Chris@16 53 end
Chris@16 54 n=1:N;
Chris@16 55 h(:,n) = repmat(sumx(n),K,1) .* (h(:,n) ./ repmat( sum( h(:,n), 1), K, 1));
Chris@16 56 if ~exist( 'z') || isempty( z)
Chris@16 57 z = rand( R, K, N);
Chris@16 58 end
Chris@16 59 for k=1:K
Chris@16 60 for n=1:N
Chris@16 61 z(:,k,n) = z(:,k,n) ./ sum(z(:,k,n));
Chris@16 62 end;
Chris@16 63 end;
Chris@16 64
Chris@16 65
Chris@16 66
Chris@16 67 % Iterate
Chris@16 68 for it = 1:iter
Chris@16 69
Chris@16 70 % E-step
Chris@19 71 zh = z .* permute(repmat(h,[1 1 R]),[3 1 2]); %% z is the source activation distribution, h the component (pitch) activation
Chris@16 72 xa=eps;
Chris@16 73 for r=1:R
Chris@16 74 for k=1:K
Chris@16 75 xa = xa + w(:,k,r) * squeeze(zh(r,k,:))';
Chris@16 76 end;
Chris@16 77 end;
Chris@16 78 Q = x ./ xa;
Chris@16 79
Chris@16 80 % M-step (update h,z)
Chris@16 81 if (lh && lz)
Chris@16 82 nh=zeros(K,N);
Chris@16 83 for k=1:K
Chris@16 84 for r=1:R
Chris@16 85 nh(k,:) = nh(k,:) + squeeze(z(r,k,:))' .* (squeeze(w(:,k,r))' * Q);
Chris@16 86 nz = h(k,:) .* (squeeze(w(:,k,r))' * Q);
Chris@16 87 nz = nz .* squeeze(z(r,k,:))';
Chris@16 88 z(r,k,:) = nz;
Chris@16 89 end;
Chris@16 90 end;
Chris@16 91 nh = h .* nh;
Chris@16 92 end
Chris@16 93
Chris@16 94
Chris@16 95 % Assign and normalize
Chris@16 96 k=1:K;
Chris@16 97 n=1:N;
Chris@16 98 if lh
Chris@16 99 nh = nh.^sh;
Chris@16 100 h(:,n) = repmat(sumx(n),K,1) .* (nh(:,n) ./ repmat( sum( nh(:,n), 1), K, 1));
Chris@16 101 end
Chris@16 102 if lz
Chris@16 103 z = z.^sz;
Chris@16 104 z(:,k,n) = z(:,k,n) ./ repmat( sum( z(:,k,n), 1), R, 1);
Chris@16 105 end
Chris@16 106
Chris@16 107 end
Chris@16 108
Chris@16 109 % Show me
Chris@16 110 if pl
Chris@16 111 subplot(3, 1, 1), imagesc(x), axis xy
Chris@16 112 subplot(3, 1, 2), imagesc(xa), axis xy
Chris@16 113 subplot(3, 1, 3), imagesc(h), axis xy
Chris@16 114 end