Spacy - 标记引用字符串
Spacy - Tokenize quoted string
我正在使用 spacy 2.0 并使用带引号的字符串作为输入。
示例字符串
"The quoted text 'AA XX' should be tokenized"
并期待提取
[The, quoted, text, 'AA XX', should, be, tokenized]
然而,我在试验时得到了一些奇怪的结果。名词 chunks 和 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])
结果
[The, quoted, text, ', AA, XX, ', should, be, tokenized]
[The quoted text 'AA XX]
[AA XX']
解决我需要的最好方法是什么
虽然您可以修改分词器并添加您自己的排除引号的自定义前缀、后缀和中缀规则,但我不确定这是这里的最佳解决方案。
对于您的用例,添加 component to your pipeline that merges (certain) quoted strings into one token before the tagger, parser and entity recognizer are called. To accomplish this, you can use the rule-based Matcher
并查找被 '
包围的标记组合可能更有意义。以下模式查找一个或多个字母数字字符:
pattern = [{'ORTH': "'"}, {'IS_ALPHA': True, 'OP': '+'}, {'ORTH': "'"}]
Here's a visual example 交互式匹配器演示中的模式。要进行合并,您可以设置 Matcher
,添加模式并编写一个函数,该函数接受一个 Doc
对象,提取匹配的跨度并通过调用 [=16] 将它们合并为一个标记=]方法。
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']
为了更优雅的解决方案,您还可以将组件重构为可重用的 class,在其 __init__
方法中设置匹配器(例如 see the docs)。
如果您首先在管道中添加组件,所有其他组件(如标记器、解析器和实体识别器)将只能看到重新标记的 Doc
。这也是为什么您可能想要编写更具体的模式,这些模式只合并您关心的某些带引号的字符串。在您的示例中,新的标记边界 改善了 预测——但我也可以想到许多其他情况,它们不会,特别是如果引用的字符串更长并且包含很大一部分句子.
我正在使用 spacy 2.0 并使用带引号的字符串作为输入。
示例字符串
"The quoted text 'AA XX' should be tokenized"
并期待提取
[The, quoted, text, 'AA XX', should, be, tokenized]
然而,我在试验时得到了一些奇怪的结果。名词 chunks 和 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])
结果
[The, quoted, text, ', AA, XX, ', should, be, tokenized]
[The quoted text 'AA XX]
[AA XX']
解决我需要的最好方法是什么
虽然您可以修改分词器并添加您自己的排除引号的自定义前缀、后缀和中缀规则,但我不确定这是这里的最佳解决方案。
对于您的用例,添加 component to your pipeline that merges (certain) quoted strings into one token before the tagger, parser and entity recognizer are called. To accomplish this, you can use the rule-based Matcher
并查找被 '
包围的标记组合可能更有意义。以下模式查找一个或多个字母数字字符:
pattern = [{'ORTH': "'"}, {'IS_ALPHA': True, 'OP': '+'}, {'ORTH': "'"}]
Here's a visual example 交互式匹配器演示中的模式。要进行合并,您可以设置 Matcher
,添加模式并编写一个函数,该函数接受一个 Doc
对象,提取匹配的跨度并通过调用 [=16] 将它们合并为一个标记=]方法。
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']
为了更优雅的解决方案,您还可以将组件重构为可重用的 class,在其 __init__
方法中设置匹配器(例如 see the docs)。
如果您首先在管道中添加组件,所有其他组件(如标记器、解析器和实体识别器)将只能看到重新标记的 Doc
。这也是为什么您可能想要编写更具体的模式,这些模式只合并您关心的某些带引号的字符串。在您的示例中,新的标记边界 改善了 预测——但我也可以想到许多其他情况,它们不会,特别是如果引用的字符串更长并且包含很大一部分句子.