有序组合算法

时间:2013-05-16 13:48:39

标签: algorithm math mapreduce

我有以下任务:

  • 有10M文件
  • 有100K个独特标签
  • 每个文档都有100个标签

对于每个标签X,我需要找到10个顶部Y标签,其中X和Y都存在于文档中,按照X和Y都存在的文档数量排序。

这个任务似乎很难解决:

  • 虽然每个100K标签的结果集只有10条记录
  • 直接保持所有组合的算法,对内存使用非常敏感:(X,Y)总共有0.5 * 10 ^ 12个组合,它增长为n ^ 2,其中n是标签数

有没有办法解决这个问题而不将所有组合保留在内存中或者破解成并行算法(类似于map reduce)来解决?如果我不需要100%准确怎么办?

2 个答案:

答案 0 :(得分:2)

我认为在一般情况下,您将无法避免非常糟糕的运行时间 - 每个文档中有5050对,以及10M文档,所有组合似乎都可能。

但是,在典型的现实世界数据中,您很少需要处理“对抗性”输入。一种可能的解决方案是首先计算所有100K项的出现次数,对它们进行排序,然后对于每个项X,执行以下操作:

  • 如果有许多带有X的文档(即不少于文档计数的1%或其他一些可调整的部分),请以X&形式对您的索引运行查询。 Y,从最流行的术语开始,然后下降,保持10号堆以跟踪最受欢迎的对。你知道max(带有X& Y的文档)= max(带有X的文档,带有Y的文档),所以你很可能能够尽早缩短这个过程。
  • 如果使用X的文档很少,那么简单地浏览该术语的所有文档并自行汇总总数就更为谨慎。

对于表现良好的文档集,其中100K术语遵循与文档计数相对应的对数曲线,您将完成远远小于(100)^ 2 * 10M的工作,这是天真的解决方案在所有情况下都需要的。当然,对于不良行为的文档集,你最终会做更多的工作,但这不应该发生在现实世界中。

对于“不是100%准确”,这是一个过于模糊的规范。允许什么样的错误?多少钱?

---评论回复(评论太大)---

a)考虑确定最多1亿个元素。您只需要保存扫描到目前为止最好的1个 - 同样的原则适用于确定N个项目的前X个。将传入的元素添加到二进制堆中,并在堆的大小超过X时删除最弱的元素。添加结束,您将拥有顶部的X

b)想象一下,你正在确定前10名X& Y对,其中X =“大象”。假设在扫描1000个Y项后,你有一个大小为10的堆,其中最小得分对的数量为300.现在假设你检查的第1001个术语有doc count 299 - 因为只有299个文档有Y个术语,最多299个文档也有X& Y,因此它不可能比你目前为止的前十对中的任何一个都好,并且因为所有Y项都按文档频率排序,实际上你现在知道你不知道我必须再检查一对!这就是max语句保证的。

c)您为每个X做出的选择纯粹是一种优化决策。如果你有许多只存在于少量文档中的X,这是一个很好的问题 - 这意味着每学期的工作量减少。

d)如果您可以忍受排名前十的错误概率(对于每个术语),您可以通过使用抽样方法而不是完整,严格的扫描来减少运行时间指数。在文档索引中,术语X越普遍,在您根据所收集的信息获得正确的前10个X& Y对之前,您必须扫描(按比例)的文档越少。在这方面提出确切的数字需要了解基础指数中术语的预期分布。特别是:术语与多少相关? N(X)/ MAXY(X)的数字一般是什么样的,其中N(X)是具有术语X的文档的数量,而MAXY(X)是具有X& Y对的文档的数量,在所有条件下最大化Y!= X

答案 1 :(得分:0)

我认为即使最坏的情况也不是你可能会害怕的。如果有N个文档,则M区分标签但每个文档只有K个标签。然后一个完整的直方图将有一个硬限制K * K * N / 2个不同的非零条目(5.5 * 10 ^ 10与你的数字),实际上它会少得多。

顺便说一句:我认为上述观点隐含在torquestomp的答案中,所以除非你对硬限制特别感兴趣,否则你应该接受他的回答。