实施学术论文:从 Elasticsearch 和 Lucene 中汲取的经验教训

借鉴我们使用 Elasticsearch 和 Lucene 的经验,了解将研究论文纳入软件应用程序的策略。

无缝连接领先的 AI 和机器学习平台。开始免费云服务试用,探索 Elastic 的生成式 AI 功能,或者立即在您的计算机上试用。

本帖分享在软件应用程序中实施学术论文的策略。它借鉴了 Elasticsearch 和 Lucene 的示例,希望能帮助其他工程师学习我们的经验。读到这些策略,你可能会想:"但这只是软件开发啊!"事实的确如此:作为工程师,我们已经掌握了正确的方法和工具,只是需要加以调整,以适应新的挑战。

背景

在开发 Elasticsearch 的过程中,我们偶尔会遇到一个重要问题,但没有简单或既定的解决方法。人们自然会问:"嗯,有没有学术论文论述过这个问题?"其他时候,学术工作是灵感的源泉。我们会遇到一篇提出新算法或数据结构的论文,然后想:"这一定很有用!"以下是 Elasticsearch 和 Apache Lucene 如何结合学术工作的几个例子:

学术论文是工程师开发数据密集型系统的宝贵资源。但是,实施这些算法可能会让人望而生畏,而且容易出错--算法描述往往很复杂,重要的实际细节被省略了。测试是一项真正的挑战:例如,我们如何才能彻底测试输出结果与数据集密切相关的机器学习算法?

像评估软件依赖性一样评估论文

添加一个新的软件依赖关系需要仔细评估:如果其他软件包不正确、速度慢或不安全,我们的项目也可能如此。在引入依赖关系之前,开发人员一定要对其质量进行评估。

这同样适用于您正在考虑实施的学术论文。也许有人会认为,论文中发表了一种算法,它就一定是正确的、性能良好的。但是,即使通过了评审程序,学术论文也可能存在问题。也许正确性证明所依赖的假设并不现实。或者,"实验 "部分显示的性能比基线高得多,但这只在特定的数据集上成立。即使论文质量很高,其方法也可能不适合您的项目。

在考虑是否对学术论文采取 "依赖 "态度时,不妨像对待软件包一样提出同样的问题:

  • 图书馆是否被广泛使用并经过 "实战检验"?→ 其他软件包是否实施了本文,效果如何?
  • 是否有性能基准?这些看起来准确和公平吗?→ 论文是否包含现实的实验?它们设计得好吗?
  • 性能的提升是否足以证明复杂性的合理性?→ 论文是否与强有力的基线方法相比较?它比基准线高出多少?
  • 这种方法能与我们的系统很好地整合吗?→ 算法的假设和权衡是否符合我们的使用情况?

不知为什么,当一个软件包发布与竞争对手的性能比较时,该软件包总是最快的!如果由第三方设计基准,可能会更加平衡。同样的现象也适用于学术论文。如果一种算法不仅在原始论文中表现出色,而且还在其他论文中作为强有力的基线出现,那么它就很有可能是可靠的。

创造性地进行测试

学术论文中的算法通常比我们日常遇到的算法类型具有更复杂的行为。也许这是一种近似算法,用精确度来换取更快的速度。也可能是一种机器学习方法,它能接收大量数据集,并产生(有时是意想不到的)输出结果。如果我们不能简单地描述这些算法的行为特征,又如何为它们编写测试程序呢?

关注不变式

在设计单元测试时,我们通常会从示例的角度来思考:如果我们给算法这个示例输入,它就应该有这样的输出。遗憾的是,对于大多数数学算法来说,基于示例的测试并不能充分涵盖它们的行为。

让我们来看看 C3 算法,Elasticsearch 使用它来确定哪个节点应该处理搜索请求。它使用一个微妙的公式对每个节点进行排名,该公式结合了节点以前的服务和响应时间以及队列大小。测试几个例子并不能真正验证我们对公式的理解是否正确。退一步思考测试不变式:如果服务时间增加,节点的等级是否会降低?如果队列规模为 0,排名是否如论文所说由响应时间决定?

关注不变式可以帮助解决一些常见问题:

  • 这种方法是否应该与顺序无关?如果是这样,以不同的顺序传递输入数据应该会得到相同的输出结果。
  • 算法中的某个步骤会产生类别概率吗?如果是这样,这些概率的总和应为 1。
  • 函数是否围绕原点对称?如果是这样,翻转输入的符号应该只是翻转输出的符号。

我们最初实施 C3 时,公式中出现了一个错误,不小心用响应时间的倒数代替了响应时间。这意味着速度较慢的节点可以排名靠前!在修复该问题时,我们确保添加了不变量检查,以防止将来出现错误。

与参考实施比较

在发表论文的同时,作者还发布了该算法的实施方案。(如果论文中包含实验,这种情况尤其可能发生,因为许多期刊都要求作者发布用于重现结果的代码)。您可以根据该参考实现测试自己的方法,确保没有遗漏算法的重要细节。

在开发用于最近邻搜索的 Lucene HNSW 实现时,我们 根据 论文作者的 参考库进行了测试 。我们针对相同的数据集运行了 Lucene 和库,比较了其结果的准确性和计算次数。当这些数字紧密匹配时,我们就知道 Lucene 忠实地实现了算法。

在将算法集成到系统中时,通常需要进行修改或扩展,例如将其扩展到多个内核,或添加启发式算法以提高性能。最好先实施"vanilla" 版本,对照参考进行测试,然后再逐步修改。这样,您就可以确信在进行定制之前已经捕捉到了所有关键部分。

与现有算法对决

最后一节提出了测试不变式的另一个想法:将算法输出与更简单、更易理解的算法输出进行比较。举例来说,Lucene 中的 block-max WAND 算法可以跳过那些无法出现在顶部结果中的文档,从而加快文档检索速度。我们很难准确描述 block-max WAND 在每种情况下的表现,但我们知道,应用它不应该改变最高结果!因此,我们的测试可以生成多个随机搜索查询,然后在 使用和不使用 WAND 优化的情况下运行这些 查询,并检查 它们 的结果是否始终一致。

这些测试的一个重要方面是,它们会 生成 用于进行比较的 随机输入 。这可以帮助解决你想不到的情况,并使意想不到的问题浮出水面。例如,Lucene 的 BM25F 评分随机比较测试有助于捕捉细微边缘情况下的错误。向算法提供随机输入的想法与 模糊(fuzzing )的概念密切相关, 模糊 是计算机安全领域的一种常用测试技术。

Elasticsearch 和 Lucene 经常使用这种测试方法。如果你看到一个测试提到两个算法之间的"决斗" (TestDuelingAnalyzers、testDuelTermsQuery......),那么你就知道这个策略正在发挥作用。

使用论文术语

当其他开发人员使用您的代码时,他们需要查阅该文件以了解其细节。关于 Elasticsearch 的 HyperLogLog++ 实现的评论说得很好:"在没有读过论文的情况下就试图理解这个类的作用,是一种冒险"。这种方法的评论也树立了一个好榜样。其中包括学术论文的链接,并重点介绍了对最初描述的算法所做的修改。

由于开发人员会根据论文来理解代码,因此使用完全相同的术语会很有帮助。由于数学符号是简洁的,这可能导致一些通常不被认为是 "好风格 "的名称,但在论文中却非常清晰。在 Elasticsearch 中,学术论文中的公式是你为数不多能遇到的神秘变量名,如rS 和 muBarSInverse


作者推荐的阅读论文方式:喝大杯咖啡。

您可以给作者发送电子邮件

在完成一篇难度很大的论文时,你可能会花几个小时来琢磨一个公式,不知道是自己理解错了,还是只是有一个错别字。如果这是一个开源项目,你可以在 GitHub 或 StackOverflow 上提问。但是,您能从哪里获得学术论文呢?作者看起来很忙,可能会因为你的邮件而感到厌烦。

相反,许多学者喜欢听到他们的想法被付诸实践的消息,并乐于通过电子邮件回答问题。如果您从事的是他们熟悉的产品,他们甚至可能会在网站上列出您的应用!

学术界使用软件开发中的许多相同工具公开讨论论文的趋势也在不断增长。如果论文附带软件包,您可以 在 Github 上 找到 常见问题的 答案。Stack Exchange 社区(如 "理论计算机科学 "和 "交叉验证")也包含有关热门论文的详细讨论。一些会议已开始在网上发表所有论文的评论。这些评论包含了与作者的来回讨论,这些讨论能让人对写作方法产生有益的见解。

待续

本篇文章主要介绍选择学术论文的基本知识,以及

但并不包括实际部署算法的所有方面。例如,如果算法只是复杂系统中的一个组件,我们如何确保对该组件的更改能带来端到端的改进?如果整合算法需要进行大量修改或扩展,而原始论文又没有涵盖这些内容,该怎么办?这些都是我们希望在今后的文章中与大家分享的重要话题。

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用