【问题标题】:What is the difference between token and span (a slice from a doc) in spaCy?spaCy中的token和span(来自文档的切片)有什么区别?
【发布时间】:2020-03-11 13:40:07
【问题描述】:

我想知道spaCy中的tokenspan有什么区别。

我们必须使用 span 的主要原因是什么?为什么我们不能简单地使用 token 来做任何 NLP?特别是当我们使用 spaCy 匹配器

背景简介: 当我想在使用返回 'match_id' 的 spaCy matcher 之后获取 span 的索引(它在 string doc 中的确切索引而不是它在 spaCy doc 中的有序索引)时,我的问题出现了, 'start' 和 'end',所以我可以从这些信息中得到 span,而不是令牌。 然后我需要创建一个training_data,它需要一个句子中单词的精确索引。如果我可以访问令牌,我可以简单地使用 token.idx 但 span 没有!所以我必须编写额外的代码来找到它的句子中单词的索引(与span相同)!

【问题讨论】:

    标签: python nlp token spacy


    【解决方案1】:

    您可以像访问列表一样访问跨度内的令牌:

    import spacy
    nlp = spacy.load('en')
    text = "This is a sentence."
    doc = nlp(text)
    span = doc[2:4]
    span_char_start = span[0].idx
    span_char_end = span[-1].idx + len(span[-1].text)
    assert text[span_char_start:span_char_end] == "a sentence"
    

    【讨论】:

      【解决方案2】:

      TokenSpan

      在 spaCy 的文档中,Token 代表文档中的单个单词、标点符号、空格等,而 Span 是文档中的切片。换句话说,SpanTokens 的有序序列。

      为什么是Spans?

      spaCy 的Matcher 提供Span 级别的信息而不是Token 级别,因为它允许匹配Tokens 的序列。就像Span 可以仅由 1 个Token 组成一样,情况不一定如此。

      考虑以下示例。我们单独匹配Token"hello",单独匹配Token"world",以及由Tokens "hello""world" 组成的Span

      >>> import spacy
      >>> nlp = spacy.load("en")
      >>> from spacy.matcher import Matcher
      >>> matcher = Matcher(nlp.vocab)
      >>> matcher.add(1, None, [{"LOWER": "hello"}])
      >>> matcher.add(2, None, [{"LOWER": "world"}])
      >>> matcher.add(3, None, [{"LOWER": "hello"}, {"LOWER": "world"}])
      

      对于"Hello world!",所有这些模式都匹配:

      >>> document = nlp("Hello world!")
      >>> [(token.idx, token) for token in document]
      [(0, Hello), (6, world), (11, !)]
      >>> matcher(document)
      [(1, 0, 1), (3, 0, 2), (2, 1, 2)]
      

      但是,第 3 个模式与 "Hello, world!" 不匹配,因为 "Hello""world" 不是连续的 Tokens(因为 "," Token),所以它们不匹配形成Span:

      >>> document = nlp("Hello, world!")
      >>> [(token.idx, token) for token in document]
      [(0, Hello), (5, ,), (7, world), (12, !)]
      >>> matcher(document)
      [(1, 0, 1), (2, 2, 3)]
      

      Spans 访问Tokens

      尽管如此,您应该能够通过迭代 Span 从 span 中获取 Token 级别的信息,就像在 Doc 中迭代 Tokens 一样。

      >>> document = nlp("Hello, world!")
      >>> span, type(span)
      (Hello, world, <class 'spacy.tokens.span.Span'>)
      >>> [(token.idx, token, type(token)) for token in span]
      [(0, Hello, <class 'spacy.tokens.token.Token'>), (5, ,, <class 'spacy.tokens.token.Token'>), (7, world, <class 'spacy.tokens.token.Token'>)]
      

      【讨论】:

      • 谢谢你,很好的解释
      • 注意idx是文档中的span索引。我更喜欢 token/word 索引,即 token.i per:spacy.io/api/token
      猜你喜欢
      • 2014-08-07
      • 2014-06-19
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 2016-04-22
      • 2017-03-15
      • 2012-09-19
      • 2017-07-13
      相关资源
      最近更新 更多