为了账号安全,请及时绑定邮箱和手机立即绑定

列表元素的相似性

列表元素的相似性

沧海一幻觉 2021-11-02 20:02:11
我有十个列表,我想获得它们的“相似性”。这是我的输入:data = [    ['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'SeasonNumber', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],     ['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'SeasonNumber', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],     ['RuntimeInMinutes', 'Genres', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', '_StudioName', 'Type', 'LanguageOfMetadata', 'ReleaseDate', 'Studio', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'TVSeriesID', 'Locales', 'EpisodeNumber', 'Name', 'Synopsis', 'Products', 'SeasonNumber', 'Platform'],     ['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'LanguageOfMetadata', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],     ['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'], 我目前的方法是将这些值集的长度与总长度进行比较。所以在上面它将是:>>> len(set(data))/len(data)0.5然而,这很粗糙,因为我想得到一个不是“全有或全无”的相似性。换句话说,类似于概念上的相似性,其中上述内容可能有 98% 的相似性(对不起,如果我无法准确地解释我在这里想要什么——但我的意思是评估相似性不仅仅是列表本身,而是其元素的相似性。
查看完整描述

2 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

查看datasketch 库及其 MinHash 数据结构。这是基于集合的Jaccard 相似性,它只是交集(它们的共同点)除以并集(所有可能的元素)。


下面是一个例子:


from datasketch import MinHash


data1 = ['minhash', 'is', 'a', 'probabilistic', 'data', 'structure', 'for',

        'estimating', 'the', 'similarity', 'between', 'datasets']

data2 = ['minhash', 'is', 'a', 'probability', 'data', 'structure', 'for',

        'estimating', 'the', 'similarity', 'between', 'documents']


m1, m2 = MinHash(), MinHash()

for d in data1:

    m1.update(d.encode('utf8'))

for d in data2:

    m2.update(d.encode('utf8'))

print("Estimated Jaccard for data1 and data2 is", m1.jaccard(m2))

如果您的集合很大,则为您提供相似性的估计。否则,只需使用内置的集合操作:


s1 = set(data1)

s2 = set(data2)

actual_jaccard = float(len(s1.intersection(s2)))/float(len(s1.union(s2)))

print("Actual Jaccard for data1 and data2 is", actual_jaccard)

如果要获取两个以上集合的 Jaccard 相似度,只需计算成对比较并取所有值的平均值(平均值):


from datasketch import *

import itertools

minhash_data = list()

for element in data:

    m = MinHash()

    for d in element:

        m.update(d.encode('utf-8'))

    minhash_data.append(m)


jaccard_sims = list()

for pair in itertools.combinations(minhash_data, 2):

    jaccard_sims.append(pair[0].jaccard(pair[1]))


average = sum(jaccard_sims) / float(len(jaccard_sims))

print("Average Jaccard similarity: {}".format(average))

平均 Jaccard 相似度:0.9512152777777778


查看完整回答
反对 回复 2021-11-02
?
桃花长相依

TA贡献1860条经验 获得超8个赞

当您说要获得两个列表之间的相似性时,有多种方法可以做到这一点。就像@Nick Pandey Jaccard 相似性。另一个称为tanimoto 比率的比率也很有效。 谷元系数


这是我的实现:


def tanimoto (list1, list2):

    intersection = [common_item for common_item in list1 if common_item in list2]

    return float(len(c))/(len(a) + len(b) - len(c))

现在,解决您必须同时比较 10 个列表的问题。您只能使用上述类似方法同时比较两个元素。但是,您可以开发自己的逻辑,让您大致了解所有事物之间的相似程度。


例如,您可以一次取五个列表并进行比较,或者更好的选择,比较前两个列表,存储 tanimoto 系数,比较接下来的两个并重复。最后取系数的平均值。在代码中更好:


def grouped(iterable, n):

    return zip(*[iter(iterable)]*n)


coeffs = []

for i, j in grouped(data, 2): # data refers to the variable in the question

    coeffs.append(tanimoto(i, j))


similarity = sum(coeffs)/len(coeffs)

希望这可以帮助 :)


查看完整回答
反对 回复 2021-11-02
  • 2 回答
  • 0 关注
  • 220 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信