我正在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
我知道如果我可以通过传递一组初始中心来获得确定性行为,因为其中一个函数参数每次都会给我相同的输出聚类,但我不知道如何实现它。
答案 0 :(得分:0)
不要选择k
个随机群集中心来启动(代码中为I=randperm(N); M=X(I(1:K),:);
),只需将群集中心作为输入参数传递给kmeans3
:
function [M,j,e] = kmeans3(X,K,Max_Its,M)
M
为k-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。