ChatGLM模型微调

2024-03-13 12:33:32 浏览数 (2)

ChatGLM3: https://github.com/THUDM/ChatGLM3

微调前建议将模型下载到本地。微调前还需要安装依赖。

代码语言:javascript复制
conda create -n chatglm3 python=3.11 -y

pip install astunparse

对话模型微调

ChatGLM3-6B 微调示例

我们使用 ToolAlpaca 数据集来进行微调。

(1)首先,克隆 ToolAlpaca 数据集

代码语言:javascript复制
cd finetune_chatmodel_demo

git clone https://github.com/tangqiaoyu/ToolAlpaca.git

数据格式如下,这个格式不能微调函数调用,函数调用需要添加tools属性,此处不展开。这种方法在微调的step较多的情况下会影响到模型的工具调用功能。

代码语言:javascript复制
[
  {
    "conversations": [
      {
        "role": "system",
        "content": "<system prompt text>"
      },
      {
        "role": "user",
        "content": "<user prompt text>"
      },
      {
        "role": "assistant",
        "content": "<assistant response text>"
      }, 
       // ... Muti Turn
      {
        "role": "user",
        "content": "<user prompt text>"
      },
      {
        "role": "assistant",
        "content": "<assistant response text>"
      }
    ]
  }
  // ...
]

(2)使用ChatGLM3项目下的脚本将数据集处理成上述需要的格式。在这里,我们有意将工具处理成了 list[str] 这样的自然语言形式,以观察模型在微调前后对工具定义的理解能力。

代码语言:javascript复制
./scripts/format_tool_alpaca.py --path "ToolAlpaca/data/train_data.json"

# ./scripts/format_advertise_gen.py --path "AdvertiseGen/train.json"

(3)以下脚本提供了微调模型的参考方式,如果是单卡,则需要指定对应的显卡,

代码语言:javascript复制
export CUDA_VISIBLE_DEVICES=6 # 指定序号6的卡

微调命令如下:

代码语言:javascript复制
./scripts/finetune_pt_multiturn.sh  # P-Tuning v2 微调

(4)微调参数调整

  1. 参考显存用量
    1. P-Tuning V2 PRE_SEQ_LEN=128, DEV_BATCH_SIZE=1, GRAD_ACCUMULARION_STEPS=16, MAX_SEQ_LEN=2048 配置下约需要 21GB 显存。
    2. 全量微调时,./scripts/finetune_ds_multiturn.sh 中的配置(MAX_SEQ_LEN=2048, DEV_BATCH_SIZE=16, GRAD_ACCUMULARION_STEPS=1)恰好用满 4 * 80GB 显存。
  2. 若尝试后发现显存不足,可以考虑
    1. 尝试降低 DEV_BATCH_SIZE 并提升 GRAD_ACCUMULARION_STEPS
    2. 尝试添加 --quantization_bit 8--quantization_bit 4
      • PRE_SEQ_LEN=128, DEV_BATCH_SIZE=1, GRAD_ACCUMULARION_STEPS=16, MAX_SEQ_LEN=1024 配置下,--quantization_bit 8 约需 12GB 显存,--quantization_bit 4 约需 7.6GB 显存。

(5)部分微调结果,其中最后的输出中展示了模型的输出目录:Model weights saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/pytorch_model.bin

代码语言:javascript复制
{'loss': 0.3164, 'learning_rate': 0.00043999999999999996, 'epoch': 3.87}
{'loss': 0.2387, 'learning_rate': 0.00042, 'epoch': 3.87}
{'loss': 0.2318, 'learning_rate': 0.0004, 'epoch': 3.87}
{'loss': 0.3259, 'learning_rate': 0.00038, 'epoch': 3.88}
{'loss': 0.2799, 'learning_rate': 0.00035999999999999997, 'epoch': 3.88}
{'loss': 0.3128, 'learning_rate': 0.00034, 'epoch': 3.89}
{'loss': 0.3261, 'learning_rate': 0.00032, 'epoch': 3.89}
{'loss': 0.3437, 'learning_rate': 0.0003, 'epoch': 3.89}
{'loss': 0.3014, 'learning_rate': 0.00028000000000000003, 'epoch': 3.9}
{'loss': 0.3655, 'learning_rate': 0.00026, 'epoch': 3.9}
{'loss': 0.3446, 'learning_rate': 0.00024, 'epoch': 3.91}
{'loss': 0.3197, 'learning_rate': 0.00021999999999999998, 'epoch': 3.91}
{'loss': 0.2865, 'learning_rate': 0.0002, 'epoch': 3.91}
{'loss': 0.2616, 'learning_rate': 0.00017999999999999998, 'epoch': 3.92}
{'loss': 0.3322, 'learning_rate': 0.00016, 'epoch': 3.92}
{'loss': 0.3059, 'learning_rate': 0.00014000000000000001, 'epoch': 3.92}
{'loss': 0.3777, 'learning_rate': 0.00012, 'epoch': 3.93}
{'loss': 0.3045, 'learning_rate': 0.0001, 'epoch': 3.93}
{'loss': 0.357, 'learning_rate': 8e-05, 'epoch': 3.94}
{'loss': 0.3153, 'learning_rate': 6e-05, 'epoch': 3.94}
{'loss': 0.2996, 'learning_rate': 4e-05, 'epoch': 3.94}
{'loss': 0.247, 'learning_rate': 2e-05, 'epoch': 3.95}
{'loss': 0.2653, 'learning_rate': 0.0, 'epoch': 3.95}
100%|██████████| 1000/1000 [6:51:46<00:00, 24.09s/it]Saving PrefixEncoder
[INFO|configuration_utils.py:483] 2024-01-19 03:31:12,260 >> Configuration saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tmp-checkpoint-1000/config.json
[INFO|configuration_utils.py:594] 2024-01-19 03:31:12,261 >> Configuration saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tmp-checkpoint-1000/generation_config.json
[INFO|modeling_utils.py:2382] 2024-01-19 03:31:12,279 >> Model weights saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tmp-checkpoint-1000/pytorch_model.bin
[INFO|tokenization_utils_base.py:2432] 2024-01-19 03:31:12,280 >> tokenizer config file saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tmp-checkpoint-1000/tokenizer_config.json
[INFO|tokenization_utils_base.py:2441] 2024-01-19 03:31:12,280 >> Special tokens file saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tmp-checkpoint-1000/special_tokens_map.json
[INFO|trainer.py:1947] 2024-01-19 03:31:12,527 >> 

Training completed. Do not forget to share your model on huggingface.co/models =)


{'train_runtime': 24706.365, 'train_samples_per_second': 0.648, 'train_steps_per_second': 0.04, 'train_loss': 0.3145294485092163, 'epoch': 3.95}
100%|██████████| 1000/1000 [6:51:46<00:00, 24.71s/it]
Saving PrefixEncoder
[INFO|configuration_utils.py:483] 2024-01-19 03:31:12,535 >> Configuration saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/config.json
[INFO|configuration_utils.py:594] 2024-01-19 03:31:12,536 >> Configuration saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/generation_config.json
[INFO|modeling_utils.py:2382] 2024-01-19 03:31:12,553 >> Model weights saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/pytorch_model.bin
[INFO|tokenization_utils_base.py:2432] 2024-01-19 03:31:12,554 >> tokenizer config file saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/tokenizer_config.json
[INFO|tokenization_utils_base.py:2441] 2024-01-19 03:31:12,554 >> Special tokens file saved in output/tool_alpaca_pt-20240118-203444-128-2e-2/special_tokens_map.json

(5)对于 P-Tuning v2 微调,可以使用以下方式进行部署

代码语言:javascript复制
cd ../composite_demo
MODEL_PATH="THUDM/chatglm3-6b" PT_PATH="path to p-tuning checkpoint" streamlit run main.py

(6)推理验证

对于输入输出格式的微调,可使用 inference.py 进行基本的推理验证。

代码语言:javascript复制
python inference.py 
    --pt-checkpoint "path to p-tuning checkpoint" 
    --model THUDM/chatglm3-6b
python inference.py 
    --tokenizer THUDM/chatglm3-6b 
    --model "path to finetuned model checkpoint" 

基座模型微调

ChatGLM3-6B-base 微调示例

base模型不具备对话能力,仅能够生成单轮回复。

(1)数据格式要求

代码语言:javascript复制
{"context": "hello", "target": "hi,I am ChatGLM3"}

context是对话的上文,也就是模型的输入,target是对话的下文,也就是模型的输出。

可以使用 AdvertiseGen 数据集来进行微调。从 Google Drive 或者 Tsinghua Cloud 下载处理好的 AdvertiseGen 数据集,将解压后的 AdvertiseGen 目录放到本目录下。

数据格式如下

代码语言:javascript复制
{"content": "类型#上衣*材质#牛仔布*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞", "summary": "简约而不简单的牛仔外套,白色的衣身十分百搭。衣身多处有做旧破洞设计,打破单调乏味,增加一丝造型看点。衣身后背处有趣味刺绣装饰,丰富层次感,彰显别样时尚。"}
{"content": "类型#裙*材质#针织*颜色#纯色*风格#复古*风格#文艺*风格#简约*图案#格子*图案#纯色*图案#复古*裙型#背带裙*裙长#连衣裙*裙领型#半高领", "summary": "这款BRAND针织两件套连衣裙,简约的纯色半高领针织上衣,修饰着颈部线,尽显优雅气质。同时搭配叠穿起一条背带式的复古格纹裙,整体散发着一股怀旧的时髦魅力,很是文艺范。"}

(2)将数据集处理成要求格式

代码语言:javascript复制
./scripts/format_advertise_gen.py --path "AdvertiseGen/train.json"

(3)微调脚本

代码语言:javascript复制
./scripts/finetune_lora.sh  # 使用Lora微调

如果你使用的是windows系统,请将脚本改为bat文件执行。同时,如果你是单卡运行环境,也可以将脚本中中的这行代码

代码语言:javascript复制
torchrun --standalone --nnodes=1 --nproc_per_node=$NUM_GPUS finetune.py 

修改为

代码语言:javascript复制
python finetune.py 

请注意,这样修改后,你需要手动设置CUDA_VISIBLE_DEVICES环境变量,以控制使用哪张显卡。

(4)注意事项

  1. 参考显存用量
    1. 按照官方脚本的默认参数运行,每一张显卡占用显存为 23GB
  2. 若尝试后发现显存不足,可以考虑
    1. 尝试降低 DEV_BATCH_SIZE 并提升 GRAD_ACCUMULARION_STEPS
    2. 尝试降低 MAX_SEQ_LEN,但是这可能会影响模型的性能
  3. 数据量和 loss 衰减
    1. 训练中 loss 在数个 step 中回升属于正常现象,但是如果连续不降,则需要检查数据集是否存在问题(覆盖范围过广,相关性太低等)。你也可以选择降低 LEARNING_RATE 或者提升 WARMUP_STEPS
    2. 通常来说,loss值在 0.5 以下时,就属于比较好的状态。
  4. 训练数据和轮次
    1. Max Steps 为训练执行的步骤,与数据集的数量无关,这个参数不等于Epoch
    2. Batch Size 为每个GPU的batch size,如果你使用了多卡训练,那么实际的batch size为 Batch Size * GPU数量
  5. 训练精度
    1. 强烈推荐使用 bf16 格式进行微调,并确认所有依赖和硬件满足微调硬件要求,否则可能出现 loss = 0 的情况。

(5)部署和推断测试同Chat微调模型

0 人点赞