一、大模型演进与Scaling Laws
大规模预训练模型(Large Pre-trained Models)是深度学习领域最重大的技术突破之一。自2017年Transformer架构提出以来,模型参数规模经历了从亿级到万亿级的爆炸式增长,催生了GPT-3/4、PaLM、LLaMA、Claude等一系列里程碑式的大语言模型(LLM)。
1.1 里程碑模型回顾
模型 发布时间 参数量 训练数据量 关键创新
GPT-3 2020 175B 570GB (45TB tokens) In-Context Learning、Few-shot泛化
PaLM 2022 540B 780B tokens PATHWAYS系统、多TPU pod训练
LLaMA 2023 7B/13B/33B/65B 1.0~1.4T tokens 小模型+更多数据的Scaling路线
Claude 2023-2025 未公开 大规模多模态 Constitutional AI、长上下文
GPT-4 2023 预估1.8T (MoE) 13T+ tokens 多模态、MoE架构、更优对齐
涌现能力(Emergent Abilities)
当模型参数量超过某一阈值(约100B)时,大模型会表现出小模型不具备的涌现能力 ,包括:上下文学习(In-Context Learning)、思维链推理(Chain-of-Thought)、指令遵循(Instruction Following)、代码生成与执行等。这些能力并非通过显式编程获得,而是大规模训练中自然涌现的现象。
1.2 Scaling Laws 与 Chinchilla 最优计算量
Scaling Laws (Kaplan et al., 2020)揭示了模型性能与三个核心因素之间的幂律关系:模型参数量(N)、训练数据量(D)、计算预算(C)。其核心发现是:在计算预算固定的情况下,同时增加模型规模和训练数据量比单独扩大其中一项更有效。
# Scaling Laws 幂律拟合(简化实现)
import numpy as np
def scaling_law_loss (N, D, alpha_N=0.076, alpha_D=0.103, E=1.69):
"""Kaplan et al. 2020 中的Scaling Law损失预测模型
Args:
N: 模型参数量(单位:百万)
D: 训练数据量(单位:百万 tokens)
alpha_N: 参数量的幂律指数
alpha_D: 数据量的幂律指数
E: 不可约损失(数据本身的熵)
Returns:
cross-entropy loss 预测值
"""
return E + (N ** - alpha_N) + (D ** - alpha_D)
# 计算不同规模下的预期损失
for N in [100 , 500 , 1000 , 5000 ]:
loss = scaling_law_loss (N, D=1000000 )
print (f"N={N}M params -> predicted loss: {loss:.4f}" )
Chinchilla 最优计算量 (Hoffmann et al., 2022)对Scaling Laws进行了关键修正,发现之前的结论低估了数据量的重要性。Chinchilla研究指出:在给定计算预算C下,最优的模型规模和数据量分配应为:模型的参数量(N)和训练tokens数(D)应该等比例增长 ,即每增加一倍的参数量,训练数据量也应增加一倍。
# Chinchilla 最优分配计算
def chinchilla_optimal (compute_budget_C_flops):
"""给定计算预算(FLOPs),返回Chinchilla最优的参数量和tokens数"""
# Chinchilla分析表明:最优时 N_opt ∝ C^0.5, D_opt ∝ C^0.5
N_opt = int (2.22e9 * (compute_budget_C_flops / 5.56e23 ) ** 0.5 )
D_opt = int (1.37e12 * (compute_budget_C_flops / 5.56e23 ) ** 0.5 )
return N_opt, D_opt
# 示例:GPT-3级别计算预算(约3.14e23 FLOPs)
N, D = chinchilla_optimal (3.14e23 )
print (f"Chinchilla Optimal N = {N/1e9:.1f}B, D = {D/1e12:.1f}T" )
# 输出: Chinchilla Optimal N ≈ 67B, D ≈ 1.0T
# 对比GPT-3的175B参数和300B tokens训练,Chinchilla认为模型过大而数据不足
Scaling Laws 的核心启示
数据量不是可选而是必需 :LLaMA系列证明,在更多数据上训练较小的模型(7B/13B)可以获得比更大模型更好的性能
收益递减不可避免 :单纯扩大模型规模的边际收益持续下降,需要配合更高质量的数据和更好的训练方法
涌现门槛 :约100B参数是一个关键门槛,跨过后涌现能力呈现非线性增长
二、大模型训练技术
训练千亿甚至万亿参数的大模型面临着极其严峻的内存和计算挑战。单张GPU(即使是H100 80GB)无法容纳一个完整的175B模型(仅参数就需要约350GB的FP16存储)。因此,分布式训练技术和内存优化策略是大模型训练的基石。
2.1 ZeRO 优化器(Zero Redundancy Optimizer)
由DeepSpeed团队(Microsoft)提出的ZeRO(零冗余优化器) 是当前最主流的大模型训练内存优化方案。ZeRO将模型状态(参数、梯度、优化器状态)分散存储到多个GPU上,消除了数据并行中的冗余存储。
# ZeRO三级优化对比(概念性代码)
class ZeROStage :
"""ZeRO优化的三个阶段,每一阶段减少的内存不同"""
P0_BASELINE = """
Stage 0 (Baseline Data Parallel):
每张GPU存储完整的: 参数 + 梯度 + 优化器状态
单卡内存 = N*(12/P + 2) bytes (N=参数量, P=DP度数)
含义: 仅分片参数,但梯度/优化器状态全量存储
"""
P1_OPTIMIZER = """
Stage 1 (ZeRO-1): 优化器状态分片
每张GPU存储完整的: 参数 + 梯度
分片的: 优化器状态
单卡内存 = N*(2 + 8/P) bytes
含义: 优化器状态分散到各卡,前向/反向时需要all-gather
"""
P2_GRADIENT = """
Stage 2 (ZeRO-2): 优化器状态 + 梯度分片
每张GPU存储完整的: 参数
分片的: 梯度 + 优化器状态
单卡内存 = N*(2 + 4/P) bytes
含义: 反向传播时reduce-scatter梯度,前向时各参数完整
"""
P3_PARAMETER = """
Stage 3 (ZeRO-3): 参数 + 梯度 + 优化器状态全部分片
每张GPU存储: 所有状态分片
单卡内存 = N*(16/P) bytes
含义: 参数也被分片,前向/反向时动态all-gather参数
"""
# 实际使用示例:DeepSpeed ZeRO-3 配置
import deepspeed
ds_config = {
"train_batch_size" : 256 ,
"zero_optimization" : {
"stage" : 3 ,
"offload_optimizer" : { # CPU Offload
"device" : "cpu" ,
"pin_memory" : True
},
"offload_param" : { # 参数卸载到CPU
"device" : "cpu"
},
"overlap_comm" : True ,
"contiguous_gradients" : True ,
"reduce_bucket_size" : 5e7 ,
"stage3_prefetch_bucket_size" : 5e7 ,
"stage3_param_persistence_threshold" : 1e6
}
}
model_engine, optimizer, _, _ = deepspeed.initialize(
model= model,
model_parameters= model.parameters(),
config_params= ds_config
)
2.2 内存优化技术
除了ZeRO之外,还有若干关键的内存优化技术:
CPU Offload(CPU卸载)
将优化器状态和部分参数从GPU显存卸载到CPU内存。虽然增加了CPU-GPU数据传输的开销(约慢2-3倍),但能让单GPU训练更大的模型。适用场景:GPU显存不足但CPU内存充裕。
Activation Checkpointing(激活检查点 / 梯度检查点)
在前向传播时仅保存部分层的激活值(检查点),而非全部保存。反向传播时重新计算丢弃的激活值。这是典型的用计算换内存 策略:可减少约60-80%的激活内存,但增加约30%的计算开销。
# Activation Checkpointing 使用示例(PyTorch)
import torch
from torch.utils.checkpoint import checkpoint
class TransformerBlockWithCheckpoint (torch.nn.Module):
def __init__ (self , d_model, nhead):
super ().__init__ ()
self .attention = torch.nn.MultiheadAttention(d_model, nhead)
self .ffn = torch.nn.Sequential(
torch.nn.Linear(d_model, d_model * 4 ),
torch.nn.GELU(),
torch.nn.Linear(d_model * 4 , d_model)
)
self .layernorm1 = torch.nn.LayerNorm(d_model)
self .layernorm2 = torch.nn.LayerNorm(d_model)
def forward_custom (self , x, mask= None ):
# 前向逻辑:需要在反向时重新计算
attn_out, _ = self .attention(x, x, x, attn_mask= mask)
x = self .layernorm1(x + attn_out)
ffn_out = self .ffn(x)
x = self .layernorm2(x + ffn_out)
return x
def forward (self , x, mask= None ):
# 使用checkpoint包装forward_custom
# 前向不保存中间激活,反向时重新计算
return checkpoint (self .forward_custom, x, mask)
# 计算节省的内存估算
def estimate_activation_memory (n_layers, d_model, seq_len, batch_size):
"""估算使用/不使用checkpoint时的激活内存"""
# 每层Transformer的激活大小(以bytes计)
bytes_per_param = 2 # FP16
activations_per_layer = batch_size * seq_len * d_model * 34
# 34≈ 实际Transformer层的激活因子(含softmax, dropout等)
without_ckpt = activations_per_layer * n_layers * bytes_per_param
with_ckpt = activations_per_layer * 2 * bytes_per_param # 仅保存2个检查点
saving = (without_ckpt - with_ckpt) / without_ckpt * 100
return without_ckpt / 1e9 , with_ckpt / 1e9 , saving
mem_no, mem_yes, pct = estimate_activation_memory (
n_layers= 32 , d_model= 4096 ,
seq_len= 2048 , batch_size= 4
)
print (f"Without checkpoint: {mem_no:.1f}GB" )
print (f"With checkpoint: {mem_yes:.1f}GB" )
print (f"Memory saving: {pct:.1f}%" )
# 输出示例: Without checkpoint: 29.1GB → With: 3.6GB → 节省87.5%
2.3 3D并行(3D Parallelism)
训练万亿参数模型需要三种并行策略的组合,称为3D并行 。学术界(Megatron-LM)和工业界(DeepSpeed)分别对该技术的成熟做出了关键贡献。
并行策略 英文名称 基本原理 通信模式 代表框架
数据并行 (DP) Data Parallelism 每张GPU持有完整模型副本,处理不同微批次数据 All-reduce (梯度同步) PyTorch DDP、DeepSpeed
张量并行 (TP) Tensor Parallelism 将单个Transformer层的权重矩阵沿行/列切分 All-reduce (每层两次) Megatron-LM
流水线并行 (PP) Pipeline Parallelism 将不同层分配到不同GPU,微批次流水线执行 P2P (点对点) GPipe、PipeDream、DeepSpeed
# Megatron-LM 张量并行(列切分Linear层)
import torch
import torch.distributed as dist
class MegatronColumnParallelLinear (torch.nn.Module):
"""将Linear层沿列方向切分到多个GPU"""
def __init__ (self , in_features, out_features, world_size):
super ().__init__ ()
self .world_size = world_size
self .rank = dist.get_rank()
# 每张GPU只持有 out_features / world_size 列
self .weight = torch.nn.Parameter(
torch.randn(out_features // world_size, in_features)
)
def forward (self , x):
# 前向:本地矩阵乘法
local_output = torch.nn.functional.linear(x, self .weight)
# All-reduce: 各GPU的结果沿着列维度合并
output = torch.zeros_like(local_output)
dist.all_reduce(local_output)
return local_output
# 3D并行组合示例(概念性)
class ThreeDParallelModel :
"""
DP=4, TP=4, PP=4 → 共需要 4×4×4 = 64张GPU
拓扑结构:
- DP组(数据并行组): 跨4个不同数据管道的GPU
- TP组(张量并行组): 同一流水线级内的4个GPU
- PP组(流水线并行组): 跨4个流水线阶段的GPU
"""
def __init__ (self ):
self .dp_size = 4
self .tp_size = 4
self .pp_size = 4
# 总GPU数 = 64
def create_process_groups (self ):
"""创建3D并行所需的通信组"""
world_size = self .dp_size * self .tp_size * self .pp_size
rank = dist.get_rank()
# 按数据并行的维度组织
dp_groups = []
for pp_idx in range (self .pp_size):
for tp_idx in range (self .tp_size):
# 该组内所有DP rank
group_ranks = [
pp_idx * self .tp_size * self .dp_size +
tp_idx * self .dp_size + dp_idx
for dp_idx in range (self .dp_size)
]
pg = dist.new_group(ranks= group_ranks)
dp_groups.append(pg)
return dp_groups
3D并行中的通信优化
实际训练时3D并行的通信开销需精心平衡:张量并行(TP)每层需要2次all-reduce,通信量最大,因此TP组内通常使用NVLink/NVSwitch高速互联(节点内 );流水线并行(PP)通信量最小(仅激活值),适合跨节点;数据并行(DP)通信量居中,通常使用RDMA网络。这种层次化设计使得训练万亿参数模型成为可能。
三、模型压缩
大模型参数量巨大,直接部署到消费级硬件上几乎不可能。模型压缩技术通过量化 、蒸馏 、剪枝 等手段,在尽量保持模型性能的前提下显著降低模型大小和推理成本。
3.1 量化技术(Quantization)
量化是将模型权重和激活值从高精度(FP32/FP16/BF16)映射到低精度(INT8/INT4)的技术。对于大模型推理,4-bit量化 已成为事实标准。
# QLoRA: 4-bit NormalFloat 量化实现原理
import torch
import torch.nn as nn
class NormalFloat4Quantizer :
"""NF4 (4-bit NormalFloat) 数据类型
NF4 假设权重服从正态分布,通过分位数量化
使得每个量化区间包含等概率的权重值,
比均匀量化更精确地保留了权重的信息。
"""
def __init__ (self ):
self .num_bits = 4
self .num_levels = 2 ** 4 # 16个量化级别
def quantize (self , weights):
"""将FP16权重量化为NF4格式"""
# 1. 计算fp32的绝对最大值(用于归一化到[-1, 1])
absmax = weights.abs ().max()
# 2. 归一化到[-1, 1]区间
weights_norm = weights / absmax
# 3. 使用正态分布分位数进行量化
# NF4的分位点基于标准正态分布的累积分布函数(CDF)
# 16个分位点均匀分布在CDF的[0.5/16, 15.5/16]区间
quantiles = torch.tensor ([
-1.0 , -0.6962 , -0.5251 , -0.3949 ,
-0.2844 , -0.1848 , -0.0911 , 0.0 ,
0.0911 , 0.1848 , 0.2844 , 0.3949 ,
0.5251 , 0.6962 , 1.0
])
# 4. 查找每个值最近的量化级别
indices = torch.zeros_like (weights, dtype= torch.uint8)
for i in range (15 ):
mask = (weights_norm > quantiles[i]) & (weights_norm <= quantiles[i+ 1 ])
indices[mask] = i
return indices, absmax # 返回量化索引和缩放因子
def dequantize (self ), indices, absmax):
"""从NF4格式恢复为FP16权重"""
# NF4量化级别的中心值
levels = torch.tensor ([
-0.8481 , -0.6107 , -0.4600 , -0.3397 ,
-0.2346 , -0.1379 , -0.0456 , 0.0456 ,
0.1379 , 0.2346 , 0.3397 , 0.4600 ,
0.6107 , 0.8481 , 1.0
])
restored = levels[indices] * absmax
return restored
# 双重量化(Double Quantization)
class DoubleQuantizer :
"""QLoRA中的双重量化:对量化常数再进行一次量化
第一次量化: float32权重 → NF4 (每组256个值,1个共享absmax)
第二次量化: 对absmax进行FP8量化 (每组64个absmax值,1个共享absmax²)
额外节省约0.5 bit/参数
"""
def quantize (self , weights):
group_size = 256
n_groups = weights.numel() // group_size
# 第一级量化:每组一个absmax
first_level_absmax = []
quantized_groups = []
for g in range (n_groups):
group = weights[g* group_size:(g+ 1 )* group_size]
absmax = group.abs ().max()
first_level_absmax.append(absmax)
q_group = (group / absmax * 15 ).round ().to (torch.int8)
quantized_groups.append(q_group)
# 第二级量化:对absmax进行FP8量化
absmax_tensor = torch.tensor (first_level_absmax)
fp8_absmax = absmax_tensor.to (torch.float8_e4m3fn)
return torch.cat (quantized_groups), fp8_absmax
3.2 GPTQ 与权重量化
GPTQ (Frantar et al., 2023)是一种后训练权重量化方法(Post-Training Quantization, PTQ),通过观察少量校准数据来确定最优量化策略。其核心思想是将权重量化看作一个优化问题:最小化量化前后该层输出的均方误差 。
GPTQ 量化流程
Hessian矩阵计算 :使用128-1024个校准样本,计算每层输出的Hessian矩阵
贪心量化顺序 :按照Hessian逆矩阵的对角元素决定量化顺序,使得误差最小的权重先被量化
误差补偿 :每个权重的量化误差通过更新其他未量化权重来补偿(反向传播Hessian信息)
分组量化 :通常以128个元素为一组,共享量化缩放因子
3.3 知识蒸馏(Knowledge Distillation)
知识蒸馏通过让学生模型 (小模型)学习教师模型 (大模型)的输出分布,实现模型压缩。与量化不同,蒸馏涉及重新训练,但可以获得比单纯量化更高的压缩率和更好的性能。
# 知识蒸馏损失函数
import torch
import torch.nn.functional as F
def knowledge_distillation_loss (
student_logits, teacher_logits, labels,
temperature= 4.0 , alpha= 0.5
):
"""知识蒸馏损失 = α * KL散度 + (1-α) * CE损失
Args:
student_logits: 学生模型的logits
teacher_logits: 教师模型的logits (需detach停止梯度)
labels: 真实标签
temperature: 温度参数,越高则softmax输出越平滑
alpha: KL散度损失的权重
"""
# 1. 蒸馏损失(KL散度)- 让学生匹配教师的输出分布
soft_targets = F.softmax(teacher_logits / temperature, dim=- 1 )
student_log_softmax = F.log_softmax(student_logits / temperature, dim=- 1 )
# KL散度: KL(P||Q) = Σ P(x) * log(P(x)/Q(x))
kl_loss = F.kl_div(
student_log_softmax, soft_targets,
reduction= 'batchmean'
) * (temperature ** 2 )
# 2. 标准交叉熵损失(对真实标签)
ce_loss = F.cross_entropy(student_logits, labels)
# 3. 综合损失
total_loss = alpha * kl_loss + (1.0 - alpha) * ce_loss
return total_loss
# 蒸馏+量化联合管线(示例)
def distillation_quantization_pipeline (teacher_model, student_config, calib_data):
"""先蒸馏再量化的联合压缩管线"""
print ("Phase 1: 初始化学生模型(通常为教师模型的1/4~1/2)" )
student_model = create_student_model (student_config)
print ("Phase 2: 知识蒸馏训练(通常需要1-10B tokens)" )
train_with_distillation (student_model, teacher_model, calib_data)
print ("Phase 3: 量化学生模型(GPTQ或RTN)" )
quantized_model = gptq_quantize (student_model, calib_data, bits= 4 )
print (f"压缩比: {teacher_model.get_memory_footprint() / quantized_model.get_memory_footprint():.1f}x" )
return quantized_model
3.4 剪枝与稀疏化
剪枝(Pruning) 通过移除对模型输出影响较小的权重、注意力头甚至完整层来减小模型规模。结构化剪枝 (移除整行/整列权重)比非结构化剪枝 (移除单个权重)更具硬件友好性。大模型剪枝面临的主要挑战是:过度剪枝会导致涌现能力不可逆地丧失,尤其对于100B以下的模型影响更为显著。
四、参数高效微调(PEFT)
全参数微调(Full Fine-tuning)需要更新模型的所有参数,对于大模型来说计算和存储成本极高。参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)技术通过在模型中插入少量可训练参数,或者将更新限制在低秩子空间中,显著降低了微调成本。
4.1 LoRA(Low-Rank Adaptation)
LoRA(低秩适配) (Hu et al., 2021)是当前最受欢迎的PEFT方法。其核心洞察是:大模型在特定任务上的参数更新具有低秩性 ——即权重更新矩阵 ΔW 的秩远小于原始权重矩阵的维度。LoRA将 ΔW 分解为两个低秩矩阵的乘积:ΔW = BA,其中 B ∈ R^(d×r),A ∈ R^(r×k),且 r ≪ min(d,k)。
# LoRA 层的PyTorch实现
import torch
import torch.nn as nn
class LoRALayer (nn.Module):
"""LoRA低秩适配层:ΔW = B @ A
Args:
in_features: 输入维度
out_features: 输出维度
rank: 低秩矩阵的秩(通常r=4,8,16,32)
alpha: 缩放超参数,最终输出为 Wx + (alpha/r) * BAx
dropout: dropout比率
"""
def __init__ (self , in_features, out_features,
rank= 8 , alpha= 16 , dropout= 0.1 ):
super ().__init__ ()
self .rank = rank
self .scaling = alpha / rank # 缩放因子
# A矩阵: 随机初始化(正态分布)
self .lora_A = nn.Parameter(
torch.randn(rank, in_features) / (in_features ** 0.5 )
)
# B矩阵: 零初始化(保证初始时ΔW=0)
self .lora_B = nn.Parameter(torch.zeros(out_features, rank))
self .dropout = nn.Dropout(dropout) if dropout > 0 else nn.Identity()
def forward (self , x, original_output):
"""LoRA前向:原始输出 + 低秩适配结果"""
# h = Wx + BAx * (alpha/r)
lora_output = (x @ self .lora_A.T) # [batch, rank]
lora_output = self .dropout(lora_output)
lora_output = lora_output @ self .lora_B.T # [batch, out_features]
return original_output + lora_output * self .scaling
# 适配器权重合并:将LoRA权重合并回原始权重
def merge_lora_weights (original_weight, lora_A, lora_B, scaling):
"""推理时将LoRA权重合并到原始权重中,消除额外计算延迟
W' = W + (alpha/r) * B @ A
合并后推理速度与原始模型完全相同
"""
delta_W = lora_B @ lora_A # [out_features, in_features]
merged_weight = original_weight + delta_W * scaling
return merged_weight
# 训练时参数效率对比
def count_trainable_params (d_model, n_layers, lora_rank):
"""对比全量微调和LoRA的可训练参数量"""
# 假设每个Transformer层有4个Linear (Q, K, V, O) + 2个FFN
params_per_layer_full = 6 * d_model * d_model # 粗略估计
params_per_layer_lora = 6 * 2 * d_model * lora_rank # A+B参数量
full = params_per_layer_full * n_layers
lora = params_per_layer_lora * n_layers
ratio = lora / full * 100
print (f"Full FT: {full/1e6:.1f}M trainable params" )
print (f"LoRA (r={lora_rank}): {lora/1e6:.1f}M trainable params ({ratio:.2f}%)" )
print (f"Memory reduction: {(1 - lora/full)*100:.1f}%" )
count_trainable_params (d_model= 4096 , n_layers= 32 , lora_rank= 8 )
# 输出: Full FT: 3217.9M → LoRA: 12.6M (0.39%) → 内存减少99.6%
4.2 AdaLoRA(自适应秩分配)
LoRA的秩r是一个需要人工设定的超参数,且所有层使用相同的秩。AdaLoRA(Zhang et al., 2023)通过奇异值分解(SVD) 形式的参数化,结合重要性评分和正则化损失,自动为不同层分配不同的秩 ——重要层保留高秩,不重要层降低秩甚至裁剪到零。
4.3 Prefix Tuning 与 P-Tuning
方法 核心机制 可训练参数 特点
Prefix Tuning
在Transformer每层的Key和Value前拼接可学习的前缀token (prefix tokens)
前缀token的嵌入向量
直接影响所有层的注意力计算,表达能力更强但参数较多
P-Tuning v2
仅在输入层前拼接可学习的prompt嵌入向量
prompt嵌入的MLP映射
实现简单、参数少,但长序列任务上效果弱于Prefix Tuning
Prompt Tuning
在输入层前添加Soft Prompt (连续可学习token)
soft prompt嵌入
最轻量级,T5中使用,大模型下效果随模型增大而提升
Adapter Layer
在Transformer层内插入bottleneck结构的Adapter模块
Adapter中的两层Linear
串行引入推理延迟,但可多任务共享
# Prefix Tuning 实现示例
class PrefixEncoder (nn.Module):
"""Prefix Tuning: 为每层Transformer的K/V前缀生成嵌入
使用MLP对prefix tokens进行编码(比直接使用嵌入更稳定)
"""
def __init__ (self , num_layers, num_prefix_tokens,
embed_dim, hidden_dim= 512 ):
super ().__init__ ()
self .num_prefix_tokens = num_prefix_tokens
self .embed_dim = embed_dim
# 可训练的prefix嵌入
self .prefix_tokens = nn.Parameter(
torch.randn(num_prefix_tokens, embed_dim)
)
# 每层独立的重参数化MLP
self .mlp = nn.ModuleList([
nn.Sequential(
nn.Linear(embed_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, embed_dim * 2 ) # *2因为K和V
)
for _ in range (num_layers)
])
def forward (self , layer_idx, batch_size):
"""对指定层生成prefix key-value对"""
# [num_prefix, embed_dim] → [batch, num_prefix, embed_dim*2]
tokens = self .prefix_tokens.unsqueeze(0 ).expand(batch_size, - 1 , - 1 )
past_key_values = self .mlp[layer_idx](tokens)
# 分割为key和value
past_key = past_key_values[..., :self .embed_dim]
past_value = past_key_values[..., self .embed_dim:]
return past_key, past_value
# P-Tuning: 可学习的prompt嵌入
class PTuningEmbedding (nn.Module):
"""P-Tuning: 在输入embedding前插入可学习prompt token"""
def __init__ (self , num_prompt_tokens, vocab_size,
embed_dim, hidden_dim):
super ().__init__ ()
self .num_prompt_tokens = num_prompt_tokens
# 可学习的Soft Prompt嵌入
self .soft_prompt = nn.Embedding(num_prompt_tokens, embed_dim)
# LSTM或MLP重参数化(P-Tuning v1使用LSTM)
self .lstm_head = nn.LSTM(
input_size= embed_dim,
hidden_size= hidden_dim,
num_layers= 2 ,
bidirectional= True ,
batch_first= True
)
self .linear = nn.Linear(hidden_dim * 2 , embed_dim)
def forward (self , batch_size):
"""生成可学习的prompt嵌入"""
prompt_ids = torch.arange(self .num_prompt_tokens).unsqueeze(0 )
prompt_ids = prompt_ids.expand(batch_size, - 1 )
# 通过LSTM+Linear重参数化,提高训练稳定性
prompt_embeds = self .soft_prompt(prompt_ids)
lstm_out, _ = self .lstm_head(prompt_embeds)
prompt_embeds = self .linear(lstm_out)
return prompt_embeds
五、大模型推理优化
大模型推理面临的核心挑战是内存带宽瓶颈 和自回归解码的效率问题 。推理优化技术从算法(KV Cache, Speculative Decoding)、系统(Continuous Batching, PagedAttention)和算子(FlashAttention, 内核融合)三个层面进行优化。
5.1 KV Cache(键值缓存)
自回归生成中,每个token的生成都需要计算注意力。KV Cache通过缓存之前所有token的Key和Value矩阵 ,避免重复计算,将注意力计算复杂度从O(n³)降低到O(n²)。对于长序列生成,KV Cache可减少约10-20倍的FLOPs ,但同时也带来了显存压力——对于8K序列长度、 batch size 1的LLaMA-7B,KV Cache约占用1GB显存。
# KV Cache 实现原理
import torch
class KVCacheManager :
"""管理自回归解码中的KV Cache"""
def __init__ (self , max_seq_len, num_layers,
num_heads, head_dim, dtype= torch.float16):
self .max_seq_len = max_seq_len
self .num_layers = num_layers
self .num_heads = num_heads
self .head_dim = head_dim
# KV Cache 分层存储: [num_layers, 2, batch, num_heads, max_seq_len, head_dim]
self .cache = [
{
"key" : torch.zeros(1 , num_heads, 0 , head_dim, dtype= dtype),
"value" : torch.zeros(1 , num_heads, 0 , head_dim, dtype= dtype),
}
for _ in range (num_layers)
]
def append (self , layer_idx, key, value):
"""追加新token的K/V到缓存中
Args:
key: [batch, num_heads, 1, head_dim]
value: [batch, num_heads, 1, head_dim]
"""
self .cache[layer_idx]["key" ] = torch.cat(
[self .cache[layer_idx]["key" ], key], dim=- 2
)
self .cache[layer_idx]["value" ] = torch.cat(
[self .cache[layer_idx]["value" ], value], dim=- 2
)
def get_attention_input (self , layer_idx):
"""从缓存获取完整的K/V用于注意力计算"""
cached_k = self .cache[layer_idx]["key" ] # [1, n_heads, seq_len, head_dim]
cached_v = self .cache[layer_idx]["value" ] # [1, n_heads, seq_len, head_dim]
return cached_k, cached_v
def estimate_memory (self , batch_size, seq_len):
"""估算KV Cache所需显存(仅计算Key+Value)"""
bytes_per_elem = 2 # FP16
total = self .num_layers * 2 * batch_size * \
self .num_heads * seq_len * self .head_dim * bytes_per_elem
print (f"KV Cache memory: {total/1e9:.2f} GB (seq_len={seq_len}, bs={batch_size})" )
return total / 1e9
# 验证:LLaMA-7B配置
cache = KVCacheManager (
max_seq_len= 4096 , num_layers= 32 ,
num_heads= 32 , head_dim= 128
)
cache.estimate_memory (batch_size= 1 , seq_len= 4096 )
# 输出: KV Cache memory: 2.15 GB (seq_len=4096, bs=1)
cache.estimate_memory (batch_size= 32 , seq_len= 8192 )
# 输出: KV Cache memory: 137.44 GB (seq_len=8192, bs=32) → 远超单卡显存
5.2 PagedAttention 与 vLLM
传统KV Cache管理存在严重的内存碎片问题 :预分配固定大小的缓存块导致大量闲置空间(内部碎片),不同序列长度差异导致浪费(外部碎片)。vLLM (Kwon et al., 2023)提出了PagedAttention ,将操作系统的虚拟内存分页思想引入KV Cache管理。
PagedAttention 核心机制
分块管理 :将KV Cache划分为固定大小的块(block),每块存储多个token的K/V
非连续存储 :逻辑上连续的序列在物理内存中可以不连续存储,通过块表(Block Table)映射
按需分配 :仅在生成新token时分配新块,杜绝预分配浪费
Copy-on-Write :支持多个序列共享相同前缀的KV Cache块,适合Beam Search和并行采样
# vLLM PagedAttention 核心逻辑(概念性简化)
class PagedAttentionBlock :
"""KV Cache的物理块,大小固定(例如16或32个token)"""
def __init__ (self , block_size, num_heads, head_dim, layer_idx):
self .block_size = block_size # 每块存储的token数
self .num_heads = num_heads
self .head_dim = head_dim
self .layer_idx = layer_idx
# 物理内存:连续块,但不同层的块可能不连续
self .key_block = torch.zeros(
block_size, num_heads, head_dim
)
self .value_block = torch.zeros(
block_size, num_heads, head_dim
)
self .num_filled = 0 # 已填充的token数
class BlockTable :
"""块表:逻辑序列 → 物理块的映射
逻辑序列 [t0, t1, ..., tn] 的K/V可能分布在
物理地址 [block_5, block_17, block_3, ...] 上
"""
def __init__ (self ):
self .logical_to_physical = {} # 逻辑块号 → 物理块号
self .free_blocks = set () # 空闲物理块池
def allocate_block (self ):
"""从空闲池分配一个物理块"""
if not self .free_blocks:
block_id = len (self .logical_to_physical) # 模拟扩展
else :
block_id = self .free_blocks.pop()
return block_id
# 连续批处理(Continuous Batching)调度逻辑
class ContinuousBatchingScheduler :
"""vLLM的连续批处理调度器
传统批处理:等待当前批次全部生成完毕才接收新请求
连续批处理:每个推理迭代后动态调整批次组成
"""
def __init__ (self ):
self .running_requests = [] # 正在生成的请求
self .waiting_queue = [] # 等待队列
self .max_num_seqs = 256 # 最大并发序列数
self .max_num_batched_tokens = 4096 # 最大批处理token数
def schedule (self ):
"""每步推理后重新调度批次"""
# 1. 移除已完成的请求
self .running_requests = [
r for r in self .running_requests
if not r.is_finished
]
# 2. 从等待队列中拉取新请求加入批次
current_tokens = sum (
r.num_generated_tokens for r in self .running_requests
)
while (self .waiting_queue
and len (self .running_requests) < self .max_num_seqs
and current_tokens < self .max_num_batched_tokens):
new_req = self .waiting_queue.pop(0 )
self .running_requests.append(new_req)
current_tokens += new_req.num_generated_tokens
print (f"Scheduled batch: {len(self.running_requests)} seqs, "
f"{current_tokens} total tokens" )
return self .running_requests
5.3 FlashAttention
FlashAttention (Dao et al., 2022)是一种对注意力计算进行IO感知优化 的算法。传统注意力计算在GPU的HBM(高带宽内存)和SRAM(片上共享内存)之间反复读写中间结果(N×N的注意力矩阵),导致严重的IO瓶颈。FlashAttention通过分块计算 (tiling)和内核融合 ,将整个注意力计算融合为单个CUDA kernel,避免了中间结果的HBM读写。
FlashAttention 的关键优化
分块计算(Tiling) :将Q、K、V矩阵分块加载到SRAM中,逐个计算注意力块,避免一次性计算完整的N×N注意力矩阵
内核融合(Kernel Fusion) :将注意力计算的所有步骤(矩阵乘法、softmax、dropout、加权求和)融合为单一kernel,减少kernel launch开销
内存合并(Memory Coalescing) :优化内存访问模式,确保同一warp内的线程访问连续内存地址
实际效果 :FlashAttention比标准注意力计算快2-4倍,内存占用从O(N²)降低到O(N),对长序列推理至关重要
5.4 推测解码(Speculative Decoding)
推测解码 (Leviathan et al., 2023)利用一个小型草稿模型 (Draft Model)一次性生成多个候选token,再由目标大模型 通过一次前向传播进行验证和修正。由于小模型的运行速度远快于大模型,且验证过程可以并行处理,推测解码在保持输出分布不变的前提下,实现了2-3倍的推理加速 。
# 推测解码(Speculative Decoding)实现
import torch
import torch.nn.functional as F
def speculative_decode (
target_model, draft_model,
input_ids, gamma= 5 , max_new_tokens= 100
):
"""推测解码:用小模型推测 + 大模型验证
Args:
target_model: 目标大模型(精确但慢)
draft_model: 草稿小模型(近似但快)
input_ids: 输入token序列 [batch, seq_len]
gamma: 推测步数/窗口大小
max_new_tokens: 最大生成token数
"""
generated = input_ids.clone()
device = input_ids.device
for step in range (0 , max_new_tokens, gamma):
current_len = generated.shape[- 1 ]
# Phase 1: 草稿模型一次性推测gamma个token(自回归,但小模型很快)
draft_tokens = []
draft_logits_all = []
draft_hidden = generated
for _ in range (gamma):
draft_logits = draft_model (draft_hidden)
draft_token = torch.multinomial (
F.softmax(draft_logits[:, - 1 , :], dim=- 1 ), 1
)
draft_tokens.append(draft_token)
draft_logits_all.append(draft_logits[:, - 1 , :])
draft_hidden = torch.cat([draft_hidden, draft_token], dim=- 1 )
# Phase 2: 目标模型并行验证所有推测token(只需一次前向)
with torch.no_grad():
target_logits = target_model (draft_hidden)
# Phase 3: 逐token验证,接受匹配的推测,回退到目标模型
n_accepted = 0
for i in range (gamma):
q = F.softmax(target_logits[:, current_len + i, :], dim=- 1 )
p = F.softmax(draft_logits_all[i], dim=- 1 )
drafted_token = draft_tokens[i]
# 拒绝采样:以 min(1, q(x)/p(x)) 的概率接受
acceptance_prob = torch.min(
torch.tensor (1.0 , device= device),
q[0 , drafted_token[0 , 0 ]] /
p[0 , drafted_token[0 , 0 ]]
)
if torch.rand(1 , device= device) < acceptance_prob:
n_accepted += 1
else :
break
# Phase 4: 接入已接受的token,必要时从目标模型采样一个额外token
if n_accepted == gamma:
# 全部接受,再从目标模型取一个token
next_token = torch.multinomial (
F.softmax(target_logits[:, - 1 , :], dim=- 1 ), 1
)
accepted_tokens = torch.cat(draft_tokens + [next_token], dim=- 1 )
else :
# 部分接受后拒绝,从目标分布q中采样备用token
adjusted_dist = F.softmax(
target_logits[:, current_len + n_accepted, :], dim=- 1
)
adjusted_dist -= F.softmax(draft_logits_all[n_accepted], dim=- 1 )
adjusted_dist = torch.clamp (adjusted_dist, min= 0 )
adjusted_dist /= adjusted_dist.sum (dim=- 1 , keepdim= True )
fallback = torch.multinomial (adjusted_dist, 1 )
accepted_tokens = torch.cat(
draft_tokens[:n_accepted] + [fallback], dim=- 1
)
generated = torch.cat([generated, accepted_tokens], dim=- 1 )
print (f"Step {step}: draft gamma={gamma}, accepted={n_accepted+1} tokens" )
return generated
六、LLM应用生态
大语言模型的崛起催生了丰富多样的应用生态。从RAG(检索增强生成) 到AI Agent ,从LangChain框架 到多轮对话系统 ,LLM的应用正在重塑信息检索、内容创作、代码开发、数据分析等各个领域。
6.1 RAG(检索增强生成)
RAG(Retrieval-Augmented Generation) (Lewis et al., 2020)通过外部知识库检索为LLM提供事实性上下文,显著缓解了LLM的幻觉(Hallucination) 问题。RAG的核心流程包括:文档切分 → 向量嵌入 → 相似度检索 → 上下文注入 → LLM生成。
# RAG 检索增强生成完整实现
import numpy as np
class SimpleRAGPipeline :
"""简易RAG检索增强生成管线"""
def __init__ (self , llm, embedding_model, chunk_size= 512 ):
self .llm = llm # 大语言模型
self .embedder = embedding_model # 文本嵌入模型
self .chunk_size = chunk_size
self .document_store = [] # 文档存储
self .embedding_store = [] # 向量存储
def add_documents (self , documents):
"""将文档添加到知识库"""
for doc in documents:
# 文档切分(chunking)
chunks = self ._chunk_text (doc, self .chunk_size)
for chunk in chunks:
self .document_store.append(chunk)
emb = self .embedder.encode (chunk)
self .embedding_store.append(emb)
self .embedding_store = np.array(self .embedding_store)
print (f"Added {len(documents)} docs → "
f"{len(self.document_store)} chunks" )
def _chunk_text (self , text, chunk_size):
"""滑动窗口式文档切分(可加上重叠)"""
overlap = chunk_size // 4 # 25%重叠避免切碎语义
step = chunk_size - overlap
chunks = []
for i in range (0 , len (text), step):
chunk = text[i:i + chunk_size]
if len (chunk) > chunk_size // 2 : # 过滤过短的尾块
chunks.append(chunk)
return chunks
def retrieve (self , query, top_k= 5 ):
"""检索最相关的top-k文档块"""
query_emb = self .embedder.encode (query)
# 余弦相似度计算
scores = np.dot(self .embedding_store, query_emb) / (
np.linalg.norm(self .embedding_store, axis=- 1 )
* np.linalg.norm(query_emb)
)
# 取top-k
top_indices = np.argsort(scores)[- top_k:][::- 1 ]
results = [(
self .document_store[i], scores[i]
) for i in top_indices]
return results
def generate (self , query, top_k= 5 ):
"""基于检索结果生成回答"""
results = self .retrieve (query, top_k)
# 构建增强的prompt
context = "\n\n---\n\n" .join ([
f"[文档 {i+1}] {doc}"
for i, (doc, score) in enumerate (results)
])
prompt = f"""基于以下检索到的上下文回答问题。
【上下文】
{context}
【问题】
{query}
【要求】
1. 仅基于所提供的上下文回答,不要编造信息
2. 如果上下文不足以回答问题,请明确指出
3. 在回答中引用相关文档编号
【回答】"""
return self .llm.generate (prompt)
# LangChain 风格的 RAG Chain
class LangChainRAGChain :
"""LangChain模块化RAG链的示意实现"""
def __init__ (self ):
self .components = {
"loader" : "DocumentLoader(PDF/Web/DB)" ,
"splitter" : "RecursiveCharacterTextSplitter" ,
"embedder" : "OpenAIEmbeddings / HuggingFaceEmbeddings" ,
"vectorstore" : "Chroma / FAISS / Pinecone / Weaviate" ,
"retriever" : "VectorStoreRetriever (similarity / MMR)" ,
"prompt" : "ChatPromptTemplate (System+Human)" ,
"llm" : "ChatOpenAI / Claude / Local LLM" ,
"output_parser" : "StrOutputParser / JsonOutputParser" ,
}
def build_chain (self , documents, query):
"""
典型的LangChain RAG链:
loader | splitter | embedder | vectorstore |
retriever | prompt | llm | output_parser
"""
# 伪代码表示实际的LangChain调用
chain = {
"load_and_split" : "递归分割文档" ,
"store_and_retrieve" : "嵌入+向量检索" ,
"format_prompt" : "将检索结果注入System Prompt" ,
"generate" : "LLM生成带引用的回答" ,
"parse_output" : "提取结构化字段/引用来源" ,
}
print ("LangChain RAG Chain assembled with 6 components" )
return chain
6.2 智能代理(Agent)
LLM Agent 通过工具调用(Tool Calling / Function Calling) 让LLM具备执行外部操作的能力。典型的Agent循环包括:思考(Thought)→ 行动(Action)→ 观察(Observation)→ 推理(Reasoning)→ 最终回答(Final Answer)。流行的Agent框架包括LangChain Agents、AutoGPT、BabyAGI、CrewAI等。
# LLM Agent 框架(ReAct模式:Reasoning + Acting)
class ReActAgent :
"""ReAct范式的智能Agent:交替思考和行动
循环:
Thought: 分析当前状态,决定下一步做什么
Action: 调用一个工具(搜索、计算、数据库查询等)
Observation: 工具返回的结果
... (循环直到得出最终答案)
Final Answer: 给出最终回答
"""
def __init__ (self , llm, tools, max_iterations= 10 ):
self .llm = llm
self .tools = tools # 可用工具的字典 {name: function}
self .max_iterations = max_iterations
def run (self , task):
"""执行Agent任务循环"""
messages = [
{"role" : "system" , "content" : f"""你是一个AI助手,可以通过调用工具完成任务。
可用工具: {', '.join(self.tools.keys())}
请用以下格式回复:
Thought: 你的思考过程
Action: 工具名称
Action Input: 工具参数(JSON格式)
Observation: 工具返回结果
...(重复)
Final Answer: 最终回答""" },
{"role" : "user" , "content" : task}
]
for iteration in range (self .max_iterations):
response = self .llm.chat (messages)
# 解析响应
if "Final Answer:" in response:
return response.split ("Final Answer:" )[- 1 ].strip()
if "Action:" in response:
# 解析工具调用
action = response.split ("Action:" )[1 ].split ("\n" )[0 ].strip()
action_input = response.split ("Action Input:" )[1 ].split ("\n" )[0 ].strip()
# 执行工具调用
if action in self .tools:
observation = self .tools[action](action_input)
else :
observation = f"Error: 未知工具 '{action}'"
# 将思考过程加入消息历史
messages.append({"role" : "assistant" , "content" : response})
messages.append({"role" : "user" , "content" : f"Observation: {observation}" })
return "Error: 达到最大迭代次数"
# 工具函数示例
def web_search_tool (query):
# 实际调用搜索引擎API
return f"搜索结果: '{query}' 的关键信息..."
def calculator_tool (expression):
try :
return eval (expression)
except :
return "计算错误"
def database_query_tool (sql):
# 实际执行SQL查询
return "查询结果: ..."
# 创建并运行Agent
agent = ReActAgent (
llm= llm,
tools= {
"web_search" : web_search_tool,
"calculator" : calculator_tool,
"db_query" : database_query_tool,
}
)
result = agent.run ("查找2024年全球GDP最高的3个国家,计算它们的GDP总和" )
6.3 多轮对话与文档问答
大模型驱动的多轮对话系统需要处理上下文管理 、记忆压缩 、对话状态追踪 等挑战。文档问答(Document QA)则结合了RAG和多轮对话的能力,允许用户对上传的文档进行自由问答。
多轮对话中的关键设计
上下文窗口管理 :使用滑动窗口或摘要技术将超长对话压缩到模型上下文中
对话状态追踪 :维护用户的偏好、当前话题、未完成的请求等结构化信息
记忆分层 :短期记忆(最近N轮对话) + 长期记忆(关键事实的向量索引)
幻觉控制 :结合RAG和grounding技术,确保回答基于可靠来源
# 多轮对话会话管理器
class ConversationManager :
"""管理多轮对话的上下文和记忆"""
def __init__ (self , llm, max_history= 20 , max_tokens= 4096 ):
self .llm = llm
self .max_history = max_history
self .max_tokens = max_tokens
# 对话状态
self .short_term = [] # 最近N轮对话(raw messages)
self .long_term = [] # 长期记忆(语义向量索引)
self .state = { # 对话状态追踪
"current_topic" : None ,
"user_preferences" : {},
"pending_actions" : [],
}
def add_message (self , role, content):
"""添加一条消息到对话历史"""
self .short_term.append({"role" : role, "content" : content})
# 超出短期记忆上限时,将最旧的对话压缩
if len (self .short_term) > self .max_history:
self._compress_history ()
def _compress_history (self ):
"""压缩早期对话历史为摘要"""
old_messages = self .short_term[:- self .max_history // 2 ]
summary_prompt = f"""将以下对话历史压缩为简要摘要,
保留关键事实、用户偏好和未完成的任务:
{' '.join(m['content'] for m in old_messages)}"""
summary = self .llm.generate (summary_prompt)
self .long_term.append(summary)
self .short_term = self .short_term[- self .max_history // 2 :]
def get_context (self ):
"""组装完整的对话上下文"""
context = {
"long_term_summary" : "\n" .join (self .long_term),
"current_state" : self .state,
"recent_messages" : self .short_term,
}
return context
# 文档问答(Document QA)— RAG + 多轮对话
class DocumentQASystem :
"""基于文档的多轮问答系统
支持: 上传文档 → 索引 → 多轮自由问答
每次回答都基于检索到的文档片段并标注来源
"""
def __init__ (self , llm, embedding_model):
self .rag = SimpleRAGPipeline (llm, embedding_model)
self .conv = ConversationManager (llm)
self .document_indexed = False
def index_document (self , file_path):
"""索引上传的文档"""
with open (file_path, 'r' , encoding= 'utf-8' ) as f:
text = f.read ()
self .rag.add_documents ([text])
self .document_indexed = True
return f"文档已索引,共 {len(self.rag.document_store)} 个文本块"
def ask (self , question):
"""基于文档和对话历史回答用户问题"""
if not self .document_indexed:
return "请先上传文档。"
# 检索相关文档片段
results = self .rag.retrieve (question, top_k= 5 )
# 构建带历史上下文的prompt
context = "\n".join([
f"[文档 {i+1}] {doc}"
for i, (doc, _) in enumerate (results)
])
full_prompt = f"""你是一个文档问答助手,基于已上传的文档内容回答用户问题。
【历史对话摘要】
{self.conv.get_context()['long_term_summary']}
【相关文档片段】
{context}
【用户问题】
{question}
请基于文档内容回答。如果文档中没有相关信息,请明确告知。
在回答中标注信息来源的文档编号。"""
answer = self .rag.llm.generate (full_prompt)
# 更新对话历史
self .conv.add_message ("user" , question)
self .conv.add_message ("assistant" , answer)
return answer
七、核心要点总结
Scaling Laws 与涌现能力 :大模型性能随参数量和训练数据量呈幂律增长,约100B参数是涌现能力的门槛。Chinchilla修正指出参数量和训练tokens数应等比例增长。
分布式训练基石 :ZeRO-3(全分片)+ 3D并行(TP+PP+DP)+ Activation Checkpointing + CPU Offload 构成了训练千亿参数模型的标准技术栈。
模型压缩三剑客 :量化(NF4/GPTQ/QLoRA)使消费级GPU运行大模型成为可能,知识蒸馏将大模型能力迁移到小模型,剪枝通过去除冗余参数进一步压缩。
PEFT 微调范式 :LoRA以0.1-1%的可训练参数达到接近全量微调的效果,AdaLoRA自适应分配秩,Prefix/P-Tuning通过soft prompt驱动模型行为。
推理加速生态系统 :KV Cache消除重复计算,PagedAttention(vLLM)解决内存碎片,FlashAttention通过IO感知优化实现2-4倍加速,推测解码(Speculative Decoding)通过"小模型推测+大模型验证"实现无损加速。
RAG + Agent 应用范式 :检索增强生成有效缓解幻觉,AI Agent通过ReAct循环实现自主任务执行,LangChain等框架提供了模块化的应用构建能力。
技术融合趋势 :量化+蒸馏联合(QAT+Distillation)、PEFT+RAG结合、Agent+工具调用融合。未来大模型的发展方向是更高效(小模型大知识)、更可靠(RAG+Grounding)、更自主(Agent+Planning)。
八、进一步思考与实践
实践路线图
入门实践 :使用Hugging Face Transformers加载LLaMA-7B模型,学习使用LoRA + PEFT库对模型进行微调
进阶探索 :部署vLLM推理服务,理解Continuous Batching和PagedAttention的配置参数
深入理解 :阅读FlashAttention v2论文并理解其CUDA kernel设计,尝试用Triton重写简化版
系统实践 :搭建完整的RAG系统(LangChain + Chroma + 主流LLM),对比不同检索策略的效果
高级挑战 :尝试使用DeepSpeed + Megatron-LM在多卡环境训练小型GPT模型(1B级别)
推荐学习资源
论文:Scaling Laws (Kaplan 2020), Chinchilla (Hoffmann 2022), LoRA (Hu 2021), FlashAttention (Dao 2022), PagedAttention (Kwon 2023)
框架:Hugging Face Transformers, DeepSpeed, vLLM, LangChain, PEFT, bitsandbytes
课程:Stanford CS224N NLP, Hugging Face NLP Course, Fast.ai Practical Deep Learning
工程:PyTorch Distributed, NVIDIA Megatron-LM, DeepSpeedExamples, vLLM仓库源码
大规模预训练模型技术正处于快速发展期,从模型架构(Transformer/MoE/状态空间模型)、训练算法(RLHF/DPO/GRPO)、推理优化(Speculative Decoding/Medusa/Lookahead Decoding)到应用范式(RAG/Agent/MCP),每个方向都在持续突破。掌握本文所涉及的六大核心技术模块,可以为深入理解和应用大模型技术打下坚实基础。
本笔记根据大规模预训练模型相关论文、开源项目及工程实践经验整理总结
参考论文:Scaling Laws, Chinchilla, ZeRO, LoRA, FlashAttention, PagedAttention, Speculative Decoding 等
本学习笔记为本人学习资料,不得转载
免责声明: 本学习笔记只供学习使用,不构成任何技术建议或投资建议。