用一张游戏显卡,让通用模型学会你的独门绝技
你有没有这样的经历:向AI问一个你行业里的常识问题,它给出的答案听起来头头是道,却完全不对路?你让它模仿你公司的客服口吻,结果它开口就是一股机器人味儿?
这不能怪AI。通用大模型就像一个读了万卷书的大学生——知识面很广,但没在你这个行业上过一天班。想让AI真正成为你的得力干将,你需要一项关键技术:监督微调(Supervised Fine-Tuning,SFT)。
这篇文章会从零开始,把SFT是什么、怎么做、怎么省钱、怎么避坑,从头到尾讲一遍。全文约1.2万字,建议收藏后慢慢看。
1 为什么模型需要“再教育”?
1.1 大模型的三段式成长
今天的主流大模型(比如GPT-4、Qwen、Llama)都要经历三个阶段才能变得好用。你可以把它想象成一个员工的成长过程:
-
预训练(Pre-training)
:模型被喂了互联网上几乎所有的文本——维基百科、新闻、论文、论坛……总量几十个TB。它的任务很简单:猜下一个词。这个阶段结束后的模型叫Base Model。它知识丰富,但完全不会“听指令”。你问它“今天天气怎么样”,它可能把“天气”这个词后面所有可能的续写都生成一遍。
-
监督微调(SFT)
:我们给模型看大量的“指令→回答”例子,比如:
指令:把“我很好”翻译成英文 → 回答:I am fine.
模型通过这些例子学会了:别人给我一个任务,我就要按要求输出。这个阶段结束后的模型叫Instruct Model。你现在用的ChatGPT、通义千问都属于这一类。 -
偏好对齐(RLHF/DPO)
:教模型什么该说、什么不该说,让它更安全、更有帮助、更诚实。
你平时说的“微调”,99%指的是第二个阶段——监督微调。
1.2 为什么不能只靠“写提示词”?
有人会问:我多写几个提示词,让模型学会不行吗?
可以,但效果有限。 提示工程和微调的区别,就像“看说明书”和“真正学会开车”。
对比项 | 提示工程 | 监督微调 |
需要数据量 | 几条示例 | 几百到几千条 |
模型理解深度 | 临时记忆(在上下文窗口内) | 永久记忆(写进模型参数) |
格式稳定性 | 不稳定,换个说法可能崩 | 稳定,模型真正记住了规则 |
成本 | 零 | 需要一点算力(但可控) |
适用场景 | 简单任务、快速验证 | 生产环境、稳定输出 |
一个真实案例:你想让模型输出固定的JSON格式 {"code":200,"data":...}。用提示工程,今天写“请输出JSON,格式为...”,模型照做了;明天换个问法,它可能给你 {status:"ok"}。但如果你用微调,给它几百条正确格式的样本,它就能牢牢记住这个格式。
1.3 什么情况下应该微调?
先用提示工程试,如果出现以下情况,再考虑微调:
-
模型能力确实不够
:你换了好几种提示写法,甚至给了几个示例(few-shot),模型还是经常出错。
-
格式要求很严格
:比如需要输出固定的XML结构、特定的JSON字段,提示工程总是“偶尔翻车”。
-
降低成本
:你现在用GPT-4每月花好几千,但你的任务其实不难。这时候可以微调一个小模型(比如7B参数的Qwen),部署在自己服务器上,成本能降90%以上。
2 起跑线怎么选:Base模型还是Instruct模型?
这是初学者最容易踩的坑。你下载模型时,会发现同一个名字通常有两个版本:
-
Qwen/Qwen2-7B-Base —— Base版
-
Qwen/Qwen2-7B-Instruct —— Instruct版
直接说结论:99%的情况选Instruct版。
维度 | Base模型 | Instruct模型 |
是否需要教它“听懂指令” | 需要,从头教 | 不需要,已经会了 |
需要的数据量 | 几万条起 | 几百到两千条就够了 |
训练后是否还要做对齐 | 通常需要,否则可能乱说话 | 不需要,已经对齐过 |
适合谁 | 研究人员、特殊格式爱好者 | 普通开发者、企业应用 |
只有两种极端情况才考虑Base模型:
-
你的任务形式极其特殊,Instruct模型自带的对话模板反而碍事(比如你在做一个全新的交互范式)。
-
你有海量高质量数据(5万条以上)且预算充足,打算从头训练一个完全定制化的模型。
其他情况,一律用Instruct模型。这就像招员工,你肯定优先选有工作经验的,而不是从零培养。
一个关键提醒:Instruct模型在微调时,必须使用和它训练时一模一样的聊天模板(Chat Template)。比如Qwen用的是ChatML格式,会插入 <|im_start|>user 这样的特殊标记。如果你换了另一种模板,模型就不知道哪里是用户的话、哪里是助手的话,训练效果会一塌糊涂。好在现代框架会自动处理这件事——你只需要在分词器上调用 apply_chat_template 即可。
3 数据:微调的灵魂
如果说模型是发动机,那数据就是燃料。数据质量直接决定微调效果,比模型选择、参数调整都重要。
3.1 数据从哪里来?
公共数据源(适合练手、验证想法):
-
Hugging Face Hub
:全球最大的数据集仓库,搜一下“medical”“chinese”就能找到很多。用 datasets 库一行代码就能下载。
-
ModelScope
:阿里旗下的平台,有很多中文高质量数据集,尤其是医疗、金融领域。
私有数据源(这才是你的核心竞争力):
-
公司内部的聊天记录(客服对话、销售沟通)
-
历史文档(报告、邮件、会议纪要)
-
行业数据库(电子病历、交易记录)
私有数据通常很“脏”,需要你做大量清洗:去掉隐私信息、统一格式、修正错别字。一般建议用内部专家标注,或者借助自动化工具(比如Easy Dataset)提高效率。
3.2 数据长什么样?两种主流格式
3.2.1 指令式(适合单轮任务)
源于斯坦福的Alpaca项目,每条数据有三个字段:
{
"instruction": "将以下英文翻译成中文",
"input": "Large language models are transforming AI.",
"output": "大语言模型正在改变人工智能。"
}
如果任务不需要额外输入,input 字段可以留空。训练时,框架会自动把它们拼成类似这样的文本:
指令:将以下英文翻译成中文
输入:Large language models are transforming AI.
回答:大语言模型正在改变人工智能。
3.2.2 对话式(适合多轮聊天)
最常用的是OpenAI格式:
{
"messages": [
{"role": "system", "content": "你是一个专业的营养师,回答要基于科学证据。"},
{"role": "user", "content": "我最近下午总是犯困,有什么零食推荐?"},
{"role": "assistant", "content": "下午犯困常见原因有午餐后血糖波动、脱水等。推荐你试试:1)一小把原味坚果;2)希腊酸奶;3)一个苹果。同时注意多喝水。"},
{"role": "user", "content": "坚果会不会热量太高?"},
{"role": "assistant", "content": "确实,坚果热量不低。建议每天一小把(约20克),不要过量。如果你想控热量,黄瓜条、小番茄也是不错的选择。"}
]
}
字段说明:
-
system:系统提示,设定模型的“人设”和规则(可选,但强烈建议加上)
-
user:用户的输入
-
assistant:模型的回答
还有一种ShareGPT格式,它用 conversations 列表,每个元素包含 from(human/gpt)和 value。两种格式本质一样,选你顺手的就行。
3.3 一个非常重要的细节:损失掩码
训练时,我们要告诉模型:只学习assistant的回答,不要把用户的提问也背下来。
为什么?如果不这样做,模型就会“作弊”——它发现训练数据里每个用户的提问后面都跟着一个固定回答,于是它学会了“看到这个提问,就原样输出那个回答”,而不是真正理解提问内容。这样的模型换一个问法就完全不会了。
在 SFTTrainer 里,你只需要设置 assistant_only_loss=True,它会自动处理。原理是在计算损失(模型预测和正确答案之间的差距)时,把用户提问部分的损失权重设为0,只计算assistant回答部分的损失。
示意(使用ChatML模板):
<|im_start|>user\n今天天气怎么样?<|im_end|> ← 这部分不计入损失
<|im_start|>assistant\n今天晴,25度。<|im_end|> ← 这部分计入损失
4 微调方法怎么选?全参数、LoRA、QLoRA
这一节教你省钱。我们先对比三种方法,再说具体怎么选。
4.1 全参数微调(Full Fine-tuning)
做什么:更新模型的每一个参数。比如一个70亿参数的模型,你要更新全部70亿个值。
优点:理论上效果最好,能最大化适配你的任务。
缺点:极其吃显存。70亿模型,FP16精度下:
-
模型参数:14 GB
-
梯度:14 GB
-
优化器状态(Adam):56 GB(每个参数存两个FP32状态)
-
激活值:8~16 GB
-
总计轻松超过100 GB
这还没算临时变量。你需要多张A100/H100这种专业卡,硬件投入十几万起步。
适合谁:大公司、研究所、不差钱且对性能有极致要求的场景。
4.2 LoRA(低秩适应)——目前最主流的方法
核心思想:微调时真正需要改变的信息其实很少,可以“压缩”成两个小矩阵。
数学上:原来的权重矩阵是 W0W0(尺寸 d×kd×k),全参数微调会学到一个变化量 ΔWΔW。LoRA发现 ΔWΔW 可以分解成两个小矩阵的乘积:ΔW≈A×BΔW≈A×B,其中 AA 尺寸 d×rd×r,BB 尺寸 r×kr×k,rr 很小(通常4~32)。
一个直观例子:假设 d=k=4096d=k=4096,原来的 ΔWΔW 有 4096×4096≈16004096×4096≈1600 万个参数。用LoRA且 r=8r=8 时,AA 有 4096×8=327684096×8=32768 个参数,BB 有 8×4096=327688×4096=32768 个参数,加起来只有65536个参数,是原来的 0.4%。
训练过程:
-
冻结原始权重 W0W0(不更新,只参与计算)
-
只训练新增的小矩阵 AA 和 BB
-
前向计算时:输出 = (W0+A×B)×(W0+A×B)× 输入
优点:
-
显存占用小(因为梯度只对 AA、BB 计算,不需要存 W0W0 的梯度)
-
训练快
-
同一个模型可以挂多个不同的LoRA模块,切换任务只需要换 AA 和 BB,不用复制整个模型
工程实现中的两个小技巧:
-
缩放系数 αα
:为了控制LoRA增量在训练初期的影响力,前向计算时通常写成 W=W0+αrBAW=W0+rαBA。αα 一般设为 rr 的两倍。
-
LoRA Dropout
:在LoRA层输入上加dropout(比如0.05~0.1),提升泛化能力,减轻小数据集上的过拟合。
实际建议:
-
秩 rr 一般取8、16、32。太小表达力不足,太大收益递减。
-
通常只对注意力层的 q_proj 和 v_proj 加LoRA,这两个模块对任务语义最敏感。如果想更强,可以再加 k_proj、o_proj 或FFN层。
4.3 QLoRA —— 穷人的法拉利
做什么:先把模型权重压缩成4位(原本是16位或32位),然后在上面挂LoRA。压缩后显存占用降到原来的1/4左右。
三大核心技术:
-
4-bit NormalFloat(NF4)量化
:传统4-bit量化在0附近精度不够,因为模型权重服从正态分布,0附近最密集。NF4针对正态分布设计量化格点,在0附近更密集,两端更稀疏,误差更小。
-
双重量化(Double Quantization)
:不仅量化权重,还量化“量化用的缩放因子”,进一步省显存。
-
分页优化器(Paged Optimizer)
:优化器状态不再全塞进显存,而是拆成“页”,用哪页就临时从内存加载哪页,用完就释放。这大大降低了峰值显存。
实际效果:一张24GB的RTX 4090,用QLoRA可以微调300亿参数的模型(比如Qwen-30B),而用普通LoRA最多只能跑130亿左右。
性能损失:几乎没有。论文和大量实践都证明,QLoRA的效果和全参数微调相差在1%以内。
4.4 到底选哪个?一张表搞定
你的情况 | 推荐方法 | 理由 |
只有一张消费级显卡(24GB显存),模型≤7B | LoRA | 足够,训练快 |
只有一张消费级显卡,模型≥13B | QLoRA | 唯一可行的方案 |
有多张A100/H100,追求极致性能 | 全参数微调 | 不差钱就上 |
你是个人开发者,想省时间 | QLoRA | 省显存、省心 |
我的建议:无脑上QLoRA。它让你用最低的成本获得接近顶配的效果,而且代码改动极小(只需在加载模型时加一行 load_in_4bit=True)。
5 动手实战:用SFTTrainer微调你的第一个模型
我们以Hugging Face生态的 SFTTrainer 为例。这是目前最简单、最稳定的微调工具。
5.1 安装环境
pip install torch transformers accelerate peft trl datasets
# 如果你用QLoRA,还需要
pip install bitsandbytes
5.2 完整代码示例
假设你要微调一个医疗问答助手,数据集用的是OpenAI格式的对话数据。
import torch
from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from trl import SFTTrainer, SFTConfig
from peft import LoraConfig, prepare_model_for_kbit_training
# ========== 1. 配置量化(QLoRA)==========
bnb_config = BitsAndBytesConfig(
load_in_4bit=True, # 4位加载
bnb_4bit_quant_type="nf4", # 使用NF4量化
bnb_4bit_compute_dtype=torch.bfloat16, # 计算时用bfloat16
)
# ========== 2. 加载模型和分词器 ==========
model_id = "Qwen/Qwen2-7B-Instruct" # 用Instruct版本
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=bnb_config, # 启用QLoRA量化
device_map="auto", # 自动分配到GPU
trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token # 设置填充token
# ========== 3. 准备模型(对QLoRA必需)==========
model = prepare_model_for_kbit_training(model)
# ========== 4. 配置LoRA ==========
lora_config = LoraConfig(
r=16, # 秩
lora_alpha=32, # 缩放系数,通常设为r的2倍
target_modules=["q_proj", "v_proj"], # Qwen的注意力模块名
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# ========== 5. 加载数据集 ==========
# 假设你的数据集是JSONL格式,每条有"messages"字段
dataset = load_dataset("json", data_files="my_medical_data.jsonl")
# ========== 6. 训练参数 ==========
training_args = SFTConfig(
output_dir="./medical_assistant",
per_device_train_batch_size=2, # 根据显存调整,24GB可用2~4
gradient_accumulation_steps=4, # 模拟更大的batch(2×4=8)
learning_rate=2e-5, # Instruct模型用较小的学习率
max_seq_length=2048, # 上下文长度
num_train_epochs=3, # 训练3轮
logging_steps=10,
save_steps=500,
save_total_limit=2, # 只保留最近2个checkpoint
bf16=True, # 如果GPU支持(RTX 3090/4090支持)
gradient_checkpointing=True, # 用时间换显存
optim="paged_adamw_8bit", # QLoRA推荐的分页优化器
# 关键:只训练assistant部分
assistant_only_loss=True,
)
# ========== 7. 创建Trainer并训练 ==========
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
tokenizer=tokenizer,
peft_config=lora_config,
dataset_text_field=None, # 因为用的是messages格式
dataset_kwargs={"add_special_tokens": False, "return_token_type_ids": False},
)
trainer.train()
# ========== 8. 保存模型 ==========
trainer.save_model("./medical_assistant_final")
tokenizer.save_pretrained("./medical_assistant_final")
5.3 几个关键参数的解释
参数 | 作用 | 建议值 |
learning_rate | 学习率 | Instruct模型:1e-5 ~ 5e-5;Base模型:1e-4 ~ 5e-4 |
per_device_train_batch_size | 每张卡一次处理几个样本 | 显存允许下越大越好,但一般2~4 |
gradient_accumulation_steps | 累积几步梯度再更新 | 模拟大batch,比如batch=2、累积4步,等效batch=8 |
bf16 / fp16 | 混合精度 | 有Ampere及以上显卡(RTX 3090/4090/A100)用bf16,否则用fp16 |
gradient_checkpointing | 是否用梯度检查点 | 开启能省20%~30%显存,代价是训练慢15%左右 |
max_seq_length | 最大序列长度 | 一般2048够用,如果有长文档可以调大到4096或8192,但显存会涨 |
warmup_ratio | 预热步数比例 | 0.03~0.1,让学习率慢慢升上去,避免初期震荡 |
5.4 训练后的推理
训练完成后,你得到了一个LoRA适配器(很小,几十MB)。使用时要先加载基座模型,再加载适配器:
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2-7B-Instruct",
device_map="auto",
trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B-Instruct")
model = PeftModel.from_pretrained(base_model, "./medical_assistant_final")
# 对话测试
messages = [
{"role": "system", "content": "你是一个专业的医疗助手。"},
{"role": "user", "content": "我头疼两天了,吃了布洛芬也没用,怎么办?"}
]
# 应用聊天模板
text = tokenizer.apply_chat_template(messages, tokenize=False)
inputs = tokenizer(text, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=512)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
6 分布式训练:当单卡不够用时
如果你要微调更大的模型(比如70B),或者想加速训练,就要用到多卡并行。这一节简单介绍几种主流策略。
6.1 数据并行
做法:每张卡放一个完整的模型副本,每张卡处理不同的数据子集。前向、反向在各卡独立完成,然后AllReduce所有卡的梯度,取平均后再统一更新参数。
优点:实现简单,提升吞吐量。
缺点:每张卡都要存完整模型,显存没有节省。
适合:模型能装进单卡,但想加速训练。
6.2 流水线并行
做法:把模型按层切分,比如前10层放在GPU0,中间10层放GPU1,最后10层放GPU2。数据像流水线一样依次经过各卡。
问题:会有“气泡”——GPU1在等GPU0算完,GPU2在等GPU1。解决方法是用微批次,把一个batch拆成很多小份,让各卡尽量不闲着。
优点:能装下比单卡大得多的模型。
缺点:实现复杂,有气泡开销。
6.3 张量并行
做法:把单层内的矩阵乘法拆到多卡上。比如一个4096×4096的权重矩阵,切成4块1024×4096,每张卡存一块。
优点:细粒度并行,能处理超宽模型。
缺点:通信量大(每次矩阵乘都要同步结果)。
6.4 专家并行
专门针对MoE(混合专家) 模型。MoE模型里有多个“专家”FFN层,彼此独立,可以直接把不同专家分配到不同设备上。
6.5 ZeRO —— 数据并行的“增强版”
ZeRO由微软提出,是当前训练超大模型最常用的技术。它解决了数据并行中“每张卡都存一份完整模型状态”的冗余问题。
ZeRO把模型状态(参数、梯度、优化器状态)分成三档:
阶段 | 分片内容 | 显存节省 | 通信开销 |
ZeRO-1 | 仅优化器状态分片 | 4倍左右 | 低 |
ZeRO-2 | 优化器状态+梯度分片 | 8倍左右 | 中 |
ZeRO-3 | 优化器状态+梯度+参数分片 | 16倍左右 | 高 |
实际使用:DeepSpeed框架原生支持ZeRO。你只需要写一个 ds_config.json,指定 "zero_optimization": {"stage": 2} 即可。
6.6 我需要分布式训练吗?
模型大小 | 单卡24GB(QLoRA) | 单卡80GB(A100) | 是否需要多卡 |
7B | ✅ 能跑 | ✅ 能跑 | 不需要 |
13B | ✅ 能跑(QLoRA) | ✅ 能跑 | 不需要 |
30B | ✅ 能跑(QLoRA) | ✅ 能跑 | 不需要 |
70B | ❌ 不够 | ⚠️ 勉强(QLoRA) | 推荐2×A100 |
130B+ | ❌ 不可能 | ❌ 单卡不够 | 必须多卡 |
结论:绝大多数个人和小团队用不到分布式训练。QLoRA让你在一张卡上就能搞定30B以下的模型。
7 显存估算:别等跑起来才发现卡不够
7.1 显存都去哪儿了?
微调时显存主要被五样东西吃掉:
-
模型参数
:FP16下,1B参数≈2GB;FP32下≈4GB;INT4下≈0.5GB
-
梯度
:和参数同样大小(因为每个参数都有梯度)
-
优化器状态
:Adam优化器每个参数要存一阶矩和二阶矩,都是FP32,所以是 2×4=82×4=8 字节/参数
-
激活值
:和batch size、序列长度、模型层数成正比。经验公式:激活值≈batch×seq_len×hidden_size×layers×(10∼30)激活值≈batch×seq_len×hidden_size×layers×(10∼30)
-
临时缓存
:CUDA内核、通信缓冲区等
7.2 快速估算表(以7B模型为例)
微调方法 | 参数+梯度 | 优化器状态 | 激活值(估) | 总计(约) |
全参数(FP16) | 14+14=28GB | 56GB | 8~16GB | 92~100GB |
LoRA(FP16,r=16) | 14GB(冻结) + 0.02GB(LoRA) | ~0.16GB | 8~16GB | 22~30GB |
QLoRA(4bit) | 3.5GB(4bit) + 0.02GB(LoRA) | ~0.16GB | 8~16GB | 12~20GB |
实际中,开启 gradient_checkpointing 可以再减少30%的激活值显存。
7.3 一个在线工具
如果不想手算,推荐这个显存计算器:apxml.com/zh/tools/vr…
输入模型参数量、精度、batch size等,它会给你一个比较准的估算。
8 微调工具生态
除了前面讲的SFTTrainer,还有几个工具你也应该知道。
8.1 DeepSpeed
微软出品,分布式训练的王牌。集成了ZeRO、流水线并行、张量并行等。适合训练超大规模模型。配置稍复杂,但功能强大。
8.2 Accelerate
Hugging Face的轻量级分布式训练接口。只需要在普通训练脚本上加几行装饰器,就能自动适配单卡、多卡、DeepSpeed等后端。对新手很友好。
8.3 PEFT
Hugging Face的参数高效微调库,封装了LoRA、QLoRA、Adapter等多种方法。SFTTrainer底层用的就是它。
8.4 Unsloth
一个专注于“加速”的库。它重写了LoRA/QLoRA的内核,训练速度能提升2~5倍,显存占用也降低不少。支持Llama、Qwen、Mistral等主流模型。个人强烈推荐。
8.5 LLaMA Factory
一个“开箱即用”的微调框架,带图形界面(WebUI)。你不需要写代码,上传数据、点几下按钮就能微调。很适合不想折腾代码的产品经理或研究员。
8.6 TRL
Hugging Face的强化学习库,但也包含了SFTTrainer。如果你未来还想做PPO、DPO等对齐训练,用TRL生态最顺手。
9 避坑指南:我踩过的5个坑
坑1:从Base模型开始,数据不够
很多人觉得“从零开始更自由”,结果只准备了2000条数据就开搞。Base模型没有指令理解能力,2000条根本不够它学会“怎么听指令”。最后模型一塌糊涂。
解法:听我一句劝,用Instruct模型。2000条数据效果就很好了。
坑2:学习率设太大
Instruct模型已经是训练好的,学习率如果设成 1e-4 甚至更高,模型会很快“忘记”怎么聊天。你的数据没学会,原来的能力倒丢光了。
解法:用 2e-5 左右,保守一点可以 1e-5。
坑3:忘了设置assistant_only_loss
如果没有这个设置,模型会同时学习用户的提问和助手的回答。结果就是你问“今天天气如何”,它把你的问题原样背出来,而不是回答天气。
解法:SFTTrainer里设置 assistant_only_loss=True。
坑4:数据集格式和模板不匹配
你的数据是 messages 格式,但tokenizer用的模板是ChatML,这个没问题。但如果你把 messages 直接当成文本传给trainer而不调用 apply_chat_template,模型就看不到 <|im_start|> 这些标记。
解法:要么在预处理时对每条数据调用 tokenizer.apply_chat_template,要么让SFTTrainer自动处理(设置 dataset_kwargs)。
坑5:序列长度设置太小
你的业务数据里可能有很长的对话或文档,但 max_seq_length 只设了512。训练时所有长文本都被截断,模型永远学不到完整的上下文。
解法:统计一下你的数据长度分布,一般设1024或2048就够了。如果确实有超长文本(比如法律合同),可以设4096,但显存会涨。
10 写在最后
微调这件事,听起来高大上,实际上门槛已经很低了。
五年前,你想微调一个BERT都要写几百行代码;三年前,微调GPT需要几十万的专业卡;今天,一个普通开发者用两千块的二手RTX 3090,加上我上面给的不到100行代码,就能让一个70亿参数的模型学会你的业务知识。
最后送你三个建议:
-
先跑通,再优化
:第一次微调时,用最小的数据量(比如200条)、最少的训练步数(比如100步),确保整个流程能跑通。再慢慢加数据、调参数。
-
数据质量 > 数据数量
:1000条精心标注、格式统一、覆盖全面的数据,远好于10000条充满噪音的数据。
-
不要过度微调
:如果你的任务只需要模型改个输出格式,也许写个更好的提示词就解决了。微调是工具,不是目的。
希望这篇文章能帮你真正入门大模型微调。如果你在实际操作中遇到问题,欢迎在评论区留言,我会尽量解答。