首页 > 解决方案 > 使用转换器和 pytorch 微调因果语言模型

问题描述

我有一些关于使用转换器和 PyTorch 微调因果语言模型的问题。

我的主要目标是微调 XLNet。但是,我发现网上大部分的帖子都是针对文本分类的,比如这个帖子run_language_model.py我想知道,有没有办法在不使用from transformers 的 GitHub的情况下微调模型?

这是我尝试微调 XLNet 的一段代码:

model = XLNetLMHeadModel.from_pretrained("xlnet-base-cased")
tokenizer = XLNetTokenizer.from_pretrained("xlnet-base-cased", do_lower_case=True)
LOSS = torch.nn.CrossEntrypoLoss()
batch_texts = ["this is sentence 1", "i have another sentence like this", "the final sentence"]
encodings = tokenizer.encode_plus(batch_texts, add_special_tokens=True,
                                  return_tensors=True, return_attention_mask=True)
outputs = model(encodings["input_ids"], encodings["attention_mask"])
loss = LOSS(outputs[0], target_ids)
loss.backward()
# ignoring the rest of codes...

我卡在最后两行。起初,当使用这个 LM 模型时,我似乎没有labels像监督学习通常那样做;其次,作为最小化损失的语言模型(这里是交叉熵),我需要用target_ids来计算损失和困惑度input_ids

以下是我的后续问题:

  1. labels在模型拟合过程中我应该如何处理?
  2. 我应该设置一些类似target_ids=encodings["input_ids"].copy()计算交叉熵损失和困惑的东西吗?
  3. 如果没有,应该如何设置target_ids
  4. 从变形金刚文档的困惑页面中,我应该如何调整其方法以适应非固定长度的输入文本?
  5. 我从文档中看到另一篇文章说它需要填充文本来进行因果语言建模。但是,从 3) 中的链接来看,填充文本没有这样的标志。我应该关注哪一个?

任何建议和意见将不胜感激!

标签: python-3.xpytorchhuggingface-transformerslanguage-model

解决方案


当使用语言模型头微调模型时,标签本身就是下一个标记(您预测下一个单词)。Huggingface 的库通过将大部分过程的复杂性隐藏在他们的方法中,使很多事情变得非常容易,当你想做一些标准的事情时,这非常好。但是如果你想做一些特别的事情,或者如果你想学习和理解细节,我建议直接在pytorch中实现训练循环;编码低级的东西是最好的学习方式。

对于这种情况,这里有一个草稿开始;训练循环远未完成,但无论如何它必须适应每个具体情况,所以我希望这几行可以帮助开始......

model = GPT2LMHeadModel.from_pretrained('distilgpt2')
tokenizer = GPT2Tokenizer.from_pretrained('distilgpt2')
# our input:
s = tokenizer.encode('In winter, the weather is',return_tensors='pt')
# we want to fine-tune to force a fake output as follows:
ss = tokenizer.encode('warm and hot',return_tensors='pt')
# forward pass:
outputs = model(s)
# check that the outout logits are given for every input token:
print(outputs.logits.size())
# we're gonna train on the token that follows the last input one
# so we extract just the last logit:
lasty = outputs.logits[0,-1].view(1,-1)
# prepare backprop:
lossfct = torch.nn.CrossEntropyLoss()
optimizer = transformers.AdamW(model.parameters(), lr=5e-5)
# just take the first next token (you should repeat this for the next ones)
labels = ss[0][0].view(1)
loss = lossfct(lasty,labels)
loss.backward()
optimizer.step()
optimizer.zero_grad()

# finetunening done: you may check the answer is already different:
y = model.generate(s)
sy = tokenizer.decode(y[0])
print(sy)

推荐阅读