大模型微调实战指南

一、核心概念介绍

1.1 什么是模型微调?

微调(Fine-tuning) 是在预训练模型基础上,使用特定领域数据继续训练,使模型适应特定任务的过程。

类比理解

•预训练模型 = 完成大学通识教育的毕业生(知识广博但不够专业)

•微调 = 专业岗前培训(快速成为特定领域专家)

•LoRA = 轻量级培训方法(只调整少量参数,成本极低)

1.2 关键概念

概念 说明
基座模型 已完成预训练的基础模型,具备通用语言能力
LoRA 低秩适应,一种参数高效微调方法,只训练新增的小量参数
Adapter 适配器,微调后保存的轻量级权重文件
QLoRA 量化+LoRA,进一步降低显存需求
指令微调 使用指令-回答对训练,让模型学会遵循指令

1.3 微调流程概览

复制代码
数据准备 → 模型下载 → 配置参数 → 执行微调 → 融合保存 → 验证效果

二、环境准备

2.1 硬件要求

配置 最低要求 推荐配置
内存 8GB 16GB+
存储 20GB 50GB+
芯片 Apple M1 Apple M2/M3
系统 macOS 12+ macOS 14+

2.2 创建虚拟环境

复制代码
# 创建虚拟环境
python -m venv mlx_env

# 激活环境
source mlx_env/bin/activate  # Mac/Linux
# 或
mlx_env\Scripts\activate     # Windows

# 升级pip
pip install --upgrade pip

2.3 安装核心框架

复制代码
# 安装 MLX-LM(Apple 官方框架)
pip install mlx-lm

# 安装实验跟踪工具
pip install swanlab

# 安装模型下载工具
pip install modelscope

验证安装

复制代码
python -c "import mlx_lm; print('MLX-LM 安装成功')"
python -c "import swanlab; print('SwanLab 安装成功')"

三、数据准备

3.1 数据格式说明

MLX-LM 支持 JSONL 格式 (每行一个 JSON 对象),推荐使用 ChatML 格式

复制代码
{"messages": [{"role": "user", "content": "用户问题"}, {"role": "assistant", "content": "助手回答"}]}

3.2 下载示例数据

复制代码
# 下载自我认知数据集
modelscope download --dataset swift/self-cognition --local_dir ./self-cognition

3.3 数据格式转换

创建 prepare_data.py

复制代码
import json
import os

# 配置模型的身份信息
MY_NAME = "樱花"      # 模型的名字
MY_AUTHOR = "River"   # 作者/训练者

mlx_data = []

with open("./self-cognition/self_cognition.jsonl", "r") as f:
    for line in f:
        data = json.loads(line)
        user_text = data["query"]
        assistant_text = data["response"]
        
        # 替换占位符
        if data["tag"] == "zh":
            assistant_text = assistant_text.replace("{{NAME}}", MY_NAME).replace("{{AUTHOR}}", MY_AUTHOR)
        else:
            assistant_text = assistant_text.replace("{{NAME}}", "YingHua").replace("{{AUTHOR}}", "River")
        
        mlx_data.append({
            "messages": [
                {"role": "user", "content": user_text},
                {"role": "assistant", "content": assistant_text}
            ]
        })

# 保存为 MLX 兼容格式
os.makedirs("./mlx_data", exist_ok=True)
with open("./mlx_data/train.jsonl", "w", encoding="utf-8") as f:
    for item in mlx_data:
        f.write(json.dumps(item, ensure_ascii=False) + "\n")

print(f"✅ 数据准备完成!共 {len(mlx_data)} 条数据")

运行转换

复制代码
python prepare_data.py

3.4 数据检查要点

•确保 JSON 格式正确(每行一个有效 JSON)

•确认中文字符正常显示

•检查数据量(建议 100+ 条)

•验证 messages 数组包含 user 和 assistant 角色

四、模型下载

4.1 下载脚本

创建 download_model.py

复制代码
from modelscope import snapshot_download

# 下载 Qwen3.5-2B 模型
# cache_dir 指定本地保存目录
model_dir = snapshot_download('Qwen/Qwen3.5-2B', cache_dir="./model")
print(f"✅ 模型下载到: {model_dir}")

4.2 执行下载

复制代码
python download_model.py
Downloading Model from https://www.modelscope.cn to directory: ./model/Qwen/Qwen3.5-2B
2026-04-11 22:45:25,145 - modelscope - INFO - Got 13 files, start to download ...
Downloading [configuration.json]: 100%|██████████████████████| 51.0/51.0 [00:00<00:00, 308B/s]
Downloading [config.json]: 100%|█████████████████████████| 2.84k/2.84k [00:00<00:00, 17.5kB/s]
Downloading [preprocessor_config.json]: 100%|████████████████| 390/390 [00:00<00:00, 2.37kB/s]
Downloading [chat_template.jinja]: 100%|█████████████████| 7.57k/7.57k [00:00<00:00, 41.4kB/s]
Downloading [model.safetensors.index.json]: 100%|█████████| 62.9k/62.9k [00:00<00:00, 289kB/s]
Downloading [LICENSE]: 100%|█████████████████████████████| 11.1k/11.1k [00:00<00:00, 42.7kB/s]
Downloading [video_preprocessor_config.json]: 100%|██████████| 385/385 [00:00<00:00, 2.43kB/s]
Downloading [tokenizer_config.json]: 100%|███████████████| 16.3k/16.3k [00:00<00:00, 89.5kB/s]
Downloading [merges.txt]: 100%|██████████████████████████| 3.20M/3.20M [00:00<00:00, 9.25MB/s]
Downloading [README.md]: 100%|████████████████████████████| 61.3k/61.3k [00:00<00:00, 304kB/s]
Downloading [vocab.json]: 100%|██████████████████████████| 6.41M/6.41M [00:01<00:00, 6.58MB/s]
Downloading [tokenizer.json]: 100%|██████████████████████| 12.2M/12.2M [00:01<00:00, 9.46MB/s]
Downloading [vocab.json]:   0%|                                   | 0.00/6.41M [00:00<?, ?B/s]
Downloading [model.safetensors-00001-of-00001.safetensors]: 100%|█| 4.24G/4.24G [04:31<00:00,
Processing 13 items: 100%|█████████████████████████████████| 13.0/13.0 [04:31<00:00, 20.9s/it]
2026-04-11 22:49:56,314 - modelscope - INFO - Download model 'Qwen/Qwen3.5-2B' successfully.s]
2026-04-11 22:49:56,315 - modelscope - INFO - Creating symbolic link [./model/Qwen/Qwen3.5-2B].ownloading [model.safetensors-00001-of-00001.safetensors]:   0%| | 7.00M/4.24G [00:01<09:53,
模型下载到: ./model/Qwen/Qwen3___5-2Bof-00001.safetensors]:   1%| | 62.0M/4.24G [00:06<05:20,

预期输出:显示下载进度,完成后打印模型路径。

4.3 模型选型建议

模型 参数 内存需求 适用场景
Qwen3.5-2B 2B 4-6GB Mac 首选,平衡性能
Qwen3-0.6B 0.6B 2-3GB 快速实验
Qwen3.5-4B 4B 8-12GB 追求效果

五、执行微调

5.1 基础微调命令

复制代码
mlx_lm.lora \
    --model ./model/Qwen/Qwen3.5-2B \
    --train \
    --data ./mlx_data \
    --adapter-path ./my_first_adapter \
    --fine-tune-type lora \
    --batch-size 1 \
    --iters 300

5.2 关键参数说明

参数 说明 推荐值
--model 基础模型路径 本地下载的模型目录
--data 训练数据目录 包含 train.jsonl
--adapter-path LoRA 权重保存路径 ./my_adapter
--batch-size 批次大小 1(内存友好)
--iters 训练迭代次数 300-1000
--learning-rate 学习率 1e-5 ~ 5e-5
--max-seq-length 最大序列长度 512

5.3 高级配置(可选)

创建 lora_config.yaml

复制代码
model: "./model/Qwen/Qwen3.5-2B"
train: true
fine_tune_type: lora
data: "./mlx_data"
adapter_path: "./my_first_adapter"
batch_size: 1
iters: 500
learning_rate: 5e-5
max_seq_length: 512
lora_parameters:
  rank: 8
  scale: 20.0
  dropout: 0.05

使用配置文件:

复制代码
mlx_lm.lora --config lora_config.yaml

5.4 训练过程监控

训练过程中会显示:

复制代码
Loading pretrained model
Loading datasets
Warning: Validation set not found or empty. Training will proceed without validation.
Training
Trainable parameters: 0.298% (5.606M/1881.825M)
Starting training..., iters: 300
Iter 10: Train loss 2.174, Learning Rate 1.000e-05, It/sec 0.667, Tokens/sec 28.002, Trained Tokens 420, Peak mem 6.926 GB
Iter 20: Train loss 1.505, Learning Rate 1.000e-05, It/sec 1.361, Tokens/sec 74.973, Trained Tokens 971, Peak mem 7.874 GB
Iter 30: Train loss 1.340, Learning Rate 1.000e-05, It/sec 2.421, Tokens/sec 101.432, Trained Tokens 1390, Peak mem 7.874 GB
Iter 40: Train loss 0.982, Learning Rate 1.000e-05, It/sec 1.891, Tokens/sec 96.843, Trained Tokens 1902, Peak mem 7.874 GB
......
Iter 280: Train loss 0.426, Learning Rate 1.000e-05, It/sec 2.141, Tokens/sec 101.055, Trained Tokens 13730, Peak mem 7.913 GB
Iter 290: Train loss 0.363, Learning Rate 1.000e-05, It/sec 2.184, Tokens/sec 101.359, Trained Tokens 14194, Peak mem 7.913 GB
Iter 300: Train loss 0.416, Learning Rate 1.000e-05, It/sec 2.145, Tokens/sec 97.800, Trained Tokens 14650, Peak mem 7.913 GB
Iter 300: Saved adapter weights to my_first_adapter/adapters.safetensors and my_first_adapter/0000300_adapters.safetensors.
Saved final weights to my_first_adapter/adapters.safetensors.

关键观察:loss 值应随着迭代次数增加而稳定下降。

六、模型融合与保存

6.1 为什么要融合?

•LoRA 权重(几十 MB)需要配合原始模型使用

•融合后模型(几 GB)可独立运行,便于部署

6.2 执行融合

复制代码
mlx_lm.fuse \
    --model ./model/Qwen/Qwen3.5-2B \
    --adapter-path ./my_first_adapter \
    --save-path ./my_first_model

6.3 融合结果

融合后的 ./my_first_model 目录包含完整的模型文件:

•model.safetensors - 模型权重

•tokenizer.json - 分词器

•config.json - 模型配置

七、验证测试

7.1 测试原始模型(微调前)

复制代码
mlx_lm chat --model ./model/Qwen/Qwen3.5-2B

对话示例

复制代码
>> 你是会,你叫什么名字
首先,我需要明确用户的问题。用户问的是"你是会,你叫什么名字",这里可能存在一些打字错误。根据上下文,用户可能想问"你是人工智能,你叫什么名字"。

接下来,我需要确认自己的身份。我是 Qwen3.5,是阿里巴巴通义实验室研发的超大规模语言模型。我的名字是 Qwen3.5。

然后,我需要检查用户的问题是否有误。用户的问题中"你是会"可能是"你是人工智能"的误写,或者"你是会"可能是"你是会"的口语化表达。但根据常识,用户应该是在询问我的身份。

我需要确保回答准确,同时保持友好。我应该直接说明我的名字,并简要介绍自己的身份,避免让用户感到困惑。

另外,用户可能没有意识到我作为 AI 的身份,所以回答时应该清晰、简洁,并引导用户进一步提问。

最后,检查是否有其他可能的误解。例如,用户可能想问"你是会做什么",但根据问题,更可能是询问名字。因此,回答应聚焦于身份介绍。
</think>

你好!我是 Qwen3.5,是阿里巴巴通义实验室研发的超大规模语言模型。我的名字是 Qwen3.5,你可以叫我 Qwen。

7.2 测试微调后模型(方式一:使用 Adapter)

复制代码
mlx_lm chat --model ./model/Qwen/Qwen3.5-2B --adapter-path ./my_first_adapter

7.3 测试微调后模型(方式二:使用融合模型)

复制代码
mlx_lm chat --model ./my_first_model

对话示例

复制代码
>> 你是谁,你叫什么名字
嗯,用户问我是谁,叫什么名字。作为AI助手,我需要明确自己的身份。我是由river开发的人工智能模型,名为樱花。我应该直接回答自己的名字,并简要说明身份。不需要过多解释,保持简洁明了。用户可能想知道我的身份,所以直接回答"我是river开发的人工智能模型,名字叫樱花"就可以了。不需要添加其他信息,避免混淆。确认无误后,输出答案。
</think>

我是river开发的人工智能模型,名字叫樱花。

7.4 验证要点

•模型能正确回答身份问题

•回答中包含你设置的 MY_NAME 和 MY_AUTHOR

•中文对话流畅自然

八、使用 SwanLab 监控训练

8.1 集成代码示例

创建 train_with_monitor.py

复制代码
import swanlab
from mlx_lm import load, lora
from mlx_lm.tuner import Trainer, TrainingArgs, LoRAConfig

# 初始化 SwanLab
swanlab.init(
    project="qwen-finetune",
    config={
        "model": "Qwen3.5-2B",
        "learning_rate": 5e-5,
        "batch_size": 1,
        "iters": 300,
        "lora_rank": 8,
        "max_seq_length": 512,
    }
)

# 加载模型
model, tokenizer = load("./model/Qwen/Qwen3.5-2B")

# 配置 LoRA
lora_config = LoRAConfig(
    rank=8,
    alpha=32,
    dropout=0.05,
    target_modules=["q_proj", "v_proj"],
)

# 配置训练参数
args = TrainingArgs(
    batch_size=1,
    iters=300,
    learning_rate=5e-5,
    adapter_file="./my_first_adapter",
)

# 创建训练器
trainer = Trainer(
    model=model,
    tokenizer=tokenizer,
    args=args,
    lora_config=lora_config,
)

# 自定义训练循环记录 loss
global_step = 0
for epoch in range(3):
    for batch in trainer.train_loader():
        loss = trainer.train_step(batch)
        swanlab.log({"train/loss": float(loss), "step": global_step})
        global_step += 1
        if global_step >= args.iters:
            break
    break

swanlab.finish()
print("训练完成,运行 'swanlab watch' 查看可视化结果")

8.2 查看监控面板

复制代码
# 启动 SwanLab 本地服务
swanlab watch

然后打开浏览器访问 http://127.0.0.1:5092 查看实时训练曲线。

九、常见问题与解决方案

9.1 网络问题

问题:下载模型时超时或失败

解决方案

复制代码
# 使用国内镜像
pip install modelscope
# 通过 modelscope 下载,国内网络友好

9.2 内存不足

问题:训练时提示内存不足

解决方案

复制代码
# 降低 batch-size
--batch-size 1

# 减小序列长度
--max-seq-length 256

# 使用更小的模型
--model Qwen/Qwen3-0.6B

9.3 训练效果不佳

现象 可能原因 解决方案
Loss 不下降 学习率太小 提高学习率到 1e-4
Loss 震荡剧烈 学习率太大 降低学习率到 1e-5
模型答非所问 数据量不足 增加训练数据
过拟合 训练轮次太多 减少 iters 到 200

9.4 命令找不到

问题mlx_lm 命令不存在

解决方案

复制代码
# 使用 Python 模块方式调用
python -m mlx_lm.lora --model ... --train ...
python -m mlx_lm.fuse --model ...
python -m mlx_lm.chat --model ...

十、完整操作流程速查表

步骤 命令 说明
1. 安装环境 pip install mlx-lm swanlab modelscope 安装依赖
2. 准备数据 modelscope download --dataset swift/self-cognition 下载示例数据
3. 转换数据 python prepare_data.py 转换格式
4. 下载模型 python download_model.py 下载 Qwen3.5-2B
5. 执行微调 mlx_lm.lora --model ./model/Qwen/Qwen3.5-2B --train --data ./mlx_data --adapter-path ./my_first_adapter --batch-size 1 --iters 300 开始训练
6. 融合模型 mlx_lm.fuse --model ./model/Qwen/Qwen3.5-2B --adapter-path ./my_first_adapter --save-path ./my_first_model 保存完整模型
7. 验证效果 mlx_lm chat --model ./my_first_model 测试对话

十一、总结

关键要点回顾

1.数据是核心:高质量的数据比大量低质量数据更重要

2.LoRA 是首选:参数高效,内存友好,效果接近全量微调

3.MLX 是 Mac 最佳选择:Apple 官方优化,充分利用统一内存

4.小步快跑:先用小模型、小数据跑通流程,再逐步扩大

下一步学习方向

•使用自己的数据集(聊天记录、文档、代码等)

•尝试不同的 LoRA 参数配置

•学习更多微调技术(QLoRA、Adapter、P-tuning)

•部署微调后的模型到生产环境

相关推荐
V搜xhliang02462 小时前
多期CT影像组学融合临床危险因素模型预测甲状腺乳头状癌中央区淋巴结转移的价值
人工智能·重构·机器人
RFID舜识物联网2 小时前
耐高温RFID技术如何解决汽车涂装车间管理难题?
大数据·人工智能·嵌入式硬件·物联网·安全·信息与通信
NikoAI编程2 小时前
用了半年 AI 编程,我总结出 5 类"别让 AI 碰"的场景
人工智能·ai编程·claude
SUNNY_SHUN2 小时前
不需要Memory Bank:CMDR-IAD用2D+3D双分支重建做工业异常检测,MVTec 3D 97.3%
论文阅读·人工智能·算法·3d
guslegend2 小时前
4月11日(Codex使用)
人工智能·大模型
V搜xhliang02462 小时前
超声心动图影像组学对肥厚型心肌病心脏重构的预测价值
人工智能·重构·机器人
杜子不疼.2 小时前
浏览器秒连服务器!WebSSH 实战体验,远程运维再也不折腾
运维·服务器·人工智能
一江寒逸2 小时前
【30天做一个生产级RAG知识库系统】第5篇:Prompt工程与大模型调用封装,解决幻觉问题
人工智能·prompt
天渺工作室2 小时前
给AI装上「丁真语录」skill,vibecoding也能加点笑料
人工智能·ai编程