有了spacy,如何确保字母序列永远不会分割成令牌

问题描述 投票:0回答:1

我正在寻找一种方法来确保序列"#*"出现在文本中的任何时间,spacy给了我令牌"#*"。我尝试了使用add_special_case添加特殊情况的所有可能方法,使用prefix_searchsuffix_searchinfix_finditertoken_match构建自定义标记生成器,但是仍然有一些情况,如果句子中出现"#*" ,即使当它被不奇怪的标记包围(应该无问题地识别标记)时,"#*"也会被拆分为[#,*]。我该怎么办?

谢谢。

python nlp tokenize spacy
1个回答
0
投票

Spacy当前对特殊字符包含特殊字符或前缀或后缀的特殊情况的处理不是理想的,也不是您在所有情况下都期望的。

这将更容易回答一些示例,这些示例显示文本的外观以及在哪里标记化无效,但是:

如果#*始终被空白包围,则应使用特殊情况:

nlp.tokenizer.add_special_case("#*", [{"ORTH": "#*"}])
print([t.text for t in nlp("a #* a")]) # ['a', '#*', 'a']

如果将#*标记为类似于to的单词,则一个选项是从前缀和后缀中删除#*,然后将这些字符与t区别对待或o。相邻的标点符号将被分割为缀,而相邻的字母/数字则不会。

如果#*可能与#*aa#*a"#*"之类的其他字符相邻,则将其添加为前缀,后缀和中缀可能是最简单的,将其添加到默认模式之前,以便像#这样的默认模式不首先匹配:

prefixes = ("#\*",) + nlp.Defaults.prefixes
nlp.tokenizer.prefix_search = spacy.util.compile_prefix_regex(prefixes).search
suffixes = ("#\*",) + nlp.Defaults.suffixes
nlp.tokenizer.suffix_search = spacy.util.compile_suffix_regex(suffixes).search
infixes = ("#\*",) + nlp.Defaults.infixes + ("#\*",)
nlp.tokenizer.infix_finditer = spacy.util.compile_infix_regex(infixes).finditer

print([t.text for t in nlp("a#* a#*a #*a '#*'")])
# ['a', '#*', 'a', '#*', 'a', '#*', 'a', "'", '#*', "'"]

这是使用刚刚添加了令牌生成器的新调试功能的一个很好的案例(免责声明:我是作者)。对于spacy v2.2.3,请尝试:

nlp.tokenizer.explain('#*')

输出[('PREFIX', '#'), ('SUFFIX', '*')]告诉您哪些模式负责最终的标记化。修改模式时,此功能应使您可以更轻松地查看修改是否按预期进行。

在上面的最后一个示例中进行修改之后,输出为:

nlp.tokenizer.explain("a#* a#*a #*a '#*'")
# [('TOKEN', 'a'), ('SUFFIX', '#*'), ('TOKEN', 'a'), ('INFIX', '#*'), ('TOKEN', 'a'), ('PREFIX', '#*'), ('TOKEN', 'a'), ('PREFIX', "'"), ('PREFIX', '#*'), ('SUFFIX', "'")]
© www.soinside.com 2019 - 2024. All rights reserved.