This question was migrated from Cross Validated because it can be answered on Stack Overflow. Migrated两年前Learn more
我刚刚开始学习编码,并开始尝试编写标准的k-means算法我在一个由三个不同高斯函数生成的数据集上尝试了我的实现,它看起来工作得很好。不过,我在iris数据集上尝试过,而且时不时(大约三分之一的时间)我的函数只返回两个集,换句话说,它只返回两个集群。
我浏览了一下本地matlab kmeans函数的代码,但由于缺乏编码知识,我最终迷失了方向。我非常感谢你的帮助!

function [R,C,P,it] = mykmeans(X,K)
% X -- data matrix
% K -- number of clusters
% C -- partition sets
% P -- matrix of prototypes
% R -- binary indicator matrix: R(i,j) specifies whether the ith data is
% classified into jth cluster
% it -- number of iterations until convergence

% N points with M dimensions
[N,M] = size(X) ;

%% Initialisation

% At this step we randomly partition the data matrix into K equally sized
% matrices and compute the centre of each of these matrices.
% I -- randomised index vector
% v -- number of data points assigned to each cluster
% U -- randomly partitioned matrices

v = N/K ;
C = cell(K,1) ;
U = cell(K,1) ;
I = randperm(N) ;
oldR = zeros(N,K) ;

% C{1} = X(I(1:v),:) ;
% U{1} = mean(X(I(1:v),:)) ;
for k=1:K
    C{k} = X(I(1+v*(k-1):k*v),:) ;
    U{k} = mean(C{k}) ;
end

P = cell2mat(U) ;

converged = 0 ;
it = 0 ;
while converged ~= 1

    %% Assignment step

    % Each element of D{n} contains squared euclidean distance of nth data
    % point from the kth prototype
    D = cell(N,1) ;
    R = zeros(N,K) ;
    for n=1:N
        D{n} = sum((repmat(X(n,:),K,1) - P).^2,2) ;
        [~,k] = min(D{n}) ;
        R(n,k) = 1 ;
    end

    %% Update step

    C = cell(K,1) ; % reset C
    for k=1:K
        for n=1:N
            P(k,:) = R(n,k)*X(n,:) + P(k,:) ; % compute numerator of mean vector
            if R(n,k) == 1
                C{k} = [C{k};X(n,:)] ;
            end
        end
    end

    P = P ./ (sum(R)') ; % divide by denominator of mean vectors to get prototypes

%% Check for convergence

    if sum(sum(R == oldR))==N*K || it == 100 % convergence criteria
        converged = 1 ;
    else
        oldR = R ;
        it = it+1 ;
    end
end %while

最佳答案

这个问题看起来确实不是编码问题,而是理解k-均值的问题。
事实上,在k-means过程中,簇可能变空您需要在代码中对此进行说明,否则结果中的集群数可能小于k。
一个可能的解决办法是:
为空集群分配一个随机数据点作为新的集群中心
选择离最大集群最远的点作为空集群的新集群中心
因此,一般做法如下:
初始化k个簇中心(例如:random)
将所有数据点分配到最近的群集中心
基于赋值重新计算簇中心
检查空群集
重复步骤2-4直到收敛(=上一次迭代中簇中心没有改变)
空簇问题的一个很好的例子可以找到here

09-11 17:56