目前不少开源模型在通用领域具有不错的效果,但由于缺乏领域数据,往往在一些垂直领域中表现不理想,这时就需要增量预训练和微调等方法来提高模型的领域能力。
但在领域数据增量预训练或微调时,很容易出现灾难性遗忘现象,也就是学会了垂直领域知识,但忘记了通用领域知识,之前介绍过增量预训练以及领域大模型训练技巧,详见:
今天给大家带来一篇增量预训练方法-Llama-Pro,对LLMs进行Transformer块扩展后,增量预训练过程中仅对新增块进行训练,有效地进行模型知识注入,并且极大程度地避免灾难性遗忘。
LLaMA Pro: Progressive LLaMA with Block Expansion
LLaMA Pro: Progressive LLaMA with Block Expansion
Paper: https://arxiv.org/abs/2401.02415
Github: https://github.com/TencentARC/LLaMA-Pro
块扩展,顾名思义,就是在原始模型中每个Transformer块或者某几个Transformer块后增加一个Transformer块,但为了保持扩展后的模型输出保持不变,需要增加的块为恒等块(输入输出相同),如下图所示。
在构建恒等块过程中,主要是将多头注意力层和FFN层中的最后一个线性层(Linear)权重置为0变成Zero-Linear,即可保持经过该块的输入输出一致。
PS:论文附录A中写了大段的推导公式来证明,在此不做过多介绍。
块的增加方式是,对原始模型的L个Transformer块分成N组,每组中包含M=L/N个Transformer块,对于每组后添加P个恒等块。代码实现具体如下:model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16)
ckpt = model.state_dict()
# original_layers是模型原始层数,layers是模型最后达到层数
split = int(original_layers / (layers - original_layers))
layer_cnt = 0
output = {}
for i in range(original_layers):
for k in ckpt:
if ('layers.' + str(i) + '.') in k:
output[k.replace(('layers.' + str(i) + '.'), ('layers.' + str(layer_cnt) + '.'))] = ckpt[k]
layer_cnt += 1
if (i+1) % split == 0:
for k in ckpt:
if ('layers.' + str(i) + '.') in k:
if 'down_proj' in k or 'o_proj' in k:
output[k.replace(('layers.' + str(i) + '.'), ('layers.' + str(layer_cnt) + '.'))] = torch.zeros_like(ckpt[k])
else:
output[k.replace(('layers.' + str(i) + '.'), ('layers.' + str(layer_cnt) + '.'))] = ckpt[k]
layer_cnt += 1
assert layer_cnt==layers
for k in ckpt:
if not 'layers' in k:
output[k] = ckpt[k]
torch.save(output, output_path)
扫描二维码添加小助手微信
请备注:姓名-学校/公司-研究方向(如:小张-哈工大-对话系统)即可申请加入自然语言处理/Pytorch等技术交流群