spaCy 中的令牌和跨度(来自文档的切片)有什么区别?
What is the difference between token and span (a slice from a doc) in spaCy?
我想知道 token 和 span 在 spaCy 中有什么区别.
另外,我们必须使用 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
是文档的一部分。换句话说,Span
是 Token
的有序序列。
为什么 Span
s?
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)]
从 Span
s
访问 Token
s
尽管如此,您应该能够通过迭代 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'>)]
我想知道 token 和 span 在 spaCy 中有什么区别.
另外,我们必须使用 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
是文档的一部分。换句话说,Span
是 Token
的有序序列。
为什么 Span
s?
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)]
从 Span
s
访问 Token
s
尽管如此,您应该能够通过迭代 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'>)]