【问题标题】:Why does spaCy not preserve intra-word-hyphens during tokenization like Stanford CoreNLP does?为什么 spaCy 不像斯坦福 CoreNLP 那样在标记化过程中保留单词内连字符?
【发布时间】:2019-02-17 00:26:05
【问题描述】:

SpaCy 版本:2.0.11

Python 版本:3.6.5

操作系统:Ubuntu 16.04

我的句子样本:

Marketing-Representative- won't die in car accident.

Out-of-box implementation

预期代币:

["Marketing-Representative", "-", "wo", "n't", "die", "in", "car", "accident", "."]

["Out-of-box", "implementation"]

SpaCy 标记(默认标记器):

["Marketing", "-", "Representative-", "wo", "n't", "die", "in", "car", "accident", "."]

["Out", "-", "of", "-", "box", "implementation"]

我尝试创建自定义标记器,但它无法处理 spaCy 使用 tokenizer_exceptions 处理的所有边缘情况(代码如下):

import spacy
from spacy.tokenizer import Tokenizer
from spacy.util import compile_prefix_regex, compile_infix_regex, compile_suffix_regex
import re
nlp = spacy.load('en')
prefix_re = compile_prefix_regex(nlp.Defaults.prefixes)
suffix_re = compile_suffix_regex(nlp.Defaults.suffixes)
infix_re = re.compile(r'''[.\,\?\:\;\...\‘\’\`\“\”\"\'~]''')

def custom_tokenizer(nlp):
    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search,
                                suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer,
                                token_match=None)
nlp.tokenizer = custom_tokenizer(nlp)
doc = nlp("Marketing-Representative- won't die in car accident.")
for token in doc:
    print(token.text)

输出:

Marketing-Representative-
won
'
t
die
in
car
accident
.

我需要有人指导我采取适当的方法。

在上面的正则表达式中进行更改可以做到这一点或任何其他方法,或者我什至尝试了 spaCy 的基于规则的匹配器,但无法创建规则来处理两个以上单词之间的连字符,例如“开箱即用”,以便可以创建匹配器以与 span.merge() 一起使用。

无论哪种方式,我都需要让包含单词内连字符的单词成为斯坦福 CoreNLP 处理的单个标记。

【问题讨论】:

    标签: python-3.x nlp spacy


    【解决方案1】:

    虽然没有记录在 spacey usage site

    看起来我们只需要为我们正在使用的 *fix 添加regex,在本例中为中缀。

    此外,我们似乎可以使用自定义 regex 扩展 nlp.Defaults.prefixes

    infixes = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.)")
    

    这会给你想要的结果。无需将默认设置为 prefixsuffix,因为我们不使用它们。

    import spacy
    from spacy.tokenizer import Tokenizer
    from spacy.util import compile_prefix_regex, compile_infix_regex, compile_suffix_regex
    import re
    
    nlp = spacy.load('en')
    
    infixes = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.)")
    
    infix_re = spacy.util.compile_infix_regex(infixes)
    
    def custom_tokenizer(nlp):
        return Tokenizer(nlp.vocab, infix_finditer=infix_re.finditer)
    
    nlp.tokenizer = custom_tokenizer(nlp)
    
    s1 = "Marketing-Representative- won't die in car accident."
    s2 = "Out-of-box implementation"
    
    for s in s1,s2:
        doc = nlp("{}".format(s))
        print([token.text for token in doc])
    

    结果

    $python3 /tmp/nlp.py  
    ['Marketing-Representative-', 'wo', "n't", 'die', 'in', 'car', 'accident', '.']  
    ['Out-of-box', 'implementation']  
    

    您可能想要修复插件正则表达式,使其对于接近应用正则表达式的其他类型的标记更加健壮。

    【讨论】:

    • 感谢您的回复。您的解决方案运行良好,尽管我仍然无法修复自定义标记器生成的标记(“Marketing-Representative-”)中的尾随连字符。不过我正在努力。
    • 为什么要这样做;中缀 = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.)")
    • 不仅如此;中缀 = nlp.Defaults.prefixes + (r"[-]~")?
    • 中缀的第一个和最后一个模式是什么 = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.) ")?
    【解决方案2】:

    我也想要修改spacy的销价,以更紧密地匹配Corenlp的语义。下面粘贴的是我想出的,它解决了这个线程中的连字符问题(包括尾随连字符)和一些额外的修复。我不得不复制默认的infix表达式并对它们进行修改,但能够简单地追加新的后缀表达式:

    
    import spacy
    from spacy.lang.char_classes import ALPHA, ALPHA_LOWER, ALPHA_UPPER
    from spacy.lang.char_classes import CONCAT_QUOTES, LIST_ELLIPSES, LIST_ICONS
    
    def initializeTokenizer(nlp):
    
        prefixes = nlp.Defaults.prefixes 
        
        infixes = (
            LIST_ELLIPSES
            + LIST_ICONS
            + [
                r'(?<=[0-9])[+\-\*^](?=[0-9-])',
                r'(?<=[{al}{q}])\.(?=[{au}{q}])'.format(
                    al=ALPHA_LOWER, au=ALPHA_UPPER, q=CONCAT_QUOTES
                ),
                # REMOVE: commented out regex that splits on hyphens between letters:
                #r"(?<=[{a}])(?:{h})(?=[{a}])".format(a=ALPHA, h=HYPHENS),
                # EDIT: remove split on slash between letters, and add comma
                #r'(?<=[{a}0-9])[:<>=/](?=[{a}])'.format(a=ALPHA),
                r'(?<=[{a}0-9])[:<>=,](?=[{a}])'.format(a=ALPHA),
                # ADD: ampersand as an infix character except for dual upper FOO&FOO variant
                r'(?<=[{a}0-9])[&](?=[{al}0-9])'.format(a=ALPHA, al=ALPHA_LOWER),
                r'(?<=[{al}0-9])[&](?=[{a}0-9])'.format(a=ALPHA, al=ALPHA_LOWER),
            ]
        )
    
        # ADD: add suffix to split on trailing hyphen
        custom_suffixes = [r'[-]']
        suffixes = nlp.Defaults.suffixes
        suffixes = tuple(list(suffixes) + custom_suffixes)
    
        infix_re = spacy.util.compile_infix_regex(infixes)
        suffix_re = spacy.util.compile_suffix_regex(suffixes)
    
        nlp.tokenizer.suffix_search = suffix_re.search
        nlp.tokenizer.infix_finditer = infix_re.finditer
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多