Тонкая настройка GPT-2

Я пытаюсь точно настроить GPT-2 для задачи: если я даю пять последовательных чисел, каковы следующие последовательные числа. Например, если input_text = "one | two | three | four | five", output_text = "six | seven... | ten".

Важные части модели, которую я использовал через API huggingface, следующие:

      class Model(pl.LightningModule):
    def __init__(self, 
                 tokenizer, 
                 lr: float) -> None:
        super().__init__()
        self.lr = lr
        self.tokenizer = Tokenizer(tokenizer)
        self.model = GPT2LMHeadModel.from_pretrained('gpt2')
        
    def common_step(self, batch: Tuple[List[str], List[str]]) -> torch.FloatTensor:
        questions, answers = batch
        combined = [input + " <EOS> " + output for input, output in zip(questions, answers)]
        tokens = {k: v.to(self.device) for k, v in self.tokenizer(combined).items()}
        
        labels = tokens["input_ids"].clone()
        labels[tokens["attention_mask"]==0] = -100

        outputs = self.model(
            input_ids=tokens["input_ids"], 
            attention_mask=tokens["attention_mask"],
            labels=labels, 
            return_dict=True
        )
        
        return outputs["loss"]
    
    def training_step(self, batch: Tuple[List[str], List[str]], *args) -> torch.FloatTensor:
        loss = self.common_step(batch)
        return loss
        
    def generate_examples(self, batch):
        questions, answers = batch
        combined = [question + " <EOS> " for question in questions]
        tokens = {k: v.to(self.device) for k, v in self.tokenizer(combined).items()}

        generated = self.model.generate(
            input_ids=tokens["input_ids"], 
            attention_mask=tokens["attention_mask"], 
        )

        print(questions[0])
        print("="*30)
        print(self.tokenizer.decode(generated[0]))

В результате я пытаюсь выдать цифры, но, к сожалению, выглядит так. Вывод начинается с того места, где отображается тег, иначе это просто копирование. Обратите внимание, что в токенизаторе GPT-2 нет:

      Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.
<|endoftext|>five thousand, five hundred and ninety-one| five thousand, five hundred and ninety-two| five thousand, five hundred and ninety-three| five thousand, five hundred and ninety-four| five thousand, five hundred and ninety-five <EOS> <|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|> fifteen thousand, four hundred and thirty-six| ten thousand, six hundred and sixty-seven| fifteen thousand and sixty‑eight| 15 thousand and eighty-nine| fifteen hundred and seventy<|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|>

Итак, вопрос в том, почему он генерирует возможного кандидата после кучи токенов <|endoftext|>. В обучающем наборе объедините ввод и вывод с помощью слова "" (это не фактический токен), и результат будет сразу без каких-либо дополнений.

Это связано с используемым мной токенизатором, который я определил ниже?

      # make sure GPT2 appends EOS in begin and end
def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
    outputs = [self.bos_token_id] + token_ids_0 + [self.eos_token_id]
    return outputs
    
GPT2Tokenizer.build_inputs_with_special_tokens = build_inputs_with_special_tokens
gpt2_tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# set pad_token_id to unk_token_id -> be careful here as unk_token_id == eos_token_id == bos_token_id
gpt2_tokenizer.pad_token = gpt2_tokenizer.unk_token

Рабочий пример на colab можно найти здесь .

0 ответов

Другие вопросы по тегам