【问题标题】:How to filter tokens from spaCy document如何从 spaCy 文档中过滤令牌
【发布时间】:2017-07-28 14:02:38
【问题描述】:

我想使用 spaCy 解析文档并应用令牌过滤器,以便最终的 spaCy 文档不包含过滤后的令牌。我知道我可以过滤令牌序列,但我对拥有实际的Doc 结构很感兴趣。

text = u"This document is only an example. " \
    "I would like to create a custom pipeline that will remove specific tokesn from the final document."

doc = nlp(text)

def keep_token(tok):
    # This is only an example rule
    return tok.pos_ not not in {'PUNCT', 'NUM', 'SYM'}

final_tokens = list(filter(keep_token, doc))

# How to get a spacy.Doc from final_tokens?

我试图从令牌列表中重建一个新的 spaCy Doc,但 API 不清楚如何做到这一点。

【问题讨论】:

    标签: python nlp spacy


    【解决方案1】:

    我很确定到目前为止你已经找到了你的解决方案,但是因为它没有在这里发布,所以我认为添加它可能会有用。

    您可以通过将 doc 转换为 numpy 数组、从 numpy 数组中删除然后再转换回 doc 来删除标记。

    代码:

    import spacy
    from spacy.attrs import LOWER, POS, ENT_TYPE, IS_ALPHA
    from spacy.tokens import Doc
    import numpy
    
    def remove_tokens_on_match(doc):
        indexes = []
        for index, token in enumerate(doc):
            if (token.pos_  in ('PUNCT', 'NUM', 'SYM')):
                indexes.append(index)
        np_array = doc.to_array([LOWER, POS, ENT_TYPE, IS_ALPHA])
        np_array = numpy.delete(np_array, indexes, axis = 0)
        doc2 = Doc(doc.vocab, words=[t.text for i, t in enumerate(doc) if i not in indexes])
        doc2.from_array([LOWER, POS, ENT_TYPE, IS_ALPHA], np_array)
        return doc2
    
    # load english model
    nlp  = spacy.load('en')
    doc = nlp(u'This document is only an example. \
    I would like to create a custom pipeline that will remove specific tokens from \
    the final document.')
    print(remove_tokens_on_match(doc))
    

    您可以查看我回答的类似问题 here

    【讨论】:

    • 这种方法不是违背了使用numpy数组的目的吗?也就是说,如果您有大量文本,则遍历 doc 中的所有标记以检查其标记,然后转换为 numpy 数组,然后再转换为 doc,在计算上是低效的。直接在列表理解中过滤标签不是更快吗?我正在寻找一种方法来一次性过滤掉文档中的标记,而不必遍历标记,这就是我希望 numpy 技巧能做到的。但是,您的代码仍会遍历文档中的每个标记,从而导致计算速度变慢。有什么想法吗?
    【解决方案2】:

    根据您想要做什么,有几种方法。

    1.获取原始文档

    SpaCy 中的令牌引用了他们的文档,因此您可以这样做:

    original_doc = final_tokens[0].doc
    

    这样你仍然可以从原句中获取 PoS、解析数据等。

    2。构造一个没有删除标记的新文档

    您可以在所有标记的字符串后面加上空格并创建一个新文档。有关text_with_ws 的信息,请参阅token docs

    doc = nlp(''.join(map(lambda x: x.text_with_ws, final_tokens)))
    

    这可能不会给你你想要的 - PoS 标签不一定是相同的,结果句子可能没有意义。

    如果这些都不是您的想法,请告诉我,也许我可以提供帮助。

    【讨论】:

    • 我知道第二种解决方案,这基本上是我们目前正在做的解决方法。但它有两个问题:1. PoS 标签可能会随着您准确指出而改变 2. 您需要重新解析文档,因此性能下降。
    • 你能解释一下你拿到文件后要做什么吗?为什么要删除令牌?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 2020-01-24
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多