我正在寻找一种方法来确保序列"#*"
出现在文本中的任何时间,spacy给了我令牌"#*"
。我尝试了各种可能的方式来添加add_special_case
的特殊情况,使用prefix_search
,suffix_search
,infix_finditer
和token_match
构建自定义标记生成器,但是仍然有一些情况当"#*"
出现在句子中时,即使它被不奇怪的标记包围(应该无问题地识别标记),"#*"
也会被拆分为[#,*]。
我该怎么办?
谢谢。
我正在寻找一种方法来确保序列"#*"
出现在文本中的任何时间,spacy给了我令牌"#*"
。我尝试了各种可能的方式来添加add_special_case
的特殊情况,使用prefix_search
,suffix_search
,infix_finditer
和token_match
构建自定义标记生成器,但是仍然有一些情况当"#*"
出现在句子中时,即使它被不奇怪的标记包围(应该无问题地识别标记),"#*"
也会被拆分为[#,*]。
我该怎么办?
谢谢。
Spacy当前对特殊情况的处理不理想,因为特殊情况下包含前缀或后缀的字符并不是在所有情况下都符合您的期望。
使用文本的外观和标记无效的示例来回答这个问题要容易一些,但是:
如果#*
始终被空白包围,则应使用特殊情况:
nlp.tokenizer.add_special_case("#*",[{"ORTH": "#*"}])
print([t.text for t in nlp("a #* a")]) # ['a','#*','a']
如果应该像#*
这样的单词对to
进行标记,则一个选项是从前缀和后缀中删除#
和*
,然后将这些字符与t
或o
的处理方式没有任何不同。相邻的标点符号将被分割为附加词,相邻的字母/数字则不会。
如果#*
可能与#*a
或a#*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',"'","'"]
这是使用刚刚添加了令牌生成器的新调试功能的一个很好的案例(免责声明:我是作者)。对于spacy v2.2.3,请尝试:
nlp.tokenizer.explain('#*')
输出[('PREFIX','#'),('SUFFIX','*')]
告诉您哪些模式负责最终的标记化。修改模式时,此功能可以让您更轻松地查看修改是否按预期进行。
在上面的最后一个示例中进行修改后,输出为:
nlp.tokenizer.explain("a#* a#*a #*a '#*'")
# [('TOKEN','a'),'#*'),('TOKEN',('INFIX',('PREFIX',"'"),"'")]