Я просмотрел ответы здесь и т. д., но они, похоже, относятся к разным случаям, когда нарезка out.last_hidden_state пошла не так, что для меня не верно.
Некоторая предыстория
Я изучаю использование преобразователей для последовательности белка анализ, в частности интерфейс преобразователей Hugging Face с моделью ProtBERT. У меня есть опыт работы с Python/биологией, но я довольно новичок в библиотеках глубокого обучения и языковых моделях.
Я узнал, что к встраиваниям (для меня) на удивление трудно получить доступ, а документация несколько противоречива/неточна (см., например, здесь).
Кроме того, интерфейсы поведения моделей непоследовательны, например, модели ESM имеют другой интерфейс ввода данных, чем модели BERT, в которых Модели BERT ожидают (только один пример пошагового руководства), что отдельные остатки будут разделены пробелами, а ESM не ожидает отсутствия пробелов. Я предполагаю, что это может быть связано с первоначальным использованием BERT для НЛП человеческого языка, в котором предполагается, что пробелы разделяют слова как токены, а не отдельные символы, имеющие семантическое содержание, как для биологических последовательностей. Это означает, что вам придется предварительно обрабатывать последовательности с помощью таких махинаций, как:
Код: Выделить всё
sequence_examples = [" ".join(list(sequence)) for sequence in sequence_examples]
Пример
Вот MWE поведения:
Код: Выделить всё
from transformers import BertModel, BertTokenizer
import random
tokenizer = BertTokenizer.from_pretrained("Rostlab/prot_bert", do_lower_case=False, truncation=True )
model = BertModel.from_pretrained("Rostlab/prot_bert")
ALPHABET = list("ACDEFGHIJKLMNPQRSTVWY")
for i in range(26):
aas = random.choices(ALPHABET, k=20)
peptide = " ".join(aas)
peptide_no_ws = "".join(aas)
encoded_input = tokenizer(peptide, return_tensors="pt", max_length=24)
outputs = model(**encoded_input)
print(peptide)
print(outputs.last_hidden_state[:, 0, :])
encoded_input = tokenizer(peptide_no_ws, return_tensors="pt", max_length=24)
outputs = model(**encoded_input)
print(peptide_no_ws)
print(outputs.last_hidden_state[:, 0, :])
Код: Выделить всё
T N F S J I L M D R C E A K Y G P V W H
tensor([[ 0.0759, 0.1376, 0.0564, ..., -0.0675, -0.0184, -0.0030]], # different!!!
grad_fn=)
TNFSJILMDRCEAKYGPVWH
tensor([[-0.1096, 0.0474, -0.0857, ..., -0.0035, -0.0569, 0.0918]], # SAME!!!
grad_fn=)
G I L P J T N K A R H Q E V Y W F M D C
tensor([[ 0.0725, 0.1307, 0.0652, ..., -0.0378, -0.0352, -0.0315]], # different!!!
grad_fn=)
GILPJTNKARHQEVYWFMDC
tensor([[-0.1096, 0.0474, -0.0857, ..., -0.0035, -0.0569, 0.0918]], # SAME!!!
Код: Выделить всё
tensor([[-0.1096, 0.0474, -0.0857, ..., -0.0035, -0.0569, 0.0918]],
grad_fn=)
Заметка о правильном способе доступа к встраиваниям
Я до сих пор не совсем уверен, каков канонический способ доступа к встраиваниям. Неудивительно, что некоторые из доступных ресурсов сами по себе представляют собой результаты LLM и, следовательно, не особенно надежны, а некоторые ответы, например. здесь, хотя фон высокого качества не так явен. Я также слышал из уст в уста, что иногда Last_hidden_states.mean(axis=1) является путем.
Независимо от конкретного пути, который я выбираю, они обеспечивают качественное поведение, аналогичное MWE, указанному выше, хотя точные значения могут отличаться.
Подробнее здесь: https://stackoverflow.com/questions/797 ... whitespace
Мобильная версия