大模型微调样本构造的trick

开局一道面试题。
面试官:大模型微调如何组织训练样本?
你:大模型训练一问一答,一指令一输出,问题和指令可以作为prompt输入,答案作为输出,计算loss的部分要屏蔽掉pad token。
面试官:多轮对话如何组织训练样本呢?
你:假设多轮为q1a1/q2a2/q3a3,那么可以转化成 q1—>a1, q1a1q2->a2, q1a1q2a2q3->a3三条训练样本。
面试官:这样的话一个session变成了三条数据,并且上文有依次重复的情况,这样会不会有啥问题?
你:数据中大部分都是pad token,训练数据利用效率低下。另外会有数据重复膨胀的问题,训练数据重复膨胀为 session数量*平均轮次数,且上文有重复部分,训练效率也会低下。
面试官:你也意识到了,有什么改进的方法吗?
你:有没有办法能一次性构造一个session作为训练样本呢?(思索)
面试官:提示你下,限制在decoder-only系列的模型上,利用模型特性,改进样本组织形式。
对于这个问题,我们思考下decoder-only模型有啥特点,第一点很关键的是其attention形式是casual的,casual简单理解就是三角阵,单个token只能看到其上文的信息。
如图所示:
其二是postion_id是只有token次序含义而无需特定指代信息,(区别于glm模型需要postion_id来标识生成span的位置等特殊的要求)。
有了这两点我们就可以设想,如果构造多轮对话样本的input为  q1 a1 q2 a2 q3 a3 ,在计算loss的时候,只需要计算 a1 a2 和 a3 部分,岂不是就可以进行session级别的训练了?
嗯为什么原来的chatglm不能用这种形式呢,虽然prefix attention可以推广为适应多轮训练的prefix attention形式,如图:
但是由于其postition id 无法简单按次序推广,故不能高效训练,这也是chatglm初代的很大的一个问题,导致后续微调的效果都比较一般。
现在chatglm2的代码针对这两个问题已经进行了改善,可以认为他就是典型的decoder-only模型了,具体表现为推断时候attention 是casual attention的形式,position id也退化为token次序增长。
那么好了,万事具备,只欠东风。我们据此实现了chatglm2-6b的代码微调。其核心代码逻辑为处理样本组织的逻辑,其他的就是大模型微调,大同小异了。
conversation = ''input_ids = []labels = []eos_id = tokenizer.eos_token_idturn_idx = 0for sentence in examples[prompt_column][i]: sentence_from = sentence[from].lower() sentence_value = '[round {}]问:'.format(turn_idx) + sentence[value] + '答:' if sentence_from == 'human' else sentence[value]+'' conversation += sentence_value sentence_ids = tokenizer.encode(sentence_value, add_special_tokens=false) label = copy.deepcopy(sentence_ids) if sentence_from != 'human' else [-100] * len(sentence_ids) input_ids += sentence_ids labels += label if sentence_from != 'human': input_ids += [eos_id] labels += [eos_id] turn_idx += 1input_ids = tokenizer.encode('') + input_ids #add gmask bos labels = [-100] * 2 + labels# #add paddingpad_len = max_seq_length - len(input_ids)input_ids = input_ids + [eos_id] * pad_len labels = labels + [-100] * pad_len  
其中有几个关键的地方,就是在开头要加上 bos和gmask,遵循模型原来的逻辑。问答提示词和轮次prompt,还有两个 保持和原模型保持一致,最后屏蔽掉pad部分的loss计算。
实测训练效果如下:
同样的数据在chatglm1上 train loss只能降到2.x左右,同时评估测试集结果,在同样的数据上rouge等指标都有不小的提升。
我们再仔细回顾下,对话session级别训练和拆开训练从原理上有啥区别?
1. session级别训练,效果之一为等价batchsize变大(1个batch可以塞下更多样本),且同一通对话产生的样本在一个bs内。
2. session级别的不同轮次产生的梯度是求平均的,拆开轮次构造训练是求和的,这样除了等价于lr会变大,还会影响不同轮次token权重的分配,另外还会影响norm的计算。
我们用一个简化地例子定量分析下,我们假设两条训练样本分为  1.问:a 答:xx 2.问: a 答:xx 问: b 答:xx  问: c 答:xx 则session级别训练影响梯度为 (ga+(ga + gb + gc)/3 )/2。对 a,b,c影响的权重分别为,2/3 1/6 1/6。 拆开训练为 (ga+ga+ (ga + gb)/2 +(ga + gb + gc)/3)/4。对 a,b,c影响的权重分别为,17/24 5/24 1/12。 从上面的权重分布来看,session级别靠后的轮次影响权重要比拆开更大。这也是更合理的,因为大部分场景下,开场白都是趋同和重复的。 一点小福利,以上面试题对应的chatglm2-6b 微调完整的代码地址为: https://github.com/spongebbob/finetune-chatglm2-6b
实现了对于 chatglm2-6b 模型的全参数微调,主要改进点在多轮对话的交互组织方面,使用了更高效的session级别高效训练,训练效果相比原版chatglm-6b有较大提升。
这可能是目前全网效果最好的chatglm2-6b全参数微调代码。

MEMS加工技术在机械手表制作中的应用
5月LED封装产品及灯泡价格出炉 暂未受贸易摩擦影响
LG公布支持Android4.0的手机名单 Ice冰激凌三明治固件升级
5G终端LTE和NR互干扰来源于哪里?应如何去解决?
BittWare采用FPGA实现I/O开关,每簇通信量大于5
大模型微调样本构造的trick
地平线发布全场景整车智能中央计算芯片征程5
MAX2683低成本高性能3.5GHz上变频器
心疼华为:美国两大运营商相继与华为终止合作
shell是什么?shell实现原理分析基于MM32 MCU的shell脚本源码
跟随同茂线性马达走进科博会
无线移动数据通信,无线移动数据通信是什么意思
画PCB图时应注意哪些问题
5G网络架构有什么特点?对承载网有什么影响?
云计算进军深度学习的方法论
Arduino警灯的制作教程
全桥直流电动机驱动器的的高性能电源控制
什么蓝牙耳机最实用?最实用的蓝牙耳机推荐
DNA存储技术在未来会有它的市场吗
PLC现场实例电气原理图及编程