中文网页自动导航挑战赛——lora微调ChatGLM经验分享

  • 继续前一篇文章,ChatGLM-6B-int4模型精度稍低,效果不理想,需要微调更大的模型。
  • 为此,租了一台32GB的 TESLA V100,来完成这次比赛。
  • 本文记录ChatGLM的lora微调下的模型调优过程。

环境配置

  • 本文使用的环境是:
    Miniconda-conda3-Python3.8(ubuntu18.04)-Cuda11.3
  • 安装必要的工具包
!pip install peft
!pip install cpm_kernels
!pip install icetk
!git clone https://github.com/THUDM/ChatGLM-6B.git
cd ChatGLM-6B
!pip install -r requirements.txt
  • 配置GPU
import torch
device = torch.device('cuda:0')
  • 导入工具包
import os
import torch
import numpy as np
import json
from transformers import AutoTokenizer, AutoModel, AutoConfig, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model, TaskType
from torch.utils.data import Dataset

配置模型及微调参数

  • 导入模型
checkpoint = "THUDM/chatglm-6b"
tokenizer = AutoTokenizer.from_pretrained(checkpoint, trust_remote_code=True)
model = AutoModel.from_pretrained(checkpoint, trust_remote_code=True)
  • 配置lora微调参数
def load_lora_config(model):
    # 设定 lora 微调参数,r=16层可训练参数
	config = LoraConfig(
	    task_type=TaskType.CAUSAL_LM, 
	    inference_mode=False,
	    r=8, 
	    lora_alpha=32, 
	    lora_dropout=0.1,
	    target_modules=["query_key_value"]
	)
        
	return get_peft_model(model, config)
  • 配置训练参数
training_args = TrainingArguments(
        output_dir = "./",
        fp16 = True,
        save_steps = 1000,
        save_total_limit = 5,
        gradient_accumulation_steps = 4,
        per_device_train_batch_size = 1,
        learning_rate = 1e-4,
        max_steps=3000,
        logging_steps=100,
        remove_unused_columns=False,
        seed=500,
        data_seed=500,
        group_by_length=False,
        dataloader_pin_memory=False
    )
    
# 配置QADataset和Trainer实例
train_dataset = QADataset(train_data, tokenizer=tokenizer)
trainer = ModifiedTrainer(
    model=model,
    train_dataset=train_dataset,
    args=training_args,
    data_collator=collate_fn,
    tokenizer=tokenizer
    )
trainer.train()

调优思路

prompt构建

  • 由于数据集的 label 数据与自然语言的格式有很大差别,因此模型在参数微调过程中数据的分布变化较大。
  • 我们对 label 重新进行构造,将其构造成自然语言的形式。
  • 再对输出的结果进行解析,将其还原为 label 的形式。

数据增广

  • 官方提供的数据集,样本个数为2.4k,为了提高模型的精度和泛化能力,使用以下手段进行数据增广:
    • 同义词替换
    • 回译
    • 删改变换
  • 进行交叉实验验证有效性,通过Bleu分数来评估结果,实验结论如下:
    • 对数据集填入词进行同义词替换,验证结果:替换1个>替换0个>替换5个
    • 进行中英回译,验证结果:替换1个+回译>替换1个
    • 对输入句子进行小规模的删改变换,验证结果:不删改变换>删1个+改1个+变换1个
  • 验证结果分析:
    • 数据集中只有部分样本可以进行同义词替换,因此增加同义词的数量会改变数据集的样本分布,不利于模型的学习,因此只扩充1倍数据效果最优。
    • 中英回译能够增加模型的泛化性,但受翻译效果的影响,对于本次比赛中的样本,没有显著提升。
    • 删改变换降低了样本输入输出的匹配度,因此模型精度有所下降。

超参数调优

  • 通过调整学习率、batchsize、学习轮数,进行交叉验证,来选择更好的训练参数。
  • 实验证明,微调8层lora参数与16层lora参数效果没有明显差距,说明8层参数量已经足够处理本次数据集规模的任务。

生成结果

  • 根据prompt构建方式,反向解析预测标签,生成对应的结果,进行提交。

结果分析

  • 整个ChatGLM-6B模型,在TESLA-V100的32G显卡单卡微调,对于10000个样本的数据集,跑15个epoch的时间大约为10小时。
  • 训练效率的提升需要使用更多的技术,如DeepSpeed、多卡并行等。
  • 训练能够达到80%的精度,想要进一步提升精度,有以下几个方向:
    • 使用付费API,进行高精度的回译数据增广
    • 使用更大的模型
    • 进行全量参数微调,或者使用更多层数的lora微调
    • 提高训练的epoch并重新调整学习率,预期能够达到90%以上的精度。(由于时间有限没有进行这部分的实验验证)