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较多的情况下会影响到模型的工具调用功能。
[
{
"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]
这样的自然语言形式,以观察模型在微调前后对工具定义的理解能力。
./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)微调参数调整
- 参考显存用量
- P-Tuning V2
PRE_SEQ_LEN=128
,DEV_BATCH_SIZE=1
,GRAD_ACCUMULARION_STEPS=16
,MAX_SEQ_LEN=2048
配置下约需要 21GB 显存。 - 全量微调时,
./scripts/finetune_ds_multiturn.sh
中的配置(MAX_SEQ_LEN=2048
,DEV_BATCH_SIZE=16
,GRAD_ACCUMULARION_STEPS=1
)恰好用满 4 * 80GB 显存。
- P-Tuning V2
- 若尝试后发现显存不足,可以考虑
- 尝试降低
DEV_BATCH_SIZE
并提升GRAD_ACCUMULARION_STEPS
- 尝试添加
--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
{'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
进行基本的推理验证。
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
文件执行。同时,如果你是单卡运行环境,也可以将脚本中中的这行代码
torchrun --standalone --nnodes=1 --nproc_per_node=$NUM_GPUS finetune.py
修改为
代码语言:javascript复制python finetune.py
请注意,这样修改后,你需要手动设置CUDA_VISIBLE_DEVICES
环境变量,以控制使用哪张显卡。
(4)注意事项
- 参考显存用量
- 按照官方脚本的默认参数运行,每一张显卡占用显存为
23GB
。
- 按照官方脚本的默认参数运行,每一张显卡占用显存为
- 若尝试后发现显存不足,可以考虑
- 尝试降低
DEV_BATCH_SIZE
并提升GRAD_ACCUMULARION_STEPS
- 尝试降低
MAX_SEQ_LEN
,但是这可能会影响模型的性能
- 尝试降低
- 数据量和 loss 衰减
- 训练中 loss 在数个 step 中回升属于正常现象,但是如果连续不降,则需要检查数据集是否存在问题(覆盖范围过广,相关性太低等)。你也可以选择降低
LEARNING_RATE
或者提升WARMUP_STEPS
。 - 通常来说,loss值在
0.5
以下时,就属于比较好的状态。
- 训练中 loss 在数个 step 中回升属于正常现象,但是如果连续不降,则需要检查数据集是否存在问题(覆盖范围过广,相关性太低等)。你也可以选择降低
- 训练数据和轮次
Max Steps
为训练执行的步骤,与数据集的数量无关,这个参数不等于Epoch
。Batch Size
为每个GPU的batch size,如果你使用了多卡训练,那么实际的batch size为Batch Size * GPU数量
。
- 训练精度
- 强烈推荐使用
bf16
格式进行微调,并确认所有依赖和硬件满足微调硬件要求,否则可能出现 loss = 0 的情况。
- 强烈推荐使用
(5)部署和推断测试同Chat微调模型