计算顺序很重要的相似度

数据挖掘 相似
2021-10-10 07:04:31

我如何计算项目顺序很重要的相似性(系数),而Jaccard 索引之类的东西没有用。

具体来说,我对比较成分很感兴趣。以简化的苹果派配料表为例:

  • 苹果
  • 强化未漂白面粉
  • 棕榈油
  • 高果糖玉米糖浆
  • 香料

然后将其与以下内容进行比较:

  1. 完全相同的成分,但顺序相反。香料是最重要的成分,而苹果是最少使用的成分
  2. 清单,但用植物油代替棕榈油,用糖代替玉米糖浆

即使您对#2 中的替换相似这一事实很天真,#2 的集合比#1 的集合更类似于原始集合。有没有一种算法可以表达这一点?

2个回答

一个有趣的问题的迟到答案:

如何计算项目顺序很重要的相似性(系数)

这正是基于字符的近似字符串匹配措施所做的,因为字符串是字符的有序列表。所以想法是将列表中的每个元素视为字符串中的一个字符并应用该算法。基于特征的主要措施是:

我会推荐前者,因为它有更清晰的解释,并且可能更普遍使用。

不确定这是否已经存在,但也许你可以建立一个新的相似性指标(我们称之为js) 有几个要求:

  • 如果列出 AB 完全一样,那么 js(A,B)=1.0
  • 如果列出 AB 完全不同(没有共同点),那么 js(A,B)=0.0
  • 如果所有元素都匹配但被打乱了,那么 js(A,B)=0.5
  • 如果 |A||B|,那么相似度度量应该考虑最长列表中的项目(例如,如果在 A, 但 B 否则是相同的,它仍然会有一些惩罚)

然后您可以构建一个基本上执行以下操作的方法(例如在python中):

def js(A, B):
    cummulative_score = 0
    longest_list = B
    shortest_list = A
    if len(A) > len(B):
        longest_list = A
        shortest_list = B

    for index, element in enumerate(longest_list):
        if index < len(shortest_list):
            if element == shortest_list[index]:
                cummulative_score += 1
            if element != shortest_list[index]:
                if element in shortest_list:
                    cummulative_score += 0.5
    return cummulative_score / len(longest_list)

然后你会有这样的事情:

In [10]: print(l)
['Apples', 'Enriched Unbleached Flour', 'Palm Oil', 'High Fructose Corn Syrup', 'Salt', 'Eggs', 'Spices']

In [11]: print(l1)
['Apples', 'Enriched Unbleached Flour', 'vegetable oil', 'sugar', 'Salt', 'Eggs', 'Spices']

In [12]: print(l2)
['Spices', 'Eggs', 'Salt', 'High Fructose Corn Syrup', 'Palm Oil', 'Enriched Unbleached Flour', 'Apples']

In [13]: print(l3)
['Enriched Unbleached Flour', 'Palm Oil', 'High Fructose Corn Syrup', 'Salt', 'Eggs', 'Spices', 'Apples']

In [14]: print(l4)
['Apples', 'Enriched Unbleached Flour', 'Palm Oil', 'High Fructose Corn Syrup', 'Salt', 'Eggs', 'Spices', 'Ice Cream']

In [15]: js(l, l1)
Out[15]: 0.7142857142857143

In [16]: js(l, l2)
Out[16]: 0.5714285714285714

In [17]: js(l, l3)
Out[17]: 0.5

In [18]: js(l, l4)
Out[18]: 0.875

In [19]: js(l, ['Nutella'])
Out[19]: 0.0