Следующий код без партии:
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
.
Только время, когда можно получить желаемый результат, - без пакетных настроек и маски внимания (теперь кажется, это не имеет значения, потому что это все равно не имеет никакого эффекта)
Затем я нашел this, в котором было предложено использовать 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?