我试图确保spacy
将点视为单独的令牌,除非它在两位数字之间。我注意到nlp.Defaults.infixes
广泛使用环视运算符,因此我遵循了示例:
infixes = nlp.Defaults.infixes + (r'''[;,:]''',
r'(?<=[a-zA-Z_])[\.^]', r'[\.^](?=[a-zA-Z_])',
)
infix_regex = spacy.util.compile_infix_regex(infixes)
nlp.tokenizer.infix_finditer = infix_regex.finditer
现在大写字母的行为符合预期:
list(nlp.tokenizer('HELLO.WORLD'))
[HELLO, ., WORLD]
但是如果右侧为小写,则失败:
list(nlp.tokenizer('HELLO.world'))
[HELLO.world]
list(nlp.tokenizer('hello.world'))
[hello.world]
list(nlp.tokenizer('hello.WORLD'))
[hello, ., WORLD]
另一个示例,正则表达式查找括号而不是斜杠:
infixes = nlp.Defaults.infixes + (r'(?<=[a-zA-Z_])[\.\(\)/](?=[a-zA-Z_])', )
infix_regex = spacy.util.compile_infix_regex(infixes)
nlp.tokenizer.infix_finditer = infix_regex.finditer
tests = [
'mid(inferior',
'mid/inferior',
'left.mid',
'left.mid/inferior']
pattern = re.compile(r'(?<=[a-zA-Z_])[\.\(\)/](?=[a-zA-Z_])')
for tt in tests:
print("-"*20)
print(pattern.split(tt))
print(list(nlp.tokenizer(tt)))
结果:
--------------------
['mid', 'inferior']
[mid, (, inferior]
--------------------
['mid', 'inferior']
[mid, /, inferior]
--------------------
['left', 'mid']
[left.mid]
--------------------
['left', 'mid', 'inferior']
[left.mid/inferior]
正如人们所看到的那样,由于某种原因,正则表达式不会在点上分割,如果单词不是纯字母,则不会在斜杠上分割,即使上述正则表达式不成问题
答案 0 :(得分:2)
这里的问题是中缀模式的顺序。它使用找到的第一个匹配项,而另一个infix模式在您的模式之前匹配。您可以先添加自定义模式:
infixes = (r'(?<=[a-zA-Z_])[\.\(\)/](?=[a-zA-Z_])', ) + nlp.Defaults.infixes
这可能会导致其他模式的副作用,尤其是如果您首先添加非常短的模式,因此在进行更改之前和之后都要仔细检查数据的总体标记化准确性,以确保其工作符合预期。这样可能很好,但是您可能需要在中间而不是在开始时添加模式以获得预期的结果。
编辑:
这无效,因为URL模式首先进入。
print(nlp.tokenizer.explain("HELLO.world"))
# [('URL_MATCH', 'HELLO.world')]
如果您不关心URL标记化,则可以设置:
nlp.tokenizer.url_match = None
删除将与令牌中的.
和/
进行很多交互的URL匹配。