LoRA & QLoRA
github地址 :https://github.com/ml-explore/mlx-examples/tree/main/llms
mlx-lm 包
您可以使用mlx-lm
包来使用低秩适应(LoRA)对大型语言模型(LLM)进行微调以适应目标任务。示例还支持量化LoRA(QLoRA)。LoRA微调适用于以下模型系列:
- Mistral
- Llama
- Phi2
- Mixtral
- Qwen2
- Gemma
- OLMo
- MiniCPM
- InternLM2
内容
- 运行
- 微调
- 评估
- 生成
- 融合
- 数据
- 内存问题
运行
这里需要访问 HuggingFace 下载,可以使用国内镜像
https://hf-mirror.com/
export HF_ENDPOINT=https://hf-mirror.com
主要命令是mlx_lm.lora
。要查看所有命令行选项的完整列表,请运行:
mlx_lm.lora --help
注意,在下面的示例中,--model
参数可以是任何兼容的Hugging Face存储库或指向转换后的模型的本地路径。
您也可以使用-c
/--config
指定YAML配置文件。有关格式的更多信息,请参见示例YAML。例如:
mlx_lm.lora --config /path/to/config.yaml
如果同时使用命令行标志,它们将覆盖配置文件中的相应值。
微调
要微调模型,请使用:
mlx_lm.lora \
--model \
--train \
--data \
--iters 600
--data
参数必须指定train.jsonl
的路径,在--train
时使用,以及在--test
时指定test.jsonl
的路径。有关数据格式的更多细节,请参见数据部分。
例如,要微调Mistral 7B,您可以使用--model mistralai/Mistral-7B-v0.1
。
如果--model
指向的是一个量化模型,那么训练将使用QLoRA,否则将使用常规LoRA。
默认情况下,适配器配置和权重存储在adapters/
目录下。您可以使用--adapter-path
指定输出位置。
您可以使用--resume-adapter-file
恢复现有适配器的微调。
评估
要计算测试集的困惑度,请使用:
mlx_lm.lora \
--model \
--adapter-path \
--data \
--test
生成
对于生成,请使用mlx_lm.generate
:
mlx_lm.generate \
--model \
--adapter-path \
--prompt ""
融合
您可以使用mlx_lm.fuse
命令生成与低秩适配器融合的模型。此命令还允许您选择性地:
- 将融合的模型上传到Hugging Face Hub。
- 将融合的模型导出为GGUF格式。注意,GGUF支持限于fp16精度的Mistral、Mixtral和Llama风格的模型。
要查看支持的选项,请运行:
mlx_lm.fuse --help
要生成融合模型,请运行:
mlx_lm.fuse --model
默认情况下,此命令将从adapters/
加载适配器,并在lora_fused_model/
路径下保存融合的模型。所有这些都是可配置的。
要上传融合模型,请向mlx_lm.fuse
提供--upload-repo
和--hf-path
参数。后者是原始模型的存储库名称,这对归因和模型版本控制很有用。
例如,要融合并上传一个衍生自Mistral-7B-v0.1的模型,请运行:
mlx_lm.fuse \
--model mistralai/Mistral-7B-v0.1 \
--upload-repo mlx-community/my-lora-mistral-7b \
--hf-path mistralai/Mistral-7B-v0.1
要将融合模型导出到GGUF,请运行:
mlx_lm.fuse \
--model mistralai/Mistral-7B-v0.1 \
--export-gguf
这将在lora_fused_model/ggml-model-f16.gguf
中保存GGUF模型。您可以使用--gguf-path
指定文件名。
数据
LoRA命令期望您使用--data
提供数据集。MLX Examples GitHub存储库有一个WikiSQL数据的示例,格式正确。
数据集可以本地指定为*.jsonl
文件,或从Hugging Face加载。
本地数据集
对于微调(--train
),数据加载器期望在数据目录中有一个train.jsonl
和一个valid.jsonl
。对于评估(--test
),数据加载器期望在数据目录中有一个test.jsonl
。
目前,*.jsonl
文件支持三种数据格式:chat
、completions
和text
。以下是这些格式的三个示例:
chat
:
{
"messages": [
{
"role": "system",
"content": "你是一个有用的助手。"
},
{
"role": "user",
"content": "您好。"
},
{
"role": "assistant",
"content": "我今天能为您提供什么帮助?"
}
]
}
completions
:
{
"prompt": "法国的首都是哪里?",
"completion": "巴黎。"
}
text
:
{
"text": "这是模型的一个示例。"
}
请注意,数据集自动确定格式。同样请注意,每行中不被加载器预期的键将被忽略。
Hugging Face数据集
要使用Hugging Face数据集,首先安装datasets
包:
pip install datasets
在YAML配置中指定Hugging Face数据集参数。例如:
hf_dataset:
name: "billsum"
prompt_feature: "text"
completion_feature: "summary"
-
使用
prompt_feature
和completion_feature
指定completions
数据集的键。使用text_feature
指定text
数据集的键。 -
要指定训练、验证或测试拆分,请设置相应的
{train,valid,test}_split
参数。 -
在
config
中指定的参数将作为关键字参数传递给datasets.load_dataset
。
通常,对于chat
和completions
格式,Hugging Face 聊天模板被使用。这默认情况下应用了模型的聊天模板。如果模型没有聊天模板,那么Hugging Face将使用默认模板。例如,使用Hugging Face的默认模板,上面chat
示例中的最终文本变为:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
Hello.<|im_end|>
<|im_start|>assistant
How can I assistant you today.<|im_end|>
如果您不确定要使用哪种格式,请从chat
或completions
开始。对于数据集格式的自定义要求,请使用text
格式自行组装内容。
内存问题
使用LoRA微调大型模型需要一台具有相当数量内存的机器。如果您需要减少内存使用,请尝试以下技巧:
-
尝试量化(QLoRA)。您可以通过使用
convert.py
和-q
标志生成量化模型来使用QLoRA。有关更多详细信息,请参见设置部分。 -
尝试使用
--batch-size
使用较小的批量大小。默认值为4
,因此将其设置为2
或1
将减少内存消耗。这可能会稍微减慢速度,但也将减少内存使用。 -
使用
--lora-layers
减少微调的层数。默认值为16
,所以您可以尝 试8
或4
。这减少了反向传播所需的内存量。如果您使用大量数据微调,这也可能降低微调模型的质量。 -
更长的例子需要更多的内存。如果您的数据有意义,您可以做的事情之一是在制作
{train, valid, test}.jsonl
文件时将示例拆分成更小的序列。 -
梯度检查点可以让内存使用量减少(更少)以换取更多的计算(更多)通过重新计算而不是存储由反向传播所需的中间值。您可以通过传递
--grad-checkpoint
标志来使用梯度检查点。对于较大的批量大小或序列长度,梯度检查点对于较小或量化模型更有帮助。
例如,在32 GB的机器上,以下命令应该运行得相当快:
mlx_lm.lora \
--model mistralai/Mistral-7B-v0.1 \
--train \
--batch-size 1 \
--lora-layers 4 \
--data wikisql
上述命令在32 GB M1 Max上运行,大约每秒钟处理250个token,使用MLX示例wikisql
数据集。