ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MLX 框架 LoRA/QLoRA 微调实战指南:用 WikiSQL 数据在 Apple silicon 上精调 LLM

MLX 框架 LoRA/QLoRA 微调实战指南:用 WikiSQL 数据在 Apple silicon 上精调 LLM 示例工程人工智能【免费下载链接】mlx-examplesExamples in the MLX framework项目地址https://gitcode.com/GitHub_Trending/ml/mlx-examples点击查看免费下载本文以 lora/README.md 为骨架系统讲解如何在 MLX 框架下使用 LoRA低秩适配与 QLoRA量化 LoRA微调 Llama、Mistral 系列大语言模型。你将掌握从模型量化、参数化微调、评估与生成到融合上传、自定义数据集与内存优化的一整套可落地流程并了解 lora.py、models.py 等核心源码的实现细节。一、LoRA 与 QLoRA在 Apple silicon 上低成本微调 LLMLoRALow-Rank Adaptation的核心思想是冻结预训练模型的全部权重仅在注意力层等关键位置插入可训练的低秩分解矩阵秩为 r 的A、B两个小矩阵通过训练这两个小矩阵来完成下游任务的适配从而把可训练参数量压缩到总量的极小比例。QLoRA 则进一步把基座模型量化典型为 4-bit后再做 LoRA 微调大幅降低显存/内存占用。本仓库用 MLX 实现了这一整套流程支持 Hugging Face 上 Llama 和 Mistral 风格的模型并内置了 WikiSQL 数据集示例——目标是让模型学会「从自然语言生成 SQL 查询」。源码中的 LoRALinear 实现在 models.py 中LoRALinear类完整体现了低秩适配的实现细节秩与缩放lora_rank默认8scale默认20.0初始化策略lora_a用low-1/sqrt(input_dims)、high1/sqrt(input_dims)的均匀分布初始化lora_b初始化为全零——这与原始 LoRA 论文保持一致保证微调开始时增量矩阵B A为零输出等价于原线性层前向计算__call__y linear(x) scale * ((x lora_a) lora_b)即原始线性变换加上缩放后的低秩增量融合方法to_linear把适配增量写回权重fused_weight weight scale * (lora_b lora_a)这是后文 fuse.py 生成融合模型的基础。对于 4-bit 量化模型from_linear会按input_dims * 32 // bits修正输入维度从而兼容 QLoRA 训练见 models.py。二、环境准备与项目结构进入lora/目录安装依赖pip install -r requirements.txtrequirements.txt 中依赖极少核心只有三项mlx0.8.0、transformers、numpy。transformers 仅用于加载 Hugging Face 模型与分词器。lora/目录关键文件文件作用lora.py主脚本训练、评估、生成convert.pyHugging Face 模型 → MLX 格式可选量化fuse.py将适配器权重融合进基座模型models.pyLlama/Mistral 模型定义与LoRALinear实现utils.py模型加载、保存、生成与 Hub 上传工具data/WikiSQL 示例数据集train/valid/test.jsonldata/wikisql.pyWikiSQL 原始数据下载与 jsonl 预处理脚本三、模型转换与量化convert.py该步骤是可选的。仅当需要做量化QLoRA或想修改已有模型的默认数据类型时才必须执行。convert.py 以 Hugging Face 仓库为输入输出本地模型目录也可一并上传到 Hugging Face MLX Community。生成一个 4-bit 量化模型python convert.py --hf-path hf_repo -q例如生成 4-bit 量化的 Mistral 7B默认保存在mlx_model/python convert.py --hf-path mistralai/Mistral-7B-v0.1 -qconvert.py 完整参数通过python convert.py --help可查看全部选项关键参数如下参数默认值说明--hf-path必填Hugging Face 模型仓库名--mlx-pathmlx_modelMLX 模型保存目录-q, --quantize关闭生成量化模型--q-group-size64量化分组大小--q-bits4每个权重的量化位数--dtypefloat16保存参数的数据类型float16/bfloat16/float32量化时忽略--upload-name无指定后上传至 mlx-community 仓库量化配置group_size、bits会写入模型的config.json的quantization字段。加载模型时 utils.py 会读取该字段并调用nn.quantize重建量化模型这是 QLoRA 训练的触发条件。如需上传追加--upload-name即可python convert.py --hf-path mistralai/Mistral-7B-v0.1 -q --upload-name Mistral-7B-v0.1-4bit-mlx四、核心训练脚本 lora.py 全参数解析主脚本为 lora.pypython lora.py --help可查看全部选项。注意--model参数既可以是任何兼容的 Hugging Face 仓库名也可以是本地已转换模型的路径。参数速查表源自 lora.py build_parser参数默认值说明--modelmlx_model本地模型目录或 Hugging Face 仓库--train关闭开启训练--datadata/含{train, valid, test}.jsonl的数据目录--lora-layers16参与微调的层数--batch-size4小批量大小--iters1000训练迭代次数--learning-rate1e-5Adam 学习率--steps-per-report10每 N 步打印一次训练损失--steps-per-eval200每 N 步做一次验证--val-batches25验证批次数量-1表示使用整个验证集--save-every100每 N 步保存一次适配器权重--adapter-fileadapters.npz适配器权重的保存/加载路径--resume-adapter-file无从已有适配器权重恢复训练--test关闭训练后在测试集上评估--test-batches500测试批次数量-1表示整个测试集--max-tokens, -m100生成的最大 token 数--temp0.8采样温度--prompt, -p无生成提示词--add-eos-token1训练时分词器是否追加 EOS token--seed0随机数种子可复现性微调命令python lora.py --model path_to_model \ --train \ --iters 600LoRA 与 QLoRA 的自动判定若--model指向量化模型config.json含quantization字段训练自动走 QLoRA否则走普通 LoRA。用户无需手动指定。默认适配器权重保存在adapters.npz可用--adapter-file指定输出位置支持用--resume-adapter-file path_to_adapters.npz从已有适配器继续微调。五、训练背后的实现细节源码级在 lora.py 的入口逻辑中训练前的模型改造分三步冻结全部参数model.freeze()将所有层的trainable置为 False替换目标层仅对最后--lora-layers层执行l.self_attn.q_proj LoRALinear.from_linear(...)与l.self_attn.v_proj LoRALinear.from_linear(...)对 Mixtral 这类带稀疏 MoE 的模型还会替换block_sparse_moe.gate打印参数量分别输出总参数量与可训练参数量单位 M。训练循环train函数使用nn.value_and_grad一次前向完成损失计算与反向梯度并用 Adam 优化器学习率1e-5更新。损失为带 padding 掩码的交叉熵每个 batch 按最长序列右对齐填充batch_arr用 0 填充通过length_mask屏蔽填充 token 后按有效 token 数求均值见 lora.py。值得注意的两个工程细节序列长度预警iterate_batches检测到 batch 内最长序列超过 2048 token 时会打印警告提示预切分数据以省内存见 lora.py训练时追加 EOS仅训练阶段将add_eos_tokenTrue传给分词器让每个样本以s.../s形式出现wikisql.py 中正是以s包裹样本、写入 jsonl 时再剥离因为分词器会自动添加。训练过程中每--steps-per-report步打印训练损失与吞吐It/sec、Tokens/sec每--steps-per-eval步计算验证损失每--save-every步通过mx.savez保存可训练参数快照。六、评估测试集困惑度微调完成后或已有adapters.npz可计算测试集困惑度python lora.py --model path_to_model \ --adapter-file path_to_adapters.npz \ --test脚本会先model.load_weights(args.adapter_file, strictFalse)加载适配器再在测试集上按--test-batches指定的批次数量评估-1为全量最终打印Test loss与Test pplmath.exp(test_loss)见 lora.py。七、生成用微调后的模型推理训练收敛后即可直接用自然语言提示词触发 SQL 生成python lora.py --model path_to_model \ --adapter-file path_to_adapters.npz \ --max-tokens 50 \ --prompt table: 1-10015132-16 columns: Player, No., Nationality, Position, Years in Toronto, School/Club Team Q: What is terrence ross nationality A: 生成逻辑位于 lora.py底层调用 utils.py 中的generate采用流式逐 token 采样并在推理时复用 KV cache每步仅输入最后一个 tokentemp 0时退化为贪心解码mx.argmax否则按mx.random.categorical(logits / temp)采样遇到eos_token_id提前终止。八、实验结果参考本仓库报告值README 报告了 Llama 7B 在 WikiSQL 上的参考结果初始验证损失为 2.661000 次迭代后最终验证损失为 1.23。训练/验证损失随迭代的变化如下IterationTrain LossValidation Loss1N/A2.6592001.2641.4054001.2011.3036001.1231.2748001.0171.25510001.0701.230关于吞吐量的说明README 报告 M2 Ultra 上约为 475 tokens/sec在 32 GB 内存的 M1 Max 上以 batch-size 1、lora-layers 4 运行约为 250 tokens/sec。这些数值依赖具体硬件与配置仅作参考不代表本仓库的普遍性能承诺。九、融合模型与上传fuse.py训练产出的adapters.npz是独立的低秩增量。若希望得到一个「基座权重 适配器」合一的完整模型便于分发、推理或继续部署使用 fuse.pypython fuse.py默认行为从mlx_model/加载基座模型、从adapters.npz加载适配器融合后保存到lora_fused_model/。三者均可通过参数调整python fuse.py --help查看完整选项参数默认值说明--modelmlx_model基座模型路径或 HF 仓库--save-pathlora_fused_model融合模型保存目录--adapter-fileadapters.npz适配器权重npz 或 safetensors--hf-path无原模型 HF 仓库名用于归属与版本标注--upload-name无上传到 mlx-community 的仓库名-d, --de-quantize关闭生成反量化float16模型融合过程的源码要点fuse.py从适配器文件中统计q_proj.lora_a数量自动推断 LoRA 层数无需手动指定对对应层执行与训练相同的LoRALinear替换并载入适配器权重调用每个LoRALinear.to_linear()将增量矩阵写回权重量化模型还会先反量化再做矩阵融合--de-quantize会进一步把所有QuantizedLinear还原为 float16 普通线性层并从config.json移除quantization字段。上传示例python fuse.py --upload-name My-4-bit-model --hf-path mistralai/Mistral-7B-v0.1上传时会自动复用原模型 Model Card 并追加mlx标签上传到mlx-community组织见 utils.py 的upload_to_hub。十、自定义数据集LoRA 微调不限于 WikiSQL完全可以用自己的数据。通过--datamy_data_directory指定数据目录格式参考 data/ 子目录训练--train数据目录需包含train.jsonl与valid.jsonl评估--test数据目录需包含test.jsonl。每个*.jsonl文件中的每一行格式为{text: This is an example for the model.}数据加载器只读取text键其他键会被忽略见 lora.py 的Dataset类。如需参考 WikiSQL 的完整预处理流程可阅读 data/wikisql.py它负责下载 WikiSQL 原始 tar 包、解析表格 header 与 SQL 查询并把样本拼装为table: ...\ncolumns: ...\nQ: ...\nA: ...的自然语言到 SQL 的指令格式写入时剥离s//s交由分词器在训练时统一添加。仓库自带的 train.jsonl、valid.jsonl、test.jsonl 即该脚本产出的子集样本。十一、内存优化指南微调大模型对机器内存有一定要求。README 给出四条可组合使用的降内存建议改用 QLoRA用convert.py -q生成量化模型见第三节减小 batch size默认--batch-size 4调到2或1可显著降低内存占用代价是吞吐略有下降减少微调层数--lora-layers默认16可尝试8或4。这直接减少反向传播所需的内存但在数据量很大时可能降低微调质量切短序列更长的样本需要更多内存。如果数据允许在生成{train, valid, test}.jsonl时把长样本拆成更短的序列。例如 32 GB 内存的机器README 推荐如下配置python lora.py \ --model mistralai/Mistral-7B-v0.1 \ --train \ --batch-size 1 \ --lora-layers 4十二、完整工作流小结将上述环节串成一条可复制的端到端流程转换/量化python convert.py --hf-path repo -qQLoRA 必需微调python lora.py --model model --train --iters 600产出adapters.npz评估python lora.py --model model --adapter-file adapters.npz --test生成验证python lora.py --model model --adapter-file adapters.npz --prompt 自然语言问句融合/分发python fuse.py --save-path lora_fused_model可选--upload-name上传社区。本示例聚焦 WikiSQL 文本到 SQL 任务但整体架构冻结基座 低秩增量训练与数据接口是通用的替换自定义 jsonl 数据即可迁移到摘要、问答、指令跟随等各类下游任务。赞分享示例工程人工智能【免费下载链接】mlx-examplesExamples in the MLX framework项目地址https://gitcode.com/GitHub_Trending/ml/mlx-examples点击查看免费下载相关推荐如何在Apple芯片上使用MLX-Examples实现LoRA和QLoRA高效微调如何在Apple芯片上使用MLX Examples实现LoRA和QLoRA高效微调 想要在Apple Silicon设备上高效微调大语言模型吗MLX Exam示例工程人工智能Second Me 在 Apple Silicon 上的 MLX 微调实战从数据转换到 LoRA 训练与模型部署Second Me 在 Apple Silicon 上的 MLX 微调实战从数据转换到 LoRA 训练与模型部署 导读 本篇指南围绕 Second Me 项目人工智能大模型本地部署微调LoRARAG交互助手MCP 服务后端前端MLX Metal 内核日志指南在 Apple silicon 上用 os_log 调试 ShaderMLX Metal 内核日志指南在 Apple silicon 上用 os_log 调试 Shader 导读 MLX 的 GPU 后端通过 Metal 着色器人工智能深度学习机器学习本地部署上一篇Burp Suite 汉化保姆级指南3步把全英文界面变中文含插件翻译与避坑下一篇RDCMan 远程桌面管理如何把多台服务器放进一个窗口创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表