K 表示当肘部图是平滑曲线时找到肘部

Posted

技术标签:

【中文标题】K 表示当肘部图是平滑曲线时找到肘部【英文标题】:K means finding elbow when the elbow plot is a smooth curve 【发布时间】:2012-06-12 21:33:56 【问题描述】:

我正在尝试使用以下代码绘制 k 的肘部:

load CSDmat %mydata
for k = 2:20
    opts = statset('MaxIter', 500, 'Display', 'off');
    [IDX1,C1,sumd1,D1] = kmeans(CSDmat,k,'Replicates',5,'options',opts,'distance','correlation');% kmeans matlab
    [yy,ii] = min(D1');      %% assign points to nearest center

    distort = 0;
    distort_across = 0;
    clear clusts;
    for nn=1:k
        I = find(ii==nn);       %% indices of points in cluster nn
        J = find(ii~=nn);       %% indices of points not in cluster nn
        clustsnn = I;         %% save into clusts cell array
        if (length(I)>0)
            mu(nn,:) = mean(CSDmat(I,:));               %% update mean
            %% Compute within class distortion
            muB = repmat(mu(nn,:),length(I),1);
            distort = distort+sum(sum((CSDmat(I,:)-muB).^2));
            %% Compute across class distortion
            muB = repmat(mu(nn,:),length(J),1);
            distort_across = distort_across + sum(sum((CSDmat(J,:)-muB).^2));
        end
    end
    %% Set distortion as the ratio between the within
    %% class scatter and the across class scatter
    distort = distort/(distort_across+eps);

        bestD(k)=distort;
        bestC=clusts;
end
figure; plot(bestD);

bestD的值(簇内方差/簇间方差)为

[
0.401970132754914
0.193697163350293
0.119427184084282
0.0872681777446508
0.0687948264457301
0.0566215549396577
0.0481117619129058
0.0420491551659459
0.0361696583755145
0.0320384092689509
0.0288948343304147
0.0262373245283877
0.0239462330460614
0.0218350896369853
0.0201506779033703
0.0186757121130685
0.0176258625858971
0.0163239661159014
0.0154933431470081
]

代码改编自 Lihi Zelnik-Manor,2005 年 3 月,加州理工学院。

聚类内方差与聚类间方差的绘图比率是一条平滑曲线,其拐点像曲线一样平滑,绘制上面给出的bestD 数据。我们如何找到此类图的拐点?

【问题讨论】:

可以分享一下剧情吗? finding the best trade-off point on a curve的可能重复 在 SO 上查看 how-do-i-determine-k-when-using-k-means-clustering。 【参考方案1】:

我认为最好只使用你的“类内失真”作为优化参数:

%% Compute within class distortion
muB = repmat(mu(nn,:),length(I),1);
distort = distort+sum(sum((CSDmat(I,:)-muB).^2));

使用这个将该值除以“distort_across”。如果你计算这个的“导数”:

unexplained_error = within_class_distortion;
derivative = diff(unexplained_error);
plot(derivative)

导数 (k) 告诉您通过添加新集群,无法解释的错误减少了多少。我建议您在此错误的减少量小于您获得的第一次减少量的十倍时停止添加集群。

for (i=1:length(derivative))
    if (derivative(i) < derivative(1)/10)
         break
    end
end
k_opt = i+1;

事实上,获得最佳集群数量的方法取决于应用程序,但我认为您可以使用这个建议获得一个好的 k 值。

【讨论】:

以上是关于K 表示当肘部图是平滑曲线时找到肘部的主要内容,如果未能解决你的问题,请参考以下文章

实施肘部方法以找到 R 中 K-Means 聚类的最佳聚类数 [关闭]

Kmeans肘子方法不返回肘子。

使用肘部法确定k-means均值的k值

K-Means聚类若干问题

PySpark如何找到适当数量的集群

颤振没有更新肘部状态