【问题标题】:Efficient comparison of 1 million vectors containing (float, integer) tuples包含(浮点数,整数)元组的 100 万个向量的有效比较
【发布时间】:2010-02-22 12:45:05
【问题描述】:

我正在从事化学/生物学项目。我们正在构建一个网络应用程序,用于将用户的实验数据与参考数据库中的预测数据进行快速匹配。参考数据库将包含多达一百万个条目。一个条目的数据是一个元组列表(向量),其中包含一个介于 0.0 和 20.0 之间的浮点值和一个介于 1 和 18 之间的整数值。例如 (7.2394 , 2) , (7.4011, 1) , (9.9367, 3) , ... ETC。 用户将输入一个类似的元组列表,然后网络应用程序必须返回 - 比如说 - 前 50 个最匹配的数据库条目。

有一点很关键:搜索算法必须考虑到查询数据和参考数据之间的差异,因为两者都可能在浮点值中包含小错误(而不是在整数值中)。(The查询数据可能包含错误,因为它来自真实实验,而参考数据是预测结果。)

编辑 - 移动文本以回答 -

我们如何在 100 万条记录中获得 1 个查询的有效排名?

【问题讨论】:

  • 您能再描述一下数据的含义吗?整数的含义是什么?两个条目之间的距离是如何定义的?
  • 可能对物质 id 有药理活性
  • 我无法给出确切的含义,但数据描述了一个二维图,其中浮点值是 x 值,整数是 y 值。通过沿 x 轴(浮点值)对数据进行分箱来定义距离,然后通过取整数值减法的绝对值来比较来自查询和参考的相应分箱。总结所有差异
  • @Stefano:不,这不是针对物质 id 的药理活性
  • 对浮点值进行分箱并添加整数差异似乎没有任何意义,因为浮点数有错误并且整数是正确的。使用您当前的距离度量 (6.999, 18) 和 (7.001, 18) 将是 (6.901,1) 和 (6.999,18) 的两倍多。

标签: database algorithm math comparison performance


【解决方案1】:

您应该在项目中添加一个物理学家 :-) 这是比较函数的一个非常常见的问题,例如看这里:

在第一个链接中,您可以阅读:“用于分析质谱的 SEQUEST 算法利用自相关和互相关来对观察到的光谱与代表肽的理想化光谱的相似性进行评分。 em>"

【讨论】:

    【解决方案2】:

    在现代机器上,对 100 万条此类记录进行有效的线性扫描只需要几分之一秒;编译后的循环应该能够以大约内存带宽执行此操作,这将在两到三毫秒内传输。

    但是,如果您真的需要对此进行优化,您可以构建一个整数值的哈希表,它将作业除以整数箱的数量。而且,如果数据按浮点数排序存储,则可以提高匹配的局部性;你知道一旦你超出了容忍度,你就可以停下来。存储多个 bin 中的每一个的偏移量将为您提供一个开始的位置。

    我想我还没有看到需要一个花哨的算法......也许可以多描述一下这个问题(如果你愿意,你可以假设相当高水平的化学和物理知识;我是一名物理学家通过培训)?

    好的,考虑到额外的信息,如果只有 100 万个参考向量并且算法就这么简单,我仍然认为没有比直接线性搜索更好的方法了。我刚刚试了一下,即使是纯 Python 实现的线性扫描也只需要大约三秒钟。制作一些随机数据进行测试需要花费数倍的时间。这在一定程度上取决于 Python 排序库中相当疯狂的优化水平,但这是高级语言的优势。

    from cmath import *
    import random
    r = [(random.uniform(0,20), random.randint(1,18)) for i in range(1000000)]
    # this is a decorate-sort-undecorate pattern
    # look for matches to (7,9)
    # obviously, you can use whatever distance expression you want
    zz=[(abs((7-x)+(9-y)),x,y) for x,y in r]
    zz.sort()
    # return the 50 best matches
    [(x,y) for a,x,y in zz[:50]]
    

    【讨论】:

    • 当然,zz=[(abs(7-a[0])+abs(9-a[1]),a) for a in r] 给出了更明智的答案。
    • 您在第一段中的时间估计似乎基于数据不足,因为您不知道列表有多长。
    • 没错,我想。它似乎有点未指定。我的意思是,这可能需要 Voronoi 图才能正确解决,但如果不了解更多有关问题的信息,就很难提供帮助。
    【解决方案3】:

    你不能对元组进行排序并在排序后的数组上执行二进制搜索吗? 我假设您的数据库是一次性完成的,条目的位置并不重要。您可以对该数组进行排序,以便元组按给定顺序排列。当用户输入一个元组时,您只需查看已排序数组的中间即可。如果查询值大于中心值,则重复上半部分的工作,否则重复下半部分的工作。

    最坏的情况是 log(n)

    【讨论】:

      【解决方案4】:

      如果您可以将您的参考数据“映射”到平面上的 x-y 坐标,那么有一种绝妙的技术可以让您选择给定距离/公差下的所有点(使用希尔伯特曲线)。

      这是detailed example。

      【讨论】:

        【解决方案5】:

        我们自己尝试的一种允许查询和引用之间存在差异的方法是对浮点值进行分箱。我们正在测试并希望为用户提供不同大小的垃圾箱的选择。 Bin 大小将为 0.1、0.2、0.3 或 0.4。所以分箱给我们留下了 50 到 200 个分箱,每个分箱都有一个 0 到 18 之间的对应整数值,其中 0 表示该分箱中没有值。参考数据可以预先分箱并存储在数据库中。然后,我们可以获取分箱查询数据并将其与参考数据进行比较。一种方法可以是针对所有箱,从参考整数值中减去查询整数值。通过总结所有差异,我们得到相似度分数,最相似的参考条目得到最低分数。

        我们想要提供的另一个(更简单)搜索选项是用户只输入浮点值。然后可以将两个查询中的整数值作为参考列表设置为 1。然后我们使用汉明距离来计算查询和参考分箱值之间的差异。 I have previously asked about an efficient algorithm for that search.

        这种分箱只是实现我们目标的一种方式。我愿意接受其他建议。也许我们可以使用主成分分析 (PCA),如 here 所述

        【讨论】:

        • 这是否意味着元组在单个数据集中可以或可以按浮点值排序?
        • 当查询值非常靠近 bin 的边缘时,Binning 会给您带来偏差。
        • @Svante:是的,它们可以按浮点值排序
        • 按浮点值排序的元组是否描述了一条连续曲线?
        • @Svante:不,它们没有描述连续曲线。它们是离散值。
        猜你喜欢
        • 1970-01-01
        • 2015-08-30
        • 1970-01-01
        • 2015-01-20
        • 1970-01-01
        • 2021-11-01
        • 1970-01-01
        • 2011-04-19
        • 2016-08-14
        相关资源
        最近更新 更多