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

Posted

技术标签:

【中文标题】在 Python 中查找将一个集群列表转换为另一个集群的映射【英文标题】:Find mapping that translates one list of clusters to another in Python 【发布时间】:2019-08-11 00:15:39 【问题描述】:

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

说我有

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

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

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

我说“最佳映射”是因为假设list3 = [3, 3, 1, 2, 2, 3, 8, 4] 然后findMapping(list1, list3) 仍会返回相同的映射,即使最终的1 变成4 而不是3

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

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

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

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

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

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]

即使使用这种转换(我需要一致地绘制集群颜色),使用 Rand 索引和/或标准化互信息似乎也是比较不需要共享标签的差异的好方法。

我也喜欢第一个 sorting both lists according the values in the data 的想法,但在比较来自非常不同数据的集群时,这可能行不通。

【问题讨论】:

我认为这个问题证明了一定程度的优点,即使据称有人认为它是重复的。我赞成它。 【参考方案1】:

您可以尝试计算两个结果之间的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

【讨论】:

是的,这就是我所期望的存在。它确实满足了我在不找到翻译的情况下测量列表之间距离的需要。如果可能的话,我仍然希望有“翻译图”,这样我就可以识别哪些项目是不同的,并为绘图生成一个全局配色方案。 有关该信息,请尝试应急矩阵:scikit-learn.org/stable/modules/generated/… 我相信您,权变矩阵可以提供将一组标签转换为另一组标签所需的信息,但是仅凭该文档而找不到示例,完全不清楚如何做到这一点。 采用列联矩阵的 np.argmax 应该得到一个列表,其中索引是键,值是映射的值。一个好的映射。 我认为如果两个分区具有不同的基数(例如,一个ground-truth集群被给定的聚类过程分成两部分),Munkres 算法可能不是一个好主意。在这种情况下,Munkres 算法会留下一些不匹配的集群,如果需要完整的分配图,那么 argmax 技术(尽管不是最理想的)是一个不错的方法。

以上是关于在 Python 中查找将一个集群列表转换为另一个集群的映射的主要内容,如果未能解决你的问题,请参考以下文章

列表推导(list comprehension)--Python

将对象列表转换为另一个对象

在给定列表中搜索将字符串转换为另一个字符串的最短方法,一次一个字符

将spring服务列表转换为另一个Entity作为响应

Javascript / Typescript:以角度将一个数组类转换为另一个数组类

Python:如何将日期时间/时间戳从一个时区转换为另一个时区?