【问题标题】:Using POS and PUNCT tokens in custom sentence boundaries in spaCy在 spaCy 的自定义句子边界中使用 POS 和 PUNCT 标记
【发布时间】:2021-09-21 06:24:06
【问题描述】:

我正在尝试使用 spaCy 将句子拆分为子句,以便使用 MLLib 进行分类。我已经搜索了两种我认为最好的解决方案之一,但运气不太好。

  1. 选项:将使用文档中的标记,即 token.pos_SCONJ 匹配并拆分为一个句子。

  2. 选项:将使用 spaCy 所拥有的任何值作为它标识为 SCONJ 的值的字典来创建一个列表

1 的问题是我只有 .text、.i 和没有 .pos_ 作为自定义边界(据我所知,需要在解析器之前运行。

2 的问题是我似乎找不到字典。这也是一种非常 hacky 的方法。

import deplacy
from spacy.language import Language

# Uncomment to visualise how the tokens are labelled
# deplacy.render(doc)

custom_EOS = ['.', ',', '!', '!']
custom_conj = ['then', 'so']


@Language.component("set_custom_boundaries")
def set_custom_boundaries(doc):
    for token in doc[:-1]:
        if token.text in custom_EOS:
            doc[token.i + 1].is_sent_start = True
        if token.text in custom_conj:
            doc[token.i].is_sent_start = True
    return doc


def set_sentence_breaks(doc):
    for token in doc:
        if token == "SCONJ":
            doc[token.i].is_sent_start = True


def main():
    text = "In the add user use case, we need to consider speed and reliability " \
           "so use of a relational DB would be better than using SQLite. Though " \
           "it may take extra effort to convert @Bot"

    nlp = spacy.load("en_core_web_sm")
    nlp.add_pipe("set_custom_boundaries", before="parser")
    doc = nlp(text)
    # for token in doc:
    #     print(token.pos_)

    print("Sentences:", [sent.text for sent in doc.sents])


if __name__ == "__main__":
    main()

电流输出
句子:['在添加用户用例中,',
'我们需要考虑速度和可靠性,
'所以使用关系数据库会比使用 SQLite 更好。',
'虽然转换@Bot可能需要额外的努力']

【问题讨论】:

    标签: python nlp spacy sentence


    【解决方案1】:

    我建议不要尝试用 is_sent_starts 做任何聪明的事情 - 虽然它是用户可访问的,但它真的不打算以这种方式使用,并且有 at least one unresolved issue 与之相关。

    由于您只需要其他分类器的这些划分,因此您只需获取字符串就足够了,对吧?在这种情况下,我建议您像往常一样运行 spaCy 管道,然后在 SCONJ 令牌上拆分句子(如果仅使用 SCONJ 适用于您的用例)。比如:

    out = []
    for sent in doc.sents:
        last = sent[0].i
        for tok in sent:
            if tok.pos_ == "SCONJ":
                out.append(doc[last:tok.i])
                last = tok.i + 1
        out.append(doc[last:sent[-1].i])
    

    或者,如果这还不够好,您可以使用依赖解析来识别子句,以查找子句中的动词(例如,通过它们与 SCONJ 的关系),保存子句,然后根据词根添加另一个句子。

    【讨论】:

    • 感谢您的回复。我想使用可能被认为是子句分隔的“最佳实践”解决方案来实施,您提供了一个非常有用的答案。
    猜你喜欢
    • 1970-01-01
    • 2016-03-10
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多