在 Python 中查找将一个聚类列表转换为另一个聚类列表的映射

Find mapping that translates one list of clusters to another in Python

我正在使用 scikit-learn 对一些数据进行聚类,我想比较不同聚类技术的结果。我立即面临一个问题,即不同运行的集群标签不同,因此即使它们完全相同地集群,列表的相似性仍然很低。

假设我有

list1 = [1, 1, 0, 5, 5, 1, 8, 1]
list2 = [3, 3, 1, 2, 2, 3, 8, 3]

我(理想情况下)喜欢一个函数,它 return 是翻译字典形式的最佳映射,如下所示:

findMapping(list1, list2)
>>> {0:1, 1:3, 5:2, 8:8}

我说 "best mapping" 因为让我们说 list3 = [3, 3, 1, 2, 2, 3, 8, 4] 然后 findMapping(list1, list3) 仍然 return 相同的映射,即使最终的 1 变成 4 而不是 3

所以最好的映射是最小化两个列表之间差异的映射。我认为这是一个很好的标准,但可能有更好的标准。

我可以编写一个试错优化算法来执行此操作,但我不是第一个想要比较聚类算法结果的人。我希望这样的东西已经存在,我只是不知道它叫什么。但是我四处寻找并没有找到任何答案。

重点是,在应用最佳翻译后,我将衡量列表之间的差异,所以也许有一种方法可以衡量索引不同的数字列表之间的差异,而无需将翻译作为中间步骤,这就是也不错

===================================

根据 Pallie 的回答,我能够创建 findMapping 函数,然后我更进一步创建了一个翻译函数,return将第二个列表转换为第一个列表的标签。

def translateLabels(masterList, listToConvert):    
  contMatrix = contingency_matrix(masterList, listToConvert)
  labelMatcher = munkres.Munkres()
  labelTranlater = labelMatcher.compute(contMatrix.max() - contMatrix)

  uniqueLabels1 = list(set(masterList))
  uniqueLabels2 = list(set(listToConvert))

  tranlatorDict = {}
  for thisPair in labelTranlater:
    tranlatorDict[uniqueLabels2[thisPair[1]]] = uniqueLabels1[thisPair[0]]

  return [tranlatorDict[label] for label in listToConvert]

即使进行了这种转换(我需要它来一致地绘制簇颜色),使用兰德索引 and/or 标准化互信息似乎是比较不需要共享的差异的好方法标签。

我也喜欢第一个 的想法,但是当比较来自非常不同的数据的集群时,这可能行不通。

您可以尝试计算两个结果之间的 adjusted Rand index。这给出了 -1 和 1 之间的分数,其中 1 是完美匹配。

或者取混淆矩阵的argmax:

list1 = ['a', 'a', 'b', 'c', 'c', 'a', 'd', 'a']
list2 = [3, 3, 1, 2, 2, 3, 8, 3]
np.argmax(contingency_matrix(list1, list2), axis=1)
array([2, 0, 1, 3])

2 表示第 2 行(值 2,簇 3)最匹配 "a" 第 0 列(2 的索引)。然后第 0 行匹配第 1 列,依此类推

对于匈牙利语方法:

m = Munkres()
contmat = contingency_matrix(list1, list2)
m.compute(contmat.max() - contmat)
[(0, 2), (1, 0), (2, 1), (3, 3)]

使用:https://github.com/bmc/munkres