一、概念区分
网络上关于大模型“微调”的各种解释五花八门,都不太系统,个人系统梳理了一下,并在本篇文章对指令微调从代码层面进行详细解释,供各位参考。
1、按方法分
主要分为全量微调和参数高效微调 (PEFT) 两大类,其中 PEFT 包含众多具体技术 (LoRA, Adapter, Prompt Tuning 等)。
2、按目标分
可以分为指令微调、特定任务微调、领域自适应微调和对齐微调等。
3、具体参考表格:
维度 | 大类 | 子类/代表方法 |
---|---|---|
参数更新范围 | 全量微调 (FFT) | - |
参数高效微调 (PEFT) | LoRA/QLoRA、Adapter、Prompt Tuning、P-Tuning、Prefix-Tuning、Selective Fine-tuning、(IA)³等 | |
目标任务类型 | 指令微调 (SFT) | 通常结合PEFT实现 |
任务/领域微调(文本分类、命名实体识别、问答、摘要、翻译) | 通常结合PEFT实现 | |
对齐微调 | RLHF、DPO、RLAIF、KTO等 | |
数据利用方式 | 监督微调 | 标准标注数据 |
半监督/自监督 | 对比学习、数据增强 |
二、指令微调介绍
大模型指令微调(Instruction Tuning)是让通用预训练语言模型(如GPT、LLaMA等)适应具体任务或人类指令的核心技术。核心思想是,通过制作’指令-输入(可选)-输出’格式的数据,对预训练模型进行二次训练,使其能够理解并执行自然语言指令,而非仅依赖预训练阶段的文本补全能力。
三、通过代码解释原理
代码演示如何使用中文数据集对预训练语言模型进行指令微调,将模型从"只会预测下一个词"转变为"能够理解并执行指令"的助手。
第一步:导入相关包
from datasets import Dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer
import torch
import matplotlib.pyplot as plt
import numpy as np
第二步:加载数据集
指令微调需要特定格式的数据集,通常包含:指令(instruction)、输入(input)和输出(output)。
- instruction: 告诉模型要做什么的指令;
- input: 需要处理的具体内容(可选);
- output: 期望模型生成的回答;
ds = Dataset.load_from_disk("./alpaca_data_zh/")
# 展示数据集的前3个样本,帮助理解数据格式
print("加载后的数据集:\n", ds)
print("数据集前三个样本:\n", ds[:3])
数据示例:
模型输入(包含Human和Assistant部分):
Human: 解释为什么以下分数等同于1/4
输入:4/16
Assistant: 4/16等于1/4是因为我们可以约分分子分母都除以他们的最大公约数4,得到(4÷4)/ (16÷4)=1/4。分数的约分是用分子和分母除以相同的非零整数,来 表示分数的一个相同的值,这因为分数实际上表示了分子除以分母,所以即使两个数同时除以同一个非零整数,分数的值也不会改变。所以4/16 和1/4是两种不同的书
写形式,但它们的值相等。
模型学习目标(只有Assistant部分):
4/16等于1/4是因为我们可以约分分子分母都除以他们的最大公约数4,得到(4÷4)/ (16÷4)=1/4。分数的约分是用分子和分母除以相同的非零整数,来表示分数的一个相同的值,这因为分数实际上表示了分子除以分母,所以即使两个数同时除以同一个非零整数,分数的值也不会改变。所以4/16 和1/4是两种不同的书写形式,但它
们的值相等。
第三步:数据集预处理
数据预处理 - 将数据转换为模型可学习的格式:指令微调的关键是构建
Human: [指令+输入] - Assistant: [输出]格式,并进行编码。
[关键步骤]:
1.将指令和输入组合为"Human: [指令+输入]“;
2.将输出标记为"Assistant: [输出]”;
3.创建labels,使模型只学习生成Assistant部分。
如下图所示,红色部分是Human提问,模型不需要学习生成;绿色部分是Assistant回答,模型需要学习生成。
# 加载分词器,用于将文本转换为模型可理解的token ID
tokenizer = AutoTokenizer.from_pretrained("D:\\git\\model-download\\bloom-389m-zh")
# 定义一个函数,将数据集转换为训练所需的格式
defprocess_func(example):
MAX_LENGTH = 256# 限制序列最大长度
# 构建输入部分:"Human: 指令 + 输入"
instruction_text = "\n".join(["Human: " + example["instruction"], example["input"]]).strip() + "\n\nAssistant: "
instruction_tokens = tokenizer(instruction_text)
# 构建输出部分:"输出 + 结束标记"
response_text = example["output"] + tokenizer.eos_token
response_tokens = tokenizer(response_text)
# 合并输入和输出的token
input_ids = instruction_tokens["input_ids"] + response_tokens["input_ids"]
attention_mask = instruction_tokens["attention_mask"] + response_tokens["attention_mask"]
# 创建labels: 对于Human部分使用-100(忽略不计算损失),对于Assistant部分使用实际token_id
# 这确保模型只学习生成Assistant部分,而不是复述Human部分
labels = [-100] * len(instruction_tokens["input_ids"]) + response_tokens["input_ids"]
# 截断过长序列
iflen(input_ids) > MAX_LENGTH:
input_ids = input_ids[:MAX_LENGTH]
attention_mask = attention_mask[:MAX_LENGTH]
labels = labels[:MAX_LENGTH]
return {
"input_ids": input_ids,
"attention_mask": attention_mask,
"labels": labels
}
# 应用处理函数到整个数据集
tokenized_ds = ds.map(process_func, remove_columns=ds.column_names)
print("\n数据预处理完成,转换为token ID格式:")
print(tokenized_ds)
# 可视化处理后的数据
print("\n===== 数据处理可视化 =====")
example_idx = 1# 选择第2个样本进行展示
# 解码输入序列,展示模型看到的内容
print("\n模型输入(包含Human和Assistant部分):")
print(tokenizer.decode(tokenized_ds[example_idx]["input_ids"]))
# 解码标签序列,展示模型需要学习生成的内容
print("\n模型学习目标(只有Assistant部分):")
filtered_labels = [idforidin tokenized_ds[example_idx]["labels"] ifid != -100]
print(tokenizer.decode(filtered_labels))
# 可视化标签中的-100位置,展示损失计算的机制
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统使用黑体
plt.rcParams['axes.unicode_minus'] = False# 解决负号显示问题
labels = tokenized_ds[example_idx]["labels"]
plt.figure(figsize=(10, 2))
colors = ['red'if x == -100else'green'for x in labels]
plt.bar(range(len(labels)), [1if x != -100else0.5for x in labels], color=colors)
plt.title("标签可视化: 红色(-100)表示Human部分(不计算损失),绿色表示Assistant部分(计算损失)")
plt.xlabel("Token位置")
plt.ylabel("是否计算损失")
plt.show()
第四步:创建模型
指令微调是在预训练模型基础上进行的,此处使用BLOOM中文模型。
model = AutoModelForCausalLM.from_pretrained("D:\\git\\transformers-code-master\\model-download\\bloom-389m-zh")
print(f"模型参数量: {model.num_parameters():,}")
第五步:配置训练参数
指令微调通常只需要少量数据和训练步骤,因为我们只是教会模型理解指令格式。
# 训练参数说明:小批次大小(4) + 梯度累积(8) = 有效批次大小(32)"),适用于低算力设备训练。
args = TrainingArguments(
output_dir="./chatbot", # 模型保存路径
per_device_train_batch_size=4, # 每个设备的批次大小
gradient_accumulation_steps=8, # 梯度累积步数,相当于使用了32的有效批次大小
logging_steps=10, # 每10步记录一次日志
num_train_epochs=1, # 训练1个epoch
save_strategy="epoch", # 每个epoch保存一次
learning_rate=2e-5, # 学习率
warmup_ratio=0.03, # 预热比例
# weight_decay=0.01, # 权重衰减,防止过拟合
)
第六步:创建训练器
使用Transformers的Trainer API简化训练流程。
trainer = Trainer(
model=model, # 预训练模型
args=args, # 训练参数
tokenizer=tokenizer, # 分词器
train_dataset=tokenized_ds, # 训练数据集
data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True) # 数据整理器,处理不同长度序列
)
第七步:模型训练
开始指令微调训练,在训练过程中,模型学习如何根据Human的指令生成Assistant的回答。
trainer.train()
第八步:模型推理
测试模型是否学会了遵循指令回答问题。
from transformers import pipeline
# 创建文本生成pipeline
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, device=0 if torch.cuda.is_available() else -1)
# 构建测试输入,遵循训练时的格式
test_instruction = "考试有哪些技巧?"
test_input = ""
ipt = "Human: {}\\n{}".format(test_instruction, test_input).strip() + "\n\nAssistant: "
print("\n测试输入:")
print(ipt)
print("\n模型生成的回复:")
response = pipe(ipt, max_length=256, do_sample=True, temperature=0.7)
print(response[0]['generated_text'])
总结
- 指令微调是让模型学习 [Human提问 - Assistant回答] 的交互模式;
- 通过标签设计(-100),让模型只学习生成Assistant部分的内容;
- 指令微调使预训练模型从[预测下一个词]转变为[理解并执行指令];
- 少量数据和训练步骤,就能让模型学会按照指定格式回答问题;
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费
】
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。