使用python散列大数字序列,创建散列集,存储和比较集合的相似性

时间:2015-11-29 19:21:59

标签: python hash set similarity

我试图找到将大型数字序列集与其他大型集进行比较的最佳方法,以便将它们相互排列。也许以下玩具示例澄清了问题,其中列表a,b和c表示时间序列中大小为3的带状疱疹。

a = [(1,2,3),(2,3,4),(3,4,5)]
b = [(1,2,3),(2,3,4),(3,4,7),(4,7,8)]
c = [(1,2,3),(2,3,5)]

set_a, set_b, set_c  = set(a), set(b), set(c)

jaccard_ab = float(len(set_a.intersection(set_b)))/float(len(set_a.union(set_b)))
jaccard_bc = float(len(set_b.intersection(set_c)))/float(len(set_b.union(set_c)))
jaccard_ac = float(len(set_a.intersection(se t_c)))/float(len(set_a.union(set_c)))

这些集合之间的相似性是:

jaccard_ab, jaccard_bc, jaccard_ac
(0.4, 0.2, 0.25)

所以在这个例子中,我们可以看到集合a和b是最相似的,得分为0.4。

我遇到了设计问题: 1)由于每组将由~1000个带状疱疹组成,我是否通过将每个木瓦转换为唯一的哈希值然后比较哈希来获得速度? 2)最初,我有超过10,000套比较所以我认为我在数据库或酸洗中存储带状疱疹(或哈希,取决于1的答案)要好得多。这是一个好方法吗? 3)随着我的工作流程中添加了一个新的集合,我需要将其与所有现有集合进行排名并显示,比如说,前10个最相似。有没有比玩具示例中更好的方法?

3 个答案:

答案 0 :(得分:3)

1)一组的成员必须是可散列的,所以python已经是计算哈希。存储一组项目的哈希将是重复的工作,因此没有必要这样做。

2)集合交集和并集的complexity近似为线性。 Jaccard的计算成本并不昂贵,10,000套不是 许多(约5000万 1 计算)。计算初始结果可能需要一个小时,但这不会花费数天。

3)完成所有组合后,根据现有结果对另一组进行排名意味着只进行10,000次比较。我想不出比这更简单的方法。

我会说这样做。

如果你想更快,那么你应该可以很容易地使用这个数据集的多处理方法。 (每个计算都独立于其他计算,因此它们都可以并行运行。)

这是一个改编自concurrent.futures examples(Python3)的例子。

import concurrent.futures

data = [
    {(1, 2, 3), (2, 3, 4), (3, 4, 5), ...},
    {(12, 13, 14), (15, 16, 17), ...},
    ...
]

def jaccard(A, B):
    return len(A & B) / len(A | B) 

with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
    futures = {executor.submit(jaccard, *sets): sets
               for sets in combinations(data, 2)}

    for future in concurrent.futures.as_completed(futures):
        jaccard_index = future.result()
        print(jaccard_index) # write output to a file or database here

[1]:

>>> from itertools import combinations
>>> print(sum(1 for i in combinations(range(10000), 2)))
49995000

答案 1 :(得分:1)

1)在构建set()时,这在内部完成。

2)我不确定你是否可以使用python来保存数据集的大小,所以我建议使用一些简单的(文本)格式,以便它可以很容易地加载,例如在C / C ++中。你需要存放带状疱疹吗?那么在飞行中生成它们呢?

3)如果您需要对所有初始数据集进行全部比较,那么google-all-pairsppjoin等内容肯定会有所帮助。它通过使用预定义的相似性阈值减少每个比较的候选集来工作。您可以修改代码以保留索引以供进一步搜索。

答案 2 :(得分:1)

您绝对应该考虑使用多核,因为此问题非常适合此任务。你可能会考虑使用PyPy,因为我看到2-3X加速比较Python 3进行大集合比较。然后你可以检查part 1: resemblance with the jaccard coefficient以获得一个神奇的C ++实现来进一步加速。这个C ++ / OpenMP解决方案是我测试过的最快的。