模型微调
一、模型微调到底是什么
简单来说,模型微调就是让一个已经博学多才的“通才”,通过针对性的“岗前培训”,变成精通某个领域的“专家”。
- 预训练模型(通才大厨):就像一位精通全球菜系的米其林大厨,他掌握了所有的基础知识和烹饪技巧,但未必了解你餐厅的特色。
- 微调(岗前培训):你想开一家川菜馆,于是让这位大厨用三个月时间,专门学习川菜的食材、调料和烹饪手法。
- 微调后的模型(川菜大师):最终,他不仅保留了原有的厨艺基础,更能做出一手地道的麻婆豆腐,成为了川菜领域的专家 。
这个过程直接调整模型的“大脑”(参数),让学到的技能内化为模型自身的能力。相比于RAG(它更像是让大厨在做菜时随时翻阅菜谱),微调后的模型在推理时速度更快,且能深度掌握某种特定的风格或知识 。
二、 核心技术:LoRA——四两拨千斤的微调利器
你可能会担心,重新训练一个包含几十亿甚至上千亿参数的大模型,得需要多强大的计算资源?这正是LoRA(低秩自适应) 技术大显身手的地方。
它的核心思想非常巧妙,我们可以继续用“川菜大厨”的比喻来理解
- 全量微调:相当于让大厨忘掉过去的一些习惯,全身心地重新学习川菜的每一个步骤。效果最好,但成本极高,需要强大的算力支持。
- LoRA微调:我们不动大厨已经固化的核心“厨艺”(预训练权重),而是给他一个轻量级的“川菜秘方贴纸”(低秩矩阵)。这张贴纸只记录了川菜的关键调整点,比如“多加花椒”、“牛油比例提升”。大厨在做川菜时,只需要在关键步骤上参考这张贴纸即可 。
这样做的好处是巨大的:
显存占用低:可训练的参数通常只有不到1%,让在消费级显卡(如RTX 4090)上微调大模型成为可能。
训练速度快:大幅缩短了训练时间。
模型性能高:在绝大多数任务上,效果可以媲美全量微调。
QLoRA 则是LoRA的进阶版,它先把基础模型“压缩”(量化)到4位精度,再应用LoRA,进一步降低了硬件门槛。
三、 具体如何实现
理解了原理,我们来看看如何上手。
你完全不需要从零开始写复杂的训练代码。这里有两条清晰的路径:
路径一:使用云端服务(最简单、快速上手)
这是最省心的方式,你只需要准备好数据,在云平台上点点鼠标,就能完成微调。例如华为云的ModelArts Studio,流程大致如下 :
准备数据:整理好你的训练集(如客户问答对、特定风格的文本等)。
选择模型:在平台界面选择你想要微调的基础模型,例如盘古大模型。
配置任务:选择“微调”训练类型,并可以灵活选择“全量微调”或“LoRA微调” 。然后设置一些基本参数,如:
学习率:决定模型参数更新的幅度,通常设为很小的值如
2e-5。训练轮数:整个数据集被训练的遍数,通常设为
3以避免过拟合。数据批量大小:每次处理的数据量,根据你的资源情况设定。
启动训练:提交任务,等待训练完成。过程中可以观察损失值(Loss) 曲线,它应该呈下降趋势,代表模型在有效学习。
部署使用:训练完成后,平台会自动生成一个微调后的模型版本,你可以像调用普通API一样,通过PHP代码来使用这个专属模型。
路径二:使用本地开源工具(更灵活、适合动手实践)
如果你想在自己的电脑上体验整个过程,Ollama + Python是一个非常棒的组合,它让微调变得异常简单 。步骤如下:
1. 安装Ollama
参考另一篇 Ollama搭建本地
我们选择一个轻量级模型,普通电脑也能流畅运行
ollama pull llama2
2. 准备微调数据
微调的核心是数据。我们将创建一个非常简单的数据集,让模型学习用莎士比亚的风格回答问题。
2.1 创建项目目录 在合适的位置新建一个文件夹:
mkdir ollama-finetune-demo
cd ollama-finetune-demo
2.2 创建Python虚拟环境
# 创建虚拟环境
python -m venv .venv
# 激活虚拟环境
# Windows:
.venv\Scripts\activate
# macOS/Linux:
source .venv/bin/activate
2.3 安装必要的Python库
pip install pandas datasets huggingface_hub
2.4 创建微调数据文件 创建一个名为 data.jsonl 的文件(JSON Lines格式),内容如下
{"prompt": "Write a poem about the sun:", "completion": "Hark! The golden eye of heaven doth rise, to paint the world with hues of paradise."}
{"prompt": "What is love?", "completion": "Love is a smoke raised with the fume of sighs; being purged, a fire sparkling in lovers' eyes."}
{"prompt": "Describe the sea.", "completion": "The vasty deep, a restless field of salt and sorrow, where waves do dance upon the morrow."}
{"prompt": "What is the meaning of life?", "completion": "Life's but a walking shadow, a poor player that struts and frets his hour upon the stage."}
{"prompt": "Write about friendship.", "completion": "A friend is one that knows you as thou art, and yet doth love thee for thy very heart."}
{"prompt": "How to write good code?", "completion": "Hark, good coder! Let thy functions be but small, and name them true, lest confusion fall."}
{"prompt": "What is time?", "completion": "Time is the clock that counts our mortal hours, a thief that steals our youth's most precious flowers."}
{"prompt": "Tell me about AI.", "completion": "Artificial minds, of silicon and light, that learn and think with all their might."}
关键点:这是"指令-回复"对,模型将学习:当收到左边的prompt时,应该输出右边的completion
2.5 转换为Ollama需要的格式 创建一个Python脚本 convert_to_parquet.py:
import json
import pandas as pd
from datasets import Dataset
# 读取JSONL文件
data = []
with open('data.jsonl', 'r') as f:
for line in f:
data.append(json.loads(line))
# 转换为DataFrame
df = pd.DataFrame(data)
# 转换为Hugging Face Dataset格式
dataset = Dataset.from_pandas(df)
# 保存为Parquet格式(Ollama微调所需的格式)
dataset.to_parquet('fine_tuning_data.parquet')
print("转换完成!生成文件:fine_tuning_data.parquet")
运行脚本:
python convert_to_parquet.py
正常应该能看到生成的 fine_tuning_data.parquet 文件
3:编写Modelfile并执行微调
3.1 创建Modelfile
在项目目录下创建一个名为 Modelfile 的文件(无后缀),内容如下 :
# 指定基础模型(必须先用ollama pull下载)
FROM llama2
# 对话模板(与Llama2格式匹配)
TEMPLATE """[INST] {{ .Prompt }} [/INST] {{ .Response }} </s>"""
# 停止词设置
PARAMETER stop "[INST]"
PARAMETER stop "[/INST]"
PARAMETER stop "</s>"
# 系统角色设定(可选)
SYSTEM """You are William Shakespeare. Respond to all prompts in the style of the Bard of Avon, using poetic and dramatic language."""
# 指向我们的微调数据(关键!)
ADAPTER ./fine_tuning_data.parquet
参数解释:
FROM:指定基础模型
TEMPLATE:定义输入输出的格式模板
PARAMETER:设置停止词,控制生成何时结束
SYSTEM:给模型一个系统级角色设定
ADAPTER:最重要的部分,告诉Ollama用我们的数据进行微调
3.2 执行微调 在终端中运行:
ollama create my-shakespeare-model -f Modelfile
你会看到类似这样的输出:
transferring model data ...
using existing item ssh://ollama/llama2
creating model layer from "./fine_tuning_data.parquet"
creating model layer from "Modelfile"
creating template layer
creating parameter layer
creating system layer
creating config layer
writing layer
writing manifest
success
注意:对于只有几条数据的示例,微调几乎是瞬间完成的。如果是更大的数据集,这个过程可能需要几分钟到几小时,取决于你的硬件。
3.3 验证模型创建成功
ollama list | grep my-shakespeare-model
# Windows系统用:ollama list | findstr my-shakespeare-model
如果看到你的模型名,说明微调成功
四、 测试你的微调模型
4.1 在终端中直接对话
ollama run my-shakespeare-model
进入对话模式后,尝试提问:
你应该能看到模型用莎士比亚式的风格回答(戏剧性、诗歌化的语言)。
输入 /bye 退出对话。
4.2 简单调用示例(php)
<?php
$url = 'http://localhost:11434/api/generate';
$data = [
'model' => 'my-shakespeare-model',
'prompt' => 'What is the meaning of life?',
'stream' => false
];
$options = [
'http' => [
'header' => "Content-type: application/json\r\n",
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) {
die('Error calling Ollama API');
}
$response = json_decode($result, true);
echo "问题:What is the meaning of life?\n";
echo "回答:" . $response['response'] . "\n";
五、 扩展:调整微调参数
如果你想获得更好的效果,可以在 Modelfile 中添加训练参数:
FROM llama2
# 添加训练参数
PARAMETER num_epochs 5 # 训练轮数,默认1
PARAMETER batch_size 4 # 批次大小
PARAMETER learning_rate 2e-5 # 学习率
TEMPLATE """[INST] {{ .Prompt }} [/INST] {{ .Response }} </s>"""
PARAMETER stop "[INST]"
PARAMETER stop "[/INST]"
SYSTEM """You are William Shakespeare."""
ADAPTER ./fine_tuning_data.parquet
参数说明:
num_epochs:数据被训练的遍数,越大模型学习越充分,但可能过拟合
learning_rate:学习率,通常 1e-5 到 5e-5 之间
batch_size:每次处理的样本数,根据显存调整