在 spaCy 的自定义句子边界中使用 POS 和 PUNCT 标记

Using POS and PUNCT tokens in custom sentence boundaries in spaCy

我正在尝试使用 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()

当前输出
句子:['In the add user use case,',
'我们需要考虑速度和可靠性,
'so the use of a relational DB would be better than using SQLite.',
'Though it may take extra effort to convert @Bot']

我建议不要尝试对 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 的关系),保存子句,然后根据词根添加另一个句子.