Lora微调Yi-6B第一个step后loss突变为0

在微调大语言模型的时候,loss是我们判断模型训练效果的一大重要指标。loss通常代表着模型效果和预期结果之间的差距,当这个差距收敛或者变化不大时,我们认为模型训练停止,此时通过validation来寻找最佳的模型超参。

而loss为0通常是被认为是异常情况,因为在大语言模型的训练中,loss的计算是每一个token位置对下一个token的预测值和预期值的交叉熵函数。 哪怕在一个样本中,模型的输出和训练集的结果完全一致几乎不可能。所以被判定为异常情况。

两个解决办法:

1. 查看label的设置,通常在dataloader的data_collator参数中会有涉及,将label设为-100的地方去掉(这里说的是自己设置的-100,hugging face中的函数会将特殊token mask掉,这个不用去掉)

2. 将lora config中的参数load_in_4bit设置为True

下面分析可能的原因:

第一种是我们在mask  label的过程中,设置错误。这里需要解释的是,什么是mask label。微调大模型时,训练集的形式是(prompt,responce)。由于模型学习的是回答问题,不需要去拟合问题的语言,所以我们只计算responce部分的loss,而不计算prompt的部分的loss。于是,在设置label的时候,我们会将prompt部分的label设置为-100(交叉熵规定对于token中含有-100的loss为0),以此避免其loss的计算。

这里如果不会设置,可以直接看这个codebase:https://github.com/allenai/open-instruct

或者参考下面的代码:  

def encode_with_prompt_completion_format(example, tokenizer, max_seq_length, add_bos=False):
    '''
    Here we assume each example has 'prompt' and 'completion' fields.
    We concatenate prompt and completion and tokenize them together because otherwise prompt will be padded/trancated 
    and it doesn't make sense to follow directly with the completion.
    '''
    # if prompt doesn't end with space and completion doesn't start with space, add space
    if not example['prompt'].endswith((' ', '\n', '\t')) and not example['completion'].startswith((' ', '\n', '\t')):
        example_text = example['prompt'] + ' ' + example['completion']
    else:
        example_text = example['prompt'] + example['completion']
    example_text = example_text + tokenizer.eos_token
    if add_bos:
        example_text = tokenizer.bos_token + example_text
    tokenized_example = tokenizer(example_text, return_tensors='pt', max_length=max_seq_length, truncation=True)
    input_ids = tokenized_example.input_ids
    labels = input_ids.clone()
    tokenized_prompt = tokenizer(example['prompt'], return_tensors='pt', max_length=max_seq_length, truncation=True)
    # mask the prompt part for avoiding loss
    labels[:, :tokenized_prompt.input_ids.shape[1]] = -100
    attention_mask = torch.ones_like(input_ids)
    return {
        'input_ids': input_ids.flatten(),
        'labels': labels.flatten(),
        'attention_mask': attention_mask.flatten(),
    }

第二个可能的原因是lora的config设置出错。这里需要将lora config的load_in_4bit参数设置为True,增强数据的稳定性。

希望对正在学习的小伙伴有所帮助!

您好!对于ChatGPT-LM模型的微调,我可以为您提供一些基本的指导。以下是一个示例代码,用于微调ChatGPT-LM模型(如chatglm2-6b)来执行Lora任务: ```python import torch from transformers import GPT2LMHeadModel, GPT2Tokenizer, GPT2Config, Trainer, TrainingArguments from torch.utils.data import Dataset, DataLoader # 加载预训练的模型和tokenizer model_name = "microsoft/DialoGPT-large" model = GPT2LMHeadModel.from_pretrained(model_name) tokenizer = GPT2Tokenizer.from_pretrained(model_name) # 构建自定义的Lora数据集 class LoraDataset(Dataset): def __init__(self, conversations): self.conversations = conversations def __len__(self): return len(self.conversations) def __getitem__(self, idx): return self.conversations[idx] # 定义微调所需的函数 def prepare_inputs(examples): # 利用tokenizer对输入进行编码 inputs = tokenizer(examples["input_text"], padding="max_length", truncation=True, max_length=512) inputs["labels"] = inputs.input_ids.clone() return inputs def compute_metrics(pred): # 计算模型在验证集上的指标,这里示例中仅计算损失(负对数似然) loss = pred.loss metrics = {"loss": loss} return metrics # 加载并处理Lora数据集 conversations = [...] # 您的Lora数据集,每个对话是一个字符串列表 dataset = LoraDataset(conversations) train_dataset = dataset[:int(0.9 * len(dataset))] val_dataset = dataset[int(0.9 * len(dataset)):] # 定义微调参数 training_args = TrainingArguments( output_dir="./lora_model", num_train_epochs=3, per_device_train_batch_size=2, per_device_eval_batch_size=2, logging_steps=1000, save_steps=5000, evaluation_strategy="steps", eval_steps=2000, save_total_limit=1, ) # 创建Trainer并进行微调 trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=val_dataset, data_collator=prepare_inputs, compute_metrics=compute_metrics, ) trainer.train() ``` 请注意,上述代码仅提供了一个简单的示例。在微调ChatGPT-LM模型时,您需要根据您的数据集和任务对代码进行适当的调整。还可以根据需要调整微调参数。 希望这可以帮到您!如果您有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值