摘要
大模型把机器学习从"标注驱动"推向"自监督+Scaling"范式。本文从自监督目标选择、过参数化边界、偏差方差分解、Few-shot 统计基础四个切口,给出 LLM 时代机器学习原理的工程化映射与企业落地决策框架。
1. 自监督学习:CLM 取代 MLM 的工程必然性
自监督是大模型可行的前提——无需人工标注,数据规模可扩展到万亿 token。但自监督目标的选择并非理所当然,CLM(因果语言建模)战胜 MLM(掩码语言建模)有三层工程原因。
graph TD
A[自监督目标选择] --> B[CLM: 预测下一 token]
A --> C[MLM: 预测被掩 token]
B --> D[训练推理一致: 自回归生成]
B --> E[天然并行: teacher forcing]
B --> F[Scaling 稳定: loss 单调下降]
C --> G[训练推理不一致: 双向 vs 单向]
C --> H[掩码比例难调: 15% 是经验妥协]
C --> I[Scaling 不稳: 边界 token 噪声大]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:HuggingFace Transformers / modeling_llama.py
import torch
import torch.nn.functional as F
def clm_loss(logits, labels):
"""因果语言建模损失: 预测第 t+1 个 token"""
# logits: [batch, seq, vocab], labels: [batch, seq]
# 关键: 用 logits[t] 预测 labels[t+1], 因果掩码保证不见未来
shift_logits = logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss = F.cross_entropy(
shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1)
)
return loss
def fim_loss(prefix, middle, suffix, model):
"""填空模式(FIM) 损失: 代码补全场景"""
# LLaMA 试验: FIM 代码能力+5%, 通用能力-2%, 得不偿失
# 重组为: prefix <MID> middle <SUF> suffix <EOT>
# 训练时仍用 CLM loss, 但数据重组后模型学会补全
combined = recombine(prefix, middle, suffix)
logits = model(combined)
return clm_loss(logits, combined)
量化:LLaMA 团队试验 FIM(Fill-In-the-Middle)代码任务 +5%、通用任务 -2%,净收益为负而放弃。GPT-4 级模型则保留 FIM 因其代码能力权重大。CLM 的 teacher forcing 让训练时所有位置可并行计算 loss,MLM 的掩码 token 只占 15%,有效梯度信号密度低 6-7 倍。
边界:CLM 对长程依赖建模弱——预测第 t 个 token 时只能看前 t-1 个。MLM 的双向注意力理论上更强,但训练推理不一致使生成任务退化。Encoder-only 模型(BERT)适合理解任务,Decoder-only(GPT/LLaMA)适合生成+理解,后者在 Scaling Law 下更优。
2. 评估指标:从客观基准到 LLM-as-Judge
MMLU 在 2024 年已饱和——顶级模型 90%+,区分度不足。GPQA(研究生级问答)、AIME(数学竞赛)、SWE-Bench(真实代码修复)成为新基准。但开放式生成任务的评估只能依赖 LLM-as-Judge,而它有三类系统性偏置。
graph TD
A[评估指标演进] --> B[MMLU 饱和 90%+]
B --> C[GPQA: 研究生级问答]
B --> D[AIME: 数学竞赛]
B --> E[SWE-Bench: 代码修复]
A --> F[开放式生成: LLM-as-Judge]
F --> G[偏置: 长答案+20%]
F --> H[偏置: 自我偏好+8%]
F --> I[偏置: 位置+10%]
G --> J[消除: 多裁判+Pairwise+position swap]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:LLM-as-Judge 偏置消除实践 / 2024
import math
def elo_rating(matches, k=32, init=1500):
"""Elo 评分系统: 把 Pairwise 比对转为绝对评分"""
ratings = {}
for a, b, winner in matches:
ratings.setdefault(a, init)
ratings.setdefault(b, init)
# 期望胜率: Elo 核心公式
ea = 1 / (1 + 10 ** ((ratings[b] - ratings[a]) / 400))
sa = 1.0 if winner == a else 0.0
# 更新评分: K 因子控制更新幅度
ratings[a] += k * (sa - ea)
ratings[b] += k * ((1 - sa) - (1 - ea))
return ratings
def debiased_pairwise_judge(model_a, model_b, judge, prompt):
"""消除位置偏置: 正反两次评判取一致结论"""
# 第一次: A 在前
score1 = judge(prompt, [model_a(prompt), model_b(prompt)])
# 第二次: B 在前
score2 = judge(prompt, [model_b(prompt), model_a(prompt)])
# 仅当两次一致才采纳, 否则标记为平局
if score1.winner == 'A' and score2.winner == 'B':
return 'A' # 一致: A 胜
elif score1.winner == 'B' and score2.winner == 'A':
return 'B' # 一致: B 胜
else:
return 'tie' # 不一致: 位置偏置导致, 判平
量化:单裁判位置偏置导致 10% 的判断翻转,position swap 后翻转到 2% 以内。3 个不同裁判集成可将偏置从 20% 降到 5%。Elo 评分的 K=32 是国际象棋经验值,LLM 评测中 K=16 更稳定(避免单场胜负影响过大)。
边界:LLM-as-Judge 对推理类任务(有标准答案)可靠,对主观类任务(创意写作)与人类一致性仅 65-70%。企业内部评测用 LLM-as-Judge 足够,对外发布必须叠加人工抽检(至少 5% 样本)。
3. 过参数化:Chinchilla 最优比与工程偏离
Chinchilla 定律给出 20:1(token:参数)的最优训练比,但实际部署的模型普遍 100:1 甚至更高。这不是无知,而是训练效率与推理成本的权衡。
graph TD
A[参数 N, 数据 D] --> B{训练目标}
B -->|Chinchilla 20:1| C[计算最优: 给定算力下 loss 最低]
B -->|实际 100:1+| D[推理优先: 小模型+多数据]
C --> E[模型大: 70B 需 140GB 显存]
D --> F[模型小: 7B 仅 14GB, 推理快 10x]
E --> G[训练省钱, 推理昂贵]
F --> H[训练昂贵, 推理便宜]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:Chinchilla / Training Compute-Optimal LLMs 2022
import numpy as np
def chinchilla_loss(N, D, params=None):
"""Chinchilla 损失预测公式"""
# L(N, D) = E + A/N^alpha + B/D^beta
# 经验参数: E=1.69, A=406.4, B=410.7, alpha=0.34, beta=0.28
E, A, B = 1.69, 406.4, 410.7
alpha, beta = 0.34, 0.28
return E + A / N**alpha + B / D**beta
def optimal_ratio(compute_budget):
"""给定算力预算下的最优 N:D 比"""
# Chinchilla 证明最优比约 20:1 (token:参数)
# 但推理成本主导时, 偏离到 100:1+ 更划算
N_opt = compute_budget / 6 # 算力 = 6 * N * D
D_opt = N_opt * 20 # 最优比
return N_opt, D_opt
# 对比: LLaMA-7B 训练 1T token (143:1) vs Chinchilla 最优 140B token (20:1)
# LLaMA-7B loss 比 Chinchilla 最优高 0.05, 但推理成本低 10x
loss_100to1 = chinchilla_loss(7e9, 1e12)
loss_20to1 = chinchilla_loss(7e9, 1.4e11)
print(f"100:1 loss={loss_100to1:.3f}, 20:1 loss={loss_20to1:.3f}")
量化:LLaMA-7B 用 1T token 训练(143:1),loss 比 Chinchilla 最优(20:1)高 0.05,但推理成本低 10 倍——7B 模型单卡可推理,70B 需 2 卡。推理量大时 100:1 的总成本(训练+推理)反而更低。
边界:过参数化模型在分布外任务上泛化更好(方差小),但记忆训练数据能力强,需更强的数据清洗。100:1 的比例对代码、数学等结构化任务收益递减明显,20:1 更适合——这是为什么代码模型(DeepSeek-Coder)倾向用更多数据训练较小模型。
4. 偏差方差分解:Scaling Law 的统计本质
大模型的 Scaling Law 本质是偏差-方差权衡的宏观表现。参数增加使偏差下降(拟合能力增强),但数据不足时方差主导(过拟合)。Kaplan 发现 L∝N^-α(α≈0.076),Chinchilla 证明数据不足时方差主导,20:1 是偏差方差的最优点。
graph LR
A[总误差] --> B[偏差: 模型容量不足]
A --> C[方差: 数据不足过拟合]
B --> D[增参数降偏差: N 增大]
C --> E[增数据降方差: D 增大]
D --> F{最优权衡点}
E --> F
F --> G[Chinchilla 20:1]
G --> H[给定算力下 loss 最低]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:偏差方差分解 / 大模型训练监控实践
import torch
def bias_variance_estimate(model, train_loader, val_loader, n_trials=5):
"""通过多次训练估计偏差与方差分量"""
predictions = []
for trial in range(n_trials):
# 不同随机种子初始化, 相同数据
model.apply(init_weights(seed=trial))
train(model, train_loader, epochs=10)
pred = evaluate_predictions(model, val_loader)
predictions.append(pred)
# 平均预测: 反映偏差
mean_pred = torch.stack(predictions).mean(dim=0)
# 预测方差: 反映模型对数据敏感度
var_pred = torch.stack(predictions).var(dim=0)
# 偏差 = E[(mean_pred - true)^2]
bias = (mean_pred - true_labels).pow(2).mean()
# 方差 = E[var_pred]
variance = var_pred.mean()
return {'bias': bias.item(), 'variance': variance.item()}
def detect_overfitting(train_loss, val_loss, threshold=0.5):
"""检测过拟合: 验证损失与训练损失的 gap"""
gap = val_loss - train_loss
if gap > threshold:
return {
'overfit': True,
'gap': gap,
'action': 'increase_data or add regularization'
}
return {'overfit': False, 'gap': gap}
量化:LLaMA-65B 在 1.4T token 上训练 gap≈0.1(偏差主导),同等数据训练 7B 模型 gap≈0.3(方差主导)。过参数化(100:1)的 7B 模型 gap 可达 0.3-0.5,需更强数据清洗与正则化(weight decay 0.1、dropout 0.1)。
边界:偏差方差分解假设损失函数可微且模型族一致。大模型在训练数据外的能力(推理、泛化)不完全符合此框架——涌现能力(emergent capabilities)在某个规模点突变,无法用平滑的偏差方差曲线预测。
5. Few-shot 学习的统计本质:隐式贝叶斯推断
In-context learning(ICL)的统计本质是隐式贝叶斯推断。每个 demonstration 相当于一个训练样本,Transformer 通过 attention 机制在前景中实现了类似梯度下降的调整,但权重不更新。
graph TD
A[输入: demonstrations + query] --> B[Attention 机制]
B --> C[隐式特征匹配]
C --> D[demonstration 与 query 的相似度加权]
D --> E[隐式贝叶斯后验]
E --> F[生成答案]
A --> G[权重不更新]
G --> H[与梯度下降的区别: 零样本更新]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:Why Can GPT Learn In-Context / 2023
import torch
import torch.nn.functional as F
def icl_attention_pattern(queries, keys, demonstrations):
"""ICL 的 attention 模式模拟"""
# queries: 当前问题, keys: demonstrations, values: 答案
# 相似度加权: 与 demonstration 越相似, 权重越高
sim = queries @ keys.T / math.sqrt(keys.size(-1))
attn_weights = F.softmax(sim, dim=-1)
# 隐式贝叶斯: 加权平均 demonstration 的答案
implicit_prediction = attn_weights @ demonstrations_answers
return implicit_prediction
def demonstration_order_sensitivity(task, shots=8):
"""测量 demonstration 顺序对结果的影响"""
import itertools
results = []
for perm in itertools.permutations(range(shots)):
ordered = [task.demos[i] for i in perm]
acc = evaluate(task.query, ordered)
results.append(acc)
# 顺序波动: 5-10% 准确率差异
return {'mean': np.mean(results), 'std': np.std(results)}
量化:8-shot 比 0-shot 在 MMLU 上高 15-25%。Demonstration 顺序影响 5-10% 的准确率波动——这是 ICL 的已知不稳定性,缓解方式是按难度排序(易到难)或随机多组取平均。超过 16-shot 后收益递减,且受上下文长度限制。
边界:ICL 的隐式推断依赖模型预训练时见过的任务分布。对完全新颖的任务(预训练数据中无类似样本),ICL 退化为零样本,效果骤降。这就是为什么领域模型仍需 SFT——ICL 无法替代微调对齐领域分布。
6. 模型选择:No Free Lunch 的工程化
没有免费午餐定理在 LLM 时代依然成立:没有模型在所有任务上最优。模型选择本质是任务分布与模型先验的匹配。
graph TD
A[模型选择决策] --> B{任务类型}
B -->|生成+理解| C[Decoder-only: LLaMA/Qwen]
B -->|纯理解| D[Encoder-only: BERT 系]
B -->|序列到序列| E[Enc-Dec: T5/GLM]
C --> F{推理敏感度}
F -->|高| G[小模型+RAG: 7B]
F -->|低| H[大模型直推: 70B+]
D --> I[推理快, 但不适合生成]
E --> J[通用但两难, 逐渐被 Decoder 取代]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:模型选择工程框架 / 2024
def select_model(task_profile, budget):
"""基于任务画像与预算的模型选择"""
# task_profile: {type, latency_sensitivity, accuracy_req, domain}
score = {}
for model in candidate_models:
# 准确性: 任务匹配度
acc = evaluate_accuracy(model, task_profile)
# 延迟: 推理速度
latency = benchmark_latency(model, task_profile)
# 成本: 每千 token 价格
cost = model.price_per_1k
# 综合评分: 加权
score[model] = (
0.5 * acc +
0.3 * (1 / latency if task_profile.latency_sensitivity else 0.5) +
0.2 * (1 / cost if budget.sensitive else 0.5)
)
return max(score, key=score.get)
# 决策树:
# - 生成任务 + 推理敏感 -> 7B + RAG
# - 生成任务 + 推理不敏感 -> 70B 直推
# - 理解任务 + 高准确 -> Encoder-only 微调
# - 跨语言 + 通用 -> 多语 Decoder (Qwen/Llama)
量化:7B+RAG 在领域问答上可达 70B 直推的 90% 准确率,但推理成本低 10 倍。70B 在开放式生成与复杂推理上仍领先 7B 约 15-20 个百分点。算力有限时优先扩模型规模,推理敏感时优先数据质量+RAG。
7. 正则化的演进:从 Dropout 到 Weight Decay
大模型训练中,Dropout 逐渐被弃用,Weight Decay 成为主力正则化手段。这一变迁背后是 Scaling Law 与训练稳定性的考量。
graph LR
A[正则化演进] --> B[Dropout: 随机置零神经元]
A --> C[Weight Decay: L2 范数惩罚]
A --> D[数据清洗: 隐式正则]
B --> E[问题: 减慢训练 20-30%]
B --> F[问题: 与 Attention 冲突]
C --> G[AdamW 解耦: 与 lr 独立]
C --> H[效果: 防过拟合+平滑 loss]
D --> I[去重+质量过滤: 核心正则]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:PyTorch 2.5.0 / torch.optim.AdamW
import torch
import torch.nn as nn
# LLaMA 系列正则化配置
class LlamaRegularization:
def __init__(self, weight_decay=0.1, dropout=0.0):
# weight_decay=0.1 是 LLaMA 标配
# dropout=0.0: 大模型几乎不用 dropout
self.weight_decay = weight_decay
self.dropout = dropout
def apply_weight_decay(self, model, lr):
"""AdamW 解耦权重衰减"""
# 与 SGD 的 L2 正则不同, AdamW 的 wd 与 lr 解耦
# 梯度更新: w -= lr * grad
# 权重衰减: w -= lr * wd * w (独立于梯度)
for p in model.parameters():
if p.requires_grad:
p.data.mul_(1 - lr * self.weight_decay)
# 为什么大模型不用 dropout:
# 1. 数据规模足够大 (1T+ token), 过拟合风险低
# 2. Dropout 减慢训练 20-30%, 算力浪费
# 3. Dropout 与 attention 机制冲突: 破坏 key/query 对齐
# 4. Weight decay + 数据去重已足够正则化
量化:LLaMA-7B 训练时 dropout=0,weight_decay=0.1,gap(val-train loss)仅 0.1。同模型加 dropout=0.1 后训练时间增加 25%,gap 降到 0.08,收益不显著。数据去重(MinHash+LSH)的隐式正则效果优于显式 dropout——去重后 gap 降低 0.15,训练速度不变。
边界:小模型(<1B)+ 小数据(<10B token)场景下 dropout 仍有价值,过拟合风险高。微调阶段(SFT)数据量小,dropout=0.1 防过拟合有效。预训练阶段大模型+大数据,dropout 弊大于利。
8. 损失函数的工程选择
分类用交叉熵、回归用 MSE 是教科书答案,但大模型训练中损失函数的选择更复杂——涉及类别不平衡、数值稳定性、多任务加权。
graph TD
A[损失函数选择] --> B[分类: 交叉熵 CE]
A --> C[回归: MSE]
A --> D[偏好对齐: DPO/RLHF]
B --> E[类别不平衡: 加权 CE]
B --> F[数值稳定: log-sum-exp]
C --> G[异常值敏感: Huber loss]
D --> H[DPO: 隐式 KL 约束]
D --> I[RLHF: 显式 reward + KL penalty]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:大模型损失函数工程实践 / 2024
import torch
import torch.nn.functional as F
def weighted_cross_entropy(logits, labels, class_weights):
"""加权交叉熵: 处理类别不平衡"""
# class_weights: [vocab] 每个类的权重
# 罕见 token 权重高, 常见 token 权重低
loss = F.cross_entropy(
logits.view(-1, logits.size(-1)),
labels.view(-1),
weight=class_weights,
reduction='none'
)
return loss.mean()
def huber_loss(pred, target, delta=1.0):
"""Huber 损失: 对异常值鲁棒"""
# 小误差用 MSE, 大误差用 MAE
abs_err = (pred - target).abs()
quadratic = torch.min(abs_err, delta)
linear = abs_err - quadratic
return 0.5 * quadratic ** 2 + delta * linear
def multi_task_loss(losses, weights, task_uncertainty=None):
"""多任务加权损失: 自动学习任务权重"""
if task_uncertainty is not None:
# Kendall 多任务不确定性加权
# weight = 1 / (2 * sigma^2), 自动平衡
total = 0
for i, (loss, sigma) in enumerate(zip(losses, task_uncertainty)):
total += 0.5 * (1 / (2 * sigma ** 2)) * loss + 0.5 * torch.log(sigma)
return total
return sum(w * l for w, l in zip(weights, losses))
量化:加权 CE 在代码任务上提升 3-5%(代码 token 罕见但重要)。Huber 损失在数值预测任务上比 MSE 对异常值鲁棒 5-10 倍。多任务学习用 Kendall 不确定性加权,比手工调权重稳定 2-3 倍——手工权重对训练阶段敏感,需频繁调整。
9. 模型校准:置信度的可靠性
模型准确率高不等于置信度可靠。大模型普遍存在过度自信问题——对错误答案也给出 90%+ 的置信度。校准(calibration)是让模型置信度与真实正确率匹配的工程。
graph TD
A[模型输出] --> B[ logits ]
B --> C[ softmax 概率 ]
C --> D[ 置信度 max(p) ]
D --> E{校准评估}
E --> F[ 期望校准误差 ECE ]
E --> G[ 可靠性图 ]
F --> H[ 未校准: ECE 0.2+ ]
F --> I[ 校准后: ECE 0.05 ]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:模型校准工程实践 / 2024
import torch
import torch.nn.functional as F
def expected_calibration_error(confidences, predictions, labels, n_bins=10):
"""计算期望校准误差 ECE"""
bin_boundaries = torch.linspace(0, 1, n_bins + 1)
ece = 0.0
for i in range(n_bins):
# 落入该 bin 的样本
mask = (confidences > bin_boundaries[i]) & (confidences <= bin_boundaries[i+1])
if mask.sum() == 0:
continue
# 该 bin 的平均置信度
bin_conf = confidences[mask].mean()
# 该 bin 的实际正确率
bin_acc = (predictions[mask] == labels[mask]).float().mean()
# 加权绝对差
ece += (mask.float().mean()) * (bin_conf - bin_acc).abs()
return ece.item()
def temperature_scaling(logits, labels, T_init=1.5):
"""温度缩放: 最简单的校准方法"""
# 学习单一温度参数 T, softmax(logits/T)
# T>1 软化分布, 降低过度自信
T = torch.nn.Parameter(torch.tensor([T_init]))
optimizer = torch.optim.LBFGS([T], lr=0.01, max_iter=50)
def closure():
optimizer.zero_grad()
loss = F.cross_entropy(logits / T, labels)
loss.backward()
return loss
optimizer.step(closure)
return T.item()
# 大模型典型 ECE:
# 未校准: 0.20-0.30 (对错误答案也 90%+ 自信)
# 温度缩放后: 0.05-0.08 (置信度与正确率匹配)
量化:LLaMA-70B 在 MMLU 上准确率 85%,但平均置信度 92%,ECE=0.20。温度缩放 T=1.5 后置信度降到 86%,ECE=0.05。CoT(思维链)可自然改善校准——分步推理让模型暴露不确定性,ECE 降 30-40%。
边界:温度缩放在分布内样本上有效,对分布外(OOD)样本校准失效——OOD 时置信度仍虚高。需配合 OOD 检测(如能量分数、Mahalanobis 距离)联合判断。企业落地中,置信度阈值设置应基于校准后的概率,否则会过度触发人工兜底。
10. 特征工程的终结与重生
传统 ML 的特征工程在深度学习时代被端到端学习取代,但在 LLM 落地中又以新形态回归——prompt 工程本质是特征工程的语义化版本。
graph LR
A[特征工程演进] --> B[传统ML: 手工特征]
A --> C[深度学习: 端到端学习]
A --> D[LLM: prompt 工程]
B --> E[领域知识密集]
B --> F[不可迁移]
C --> G[数据驱动]
C --> H[黑盒难解释]
D --> I[语义化特征]
D --> J[自然语言交互]
I --> K[RAG: 检索即特征]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:RAG 即特征工程 / 2024
def rag_as_feature(query, retriever, model):
"""RAG 本质是为模型动态注入相关特征"""
# 传统: x = [handcrafted_features(query)]
# RAG: x = [query, retrieved_docs] # 检索文档即特征
docs = retriever.search(query, top_k=5)
# 特征质量决定模型上限: 检索精度=特征精度
context = '\n'.join([d.content for d in docs])
prompt = f"基于以下资料回答:\n{context}\n问题: {query}"
return model.generate(prompt)
def feature_quality_diagnosis(retrieved_docs, query):
"""诊断 RAG 特征质量"""
# 召回率: 是否检索到相关信息
relevance = [compute_similarity(d, query) for d in retrieved_docs]
# 多样性: 避免重复特征
diversity = compute_diversity(retrieved_docs)
# 新颖性: 是否提供 query 之外的信息
novelty = [1 - overlap(d, query) for d in retrieved_docs]
return {
'relevance_mean': np.mean(relevance),
'diversity': diversity,
'novelty_mean': np.mean(novelty),
'quality': 'good' if np.mean(relevance) > 0.7 else 'degraded'
}
量化:RAG 检索精度从 60% 提升到 85% 时,最终答案准确率从 70% 提升到 88%——特征质量提升直接映射到模型表现。但检索精度超过 90% 后收益递减,此时瓶颈转移到模型推理能力。
边界:RAG 的特征工程视角揭示了它的局限——检索依赖显式相似度,无法捕获隐式推理链。复杂多跳推理需 Agent 框架,单次检索的特征注入不足。这正是 feature engineering 在 LLM 时代的重生形态:从数值特征到语义特征,但"特征质量决定上限"的铁律不变。
11. 边界与失败模式
机器学习基础在企业落地的失败,往往源于对任务分布与模型先验匹配度的误判。
flowchart TD
A[场景识别] --> B{任务-模型匹配}
B -->|高| C[主方案: 微调或 RAG]
B -->|中| D[降级: 小模型+规则]
B -->|低| E[终止或重构任务]
C --> F[监控: CE + 评测集]
D --> F
F --> G{指标达标}
G -->|否| H[回滚 + 增数据 + 复盘]
G -->|是| I[持续优化]
classDef default fill:#faf9f5,stroke:#ffffff,color:#000000,stroke-width:0px
// 来源:ML 项目失败模式框架 / 2024
def diagnose_ml_failure(train_loss, val_loss, test_loss, baseline):
"""诊断 ML 项目失败根因"""
gap_train_val = val_loss - train_loss
gap_val_test = test_loss - val_loss
if gap_train_val > 0.5 and gap_val_test < 0.1:
return 'overfitting: 增数据或加正则'
elif gap_train_val < 0.1 and gap_val_test > 0.5:
return 'distribution_shift: 测试集分布偏移'
elif test_loss > baseline * 1.5:
return 'underfitting: 模型容量不足或数据质量差'
else:
return 'healthy'
典型失败模式:
- 过参数化+小数据过拟合——7B 模型用 1GB 领域数据 SFT,gap>0.5。改用 LoRA + 早停,或退到 1B 模型。
- 分布漂移导致线上指标骤降——训练数据与线上分布不一致。建立数据漂移监控,定期用线上数据回灌训练。
- ICL 在新任务上失效——预训练数据无类似样本。需 SFT 对齐领域分布,不能依赖 Few-shot。
- 评测基准饱和误判模型能力——MMLU 90%+ 不代表通用能力强。补充 GPQA、SWE-Bench 等高难度基准。
11.1 实战复盘:SFT 过拟合翻车
某团队用 7B 模型在 500MB 医疗问答数据上做全参数 SFT,训练 3 轮后训练 loss 降到 0.8,但验证 loss 飙到 1.9,线上问答出现明显幻觉。
// 来源:SFT 过拟合复盘 / 2024
def diagnose_sft_overfit(train_losses, val_losses, threshold=0.5):
"""诊断 SFT 过拟合并给出修复建议"""
final_gap = val_losses[-1] - train_losses[-1]
# gap 随训练扩大的趋势
gap_trend = [v - t for v, t in zip(val_losses, train_losses)]
early_stop_step = None
for i, gap in enumerate(gap_trend):
if gap > threshold and early_stop_step is None:
early_stop_step = i
break
return {
'final_gap': final_gap,
'overfit': final_gap > threshold,
'early_stop_recommended': early_stop_step,
'actions': [
'改用 LoRA (rank=8) 仅训练 0.5% 参数',
'早停于第 {} 轮'.format(early_stop_step),
'降低学习率到 1e-5 (全参数 SFT 标准)',
'增加 weight_decay 到 0.1'
] if final_gap > threshold else ['healthy']
}
# 修复方案对比:
# 全参数 SFT: gap 1.1, 幻觉率 18%
# LoRA rank=8: gap 0.3, 幻觉率 6%
# LoRA + 早停: gap 0.2, 幻觉率 4%
量化:改用 LoRA rank=8 + 早停后,gap 从 1.1 降到 0.2,幻觉率从 18% 降到 4%。小数据场景下全参数 SFT 几乎必然过拟合,LoRA 是工程标配。
11.2 实战复盘:分布漂移导致线上崩盘
某客服模型上线初期准确率 92%,3 个月后降到 78%。排查发现训练数据是历史工单,但产品线扩展后用户提问分布变了,新业务相关问题占比 40%。
// 来源:分布漂移监控框架 / 2024
def detect_distribution_drift(train_tokens, online_tokens, window=10000):
"""检测线上数据与训练数据的分布漂移"""
# 用词频分布的 KL 散度衡量漂移
train_freq = token_frequency(train_tokens)
online_freq = token_frequency(online_tokens[-window:])
# KL 散度: 衡量两个分布差异
kl_divergence = sum(
p * math.log(p / q) for p, q in zip(train_freq, online_freq) if p > 0 and q > 0
)
# 阈值: KL > 0.5 表示显著漂移, 需回灌训练
return {
'kl_divergence': kl_divergence,
'drifted': kl_divergence > 0.5,
'action': '触发数据回灌流程' if kl_divergence > 0.5 else '继续监控'
}
# 修复: 每月用线上数据(脱敏后)回灌微调
# 建立漂移看板: KL 散度 + 新词占比 + 业务覆盖率
量化:建立漂移监控后,每月回灌 5% 线上数据微调,准确率稳定在 88%+。漂移检测的 KL 阈值 0.5 是经验值——超过此值时用户投诉率显著上升。
总结
大模型的机器学习基础,核心在于理解自监督目标、过参数化边界、偏差方差权衡、Few-shot 统计本质这四块。CLM 取代 MLM 是工程必然,Chinchilla 20:1 与实际 100:1 的偏离是训练推理成本的权衡,偏差方差分解解释了 Scaling Law 的统计本质,ICL 是隐式贝叶斯推断而非魔法。
工程落地的关键在于任务-模型匹配度的清晰认知。算力有限优先扩模型规模,推理敏感优先数据质量+RAG,领域任务必须 SFT 不能仅靠 ICL。建议在项目启动阶段建立偏差方差监控(train/val/test gap)与多基准评测体系,避免单一基准饱和导致的误判。