Как вычисляются векторы токенов в spacy-pytorch-transformers
В настоящее время я работаю с spacy-pytorch-transformer
пакет, чтобы поэкспериментировать с соответствующими вложениями.
При чтении вводной статьи (по сути, GitHub README) я понял, что вложения на уровне токенов являются средним значением по сравнению с встраиванием всех соответствующих частей слова, т.е.embed(complex)
будет таким же, как 1/2 * embed(comp#) * embed(#lex)
.
Согласно статье BERT, это должно просто использовать last_hidden_state
свойство сети, но мой MCVE ниже показывает, что это не то же самое для Spacy 2.1.8 и spacy-pytorch-transformers 0.4.0, по крайней мере, для BERT и RoBERTa (не проверял это для других моделей):
import spacy
import numpy as np
nlp = spacy.load("en_pytt_robertabase_lg") # either this or the BERT model
test = "This is a test" # Note that all tokens are directly aligned, so no mean has to be calculated.
doc = nlp(test)
# doc[0].vector and doc.tensor[0] are equal, so the results are equivalent.
print(np.allclose(doc[0].vector, doc._.pytt_last_hidden_state[1, :]))
# returns False
Смещение 1 для скрытых состояний связано с <CLS>
токен в качестве первого входа, который соответствует задаче классификации предложений; Я даже проверил с любым доступным другим токеном для своего предложения (у которого нет проблем с выравниванием токенов согласноdoc._.pytt_alignment
), так что я никак не могу здесь что-то пропустить.
Согласно исходному коду, соответствующий хук перезаписывается просто для возврата соответствующей строки в тензоре, поэтому я не вижу здесь никакого преобразования. Есть ли что-то очевидное, чего мне здесь не хватает, или это отклоняется от ожидаемого поведения?
1 ответ
Похоже, что за этим стоит более сложная схема взвешивания, которая также учитывает [CLS]
а также [SEP]
токены выходят в каждой последовательности.
Это также было подтверждено сообщением о проблеме от разработчиков spaCy.
К сожалению, похоже, что эта часть кода с тех пор переименована в spacy-transformers
.