ChatGLM2-6B
ChatGLM2-6B copied to clipboard
[BUG/Help] ptuning后,效果非常差,比ChatGLM-6B差非常多
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
可以比较一下两者的训练loss?
- 检查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]
- 观察训练中loss、lr变化?
- prompt拼接、max_len、训练数据等因素?
- 可尝试(Q)LORA训练,保留原始权重能力,看看效果,
可以比较一下两者的训练loss?
@duzx16 ChatGLM2的loss为0,但是ChatGLM的loss为0.1左右。感觉ChatGLM2的P-Tuning训练有问题。 类似:https://github.com/THUDM/ChatGLM2-6B/issues/200
loss越来越高,相同的参数和数据,在ChatGLM-6B下面做微调,loss是一直下降的。
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("
修复后:
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团队官方确认。
可以比较一下两者的训练loss?
@duzx16 ChatGLM2的loss为0,但是ChatGLM的loss为0.1左右。感觉ChatGLM2的P-Tuning训练有问题。 类似:#200
loss 为 0 说明计算过程中产生了 nan,需要把学习率调小,或者更改初始化
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 收到,谢谢杜老师指点!
- 检查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]
- 观察训练中loss、lr变化?
- prompt拼接、max_len、训练数据等因素?
- 可尝试(Q)LORA训练,保留原始权重能力,看看效果,
这里拼接方式2是否有错误? 麻烦修正或说明下,有误导别人
- 检查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]
- 观察训练中loss、lr变化?
- prompt拼接、max_len、训练数据等因素?
- 可尝试(Q)LORA训练,保留原始权重能力,看看效果,
这里拼接方式2是否有错误? 麻烦修正或说明下,有误导别人
按照拼接方式2修改后,加载模型后无法正常得到结果,应该是不对的吧?但是对原拼接方式又不太理解这样的用意:[gMASK] [sop] a句tokens b句tokens [eop]
这是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刚发布时反向研究复现训练代码时的推断,现在已经不存在这个问题了。
PTuning它会在模型输入的前面加上一些虚拟向量,因此会严重破坏已学习的知识。
各位大佬,请问对于分类任务,这个b_ids应该是什么呢,如果b_ids是类别信息,会存在标签信息泄露吧 @lilongxian @duzx16