赞
踩
指令微调(Instruction Tuning)是指使用自然语言形式的数据对预训练后的大语言模型进行参数微调。
通常来说,适合微调的场景主要分为行业场景和通用场景
对于行业场景:
对于通用场景:
学术界围绕传统 NLP 任务(如机器翻译、文本摘要和文本分类等)发布了大量的开源数据集合,这些数据是非常重要的监督学习数据资源,可以用于指令数据集的构造。通常来说,这些 NLP 数据集都包括输入和输出两个主要部分。例如,在中英翻译任务中,输入是“大语言模型已经成为机器学习的一个重要研究方向”,而相应的输出则是“Large language models have become one important research direction for machine learning”。为了生成指令化的训练数据,一个非常关键的步骤就是为上述的“输入-输出”对数据添加任务描述信息,用于指导模型去理解任务目标以及相关信息。在上述的例子中,可以向中译英的翻译数据集中添加指令,例如“请把这个中文句子翻译成英文”。通过上述操作,就可以将一个 NLP 任务
https://github.com/THUDM/ChatGLM3/tree/main/finetune_demo
我们将微调的参数统一放置在finetune_demo/configs
下,将会有四个文件
.
├── deepspeed.json
├── lora.yaml
├── ptuning_v2.yaml
└── sft.yaml
分别为 deepspeed运行参数,lora配置文件,ptuningv2 配置文件和全参微调的配置文件。
每一份配置文件除了在细节上有一定区别,其他配置大同小异,我们针对每个参数做了简单的解释。
data_config
这些参数是关于数据集的位置
train_file
训练集地址val_file
验证集地址test_file
测试集地址max_input_length
微调模型输入的最大长度,默认为128
。max_output_length
微调模型输出的最大长度,默认为256
。peft_config
Huggingface PEFT 框架的相关参数,peft_type
选择高效微调的方式,可以为LORA
或者 PREFIX_TUNING
,并需要搭配对应的参数。
LORA
,则这些参数是必须的
LORA_RANK
:这个参数决定了模型参数修改的复杂度和灵活性。较低的秩意味着更少的参数和更快的训练速度,但可能减少模型的灵活性。较高的秩可以提高模型的灵活性,但会增加参数数量和计算负担。我们默认设置为8
。lora_alpha
是控制LoRA调整幅度的参数。它决定了对原始模型参数的修改程度。较高的lora_alpha
值意味着对原始模型参数的更大调整,这可能有助于模型更好地适应新的任务或数据,但也可能导致过拟合。较低的值则意味着较小的调整,可能保持模型的泛化能力,但可能不足以充分适应新任务。我们默认设置为32
lora_dropout
指的是在LoRA层应用的dropout比率。这意味着在训练过程中,网络的一部分连接会随机断开,以防止模型过度依赖于训练数据中的特定模式。较高的dropout比率可以增加模型的泛化能力,但也可能导致学习效率降低。我们设置为0.1
。target_modules
(不可修改的参数): 调整ChatGLM3
系列模型必须使用query_key_value
,这里没有在配置文件写出。PREFIX_TUNING
,则这些参数是必须的
num_virtual_tokens
指定了在前缀调优中使用的虚拟令牌的数量。这里设置为 100,意味着在每个层前添加 100 个可训练的虚拟令牌。这些虚拟令牌对于引导模型学习特定任务是重要的,因为它们为模型提供了额外的、可调整的上下文信息。如果你使用 sft 全量微调,则不应该有任何peft_config
参数。
training_args
这些参数是关于训练中通用的参数
output_dir
: 训练过程中输出文件的目录,默认是 ./output
。max_steps
: 训练的最大步数,这里设置为 10000
。per_device_train_batch_size
: 每个设备上的训练批量大小,默认是 4
。dataloader_num_workers
: 数据加载时使用的工作进程数,默认值是 16
。remove_unused_columns
: 是否移除未使用的列,默认设置为 False
。save_strategy
: 保存策略,默认是按步数保存(steps)。save_steps
: 保存步数,默认设置为每 500
步保存一次。log_level
: 日志等级,默认设置为 info
,可改为debug
。
logging_steps
: 日志记录步数,默认为每 10 步记录一次。per_device_eval_batch_size
: 每个设备上的评估批量大小,默认值为16
。evaluation_strategy
: 评估策略,默认是按步数评估(steps)。
eval_steps
: 评估步数,默认设置为每 500
步进行一次评估。predict_with_generate
: 是否在预测时生成输出,这里设置为True
。微调数据集采用 ChatGLM3 对话格式约定,对不同角色添加不同 loss_mask
从而在一遍计算中为多轮回复计算 loss
。对于数据文件,样例采用如下格式
[ { "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>" } ] } // ... ]
请注意,这种方法在微调的step较多的情况下会影响到模型的工具调用功能
[ { "tools": [ // available tools, format is not restricted ], "conversations": [ { "role": "system", "content": "<system prompt text>" }, { "role": "user", "content": "<user prompt text>" }, { "role": "assistant", "content": "<assistant thought to text>" }, { "role": "tool", "name": "<name of the tool to be called", "parameters": { "<parameter_name>": "<parameter_value>" }, "observation": "<observation>" }, { "role": "assistant", "content": "<assistant response to observation>" }, // ... Muti Turn { "role": "user", "content": "<user prompt text>" }, { "role": "assistant", "content": "<assistant response text>" } ] } // ... ]
tools
字段使用 json.dumps(..., ensure_ascii=False)
格式化后插入为首条 system prompt。bool
类型的 loss
字段,表示该字段所预测的内容是否参与 loss
计算。若没有该字段,样例实现中默认对 system
, user
不计算 loss
,其余角色则计算 loss
。tool
并不是 ChatGLM3 中的原生角色,这里的 tool
在预处理阶段将被自动转化为一个具有工具调用 metadata
的 assistant
角色(默认计算 loss
)和一个表示工具返回值的 observation
角色(不计算 loss
)。Code interpreter
的微调任务。system
角色为可选角色,但若存在 system
角色,其必须出现在 user
角色之前,且一个完整的对话数据(无论单轮或者多轮对话)只能出现一次 system
角色。在上述案例中,如果你想使用多张显卡,可以使用以下代码来实现多卡调用微调。
请注意,每张显卡至少需要预留完整的模型读入的显存。
下面代码仅作为样例,具体应该根据你的硬件和模型位置进行调整,直接复制代码大概率无法运行。
torchrun --standalone --nnodes=1 --nproc_per_node=8 finetune_hf.py data/AdvertiseGen_fix THUDM/chatglm3-6b configs/sft.yaml --deepspeed configs/deepspeed.json
如果按照上述方式进行训练,每次微调都会从头开始,如果你想从训练一半的模型开始微调,你可以加入第四个参数,这个参数有两种传入方式:
yes
, 自动从最后一个保存的 Checkpoint开始训练XX
, 断点号数字 例 600
则从序号600 Checkpoint开始训练例如,这就是一个从最后一个保存点继续微调的示例代码:
cd finetune_demo
python finetune_hf.py data/AdvertiseGen/ THUDM/chatglm3-6b configs/lora.yaml yes
您可以在 finetune_demo/inference_hf.py
中使用我们的微调后的模型,仅需要一行代码就能简单的进行测试。
python inference_hf.py your_finetune_path --prompt your prompt
这样,得到的回答就微调后的回答了。
在训练的文件中,会保存adapter_config.json
文件,文件会会记载该 LORA 权重依赖的原始权重。
"base_model_name_or_path": "your_lora_model",
在加载推理的时候,会自动的合并权重进行推理,因此,只需要在hf代码上载入这个权重就行了。
但是,在其他demo中,载入方式并不是inference.py
的模型载入方式,因此,需要您自行按照以下方式修改代码:
finetune_demo/inference_hf.py
中读入模型的方式替换 demo 中读入模型的方式。请注意,对于 LORA 和 P-TuningV2 我们没有合并训练后的模型,而是在
adapter_config.json
中记录了微调型的路径,如果你的原始模型位置发生更改,则你应该修改adapter_config.json
中base_model_name_or_path
的路径。
def load_model_and_tokenizer( model_dir: Union[str, Path], trust_remote_code: bool = True ) -> tuple[ModelType, TokenizerType]: model_dir = _resolve_path(model_dir) if (model_dir / 'adapter_config.json').exists(): model = AutoPeftModelForCausalLM.from_pretrained( model_dir, trust_remote_code=trust_remote_code, device_map='auto' ) tokenizer_dir = model.peft_config['default'].base_model_name_or_path else: model = AutoModelForCausalLM.from_pretrained( model_dir, trust_remote_code=trust_remote_code, device_map='auto' ) tokenizer_dir = model_dir tokenizer = AutoTokenizer.from_pretrained( tokenizer_dir, trust_remote_code=trust_remote_code ) return model, tokenizer
/path/to/finetune_adapter_model
,原始模型地址为path/to/base_model
,则你应该使用/path/to/finetune_adapter_model
作为model_dir
。basic_demo/web_demo_gradio.py
的效果。微调是一种让预先训练好的模型适应特定任务或数据集的低成本方案。这种情况下,模型会学习开发者提供的微调数据。
知识库是使用向量数据库(或者其他数据库)存储数据,可以外挂,作为LLM的行业信息提供方。
简单理解, 微调相当于让大模型去学习了新的一门学科,在回答的时候完成闭卷考试。
知识库相当于为大模型提供了新学科的课本,回答的时候为开卷考试。
知识库和微调并不是冲突的,它们是两种相辅相成的行业解决方案。开发者可以同时使用两种方案来优化模型。例如:
使用微调的技术微调ChatGLM3-6B大模型模拟客服的回答的语气和基础的客服思维。
接着,外挂知识库将最新的问答数据外挂给ChatGLM3-6B,不断更新客服回答的内容信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。