заполнение и маска внимания не работают должным образом при пакетном вводе в модели языка GPT - PullRequest
0 голосов
/ 07 марта 2020

Следующий код без пакета:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()
context=torch.tensor([tokenizer.encode("This is")])
output, past = model(context)
token = torch.argmax(output[..., -1, :])
print(tokenizer.decode(token.item()))

output: ' a'

Работает нормально. Теперь я расширил это до настройки пакета:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()

context=[torch.tensor(tokenizer.encode("This is ")),torch.tensor(tokenizer.encode("Hello How are "))]
context=pad_sequence(context,batch_first=True)

mask=torch.tensor([[1,1,0],[1,1,1]])
output, past = model(context,attention_mask=mask)
token = torch.argmax(output[..., -1, :],dim=1)
tokenizer.decode(token)

output: '\n you'

Здесь \n - следующий токен для первого контекста, а you - следующий токен для второго контекста пакета. Но ожидаемый следующий токен для первого контекста - a, так как все настройки одинаковы. Кроме того, если вы уменьшите второй контекст до 2 токенов, вы получите a в этом параметре пакета. Так ясно, модель не может понять, отступы. Кроме того, маска внимания не работает. Потому что после заполнения следующий токен последовательности this is равен 0 (нулю). И согласно маске внимания ([1,1,0]), этого нуля следует избегать, и должны присутствовать только жетоны this и is. Доказательства того, что эта маскировка внимания не работает:

  • Используйте маску внимания [1,1,1], что означает присутствие даже на нулевом заполнении, вы получите тот же результат, который \n.

  • Используйте строку this is!. Здесь ! имеет нулевой индекс в словарной матрице. Снова вы получаете тот же вывод, который равен \n.

. Только раз можно получить желаемый результат без настроек пакета и маски внимания (теперь кажется, что это не так). важно, потому что это никак не влияет)

Тогда я нашел это , в котором предлагалось использовать pad_token. Поэтому я использовал следующее:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch
from torch.nn.utils.rnn import pad_sequence  

tokenizer = GPT2Tokenizer.from_pretrained("gpt2",pad_token="<PAD>")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()

context=[torch.tensor(tokenizer.encode("This is <PAD> ")),torch.tensor(tokenizer.encode("Hello How are"))]
context=torch.stack(context)
print(context)
mask=torch.tensor([[1,1,0],[1,1,1]])

output, past = model(context,attention_mask=mask)
token = torch.argmax(output[..., -1, :],dim=1)
tokenizer.decode(token)

output: 'The you'

Здесь The - следующий токен для первого контекста, а you - следующий токен для второго контекста пакета. Это тоже не работает. Потому что The не ожидается для первого контекста.

Как использовать последовательность переменной длины в пакетном режиме в модели gpt / gpt2?

1 Ответ

0 голосов
/ 10 марта 2020

Я не уверен, поможет ли это, но вам не нужно реализовывать свои собственные маскировки внимания и заполнения. Библиотека Transformers предоставляет функции encode_plus () и batch_encode_plus () , которые будут выполнять токенизацию, генерировать маски внимания и выполнять заполнение для вас. Результаты выдаются в виде Python словарей.

...