Я построил свою собственную модель Transformer в pytorch на основе «Внимание - все, что вам нужно» для выполнения задачи машинного перевода. Но, к сожалению, это не работает хорошо, потому что потеря поезда не уменьшается должным образом, а потеря проверки даже увеличивается. Кроме того, балл BLEU, который я использовал для оценки производительности модели, остается равным 0, что я не вижу причины. Я публикую эту топику c для получения совета по программированию трансформатора. Я не знаю, какая часть моего кода неверна, поэтому я думаю, что должен знать общую идею Transformer.
По моему мнению, сама модель не является проблемой, так как я ссылался на учебник блога по реализации Трансформаторы. Поэтому я думаю, что проблема заключается в предварительной обработке данных или процедуре обучения. Я подготовил набор данных на английском / французском языке, токенизировал его с помощью SentencePiece и предварительно обработал данные с помощью следующих форм.
ex) (En) tok1 tok2 tok3 tok4 => (Fr) tokA tokB tok C tokD
src_input: tok1 tok2 tok4 pad pad
tar_input: sos tokA tokB tok C tokD pad
tar_output: tokA tokB tok C tokD eos pad
Если мы говорим, что максимальная длина равна 6, тогда мы должны добавить отступы, как указано выше. И я хочу знать, что это правильный метод. Я поставил src_input в кодировщик и tar_input в декодер в качестве целевого ввода. Затем, после получения окончательного результата в форме (batch_size, max_len, target_vocab_size), я поместил этот слой LogSoftmax и рассчитал NllLoss с помощью tar_output.
Это коды предварительной обработки данных.
def add_padding(tokenized_text):
if len(tokenized_text) < seq_len:
left = seq_len - len(tokenized_text)
padding = [pad_id] * left
tokenized_text += padding
return tokenized_text
def process_src(text_list):
print("Tokenizing & Padding src data...")
tokenized_list = []
for text in tqdm(text_list):
tokenized = src_sp.EncodeAsIds(text.strip())
tokenized_list.append(add_padding(tokenized))
print(f"The shape of src data: {np.shape(tokenized_list)}")
return tokenized_list
def process_tar(text_list):
print("Tokenizing & Padding tar data...")
input_list = []
output_list = []
for text in tqdm(text_list):
tokenized = tar_sp.EncodeAsIds(text.strip())
input_tokenized = [sos_id] + tokenized
output_tokenized = tokenized + [eos_id]
input_list.append(add_padding(input_tokenized))
output_list.append(add_padding(output_tokenized))
print(f"The shape of tar(input) data: {np.shape(input_list)}")
print(f"The shape of tar(output) data: {np.shape(output_list)}")
return input_list, output_list
И это для обучения.
output = self.model(src_input, tar_input, encoder_mask, masked_attn_mask, attn_mask) # (B, L, vocab_size)
self.optim.zero_grad()
loss = self.criterion(output.view(-1, sp_vocab_size), tar_output.view(batch_size * seq_len))
loss.backward()
self.optim.step()
Пожалуйста, укажите, если я ошибаюсь.
Большое спасибо.