排序列表差异

Posted

技术标签:

【中文标题】排序列表差异【英文标题】:Sorted list difference 【发布时间】:2010-10-25 23:07:21 【问题描述】:

我有以下问题。

我有一组元素,可以通过某种算法 A 进行排序。分拣不错,就是很贵。

还有一个算法B可以逼近A的结果,速度快很多,但是排序不会完全一样。

将 A 的输出作为“黄金标准”,我需要对在相同数据上使用 B 所导致的误差进行有意义的估计。

任何人都可以建议我可以查看的任何资源来解决我的问题吗? 提前致谢!

编辑:

根据要求:添加一个示例来说明案例: 如果数据是字母表的前 10 个字母,

A 输出:a,b,c,d,e,f,g,h,i,j

B 输出:a,b,d,c,e,g,h,f,j,i

产生的误差有哪些可能的测量方法,这将允许我调整算法 B 的内部参数以使结果更接近 A 的输出?

【问题讨论】:

【参考方案1】:

斯皮尔曼的 rho

我想你想要的是Spearman's rank correlation coefficient。使用两个排序的索引 [rank] 向量(完美A 和近似B),您可以计算等级相关rho,范围从-1(完全不同)到1(完全相同):

其中 d(i) 是 A 和 B 之间每个字符的等级差异

您可以将误差度量定义为距离D := (1-rho)/2

【讨论】:

是的,这看起来很像我要找的东西,谢谢!【参考方案2】:

我会确定最大的正确排序的子集。

                               +-------------> I
                               |   +--------->
                               |   |
A -> B -> D ----->  E  -> G -> H --|--> J
     |             ^ |             |    ^
     |             | |             |    |
     +------> C ---+ +-----------> F ---+

在您的示例中,10 分中有 7 分,因此算法得分为 0.7。其他集合的长度为 6。正确排序得分 1.0,反向排序得分 1/n。

我认为这与反转次数有关。 x + y 表示 x y(错误顺序)。

A + B + D - C + E + G + H - F + J - I

我们得到几乎相同的结果 - 9 个中有 6 个是正确的,得分为 0.667。再次正确排序分数 1.0 和反向排序分数 0.0,这可能更容易计算。

【讨论】:

【参考方案3】:

您是否正在寻找一些算法来计算基于以 A 排序的数组和以 B 排序的数组作为输入的差异?或者您是否正在寻找一种通用方法来确定使用 B 排序时数组的平均偏差?

如果是第一个,那么我建议一些简单的方法,比如每个项目与它应该在的位置之间的距离(平均值会比总和更好,以消除数组长度作为一个问题)

如果是第二个,那么我想我需要了解更多关于这些算法的信息。

【讨论】:

这还不够好,好像列表是 z, a, b, c, d……整个列表移动了 1。【参考方案4】:

很难给出一个好的通用答案,因为适合您的解决方案取决于您的应用程序。

我最喜欢的选项之一就是有序元素对的数量除以对的总数。这是一个很好的、简单的、易于计算的指标,它只是告诉你有多少错误。但它没有尝试量化这些错误的严重程度。

double sortQuality = 1;
if (array.length > 1) 
   int inOrderPairCount = 0;
   for (int i = 1; i < array.length; i++) 
      if (array[i] >= array[i - 1]) ++inOrderPairCount;
   
   sortQuality = (double) inOrderPairCount / (array.length - 1);

【讨论】:

【参考方案5】:

计算RMS Error 可能是许多可能的方法之一。这是小python代码。

def calc_error(out_A,out_B):
        # in    <= input
        # out_A <= output of algorithm A
        # out_B <= output of algorithm B

        rms_error = 0

        for i in range(len(out_A)):
            # Take square of differences and add
            rms_error +=  (out_A[i]-out_B[i])**2 

        return rms_error**0.5   # Take square root

>>> calc_error([1,2,3,4,5,6],[1,2,3,4,5,6])
0.0
>>> calc_error([1,2,3,4,5,6],[1,2,4,3,5,6]) # 4,3 swapped
1.414
>>> calc_error([1,2,3,4,5,6],[1,2,4,6,3,5]) # 3,4,5,6 randomized
2.44

注意: 取平方根不是必需的,但取平方是因为差值之和可能为零。我认为 calc_error 函数给出了错误放置对的近似数量,但我没有任何方便的编程工具,所以:(。

看看this question.

【讨论】:

我也在考虑 RMSE。但是最初的问题说“排序很昂贵”,所以我必须假设必须计算错误度量,而无需进行规范排序进行比较。如果没有规范顺序,您将无法计算 RMSE。 不,OP 可以访问黄金标准进行培训。他想要一个误差函数,这样他就可以在松开它之前优化他的近似分拣机。【参考方案6】:

你可以试试hamming distance

【讨论】:

我不认为汉明距离是解决这个问题的好方法。它提供了逐个元素的比较,但两个元素之间的距离并不能说明排序质量。 你是对的,我不是说只使用汉明距离,而是说涉及它的东西。如果他想进行更昂贵的估算,他应该使用距离计算。【参考方案7】:

如果有人使用 R 语言,我已经实现了一个函数,该函数使用@bubake 上述方法计算“spearman 秩相关系数”:

get_spearman_coef <- function(objectA, objectB) 
  #getting the spearman rho rank test 
  spearman_data <- data.frame(listA = objectA, listB = objectB)
  spearman_data$rankA <- 1:nrow(spearman_data) 
  rankB <- c()
  
  for (index_valueA in 1:nrow(spearman_data)) 
    for (index_valueB in 1:nrow(spearman_data)) 
      
      if (spearman_data$listA[index_valueA] == spearman_data$listB[index_valueB]) 
        rankB <- append(rankB, index_valueB)
      
      
      
    
  
  spearman_data$rankB <- rankB
  spearman_data$distance <-(spearman_data$rankA - spearman_data$rankB)**2
  
  spearman <- 1 - ( (6 * sum(spearman_data$distance)) / (nrow(spearman_data) * ( nrow(spearman_data)**2 -1) ) )
  print(paste("spearman's rank correlation coefficient"))
  return( spearman)  

结果:

get_spearman_coef(c("a","b","c","d","e"), c("a","b","c","d","e") )

斯皮尔曼等级相关系数:1

get_spearman_coef(c("a","b","c","d","e"), c("b","a","d","c","e") )

斯皮尔曼等级相关系数:0.9

【讨论】:

以上是关于排序列表差异的主要内容,如果未能解决你的问题,请参考以下文章

git解析日志常用命令

希尔排序在不同增量序列下的效率差异

使用差异列表快速序列化 BST

如何在查找2个列表的差异时维护输出列表的顺序

按长度对字符串的 ArrayList 进行排序

比较两个通用列表差异的最快方法