ChatGLM2-6B icon indicating copy to clipboard operation
ChatGLM2-6B copied to clipboard

[BUG/Help] ptuning后,效果非常差,比ChatGLM-6B差非常多

Open ljch2018 opened this issue 1 year ago • 2 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current Behavior

{"labels": "问答-私域", "predict": "用户"} {"labels": "问答-文档搜索", "predict": "问答"} {"labels": "问答-私域", "predict": ""} {"labels": "问答-私域", "predict": "据"} {"labels": "问答-IThelp", "predict": ""} {"labels": "纯公域", "predict": ""} {"labels": "问答-私域", "predict": ""} {"labels": "问答-私域", "predict": ""} {"labels": "问答-行政", "predict": "问答"} {"labels": "问答-IThelp", "predict": "问答"} {"labels": "问答-HR", "predict": "用户"} {"labels": "问答-HR", "predict": ""} {"labels": "任务-通话", "predict": ""}

请问有ChatGLM2-6B的P-Tuning后的效果评估吗?怎么设置才能获取正确的结果?

Expected Behavior

Steps To Reproduce

Environment

- OS:
- Python:
- Transformers:
- PyTorch:
- CUDA Support (`python -c "import torch; print(torch.cuda.is_available())"`) :

Anything else?

No response

ljch2018 avatar Jul 05 '23 10:07 ljch2018

可以比较一下两者的训练loss?

duzx16 avatar Jul 05 '23 13:07 duzx16

  1. 检查tokenizer.build_inputs_with_special_tokens(a_ids, b_ids)是否拼接正确: chatGLM1:input 为: a句token ... [gmask] [bos] b句token,... [eos] chatGLM2:input 为 : a句token ... [gMASK] [sop] b句token [eop]
  2. 观察训练中loss、lr变化?
  3. prompt拼接、max_len、训练数据等因素?
  4. 可尝试(Q)LORA训练,保留原始权重能力,看看效果,

lilongxian avatar Jul 05 '23 13:07 lilongxian

可以比较一下两者的训练loss?

@duzx16 ChatGLM2的loss为0,但是ChatGLM的loss为0.1左右。感觉ChatGLM2的P-Tuning训练有问题。 类似:https://github.com/THUDM/ChatGLM2-6B/issues/200

ljch2018 avatar Jul 06 '23 02:07 ljch2018

image loss越来越高,相同的参数和数据,在ChatGLM-6B下面做微调,loss是一直下降的。

isacck avatar Jul 06 '23 03:07 isacck

6月25日官方的hf代码里:tokenizer.build_inputs_with_special_tokens(a_ids, b_ids)拼接正确性存疑,刚才我看了hf代码,这块拼接算法还是6月25日的。 在我7月4日的开源的项目https://github.com/lilongxian/LL-BaiYang/tree/main/glm2_core里已经修改为以下拼接格式: chatGLM2:input 为 : a句token ... [gMASK] [sop] b句token [eop] 这块势必会影响微调训练的质量。 def build_inputs_with_special_tokens( self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None ) -> List[int]: 以下为glm2-6B源代码 prefix_tokens = self.get_prefix_tokens() # [gMASK_id, sop_id] token_ids_0 = prefix_tokens + token_ids_0 if token_ids_1 is not None: token_ids_0 = token_ids_0 + token_ids_1 + [self.get_command("")] return token_ids_0

     修复后:
    prefix_tokens = self.get_prefix_tokens()  # [gMASK_id, sop_id]
    token_ids_0 += prefix_tokens  # a1,a2,...an,[gMASK],<sop>
    if token_ids_1 is not None:
        token_ids_0 += token_ids_1 + [self.get_command("eop")]
    return token_ids_0

另外,在GPU资源允许情况下,尽量增加梯度累加器的批大小;初始学习率尝试减小。

这只是我的一点看法,希望能给大家带来点帮助,正确性还需要GLM团队官方确认。

lilongxian avatar Jul 06 '23 03:07 lilongxian

可以比较一下两者的训练loss?

@duzx16 ChatGLM2的loss为0,但是ChatGLM的loss为0.1左右。感觉ChatGLM2的P-Tuning训练有问题。 类似:#200

loss 为 0 说明计算过程中产生了 nan,需要把学习率调小,或者更改初始化

duzx16 avatar Jul 06 '23 03:07 duzx16

6月25日官方的hf代码里:tokenizer.build_inputs_with_special_tokens(a_ids, b_ids)拼接正确性存疑,刚才我看了hf代码,这块拼接算法还是6月25日的。 在我7月4日的开源的项目https://github.com/lilongxian/LL-BaiYang/tree/main/glm2_core里已经修改为以下拼接格式: chatGLM2:input 为 : a句token ... [gMASK] [sop] b句token [eop] 这块势必会影响微调训练的质量。 def build_inputs_with_special_tokens( self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None ) -> List[int]: 以下为glm2-6B源代码 prefix_tokens = self.get_prefix_tokens() # [gMASK_id, sop_id] token_ids_0 = prefix_tokens + token_ids_0 if token_ids_1 is not None: token_ids_0 = token_ids_0 + token_ids_1 + [self.get_command("")] return token_ids_0

     修复后:
    prefix_tokens = self.get_prefix_tokens()  # [gMASK_id, sop_id]
    token_ids_0 += prefix_tokens  # a1,a2,...an,[gMASK],<sop>
    if token_ids_1 is not None:
        token_ids_0 += token_ids_1 + [self.get_command("eop")]
    return token_ids_0

另外,在GPU资源允许情况下,尽量增加梯度累加器的批大小;初始学习率尝试减小。

这只是我的一点看法,希望能给大家带来点帮助,正确性还需要GLM团队官方确认。

修改前的拼接方式就是正确的

duzx16 avatar Jul 06 '23 03:07 duzx16

@duzx16 收到,谢谢杜老师指点!

lilongxian avatar Jul 06 '23 03:07 lilongxian

  1. 检查tokenizer.build_inputs_with_special_tokens(a_ids, b_ids)是否拼接正确: chatGLM1:input 为: a句token ... [gmask] [bos] b句token,... [eos] chatGLM2:input 为 : a句token ... [gMASK] [sop] b句token [eop]
  2. 观察训练中loss、lr变化?
  3. prompt拼接、max_len、训练数据等因素?
  4. 可尝试(Q)LORA训练,保留原始权重能力,看看效果,

这里拼接方式2是否有错误? 麻烦修正或说明下,有误导别人

echoht avatar Jul 13 '23 04:07 echoht

  1. 检查tokenizer.build_inputs_with_special_tokens(a_ids, b_ids)是否拼接正确:

chatGLM1:input 为: a句token ... [gmask] [bos] b句token,... [eos]

chatGLM2:input 为 : a句token ... [gMASK] [sop] b句token [eop]

  1. 观察训练中loss、lr变化?
  1. prompt拼接、max_len、训练数据等因素?
  1. 可尝试(Q)LORA训练,保留原始权重能力,看看效果,

这里拼接方式2是否有错误? 麻烦修正或说明下,有误导别人

按照拼接方式2修改后,加载模型后无法正常得到结果,应该是不对的吧?但是对原拼接方式又不太理解这样的用意:[gMASK] [sop] a句tokens b句tokens [eop]

Single430 avatar Sep 07 '23 08:09 Single430

这是chatGLM2-6B刚发布时候在复现微调训练时遇到的问题,因为没有论文参考,所以开始按chatGLM1-6B的拼接思路,后来根据多次实验对比,可以断定:

chatGLM2:input 为 : [gMASK]sop a句token b句token eos

官方代码拼接方式是对的。

大家必须要纠结为什么把句子级掩码标记[gMASK]放在开头,因为这和预训练有关,在预训练中代表的是被mask的整个句子,反应在位置向量里则是整个被mask掉的句子在整个文本中的位置。这个位置索引确定后,不管放在哪里都已一样的,和mpnet位置补偿类似,很明显可以推断预训练中放在了开头,后面才是不计算loss的句子tokens,所以后面的放在sop和eop之间。所以在微调训练中,[gMASK]也放在开头,后面为 sop a句token b句token eos,这样把[gMASK]sop作为一个整体放在前面,最后结尾是eos, 看起来也更顺眼,和llama1&2的 s a +b /s就很相似了。

注意上面 s /s eos 都带尖括号

这个问题可以关闭了,这是chatGLM2-6B刚发布时反向研究复现训练代码时的推断,现在已经不存在这个问题了。

lilongxian avatar Sep 07 '23 09:09 lilongxian

PTuning它会在模型输入的前面加上一些虚拟向量,因此会严重破坏已学习的知识。

wizardforcel avatar Oct 17 '23 01:10 wizardforcel

各位大佬,请问对于分类任务,这个b_ids应该是什么呢,如果b_ids是类别信息,会存在标签信息泄露吧 @lilongxian @duzx16

tcoln avatar May 29 '24 09:05 tcoln