Holmes 4.0:基于语义的信息提取与智能搜索库

6 阅读17分钟

Holmes 4.0介绍

几周前,某机构发布了Holmes的4.0版本,该版本现已在宽松的MIT许可证下提供。Holmes是spaCy生态中的一个库,运行在spaCy之上,支持英语和德语的信息提取与智能搜索。Holmes超越了简单的匹配算法,允许用户在文档语料库中查找特定的概念。

Holmes提供两种主要的搜索机制。第一种是结构匹配,旨在精确地在语料库中找到表达给定概念的文本片段,适用于提取结构化信息(例如存入关系数据库)。第二种是主题匹配,其匹配更模糊,构成了实时搜索机器的基础。结构匹配是两者中更基础的机制,因此将首先解释它,然后讨论建立在其之上的主题匹配。

Holmes的历史

最初版本的Holmes是在msg systems工作时编写的,这是一家总部位于慕尼黑附近的大型国际IT咨询公司。Holmes部分基于更早前另一家雇主开发的概念,这些概念在一项美国专利中有所描述。目前Holmes在某机构维护,该专利现由某中心控制。得益于某中心和msg systems的善意与开放,得以在某机构继续维护该库,并首次在宽松的MIT许可证下提供。这意味着人们现在可以自由使用它,并可以根据需要进行扩展,而无需担心专利或其他法律问题。

1. 结构匹配

用户可以告诉Holmes要查找的概念,指定一个短语和识别单个词的策略,然后由库来查找复杂的示例。

1.1 识别同一概念的不同表达方式

像spaCy的Matcher这样的工具是执行信息提取的有效方式:Matcher允许用户指定词汇和语法特征,以便在大量文档中查找短语。然而,由于同一件事可以用多种不同的方式表达(见图1),这通常需要许多规则来捕捉一个单一概念。这种变化体现在两个层面。一方面,四个例子具有不同的表层语法结构;另一方面,像acquire、buy和take over这样的词组被用作同义词,而像公司这样的实体的具体实例则有MaxLinear和Datto等名称。

图1:宣布公司收购的不同标题

Holmes结构匹配的目标是抽象掉这两种类型的变化,使用户能够专注于他们想要提取的信息。可以告诉Holmes“一家公司收购另一家公司”是要查找的概念,指定识别公司名称和“收购”同义词的策略,然后由库来查找复杂示例,而无需编写大量额外规则。

1.2 推导句子结构的含义

短语内单词之间的语法关系决定了这些单词的个体含义如何组合形成短语的整体含义。驱动此过程的规则适用于任何共享给定结构的短语,无论涉及的具体单词是什么(见图2)。Holmes的核心是一组规则,这些规则将由标准spaCy模型输出的句法表层结构转换为相应的底层语义结构。与典型的基于规则的系统不同(那些系统为特定任务开发规则,并处理该任务特有的单词和短语),这些被称为元规则的规则:

  • 描述语言的基本语法和语义结构
  • 对任何涉及用该语言书写的文本的任务都有效
  • 作为核心库的标准、静态部分进行维护

图2:平行的语法结构

例如,从图2“结构2”行中的句子推导出正确语义结构所需的元规则,将处理识别被动结构“is … by”并为被动动词的论元分配正确的语义角色;而“结构3”和“结构4”行所需的元规则将处理由名词和分词构成的复合词。

谓词逻辑 任何句子传达的含义都可以使用谓词逻辑来捕捉。例如,句子“The child gave the dog a bone”表达了一个一阶谓词逻辑表示:give(child, dog, bone),将谓词give与论元childdogbone联系起来。实际上,能够为语料库中的每个句子推导出正确的逻辑结构可以被视为自然语言理解的“圣杯”:一台真正理解文本含义的机器可能远远超出了通过图灵测试的水平!Holmes远未设定如此雄心勃勃的目标,而是使用其元规则来转换句法分析树,使得表达相同含义的句子呈现出匹配的语义结构。元规则及其生成的结构虽然深受谓词逻辑的启发,但并不旨在对应于任何严格的形式化、逻辑或语言学理论表示:它们只做任何能够有效匹配含义的事情。

图3:具有共同语义结构的不同句子

图3展示了四个具有不同语法形式但都呈现出共同语义结构的句子。请注意,在每种情况下,只有词汇词(承载独立含义的词)在转换后保留在语义结构中,而像“a”和“the”这样的语法词则被抽象掉了。

虽然图3中的示例涉及单个一阶谓词逻辑,但真实文本中的大多数句子使用从属关系和关系从句等策略来表达高阶逻辑结构。一个词可以同时作为一个谓词逻辑的论元和另一个谓词逻辑的谓词(图4中的“give”)。并且像关系从句(图5)和控制结构(图6)这样的语言现象可以产生非树形的语义图结构。主流解析算法旨在生成树,这是我们依赖标准spaCy模型和元规则的组合来生成Holmes语义结构的原因之一,而不是试图训练模型直接从原始文本生成它们。

共指消解 如图1中前两个句子所示,像“it”这样的代词通常指回文本中较早出现的名词。代词重新实例化其先行词的含义,该含义构成了包含该代词的任何谓词逻辑的一部分,而无需明确重新表达该名词。Holmes通过在后台调用一个名为Coreferee的库来解析代词和其他照应语。尽管Coreferee用于各种项目,但它是为支持Holmes而编写的,并专注于与Holmes相关的共指类型。像Holmes本身一样,Coreferee诞生于msg systems,基于spaCy,属于spaCy生态,现在在某机构维护。

1.3 将搜索短语与文档匹配

如果Holmes使用的语义结构最好表示为图,那么库用户如何以简单的方式指定他们想要搜索的内容?最方便的解决方案镜像了待搜索文档本身的处理方式:用户编写简单的句子或短语,从中推导出由正确的语义关系链接的相关词汇词组成的语义结构。这些搜索短语最好想象为模板,它们匹配文档语料库中所有位置对应的概念。

图7:搜索短语与文档匹配

搜索短语必须基于单个句子,该句子对应于一个单一的spaCy依存树,其根部有一个单词。每当注册一个新的搜索短语时,Holmes会生成一个可以匹配其根词的所有单词的列表;每当向语料库添加一个新文档时,Holmes会将该文档包含的所有单词添加到一个倒排索引中。匹配搜索短语首先查询倒排索引,以找到文档语料库中与该搜索短语根词匹配的所有单词。对于每个这样的单词,然后执行子图匹配,以检查其周围的结构是否也与搜索短语的其余部分相对应。

编写搜索短语 编写有效的搜索短语最初可能有些违反直觉。搜索短语最好用语法正确的语言表达(例如“a dog chases a cat”),而不是仅仅作为单词的集合(例如“dog chase cat”),因为尽管搜索短语中的语法词(在这种情况下是两个“a”)在推导其语义结构的过程中会被抽象掉,但包含它们可以确保spaCy解析器和元规则正确理解所表达的内容。

1.4 匹配单个单词的含义

Holmes总是匹配同一个词的不同形式(例如“company”匹配“companies”;“go”匹配“went”)。然而,该库的真正威力在于其将语义子图匹配与另外四种策略相结合的能力,这极大地扩展了搜索短语中单个单词与被搜索文档中单个单词之间的匹配范围:

  1. 基于派生关系的匹配:Holmes可以匹配共享相同词干的相关词(例如“inform”匹配“information”)。利用这种关系需要元规则来捕捉两个词类周围各种语法结构之间的意义对应关系。例如,“a lawyer accuses”应该匹配“an accusation by a lawyer”,但不匹配“an accusation of a lawyer”。请注意,依赖关系可能以相反方向匹配,例如“adopting a resolution”(依赖关系以“adopting”为首)匹配“the adopted resolution”(依赖关系以“resolution”为首)。

  2. 基于实体的匹配:spaCy模型识别并标记属于命名实体类(如人物、公司、地点)的标记。Holmes允许在搜索短语中使用形式为ENTITY<label>的占位符来指定命名实体类,其中<label>表示spaCy模型分配给被搜索文档中标记或跨度的实体标签。例如,搜索短语“An ENTITYPERSON visits an ENTITYGPE”将匹配文档句子“Richard Hudson visited Berlin”。安装Holmes后,可以通过输入或复制下面的Python代码亲自尝试。

    import holmes_extractor as holmes
    manager = holmes.Manager("en_core_web_trf", number_of_workers=1)
    manager.register_search_phrase("An ENTITYPERSON visits an ENTITYGPE")
    manager.parse_and_register_document("Richard Hudson visited Berlin")
    print(manager.match())
    
  3. 基于本体的匹配:本体捕捉单词之间的关系,如同义关系(两个词含义相同,例如“dog”和“hound”)、上下位关系(一个词是另一个词的具体类型,例如“puppy”是“dog”的一种)和类成员关系(例如“Fido”是“dog”类的一个命名个体)。可以向Holmes提供外部手工制作的本体,该本体捕捉所提取信息的问题领域中术语之间的关系,Holmes在匹配搜索短语时会考虑它:在搜索文档中匹配给定搜索短语单词的单词范围将扩展到包括由该单词的同义词、下位词和命名个体形成的子树。下位词和同义关系是可传递的,这样的子树包括下位词的下位词、下位词的下位词的下位词、下位词的同义词等等。例如,使用图8中的本体,搜索短语“An animal yawns”将匹配文档短语“The puppy yawned”。 图8:本体内的关系

  4. 基于词向量的匹配:在标准spaCy模型中,语言中的每个单词都与一个词向量相关联——一个多维向量,表示单词的含义,源自用于训练模型的语料库中该单词出现的各种上下文。两个单词含义的相似性可以通过测量它们的词向量之间的夹角来近似估计:使用这种技术,spaCy估计“dog”和“puppy”的相似度为85.9%;“dog”和“horse”的相似度为62.5%;“dog”和“pencil”的相似度为20.8%。Holmes允许规定,当潜在匹配中单词对的平均词向量相似度高于可配置的阈值时,搜索短语应匹配文档语料库中的段落。

构建本体 本体以标准OWL格式存储,可以使用优秀的开源工具Protégé创建和管理。但请注意,只有在想使用与示例中不同的本体尝试基于本体的匹配时才需要下载Protégé,并且完全可以在没有任何本体的情况下使用Holmes。

1.5 尝试结构匹配

图1示例中的四个句子可以使用单个搜索短语进行匹配,该搜索短语使用基于实体的匹配策略来查找公司名称,并使用基于本体的匹配策略来捕捉“take over”的同义词:

  1. 下载Protégé并创建一个本体,将“purchase”、“acquire”、“buy”、“take over”和“takeover”定义为一组同义词。请注意,只需选择其中一个单词并将其他四个定义为其等价词即可实现;Holmes随后将推断该组内剩余的同义关系。以RDF/XML格式保存本体,文件名为holmes_test.owl。或者,[在此处下载holmes_test.owl]。
  2. 安装Holmes并输入或复制下面的Python代码。
    # 设置
    import holmes_extractor as holmes
    ontology = holmes.Ontology("holmes_test.owl")
    manager = holmes.Manager("en_core_web_trf", ontology=ontology, number_of_workers=1)
    
    # 注册搜索短语
    manager.register_search_phrase("An ENTITYORG takes over an ENTITYORG")
    
    # 解析文档
    manager.parse_and_register_document("Royal Bank of Scotland announces it intends to acquire Brewin Dolphin", "1")
    manager.parse_and_register_document("Chipmaker MaxLinear Inc announced on Thursday it will buy Silicon Motion Technology Corp for nearly $4 billion.", "2")
    manager.parse_and_register_document("Last month, cybersecurity company Mandiant was purchased by Alphabet", "3")
    manager.parse_and_register_document("The Datto takeover by the company Kaseya", "4")
    
    # 执行匹配
    matches = manager.match()
    
    # 检查所有文档是否匹配
    print(len(matches)) # -> 4
    
    # 提取进行收购的公司
    print([match['word_matches'][0]['document_phrase'] for match in matches]) # -> ['Royal Bank', 'Chipmaker MaxLinear Inc', 'Alphabet', 'Kaseya']
    
    # 提取被收购的公司
    print([match['word_matches'][2]['document_phrase'] for match in matches]) # -> ['Brewin Dolphin', 'Silicon Motion Technology Corp', 'cybersecurity company Mandiant', 'Datto']
    

2. 主题匹配

在主题匹配中,几个较小的“短语片段”各自独立地与文档语料库进行匹配,然后汇总结果。

2.1 用短语片段捕捉模糊含义

到目前为止,我们一直在研究结构匹配:搜索短语用于检索文档语料库中与其语义结构完全相同的段落。这种机制优先考虑精确度而非召回率:搜索短语越大,文档语料库中任何段落匹配它的可能性就越小。Holmes提供的第二种搜索机制——主题匹配,则优先考虑召回率而非精确度,关注文档是关于什么的,而不是它们具体说了什么。

我们看到,针对文档语料库的结构匹配将每个搜索短语作为一个单一的语义图整体使用。另一方面,主题匹配基于一个搜索查询,该查询也被转换为一个或多个语义结构,但Holmes会继续从这些语义结构中推导出迷你搜索短语,每个包含一个或两个词汇词,称之为短语片段(图9)。这些短语片段各自独立地与文档语料库进行匹配,结果被汇总:一个主题匹配是多个短语片段匹配的集合。 图9:短语片段的生成

虽然结构匹配中使用的搜索短语必须符合若干规则,因此需要由专家用户特意编写,但主题匹配可以由任何文本驱动,当无法控制搜索输入的内容和质量时,这很有用。

适合选择主题匹配的情况包括:

  • 由实时输入的短查询驱动的智能搜索
  • 在文档语料库中搜索与另一篇直接用作长查询以驱动搜索的现有文档主题相同的段落
  • 每当信息源包含关于特定主题的帖子时触发警报

制定有效的搜索查询 与结构匹配的搜索短语一样,主题匹配的搜索查询最好表述为完整、合乎语法的句子(例如“a dog chases a cat”),而不是标准搜索引擎中典型的松散单词集合(例如“dog chase cat”)。

2.2 为主题匹配评分

主题匹配根据多种因素进行评分,包括:

  • 构成主题匹配的短语片段匹配在文档中彼此接近的程度
  • 短语片段匹配是由一个还是两个单词组成,两个单词的匹配得分高得多
  • 是否有任何两个单词的短语片段匹配重叠
  • 匹配到的单词在语料库中的稀有程度
  • 由于单词通过词向量相似度或本体关系而非直接匹配而产生的任何不确定性

获得高分的主题匹配的文档段落将在彼此紧密接近的位置表达查询短语中包含的许多相同语义关系,因此很可能呈现类似的概念或至少关注相同的主题。

作为问答系统的主题匹配 由主题匹配驱动的智能搜索支持额外的单词匹配策略,从而实现问答。如果搜索查询中的第一个单词是例如“Where”,Holmes会将该单词匹配到文档语料库中的空间状语短语,如“In the kitchen”,并将此类短语作为潜在答案返回。请注意,主题匹配的模糊性意味着此类短语是否真正回答了所提出的问题,取决于从查询短语推导出的其他短语片段是否也在相同的语法结构中匹配。这可以通过计算查询短语与其自身匹配所得的分数,并检查给定主题匹配的分数与该理论最大值的接近程度来确定。

2.3 确保可接受的性能

主题匹配过程利用了许多性能优化,包括:

  • 从两个单词中在文档语料库中出现频率较低的那个开始匹配两个单词的短语片段
  • 如果两个单词在文档语料库中都非常频繁,则完全不匹配两个单词的短语片段
  • 仅尝试对文档语料库中相对稀有的单词进行基于词向量的匹配

这些优化使得对包含数百万单词的文档语料库进行实时查询的主题匹配变得可行。然而,尽管主题匹配采用多处理以充分利用每台机器上所有可用的处理器,并且在其他方面具有水平和垂直可扩展性,但将其应用于真正庞大的语料库(如主流在线搜索引擎所爬取的语料库)仍然可能不具有成本效益。

2.4 尝试主题匹配

基于主题匹配的智能搜索在一个演示网站上有例证。用于英语的文档语料库由六部查尔斯·狄更斯的小说组成。所有匹配策略都处于活动状态。搜索引擎使用一个非常小而简单的本体,捕捉书中主要角色使用的名称之间的等价关系,例如“David”、“Copperfield”和“David Copperfield”形成一个同义词组。

您也可以亲自尝试主题匹配:安装Holmes并输入或复制下面的Python代码。

# 设置
import holmes_extractor as holmes
manager = holmes.Manager("en_core_web_trf", number_of_workers=1)

# 解析文档
manager.parse_and_register_document("The dog was thinking about whether he wanted to chase the neighbourhood cat.", "1")
manager.parse_and_register_document("The cat kept chasing around and was hoping she wouldn't see a dog anytime soon.", "2")
manager.parse_and_register_document("The children discussed dogs, cats and chasing", "3")

# 执行主题匹配
topic_matches = manager.topic_match_documents_against("Increasingly, his life's work appeared to revolve around watching dogs chasing cats.")

# 打印每个文档的分数
print([tm['document_label'] + ": " + str(tm['score']) for tm in topic_matches])

# 打印所有主题匹配信息
print(topic_matches)

3. 结论

我们已经看到,Holmes是一个通用的、开箱即用的工具,用于在英语或德语文本中进行信息提取和智能搜索。请花点时间尝试一下,或者看看演示网站。如果喜欢所看到的内容,请在社交媒体上分享您的体验或查看代码仓库。