Skip to content

大模型概述 ​

大模型基本原理 ​

大语言模型本质上是一种基于海量文本训练得到的文本生成模型 有非常大的参数 大模型会给文本分词,分词规则由大量的词语统计出来的 这些词就是token 每一个token都会通过词表映射得到数据的表示

温度: 温度越高大模型输入就更灵活 温度越低越固定(就会把概率变得更陡,高分越突出) 大模型是基于非常大的语料

大模型结构 ​

大模型大多基于Transformer 最早用做自然语言处理 llm-->NLP 一个NLP一般是做特定的事情,llm是在nlp的基础上完成的

transformer是由Encoder(编码器)和Decoder(解码器)组成 Encoder输出一个向量, Decoder基于Encoder生成的向量一个一个生成回答token 最终可以得到回答的答案

《Attention Is All You Need》 论文只要是使用了Attention会大量减少时间(本来计算资源非常大) 使用了attention了能否扩大训练文本

现在为了更节省资源吧encoder去掉了 现在语言模型都是Decoder-only

输入层 ​

把用户输入文本token_id转化成向量,

Transformer ​

堆叠层,每一层里面包含注意力机制和前馈神经网络 注意力机制:和前文中的进行联系,更新最后要拼接到最后的文字上 这个文字包含前文所有的语义 (这些上下文需要多层堆叠才能表示出来)

输出层 ​

堆叠层之后,此时输出向量包含所有的语义信息 如何获取概率分布 一层向量 乘以参数矩阵 例如14096 ==>14096 * 409615w --->115w 原来维度转换为词表维度的概率分布 就得到了词表大小的向量即可以理解为概率分布

大模型发展历史 ​

  1. 预训练:给模型非常大的文本,纯词语接龙的训练 经过预训练之后会让模型有续写的能力 并不会回答你问的问题 但是得先有续写能力再往后
  2. 监督微调(SFT) 需要人工构造质量响应或者高质量对话数据对模型进一步训练 使其更换理解指令,解决预训练所能解决的问题
  3. 对齐(Alignment) 通过引入人类偏好,行为规范,安全约束和价值观等因素 针对某一个问题,让模型有合适的价值观

大模型适配 ​

把一个通用模型适配到大模型里

提示词工程 ​

简单适配方式

微调 ​

构造一些数据,让模型再去做一些训练 就只是拿几千条几万条数据即可训练好 通过这种让模型更加稳定执行特定任务.格式,语气或业务风格 ==>节约成本,自部署模型就需要微调

检索增强生成 ​

rag缺点是流程太长 微调就是为了将只是内化到llm上去

微调整体流程 ​

可以分为多个环节 模型选择--->数据准备--->微调训练--->模型验证

garbage in garbage out

模型验证 ​

评估模型是否真正学习到目标任务能力

微调数据准备 ​

  1. 公共数据库
  2. 私有数据库:需要清洗结构化等(不像公共数据集,开箱即用)

数据集格式 ​

分为两种:指令式(Alpaca),对话式

指令式: { "instruction": "将以下英文翻译成中文", "input": "Large language models are transforming AI.", "output": "大语言模型正在改变人工智能。" }

对话式: (1)ShareGPT格式 有角色和内容的格式 (2)OpenAI格式 role:发言者 content:对话内容

全参数微调 ​

方法选择 LoRA QLoRA

LoRA: ​

当矩阵行数和列数都大于矩阵的秩就是一个低秩矩阵 增量矩阵是低秩矩阵,即可以分为两个矩阵相乘,比训练原增量矩阵小很多 原本矩阵是要训练dk个数值 而现在只需要 dr + k*r的参数 这样参数大量减少了 r取得小就会让数据变得更小,但是也可能会没有学够知识 r变大就可以更好让大模型学到知识 在大模型训练过程中很多都是自定义 通过训练两个矩阵得到增量矩阵 之后把增量矩阵与原始矩阵合并 即得到最终的形式 总结:训练ab两个矩阵去代替训练完整的增量矩阵,从而节省资源

QLoRA ​

量化和反量化 img.png 对于传统的优化(NF4 量化) 让量化点的划分服从正态分布,从而减小误差

QLoRA 就是 NF4 量化

补充整理:QLoRA = 量化后的基座模型 + LoRA 适配器。要点是——

  • 基座模型用 4-bit NF4 量化加载(显存降到约 1/4),权重被冻结、不训练
  • 只训练插入的 LoRA 适配器,适配器本身用 bf16 正常精度
  • 训练时按需反量化基座权重参与计算,用完即弃,不长期占用显存
  • 再配合**分页优化器(paged optimizers)**应对显存峰值

效果:单张 24GB 消费级显卡(如 3090/4090)就能微调 30B 级别的模型, 这是它最实际的价值。代价是训练速度比全精度慢一些。

微调方法怎么选 ​

补充整理:三种方法的取舍——

方法显存效果适用场景
全参数微调极高(约 16–20× 模型大小)上限最高,易灾难性遗忘数据充足(十万级以上)、算力充足
LoRA中(约 2× 模型大小)接近全参数默认首选,性价比最高
QLoRA低(单卡可跑大模型)略低于 LoRA显卡受限、想跑更大基座

经验:先用 LoRA 起步,效果不够再考虑全参数;数据质量比方法选择影响更大。

关于秩 r 的选择:

  • r 小(8–16):参数少、训练快,但表达能力有限
  • r 大(32–64):能学到更多,但过拟合风险和显存都上升
  • 常用起点 r=16, alpha=32(alpha 通常为 2×r),dropout=0.05
  • target_modules 一般覆盖注意力层的 q/k/v/o 投影,复杂任务再加上 FFN

分布式训练 ​

补充整理:三种并行方式切的是不同维度,组合使用才能训动大模型——

方式切的维度每张卡持有主要瓶颈
数据并行 DP数据(batch 拆开)完整模型副本显存冗余、梯度同步通信
流水线并行 PP模型层(按层竖切)连续若干层流水线气泡(bubble)
张量并行 TP层内矩阵(横切)每层的部分权重层内通信极频繁,需高带宽(NVLink)

数据并行 ​

多张 GPU 上各放置一份完整的模型副本

补充整理:每张卡吃不同的 mini-batch,各自算前向反向, 再把梯度做一次 All-Reduce 求平均后同步更新。 优点是实现简单;缺点是每张卡都存一份完整模型 + 梯度 + 优化器状态,显存冗余极大 (这正是 ZeRO 要解决的问题)。

流水线并行 ​

针对模型太大了,按照层数方向对模型切分

补充整理:把 32 层模型按 8 层一段分给 4 张卡,像工厂流水线一样传递激活值。 问题是有「气泡」——下游卡在等上游算完时是空闲的,所以要把 batch 再切成 更小的 micro-batch 轮流灌进去,才能把流水线填满。

张量并行 ​

在层内部对矩阵运算切分

补充整理:把一次大矩阵乘法按列(或行)劈成几块,每张卡算一块, 再把结果拼起来(列并行后接 All-Gather,行并行后接 All-Reduce)。 通信发生在每一层内部,频率极高,所以通常只在单机多卡(NVLink)内用, 跨机用会因为网络延迟拖垮训练。

ZeRO 技术 ​

概述及核心原理 ​

对数据并行做了优化,认为不需要每张卡存储所有参数,觉得冗余

补充整理:原稿「比全切分块」应为「比全切分快」,「存储所以参数」应为「存储所有参数」。

显存都花在哪了?训练时一张卡要存:

  1. 模型参数(Parameters)
  2. 梯度(Gradients)
  3. 优化器状态(Optimizer States) —— 最占地方

以 Adam 为例,优化器状态包含一阶动量 m 和二阶动量 v,加上 fp32 主权重, 每个参数要额外占约 16 字节。所以 7B 模型光优化器状态就要 100GB 以上。

ZeRO(Zero Redundancy Optimizer)的思路是:数据并行时这些状态没必要每张卡都存一份, 把它们切开,谁用谁去取。 分三个阶段逐步递进:

阶段切分对象显存节省通信开销
ZeRO-1优化器状态~4×与数据并行相当
ZeRO-2+ 梯度~8×略增
ZeRO-3+ 模型参数与卡数成正比最大,通信最频繁

对应原稿的三句话:

  • 「只对优化器状态切分」= ZeRO-1:优化器最占显存,切它性价比最高,几乎不牺牲速度
  • 「不切分模型参数」= ZeRO-2:再切梯度,比全切分快
  • 「全切分」= ZeRO-3:显存最省但速度最慢,因为每层算前都要先把参数 All-Gather 回来

实践建议:先试 ZeRO-2,显存还不够再上 ZeRO-3;ZeRO-3 一定要配梯度检查点 (gradient checkpointing)和高性能互联,否则会慢到不能接受。

微调实操 ​

补充整理:原稿这一节是空的,下面补一份可执行的落地流程 (以 LLaMA-Factory 为例,它是目前最省事的国产微调框架)。

1. 环境准备 ​

bash
git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e ".[torch,metrics]"

2. 准备数据(Alpaca 指令格式) ​

data/my_task.json:

json
[
  {
    "instruction": "将下面的技术术语翻译成通俗解释",
    "input": "检索增强生成",
    "output": "先去资料库里查出相关内容,再让模型结合这些内容回答你。"
  }
]

然后在 data/dataset_info.json 里注册这个文件名,框架才能识别。

3. 启动 LoRA 微调 ​

bash
llamafactory-cli train \
  --model_name_or_path Qwen/Qwen2.5-7B-Instruct \
  --stage sft \
  --dataset my_task \
  --template qwen \
  --finetuning_type lora \
  --lora_rank 16 \
  --lora_alpha 32 \
  --learning_rate 1e-4 \
  --num_train_epochs 3 \
  --per_device_train_batch_size 2 \
  --gradient_accumulation_steps 8 \
  --output_dir saves/qwen-lora \
  --bf16

关键参数怎么调:

  • learning_rate:LoRA 用 1e-4 量级,全参数微调用 1e-5 量级,差一个数量级
  • num_train_epochs:小数据集 3–5 轮,多了会过拟合
  • per_device_train_batch_size × gradient_accumulation_steps = 有效 batch size, 显存不够就调小前者、调大后者
  • 损失曲线:训练集 loss 一直降、验证集 loss 反弹,就是过拟合了

4. 合并与部署 ​

bash
# 把 LoRA 权重合并回基座,得到一个完整模型
llamafactory-cli export \
  --model_name_or_path Qwen/Qwen2.5-7B-Instruct \
  --adapter_name_or_path saves/qwen-lora \
  --export_dir merged/qwen-sft

# 用 vLLM 起推理服务(吞吐比原生 transformers 高数倍)
python -m vllm.entrypoints.openai.api_server \
  --model merged/qwen-sft \
  --served-model-name qwen-sft

5. 效果验证 ​

不能只靠「感觉变好了」。至少做三件事:

  1. 留一批没参与训练的测试集,跑客观指标(分类看准确率,生成看人工/模型打分)
  2. 和基座模型 + 提示词对比,确认微调确实带来了增量(很多时候精心写提示词就够了)
  3. 检查灾难性遗忘:微调后通用能力有没有明显退化

一句话总结流程:先想清楚能不能用提示词/RAG 解决,解决不了再微调; 微调的核心工作量在数据清洗,不在跑命令。