spaCy 中的令牌和跨度(来自文档的切片)有什么区别?

What is the difference between token and span (a slice from a doc) in spaCy?

我想知道 tokenspanspaCy 中有什么区别.

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

简要背景: 在使用 spaCy matcher which returns 'match_id'、'start' 和 'end',这样我就可以跨出这些信息,而不是令牌。 然后我需要创建一个 training_data ,它需要句子中单词的精确索引。如果我可以访问令牌,我可以简单地使用 token.idx 但 span 没有那个!所以我不得不写额外的代码来找到单词的索引(与跨度相同)在它的句子中!

您可以像访问列表一样访问范围内的令牌:

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"

Token 对比 Span

根据 spaCy 的文档,Token represents a single word, punctuation symbol, whitespace, etc. from a document, while a Span 是文档的一部分。换句话说,SpanToken 的有序序列。

为什么 Spans?

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

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

>>> 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)]

但是,第三个模式与 "Hello, world!" 不匹配,因为 "Hello""world" 不是连续的 Token(因为 "," 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 从跨度中获取 Token 级别的信息,就像您可以在 Token 中迭代一样Doc.

>>> 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'>)]