Spacy - Tokenize引用字符串

use*_*007 6 nlp python-3.x spacy

我正在使用spacy 2.0并使用带引号的字符串作为输入.

示例字符串

"The quoted text 'AA XX' should be tokenized"
Run Code Online (Sandbox Code Playgroud)

并期望提取

[The, quoted, text, 'AA XX', should, be, tokenized]
Run Code Online (Sandbox Code Playgroud)

然而,我在尝试时得到了一些奇怪的结果.Noun chunk和ents失去了其中一个引用.

import spacy
nlp = spacy.load('en')
s = "The quoted text 'AA XX' should be tokenized"
doc = nlp(s)
print([t for t in doc])
print([t for t in doc.noun_chunks])
print([t for t in doc.ents])
Run Code Online (Sandbox Code Playgroud)

结果

[The, quoted, text, ', AA, XX, ', should, be, tokenized]
[The quoted text 'AA XX]
[AA XX']
Run Code Online (Sandbox Code Playgroud)

解决我需要什么的最佳方法是什么

Ine*_*ani 11

虽然您可以修改标记生成器并添加自己的自定义前缀,后缀和中缀规则来排除引号,但我不确定这是否是最佳解决方案.

对于您的用例,在调用标记器,解析器和实体识别器之前,将组件添加到管道中可能更有意义,该组件将(某些)引用的字符串合并到一个标记中.要实现此目的,您可以使用基于规则Matcher并查找包围的标记组合'.以下模式查找一个或多个字母数字字符:

pattern = [{'ORTH': "'"}, {'IS_ALPHA': True, 'OP': '+'}, {'ORTH': "'"}]
Run Code Online (Sandbox Code Playgroud)

这是交互式匹配器演示中模式的可视化示例.要进行合并,您可以设置Matcher,添加模式并编写一个接受Doc对象的函数,提取匹配的跨度并通过调用它们的.merge方法将它们合并为一个标记.

import spacy
from spacy.matcher import Matcher

nlp = spacy.load('en')
matcher = Matcher(nlp.vocab)
matcher.add('QUOTED', None, [{'ORTH': "'"}, {'IS_ALPHA': True, 'OP': '+'}, {'ORTH': "'"}])

def quote_merger(doc):
    # this will be called on the Doc object in the pipeline
    matched_spans = []
    matches = matcher(doc)
    for match_id, start, end in matches:
        span = doc[start:end]
        matched_spans.append(span)
    for span in matched_spans:  # merge into one token after collecting all matches
        span.merge()
    return doc

nlp.add_pipe(quote_merger, first=True)  # add it right after the tokenizer
doc = nlp("The quoted text 'AA XX' should be tokenized")
print([token.text for token in doc])
# ['The', 'quoted', 'text', "'AA XX'", 'should', 'be', 'tokenized']
Run Code Online (Sandbox Code Playgroud)

对于更优雅的解决方案,您还可以将组件重构为可重用的类,以便在其__init__方法中设置匹配器(请参阅文档以获取示例).

如果您首先在管道中添加组件,那么所有其他组件(如标记器,解析器和实体识别器)将只能看到重新标记的组件Doc.这也是为什么你可能想要编写更具体的模式,只合并你关心的某些引用字符串.在您的示例中,新的令牌边界改进了预测 - 但我也可以想到许多其他情况,但是我没有,特别是如果引用的字符串更长并且包含句子的重要部分.