ymcui / Chinese-LLaMA-Alpaca-2

中文LLaMA-2 & Alpaca-2大模型二期项目 + 64K超长上下文模型 (Chinese LLaMA-2 & Alpaca-2 LLMs with 64K long context models)
Apache License 2.0
7.01k stars 571 forks source link

run_clm_sft_with_peft.py微调过程中计算acc,在评估指标计算函数compute_metrics中,要求拿到预测label和原始label,先对模型预测结果predictions的tokenid解码成中文再评估中文准确率acc,为什么predictions(预测结果)的前面系统提示词和instruction与inputs(原始所有输入)的tokenid不同,导致解码混乱,不能用"[/INST]"分割出label,这是什么原因,或者还有什么方法能拿到预测label? #492

Closed feifei05 closed 6 months ago

feifei05 commented 6 months ago

提交前必须检查以下项目

问题类型

模型训练与精调

基础模型

Chinese-Alpaca-2 (7B/13B)

操作系统

Linux

详细描述问题

这是run_clm_sft_with_peft.py代码中写的compute_metrics函数的一条数据解码代码,输出了preds[0], labels[0], inputs[0]的tokenid,preds是预测结果,labels是原始label,inputs是原始完整输入数据,包含系统提示词和instruction和样本的标签(就是答案),为什么通过这个函数拿到的preds的前面的tokenid会和原始完整inputs的前面的tokenid不一样,为什么在inference_hf.py推理中,用generate生成答案的前面的系统提示词和instruction和对话的问题是一样,只有答案不一样,因为我要解码答案成中文才能进行计算acc指标,在微调过程中计算acc,有没有其他函数或者方法能拿到预测的label,或者是我哪里有问题?
然后下面也给出了我初始化Trainer代码。

# def compute_metrics(eval_preds):
    preds, labels, inputs= eval_preds
    tokenizer_kwargs = {
        "cache_dir": None,
        "use_fast": True,
        "revision": "main",
        "use_auth_token": None,
    }
    # print(f"-------------preds.shape:", preds.shape, type(preds), len(preds), preds)
    # print(f"-------------labels.shape:", labels.shape, type(labels), len(labels), labels)

    tokenizer_name_or_path = "/share1/zouff/llm_model/chinese-alpaca-2-13b-hf"
    tokenizer = LlamaTokenizer.from_pretrained(tokenizer_name_or_path,
                                               **tokenizer_kwargs)
    print(inputs.shape, len(inputs))
    print("-----------------------inputs[0], preds=[0],labels[0]", inputs[0], preds[0], labels[0])
    de1 = tokenizer.decode(inputs[0], skip_special_tokens=True)
    print("-----------------------------------解码inputs[0]", de1)
    labe = [pre_id for pre_id in labels[0] if pre_id != -100]
    de2 = tokenizer.decode(labe, skip_special_tokens=True)
    print("-----------------------------------解码labels[0]", de2)

###下面是我初始化Trainer代码。
trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
        eval_dataset={'train':train_dataset, 'eval':eval_dataset},
        tokenizer=tokenizer,
        data_collator=data_collator,
        compute_metrics=compute_metrics if training_args.do_eval and not is_torch_tpu_available() else None,
        preprocess_logits_for_metrics=preprocess_logits_for_metrics if training_args.do_eval and not is_torch_tpu_available() else None,
        callbacks=([SavePeftModelCallback] if isinstance(model, PeftModel) else None),
    )

依赖情况(代码类问题务必提供)

# transformers= 4.34.0
#deepspeed=0.12.3
#peft=0.5.0

运行日志或截图

#下面是inputs[0],preds[0], labels[0], inputs[0]原始输入完全正确,preds[0]预测结果乱码,不出现label分隔符,inputs[0]是原始label。为什么preds[0]和inputs[0]前面的系统提示词和instruction不同
![1](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/assets/69673314/1440ac08-dbd3-4209-94ff-c0b7f46fdddb)
![2](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/assets/69673314/ad845342-dc08-46b3-84df-aabcad2830d8)
![3](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2/assets/69673314/f786d251-f24a-48fd-9975-0cffcff181ba)
feifei05 commented 6 months ago

1 2 ![Uploading 3.png…]()

feifei05 commented 6 months ago

3

feifei05 commented 6 months ago

上面是inputs[0],preds[0], labels[0], inputs[0]原始输入完全正确,preds[0]预测结果乱码,不出现label分隔符,inputs[0]是原始label。为什么preds[0]和inputs[0]前面的系统提示词和instruction不同

iMountTai commented 6 months ago

preds本身就是模型从第一个预测token开始的输出,前面乱的正常。想计算acc要看你的loss计算方式,loss计算方式影响数据处理的形式和metric计算,比如只看SFT数据的response部分,自己调试一下吧,不是我们repo相关的问题。

feifei05 commented 6 months ago

"SFT数据的response"这是指哪个函数的输出,如果用generate生成的response是可以拿到label,但是这种方式很慢