在 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)]
我正在使用 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)]