Contents

gmixcv.m

From A First Course in Machine Learning, Chapter 6. Simon Rogers, 01/11/11 [simon.rogers@glasgow.ac.uk] Fitting a Gaussian mixture

clear all;close all;
path(path,'../utilities');

Load the data

load ../data/kmeansdata

Plot the data

figure(1);hold off
plot(X(:,1),X(:,2),'ko');

Do a 10-fold CV

NFold = 10;
N = size(X,1);
sizes = repmat(floor(N/NFold),1,NFold);
sizes(end) = sizes(end) + N - sum(sizes);
csizes = [0 cumsum(sizes)];
order = randperm(N); % Randomise the data order
MaxIts = 100;

Loop over K

Kvals = 1:10;
for kv = 1:length(Kvals)
    K = Kvals(kv);
    for fold = 1:NFold
        fprintf('\nK: %g, fold: %g',K,fold);
        foldindex = order(csizes(fold)+1:csizes(fold+1));
        trainX = X;
        trainX(foldindex,:) = [];
        testX = X(foldindex,:);

        % Train the mixture
        means = randn(K,2);
        for k = 1:K
            covs(:,:,k) = rand*eye(2);
        end
        priors = repmat(1/K,1,K);
        B = [];
        B(1) = -inf;
        converged = 0;
        it = 0;
        tol = 1e-2;
        Ntrain = size(trainX,1);
        D = size(X,2);
        while 1
            it = it + 1;
            % Update q
            temp = zeros(Ntrain,K);
            for k = 1:K
                const = -(D/2)*log(2*pi) - 0.5*log(det(covs(:,:,k)));
                Xm = trainX - repmat(means(k,:),Ntrain,1);
                temp(:,k) = const - 0.5 * diag(Xm*inv(covs(:,:,k))*Xm');
            end

            % Compute the Bound on the likelihood
            if it>1
                B(it) = sum(sum(q.*log(repmat(priors,Ntrain,1)))) + ...
                    sum(sum(q.*temp)) - ...
                    sum(sum(q.*log(q)));
                if abs(B(it)-B(it-1))<tol
                    converged = 1;

                end
            end

            if converged == 1 || it>MaxIts
                break
            end

            temp = temp + repmat(priors,Ntrain,1);

            q = exp(temp - repmat(max(temp,[],2),1,K));
            % Minor hack for numerical issues - stops the code crashing when
            % clusters are empty
            q(q<1e-3) = 1e-3;
            q(q>1-1e-3) = 1-1e-3;
            q = q./repmat(sum(q,2),1,K);
            % Update priors
            priors = mean(q,1);
            % Update means
            for k = 1:K
                means(k,:) = sum(trainX.*repmat(q(:,k),1,D),1)./sum(q(:,k));
            end
            % update covariances
            for k = 1:K
                Xm = trainX - repmat(means(k,:),Ntrain,1);
                covs(:,:,k) = (Xm.*repmat(q(:,k),1,D))'*Xm;
                covs(:,:,k) = covs(:,:,k)./sum(q(:,k));
            end


        end



        % Compute the held-out likelihood
        Ntest = size(testX,1);
        temp = zeros(Ntest,K);
        for k = 1:K
            const = -(D/2)*log(2*pi) - 0.5*log(det(covs(:,:,k)));
                Xm = testX - repmat(means(k,:),Ntest,1);
                temp(:,k) = const - 0.5 * diag(Xm*inv(covs(:,:,k))*Xm');

        end
        temp = exp(temp).*repmat(priors,Ntest,1);
        outlike(kv,csizes(fold)+1:csizes(fold+1)) = log(sum(temp,2))';


    end
end
K: 1, fold: 1
K: 1, fold: 2
K: 1, fold: 3
K: 1, fold: 4
K: 1, fold: 5
K: 1, fold: 6
K: 1, fold: 7
K: 1, fold: 8
K: 1, fold: 9
K: 1, fold: 10
K: 2, fold: 1
K: 2, fold: 2
K: 2, fold: 3
K: 2, fold: 4
K: 2, fold: 5
K: 2, fold: 6
K: 2, fold: 7
K: 2, fold: 8
K: 2, fold: 9
K: 2, fold: 10
K: 3, fold: 1
K: 3, fold: 2
K: 3, fold: 3
K: 3, fold: 4
K: 3, fold: 5
K: 3, fold: 6
K: 3, fold: 7
K: 3, fold: 8
K: 3, fold: 9
K: 3, fold: 10
K: 4, fold: 1
K: 4, fold: 2
K: 4, fold: 3
K: 4, fold: 4
K: 4, fold: 5
K: 4, fold: 6
K: 4, fold: 7
K: 4, fold: 8
K: 4, fold: 9
K: 4, fold: 10
K: 5, fold: 1
K: 5, fold: 2
K: 5, fold: 3
K: 5, fold: 4
K: 5, fold: 5
K: 5, fold: 6
K: 5, fold: 7
K: 5, fold: 8
K: 5, fold: 9
K: 5, fold: 10
K: 6, fold: 1
K: 6, fold: 2
K: 6, fold: 3
K: 6, fold: 4
K: 6, fold: 5
K: 6, fold: 6
K: 6, fold: 7
K: 6, fold: 8
K: 6, fold: 9
K: 6, fold: 10
K: 7, fold: 1
K: 7, fold: 2
K: 7, fold: 3
K: 7, fold: 4
K: 7, fold: 5
K: 7, fold: 6
K: 7, fold: 7
K: 7, fold: 8
K: 7, fold: 9
K: 7, fold: 10
K: 8, fold: 1
K: 8, fold: 2
K: 8, fold: 3
K: 8, fold: 4
K: 8, fold: 5
K: 8, fold: 6
K: 8, fold: 7
K: 8, fold: 8
K: 8, fold: 9
K: 8, fold: 10
K: 9, fold: 1
K: 9, fold: 2
K: 9, fold: 3
K: 9, fold: 4
K: 9, fold: 5
K: 9, fold: 6
K: 9, fold: 7
K: 9, fold: 8
K: 9, fold: 9
K: 9, fold: 10
K: 10, fold: 1
K: 10, fold: 2
K: 10, fold: 3
K: 10, fold: 4
K: 10, fold: 5
K: 10, fold: 6
K: 10, fold: 7
K: 10, fold: 8
K: 10, fold: 9
K: 10, fold: 10

Plot the evolution in log likelihood

errorbar(Kvals,mean(outlike,2),std(outlike,1,2)./sqrt(N));
xlabel('K');
ylabel('Average held-out likelidood (+- standard error)');