实现k-means与MATLAB具有相同的解决方案

时间:2014-03-04 17:30:52

标签: matlab k-means

我正在MATLAB中实现另一个kmeans函数,我想知道是否有任何方法可以使用相同(或稍微不同)的质心解决方案,

我的k-means功能是:

function [M,j,e] = kmeans3(X,K,Max_Its)

[N,D]=size(X);  
I=randperm(N);  
M=X(I(1:K),:);  
Mo = M;         

for n=1:Max_Its
    for k=1:K
        Dist(:,k) = sum((X - repmat(M(k,:),N,1)).^2,2);
    end
    [i,j]=min(Dist,[],2);

    for k=1:K
        if size(find(j==k))>0
            M(k,:) = mean(X(find(j==k),:));
        end
    end
    Z = zeros(N,K);
    for m=1:N
        Z(m,j(m)) = 1;  
    end
    e = sum(sum(Z.*Dist)./N);
    fprintf('%d Error = %f\n', n, e);
    Mo = M;
end

我知道如果我可以通过传递一组初始中心来获得确定性行为,因为其中一个函数参数每次都会给我相同的输出聚类,但我不知道如何实现它。

1 个答案:

答案 0 :(得分:0)

不要选择k个随机群集中心来启动(代码中为I=randperm(N); M=X(I(1:K),:);),只需将群集中心作为输入参数传递给kmeans3

function [M,j,e] = kmeans3(X,K,Max_Its,M)

Mk-by-D


另外,我强烈建议您使用bsxfun对您的实施进行矢量化。请参阅我对问题"optimizing manually-coded k-means in MATLAB"的解决方案。基本上,for n=1:Max_Its循环的内部看起来像:

% Calculate all high-dimensional distances at once
kdiffs = bsxfun(@minus,X,permute(M,[3 2 1])); % NxDx1 - 1xDxK => NxDxK
Dm = sum(kdiffs.^2,2); % no need to do sqrt
Dm = squeeze(Dm); % Nx1xK => NxK

% Find closest cluster center for each point
[~,ik] = min(Dm,[],2); % Nx1

% Calculate the new cluster centers (mean the data)
M_new = zeros(k,D);
for i=1:k,
    indk = ik==i;
    clustersizes(i) = nnz(indk);
    M_new(i,:) = mean(X(indk,:))';
end

M = M_new; % update and iterate

请注意,M_new每个群集都有一行,但如果群集没有成员,则该行将为NaN s。