在 SpaCy 中使用 PhraseMatcher 查找多种匹配类型
Using PhraseMatcher in SpaCy to find multiple match types
SpaCy 文档和示例表明 PhraseMatcher class 可用于匹配文档中的标记序列。必须提供将要匹配的序列词汇表。
在我的应用程序中,我的文档是标记和短语的集合。有不同类型的实体。数据是远程自然语言(文档是一组具有半随机顺序的关键字)。我正在尝试查找多种类型的匹配项。
例如:
yellow boots for kids
如何使用 SpaCy 的 PhraseMatches 找到颜色(例如黄色)、产品类型(例如靴子)和年龄(例如儿童)的匹配项?这是一个很好的用例吗?如果不同的实体匹配重叠(例如颜色在颜色列表和材料列表中匹配),是否可以产生所有独特的情况?
我不能真正使用序列标注器,因为数据结构松散且充满歧义。我有一个实体列表(例如颜色、年龄、产品类型)和相关值列表。
一个想法是实例化多个 PhraseMatcher 对象,每个实体一个,分别进行匹配,然后合并结果。每个实体类型都会有自己的词汇表。这听起来很简单,但效率不高,尤其是合并部分。值列表相当大。在走这条路之前,我想知道这是否是个好主意,或者是否有更简单的方法可以使用 SpaCy 来做到这一点。
spaCy 的 PhraseMatcher
支持添加包含多个模式的多个规则,并为您添加的每个匹配器规则分配 ID。如果两个规则重叠,则两个匹配项都将被 returned。所以你可以这样做:
color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]
matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)
当您在 doc
上调用 matcher
时,spaCy 将 return 一个包含 (match_id, start, end)
个元组的列表。因为 spaCy 将所有字符串存储为整数,所以您返回的 match_id
也将是一个整数 - 但您始终可以通过在词汇表的 StringStore
中查找来获得字符串表示形式,即 nlp.vocab.strings
:
doc = nlp("yellow fabric")
matches = matcher(doc)
for match_id, start, end in matches:
rule_id = nlp.vocab.strings[match_id] # get the unicode ID, i.e. 'COLOR'
span = doc[start : end] # get the matched slice of the doc
print(rule_id, span.text)
# COLOR yellow
# MATERIAL yellow fabric
添加匹配器规则时,还可以定义一个on_match
callback function作为Matcher.add
的第二个参数。如果您想触发特定操作,这通常很有用 - 例如,如果找到 COLOR
匹配项,则执行一件事,如果找到 PRODUCT
匹配项,则执行其他操作。
如果你想更优雅地解决这个问题,你可能还想考虑将你的匹配器与 custom pipeline component or custom attributes 结合起来。例如,您可以编写一个简单的组件,当您在文本上调用 nlp()
时自动 运行,找到匹配项,并设置 Doc._.contains_product
或 Token._.is_color
属性。文档中有一些示例可以帮助您入门。
SpaCy 文档和示例表明 PhraseMatcher class 可用于匹配文档中的标记序列。必须提供将要匹配的序列词汇表。
在我的应用程序中,我的文档是标记和短语的集合。有不同类型的实体。数据是远程自然语言(文档是一组具有半随机顺序的关键字)。我正在尝试查找多种类型的匹配项。
例如:
yellow boots for kids
如何使用 SpaCy 的 PhraseMatches 找到颜色(例如黄色)、产品类型(例如靴子)和年龄(例如儿童)的匹配项?这是一个很好的用例吗?如果不同的实体匹配重叠(例如颜色在颜色列表和材料列表中匹配),是否可以产生所有独特的情况?
我不能真正使用序列标注器,因为数据结构松散且充满歧义。我有一个实体列表(例如颜色、年龄、产品类型)和相关值列表。
一个想法是实例化多个 PhraseMatcher 对象,每个实体一个,分别进行匹配,然后合并结果。每个实体类型都会有自己的词汇表。这听起来很简单,但效率不高,尤其是合并部分。值列表相当大。在走这条路之前,我想知道这是否是个好主意,或者是否有更简单的方法可以使用 SpaCy 来做到这一点。
spaCy 的 PhraseMatcher
支持添加包含多个模式的多个规则,并为您添加的每个匹配器规则分配 ID。如果两个规则重叠,则两个匹配项都将被 returned。所以你可以这样做:
color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]
matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)
当您在 doc
上调用 matcher
时,spaCy 将 return 一个包含 (match_id, start, end)
个元组的列表。因为 spaCy 将所有字符串存储为整数,所以您返回的 match_id
也将是一个整数 - 但您始终可以通过在词汇表的 StringStore
中查找来获得字符串表示形式,即 nlp.vocab.strings
:
doc = nlp("yellow fabric")
matches = matcher(doc)
for match_id, start, end in matches:
rule_id = nlp.vocab.strings[match_id] # get the unicode ID, i.e. 'COLOR'
span = doc[start : end] # get the matched slice of the doc
print(rule_id, span.text)
# COLOR yellow
# MATERIAL yellow fabric
添加匹配器规则时,还可以定义一个on_match
callback function作为Matcher.add
的第二个参数。如果您想触发特定操作,这通常很有用 - 例如,如果找到 COLOR
匹配项,则执行一件事,如果找到 PRODUCT
匹配项,则执行其他操作。
如果你想更优雅地解决这个问题,你可能还想考虑将你的匹配器与 custom pipeline component or custom attributes 结合起来。例如,您可以编写一个简单的组件,当您在文本上调用 nlp()
时自动 运行,找到匹配项,并设置 Doc._.contains_product
或 Token._.is_color
属性。文档中有一些示例可以帮助您入门。