如何添加特定子字符串以在 spaCy 中标记化?
How can I add a specific substring to tokenize on in spaCy?
我正在使用 spaCy
对字符串进行标记化,该字符串可能包含特定的子字符串。如果存在子字符串,我希望 spaCy
将子字符串视为标记,而不管它有任何其他规则。我想保持所有其他规则不变。这可能吗?
举个具体的例子,假设感兴趣的子串是'banana'
;我希望 'I like bananabread.'
被标记为 ['I', 'like', 'banana', 'bread', '.']
。
从这里我该何去何从(请记住,我想保持分词器规则的其余部分完好无损)?我尝试将 'banana'
添加到前缀、后缀和中缀,但没有成功。
标记化发生在 spaCy 管道的开头,因此您应该先对文本进行预处理。
我写了一个函数,它使用正则表达式来填充复合词中的子字符串:
import re
text = 'I eat bananas and bananabread at the bookstore.'
def separate_compound_toks(text):
anti_compound = sorted(['banana', 'store'])
anti_compound = "|".join(t.lower() for t in anti_compound)
# pad word from end
pattern_a = re.compile(r'(?i)({sub})(?=[a-z]{{3,}})'.format(sub=anti_compound))
text = re.sub(pattern_a, r' ', text)
# pad word from beginning
pattern_b = re.compile(r'(?i)(?<![^a-z])({sub})'.format(sub=anti_compound))
text = re.sub(pattern_b, r' ', text)
return text
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp(separate_compound_toks(text))
print([tok.text for tok in doc])
# ['I', 'eat', 'bananas', 'and', 'banana', 'bread', 'at', 'the', 'book', 'store', '.']
将字符串添加为前缀、后缀和中缀应该可行,但根据您使用的 spacy 版本,您可能 运行 在测试时遇到缓存错误。此错误已在 v2.2+ 中修复。
使用 spacy v2.3.2:
import spacy
nlp = spacy.load("en_core_web_sm")
text = "I like bananabread."
assert [t.text for t in nlp(text)] == ['I', 'like', 'bananabread', '.']
prefixes = ("banana",) + nlp.Defaults.prefixes
suffixes = ("banana",) + nlp.Defaults.suffixes
infixes = ("banana",) + nlp.Defaults.infixes
prefix_regex = spacy.util.compile_prefix_regex(prefixes)
suffix_regex = spacy.util.compile_suffix_regex(suffixes)
infix_regex = spacy.util.compile_infix_regex(infixes)
nlp.tokenizer.prefix_search = prefix_regex.search
nlp.tokenizer.suffix_search = suffix_regex.search
nlp.tokenizer.infix_finditer = infix_regex.finditer
assert [t.text for t in nlp(text)] == ['I', 'like', 'banana', 'bread', '.']
(在 v2.1 或更早版本中,tokenizer 自定义仍然适用于新加载的 nlp
,但如果您已经使用 nlp
管道处理了一些文本,然后修改设置,错误在于它会使用缓存中存储的标记化而不是新设置。)
我正在使用 spaCy
对字符串进行标记化,该字符串可能包含特定的子字符串。如果存在子字符串,我希望 spaCy
将子字符串视为标记,而不管它有任何其他规则。我想保持所有其他规则不变。这可能吗?
举个具体的例子,假设感兴趣的子串是'banana'
;我希望 'I like bananabread.'
被标记为 ['I', 'like', 'banana', 'bread', '.']
。
从这里我该何去何从(请记住,我想保持分词器规则的其余部分完好无损)?我尝试将 'banana'
添加到前缀、后缀和中缀,但没有成功。
标记化发生在 spaCy 管道的开头,因此您应该先对文本进行预处理。
我写了一个函数,它使用正则表达式来填充复合词中的子字符串:
import re
text = 'I eat bananas and bananabread at the bookstore.'
def separate_compound_toks(text):
anti_compound = sorted(['banana', 'store'])
anti_compound = "|".join(t.lower() for t in anti_compound)
# pad word from end
pattern_a = re.compile(r'(?i)({sub})(?=[a-z]{{3,}})'.format(sub=anti_compound))
text = re.sub(pattern_a, r' ', text)
# pad word from beginning
pattern_b = re.compile(r'(?i)(?<![^a-z])({sub})'.format(sub=anti_compound))
text = re.sub(pattern_b, r' ', text)
return text
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp(separate_compound_toks(text))
print([tok.text for tok in doc])
# ['I', 'eat', 'bananas', 'and', 'banana', 'bread', 'at', 'the', 'book', 'store', '.']
将字符串添加为前缀、后缀和中缀应该可行,但根据您使用的 spacy 版本,您可能 运行 在测试时遇到缓存错误。此错误已在 v2.2+ 中修复。
使用 spacy v2.3.2:
import spacy
nlp = spacy.load("en_core_web_sm")
text = "I like bananabread."
assert [t.text for t in nlp(text)] == ['I', 'like', 'bananabread', '.']
prefixes = ("banana",) + nlp.Defaults.prefixes
suffixes = ("banana",) + nlp.Defaults.suffixes
infixes = ("banana",) + nlp.Defaults.infixes
prefix_regex = spacy.util.compile_prefix_regex(prefixes)
suffix_regex = spacy.util.compile_suffix_regex(suffixes)
infix_regex = spacy.util.compile_infix_regex(infixes)
nlp.tokenizer.prefix_search = prefix_regex.search
nlp.tokenizer.suffix_search = suffix_regex.search
nlp.tokenizer.infix_finditer = infix_regex.finditer
assert [t.text for t in nlp(text)] == ['I', 'like', 'banana', 'bread', '.']
(在 v2.1 或更早版本中,tokenizer 自定义仍然适用于新加载的 nlp
,但如果您已经使用 nlp
管道处理了一些文本,然后修改设置,错误在于它会使用缓存中存储的标记化而不是新设置。)