连字词的空格标记化 [英] spaCy - Tokenization of Hyphenated words

查看:14
本文介绍了连字词的空格标记化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

再见,

我正在尝试对连接的单词进行后处理,这些单词被标记为单独的标记,而它们本应是一个单独的标记。例如:

Example:

Sentence: "up-scaled"
Tokens: ['up', '-', 'scaled']
Expected: ['up-scaled']

目前,我的解决方案是使用匹配器:

matcher = Matcher(nlp.vocab)
pattern = [{'IS_ALPHA': True, 'IS_SPACE': False},
           {'ORTH': '-'},
           {'IS_ALPHA': True, 'IS_SPACE': False}]

matcher.add('HYPHENATED', None, pattern)

def quote_merger(doc):
    # this will be called on the Doc object in the pipeline
    matched_spans = []
    matches = matcher(doc)
    for match_id, start, end in matches:
        span = doc[start:end]
        matched_spans.append(span)
    for span in matched_spans:  # merge into one token after collecting all matches
        span.merge()
    #print(doc)
    return doc

nlp.add_pipe(quote_merger, first=True)  # add it right after the tokenizer
doc = nlp(text)

但是,这将导致以下预期问题:

Example 2:

Sentence: "I know I will be back - I had a very pleasant time"
Tokens: ['i', 'know', 'I', 'will', 'be', 'back - I', 'had', 'a', 'very', 'pleasant', 'time']
Expected: ['i', 'know', 'I', 'will', 'be', 'back', '-', 'I', 'had', 'a', 'very', 'pleasant', 'time']
是否有一种方法可以使我只能处理字符之间没有空格的由连字符分隔的单词?这样,像"Up-Scale"这样的单词将被匹配并组合成单个标记,而不是".."。Back-i..‘

非常感谢

编辑: 我已经尝试了发布的解决方案:Why does spaCy not preserve intra-word-hyphens during tokenization like Stanford CoreNLP does?

但是,我没有使用此解决方案,因为它导致带有撇号(‘)的单词和带有小数的数字的标记化错误:

Sentence: "It's"
Tokens: ["I", "t's"]
Expected: ["It", "'s"]

Sentence: "1.50"
Tokens: ["1", ".", "50"]
Expected: ["1.50"]

这就是我使用Matcher而不是尝试编辑正则表达式的原因。

推荐答案

匹配器实际上不是用于此的正确工具。您应该改为修改令牌化程序。

如果您希望保留处理其他所有内容的方式,并且只更改连字符的行为,则应该修改现有的中缀模式并保留所有其他设置。当前的英语中缀模式定义如下:

https://github.com/explosion/spaCy/blob/58533f01bf926546337ad2868abe7fc8f0a3b3ae/spacy/lang/punctuation.py#L37-L49

您可以在不定义定制记号赋值器的情况下添加新模式,但如果不定义定制记号赋值器,则无法删除模式。因此,如果您注释掉连字符模式并定义一个自定义标记器:

import spacy
from spacy.tokenizer import Tokenizer
from spacy.lang.char_classes import ALPHA, ALPHA_LOWER, ALPHA_UPPER, CONCAT_QUOTES, LIST_ELLIPSES, LIST_ICONS
from spacy.util import compile_infix_regex

def custom_tokenizer(nlp):
    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
            ),
            r"(?<=[{a}]),(?=[{a}])".format(a=ALPHA),
            #r"(?<=[{a}])(?:{h})(?=[{a}])".format(a=ALPHA, h=HYPHENS),
            r"(?<=[{a}0-9])[:<>=/](?=[{a}])".format(a=ALPHA),
        ]
    )

    infix_re = compile_infix_regex(infixes)

    return Tokenizer(nlp.vocab, prefix_search=nlp.tokenizer.prefix_search,
                                suffix_search=nlp.tokenizer.suffix_search,
                                infix_finditer=infix_re.finditer,
                                token_match=nlp.tokenizer.token_match,
                                rules=nlp.Defaults.tokenizer_exceptions)


nlp = spacy.load("en")
nlp.tokenizer = custom_tokenizer(nlp)
print([t.text for t in nlp("It's 1.50, up-scaled haven't")])
# ['It', "'s", "'", '1.50', "'", ',', 'up-scaled', 'have', "n't"]
在初始化新的令牌化器时,您确实需要提供当前的前缀/后缀/令牌_匹配设置,以保留现有的令牌化器行为。另请参阅(德语,但非常相似):https://stackoverflow.com/a/57304882/461847

编辑以添加(因为这看起来确实不必要地复杂,而且您确实应该能够重新定义中缀模式,而无需加载整个新的自定义记号赋值器):

如果您刚刚加载了模型(v2.1.8),并且还没有调用nlp(),您也可以只替换infix_re.finditer,而不创建自定义标记器:

nlp = spacy.load('en')
nlp.tokenizer.infix_finditer = infix_re.finditer

有一个缓存错误,有望在V2.2中得到修复,使其在任何时候都能正确工作,而不仅仅是在新加载的模型上。(否则这种行为非常令人困惑,这就是为什么在2.1.8版中创建自定义记号赋值器是更好的通用建议。)

这篇关于连字词的空格标记化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆