【问题标题】:How can I match up cluster labels to my 'ground truth' labels in Matlab如何将集群标签与 Matlab 中的“基本事实”标签匹配
【发布时间】:2012-07-25 21:28:31
【问题描述】:

我在这里搜索并用谷歌搜索过,但无济于事。在 Weka 中进行聚类时,有一个方便的选项,即类到聚类,它与算法生成的聚类相匹配,例如简单的 k-means,到您作为类属性提供的“基本事实”类标签。这样我们就可以看到聚类准确率(错误百分比)。

现在,我如何在 Matlab 中实现这一点,即翻译我的 clusterClasses 向量,例如[1, 1, 2, 1, 3, 2, 3, 1, 1, 1] 与提供的地面实况标签向量相同的索引,例如[2, 2, 2, 3, 1, 3]?

我觉得可能是基于集群中心和标签中心,但是不知道怎么实现!

任何帮助将不胜感激。

文森特

【问题讨论】:

  • 假设您的集群数量与您拥有的基本事实标签数量相同,那么我相信您会根据 ARI 等指标对您的模型进行评分。

标签: matlab cluster-analysis weka


【解决方案1】:

几个月前,我在进行聚类时偶然发现了一个类似的问题。我并没有很长时间地搜索内置解决方案(尽管我确信它们一定存在)并最终编写了我自己的小脚本,以便将我找到的标签与基本事实进行最佳匹配。代码非常粗糙,但它应该可以帮助您入门。

它基于尝试所有可能的标签重新排列,以查看最适合真值向量的女巫。这意味着给定一个聚类结果yte = [3 3 2 1] 和基本事实y = [1 1 2 3],脚本将尝试匹配[3 3 2 1], [3 3 1 2], [2 2 3 1], [2 2 1 3], [1 1 2 3] and [1 1 3 2]y 以找到最佳匹配。

这是基于使用内置脚本 perms() 女巫不能处理超过 10 个独特的集群。对于 7-10 个独特的集群,代码也可能会变慢,因为复杂性会随着因子的增长而增长。

function [accuracy, true_labels, CM] = calculateAccuracy(yte, y)
%# Function for calculating clustering accuray and matching found 
%# labels with true labels. Assumes yte and y both are Nx1 vectors with
%# clustering labels. Does not support fuzzy clustering.
%#
%# Algorithm is based on trying out all reorderings of cluster labels, 
%# e.g. if yte = [1 2 2], try [1 2 2] and [2 1 1] so see witch fit 
%# the truth vector the best. Since this approach makes use of perms(),
%# the code will not run for unique(yte) greater than 10, and it will slow
%# down significantly for number of clusters greater than 7.
%#
%# Input:
%#   yte - result from clustering (y-test)
%#   y   - truth vector
%#
%# Output:
%#   accuracy    -   Overall accuracy for entire clustering (OA). For
%#                   overall error, use OE = 1 - OA.
%#   true_labels -   Vector giving the label rearangement witch best 
%#                   match the truth vector (y).
%#   CM          -   Confusion matrix. If unique(yte) = 4, produce a
%#                   4x4 matrix of the number of different errors and  
%#                   correct clusterings done.

N = length(y);

cluster_names = unique(yte);
accuracy = 0;
maxInd = 1;

perm = perms(unique(y));
[pN pM] = size(perm);

true_labels = y;

for i=1:pN
    flipped_labels = zeros(1,N);
    for cl = 1 : pM
        flipped_labels(yte==cluster_names(cl)) = perm(i,cl);
    end

    testAcc = sum(flipped_labels == y')/N;
    if testAcc > accuracy
        accuracy = testAcc;
        maxInd = i;
        true_labels = flipped_labels;
    end

end

CM = zeros(pM,pM);
for rc = 1 : pM
    for cc = 1 : pM
        CM(rc,cc) = sum( ((y'==rc) .* (true_labels==cc)) );
    end
end

例子:

[acc newLabels CM] = calculateAccuracy([3 2 2 1 2 3]',[1 2 2 3 3 3]')

acc =

0.6667


newLabels =

 1     2     2     3     2     1


CM =

 1     0     0
 0     2     0
 1     1     1

【讨论】:

  • 谢谢!这似乎是一种享受。我正在使用 9 个集群,但阶乘似乎不是问题。干杯:)
  • 我设法找到了一个更快的实现,也许有一天这会对某人有所帮助! mathworks.com/matlabcentral/fileexchange/…
【解决方案2】:

您可能希望研究更灵活的集群评估方法。例如对计数指标。

“class= 集群”假设对于从机器学习进入集群的人来说是典型的。但相反,您应该假设某些类可能由多个集群组成,或者多个类实际上是集群的。这些是聚类算法应该实际检测到的有趣情况。

【讨论】:

    【解决方案3】:

    我需要 Python 的这个确切的东西并转换了 Vidar 发布的代码(接受的答案)。我将代码分享给任何感兴趣的人。我重命名了变量并删除了混淆矩阵(大多数机器学习库都为此内置了函数)。我注意到文森特 (http://www.mathworks.com/matlabcentral/fileexchange/32197-clustering-results-measurement) 链接的更快实现为时已晚。可能更好地适应 Python。

    #tested with python 3.6
    def remap_labels(pred_labels, true_labels):
        """Rename prediction labels (clustered output) to best match true labels."""
        # from itertools import permutations # import this into script.
        pred_labels, true_labels = np.array(pred_labels), np.array(true_labels)
        assert pred_labels.ndim == 1 == true_labels.ndim
        assert len(pred_labels) == len(true_labels)
        cluster_names = np.unique(pred_labels)
        accuracy = 0
    
        perms = np.array(list(permutations(np.unique(true_labels))))
    
        remapped_labels = true_labels
        for perm in perms:
            flipped_labels = np.zeros(len(true_labels))
            for label_index, label in enumerate(cluster_names):
                flipped_labels[pred_labels == label] = perm[label_index]
    
            testAcc = np.sum(flipped_labels == true_labels) / len(true_labels)
            if testAcc > accuracy:
                accuracy = testAcc
                remapped_labels = flipped_labels
    
        return accuracy, remapped_labels
    

    【讨论】:

      【解决方案4】:

      按照@Vidar 的想法,我编写了自己的代码来查找最佳标签对应关系。我假设初始标签是整数 $0..K$ 并找到最匹配的标签重命名。代码依赖函数itertools.permutationsthis answer建议):

      import numpy as np
      from itertools import permutations
      
      def match_labels(labels, labels0, K):
          perms = list(permutations(range(K)))
          nmatch = 0
          for jperm, perm in enumerate(perms):
              labs = np.array([perm[l] for l in labels])
              newmatch = (labs == labels0).sum()
              if newmatch > nmatch:
                  nmatch = newmatch
                  newlabels = labs
                  matchtable = list(perm)
          return newlabels, matchtable
      

      This thread 建议使用更先进的技术来验证聚类的质量。第一个尝试的可能是 Rand index,在许多库中都可用(例如,在 scikit-learn 中)。

      【讨论】:

        猜你喜欢
        • 2020-12-14
        • 2021-06-18
        • 2020-12-05
        • 1970-01-01
        • 2020-07-10
        • 1970-01-01
        • 2022-10-31
        • 1970-01-01
        • 2018-10-13
        相关资源
        最近更新 更多