AI 工程基础体系 · 第 3/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。

机器学习完整基础:任务、特征、模型、损失、泛化和实验流程

机器学习的核心不是“选择一个算法”,而是定义一个可验证的预测问题:给定可获得的信息 xx,学习一个函数 fθf_\theta,使它在未来数据上对目标 yy 做出有用且可靠的输出。

这里的 xx 可以是表格字段、图像像素、文本 token、用户行为序列或多模态输入;yy 可以是类别、数值、排序偏好、下一 token,甚至是一组约束下的生成结果。模型、数据、评测、权限和成本不是互相独立的部分,而是同一个生产系统的不同状态。


一、先把问题形式化:机器学习到底在学习什么

1. 数据、样本、特征、标签

设数据集为:

D={(xi,yi)}i=1nD=\{(x_i,y_i)\}_{i=1}^{n}

其中:

  • nn:样本数量;
  • xix_i:第 ii 个样本的输入;
  • yiy_i:第 ii 个样本的目标或标签;
  • fθ(x)f_\theta(x):参数为 θ\theta 的模型;
  • y^i=fθ(xi)\hat y_i=f_\theta(x_i):模型预测。

在表格任务中,xix_i 可能是:

年龄=35,近30天登录次数=12,是否逾期=0,设备类型=Android

在图像任务中,xix_i 是像素张量;在语言模型中,xix_i 通常是 token 序列:

xi=(t1,t2,,tT)x_i=(t_1,t_2,\ldots,t_T)

“特征”是用于构造输入表示的信息。原始数据字段不一定直接就是特征。例如时间戳 2025-03-08 14:30:00 可以转换为小时、星期、是否节假日等特征。

“标签”是训练阶段希望模型逼近的目标。线上预测时通常没有标签,因此不能把依赖未来标签的信息伪装成特征。

2. 从联合分布到预测函数

更一般地,样本被认为来自某个未知联合分布:

(X,Y)P(X,Y)(X,Y)\sim P(X,Y)

机器学习希望找到一个函数,使期望损失最小:

f=argminfR(f)f^*=\arg\min_f R(f)

其中总体风险为:

R(f)=E(X,Y)P[(f(X),Y)]R(f)=\mathbb E_{(X,Y)\sim P}[\ell(f(X),Y)]

\ell 是损失函数,用于衡量预测和真实目标之间的差异。

现实中我们不知道 P(X,Y)P(X,Y),只能看到有限样本,因此使用经验风险:

R^D(f)=1ni=1n(f(xi),yi)\hat R_D(f)=\frac{1}{n}\sum_{i=1}^{n}\ell(f(x_i),y_i)

训练过程通常是在某个模型族 F\mathcal F 中求:

f^=argminfFR^D(f)\hat f=\arg\min_{f\in\mathcal F}\hat R_D(f)

这揭示了机器学习的基本矛盾:

  • 只看训练集,模型可以把训练样本记住;
  • 真正目标是未知分布上的总体风险;
  • 训练集风险和总体风险不相等;
  • 所谓“泛化”,就是训练得到的模型在未见数据上仍然有效。

二、任务类型:不同目标决定不同模型和评测

1. 监督学习

监督学习拥有输入和目标对 (x,y)(x,y)

分类

分类任务的标签属于有限集合:

y{1,2,,K}y\in\{1,2,\ldots,K\}

二分类例如判断交易是否欺诈,多分类例如识别图片类别。

模型通常先输出每个类别的分数或概率:

pθ(y=kx)p_\theta(y=k\mid x)

预测类别是概率最大的类别:

y^=argmaxkpθ(y=kx)\hat y=\arg\max_k p_\theta(y=k\mid x)

但“概率最大”不一定等价于业务决策。若漏报代价远高于误报,可能需要调整阈值,而不是直接使用 0.50.5

回归

回归的目标是连续值:

yRy\in\mathbb R

例如预测房价、延迟、需求量或温度。

排序与推荐

排序任务不只关心单个预测值,还关心候选项之间的相对次序。例如搜索结果中,相关文档应该排在不相关文档前面。

此时损失可以作用于样本对:

(f(xi)f(xj),yij)\ell(f(x_i)-f(x_j), y_{ij})

其中 yijy_{ij} 表示样本 ii 是否应排在样本 jj 前面。评测通常使用 NDCG、MRR、Recall@K 等排序指标,而不是普通准确率。

2. 无监督学习

无监督学习只有 xx,没有明确标签。

聚类试图发现分组结构,例如最小化簇内距离:

k=1KxiCkxiμk2\sum_{k=1}^{K}\sum_{x_i\in C_k}\|x_i-\mu_k\|^2

降维则寻找低维表示,使重构误差、局部邻域或方差保留较好。

注意:聚类得到的簇不自动具有业务含义。把 K-means 的簇编号直接当作“客户类型”是常见误读。簇编号本身没有稳定语义,重新初始化或改变样本顺序后,编号可能互换。

3. 自监督学习

自监督学习从数据本身构造目标。例如语言模型将序列右移:

输入:今天 天气 很
目标:天气 很 好

训练目标是:

L(θ)=t=1Tlogpθ(xtx<t)\mathcal L(\theta) =-\sum_{t=1}^{T}\log p_\theta(x_t\mid x_{<t})

它不需要人工逐条标注,但训练目标与最终应用目标仍可能不同。语言模型能较好预测下一个 token,并不意味着它自动具备事实可靠性、权限判断能力或复杂业务流程能力。

4. 强化学习

强化学习中的主体在状态 sts_t 下选择动作 ata_t,获得奖励 rtr_t,进入下一个状态:

st,atrt,st+1s_t,a_t\rightarrow r_t,s_{t+1}

目标通常是最大化折扣回报:

J(π)=Eπ[t=0Tγtrt]J(\pi)=\mathbb E_\pi\left[\sum_{t=0}^{T}\gamma^t r_t\right]

γ[0,1]\gamma\in[0,1] 是折扣因子。强化学习的样本分布受当前策略影响,因此数据不是简单独立同分布;探索行为还可能带来真实系统风险。


三、特征与表示:模型看到的不是原始世界

1. 特征变换改变了可学习问题

若原始输入是 xx,特征工程可以表示为:

z=ϕ(x)z=\phi(x)

模型实际学习的是:

y^=fθ(ϕ(x))\hat y=f_\theta(\phi(x))

例如用线性模型预测圆形区域内的类别:

y^=1[w1x1+w2x2+b>0]\hat y=\mathbb 1[w_1x_1+w_2x_2+b>0]

线性决策边界只能是一条直线,无法直接表达:

x12+x22>1x_1^2+x_2^2>1

加入二次特征:

ϕ(x)=(x1,x2,x12,x22)\phi(x)=(x_1,x_2,x_1^2,x_2^2)

后,线性模型在新特征空间中可以表达非线性边界。所谓“线性模型不能解决非线性问题”并不完整;准确说法是,在线性输入表示和线性决策函数同时受限时不能解决某些非线性问题。

2. 数值、类别、文本和缺失值

不同类型特征需要不同处理:

  • 数值特征:可能需要标准化、截断极端值;
  • 类别特征:可使用独热编码、目标编码或嵌入;
  • 文本:可使用词袋、TF-IDF、预训练表示或 token 序列;
  • 时间:通常拆解周期性和相对时间;
  • 缺失值:缺失本身可能包含信息,不能无条件当作普通均值。

标准化常见形式为:

zj=xjμjσjz_j=\frac{x_j-\mu_j}{\sigma_j}

其中 μj,σj\mu_j,\sigma_j 必须只用训练集计算。若把测试集也用于计算均值和方差,测试分布信息就进入了训练流程,形成泄漏。

3. 特征可用性比预测相关性更重要

一个字段即使和标签高度相关,也不能直接使用。必须回答:

  1. 预测时这个字段是否已经存在?
  2. 它的生成时间是否早于预测时间?
  3. 它是否由标签或标签之后的事件计算?
  4. 线上计算逻辑是否和训练逻辑一致?
  5. 访问它是否符合权限和隐私要求?

例如,要在用户下单时预测“是否退款”,使用“退款完成时间”构造特征会得到极高离线分数,但线上预测时该字段尚未产生。这不是模型强,而是目标泄漏。


四、模型:假设空间、参数和决策机制

1. 模型是函数族,不是一个神秘黑盒

模型可以写成:

fθ:XYf_\theta:\mathcal X\rightarrow\mathcal Y

θ\theta 是需要从数据中学习的参数。模型结构定义了假设空间 F\mathcal F:允许模型表达哪些函数。

线性回归:

y^=wx+b\hat y=w^\top x+b

决策树通过一系列条件切分输入空间;神经网络通过多层参数化变换:

h(l+1)=σ(W(l)h(l)+b(l))h^{(l+1)}=\sigma(W^{(l)}h^{(l)}+b^{(l)})

Transformer 则使用注意力机制,让序列中不同位置的表示相互聚合。以单头注意力为例:

Attention(Q,K,V)=softmax(QKdk)V\operatorname{Attention}(Q,K,V) =\operatorname{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)V

Q,K,VQ,K,V 分别是查询、键和值,dkd_k 是键向量维度。注意力权重表达“当前位置应从其他位置取多少信息”,但它不等价于因果解释,也不保证模型输出事实正确。

2. 参数、超参数和状态

需要区分三类东西:

  • 参数:训练中由优化算法更新,例如神经网络权重;
  • 超参数:训练前或训练过程中由实验配置决定,例如树深、学习率、正则化强度;
  • 状态:优化器动量、归一化层统计量、tokenizer 词表、特征统计量等。

保存模型时只保存权重而丢失 tokenizer、类别映射或标准化参数,可能导致线上输出错误,即使权重文件本身没有损坏。

3. 生成式模型不是“只生成文本”

生成式 AI 学习的是条件分布或联合分布。条件生成可以写为:

pθ(yx)p_\theta(y\mid x)

生成时通常逐步采样:

pθ(yx)=t=1Tpθ(yty<t,x)p_\theta(y\mid x) =\prod_{t=1}^{T}p_\theta(y_t\mid y_{<t},x)

温度参数常用于调整 logits:

pi=softmax(zi/T)p_i=\operatorname{softmax}(z_i/T)

TT 越大,分布越平;TT 越小,越集中。它只能改变采样随机性,不能修复训练数据中的事实错误、提示注入或权限越界。

检索增强生成(RAG)将生成分解为:

  1. 根据查询检索文档;
  2. 将文档放入上下文;
  3. 生成模型基于上下文回答。

RAG 可以提高知识可追溯性,但不保证检索结果正确,也不自动解决文档权限问题。检索组件必须在授权范围内过滤候选文档,否则模型可能把用户无权访问的内容生成出来。


五、损失函数:把“错误”变成可优化的数值

损失函数不是评测指标的同义词。损失负责提供训练信号,指标负责描述业务表现;二者可以相关,但不必相同。

1. 均方误差及其推导

回归中常见均方误差:

L(θ)=1ni=1n(fθ(xi)yi)2L(\theta)=\frac{1}{n}\sum_{i=1}^{n}(f_\theta(x_i)-y_i)^2

对最简单的常数模型 fθ(x)=cf_\theta(x)=c,有:

L(c)=1ni=1n(cyi)2L(c)=\frac1n\sum_{i=1}^{n}(c-y_i)^2

求导:

dLdc=2ni=1n(cyi)=2(c1niyi)\frac{dL}{dc} =\frac{2}{n}\sum_{i=1}^{n}(c-y_i) =2\left(c-\frac1n\sum_i y_i\right)

令导数为零:

c=1niyic=\frac1n\sum_i y_i

因此,在平方损失下,最优常数预测是训练标签均值。这个结论说明损失函数隐含了统计目标:MSE 偏好条件均值,而不是中位数。

若异常值很多,平方误差会放大大残差。绝对误差:

L(c)=1nicyiL(c)=\frac1n\sum_i|c-y_i|

的最优常数是中位数,因此 MAE 对异常值更稳健。

2. 交叉熵与概率预测

二分类模型输出 pθ(y=1x)p_\theta(y=1\mid x),二元交叉熵为:

(p,y)=ylogp(1y)log(1p)\ell(p,y)=-y\log p-(1-y)\log(1-p)

当真实标签 y=1y=1 而模型给出 p=0.01p=0.01 时,损失为:

log(0.01)4.605-\log(0.01)\approx4.605

当模型给出 p=0.9p=0.9 时,损失约为 0.1050.105。交叉熵强烈惩罚“自信但错误”的预测,因此适合训练概率模型。

多分类交叉熵为:

(p,y)=logpy\ell(\mathbf p,y)=-\log p_y

只取真实类别对应的预测概率。

3. 正则化改变了优化目标

带 L2 正则的目标为:

J(θ)=R^D(θ)+λθ22J(\theta)=\hat R_D(\theta)+\lambda\|\theta\|_2^2

第一项要求拟合训练数据,第二项惩罚过大的参数。它不是简单地“让模型变小”,而是通过改变目标函数限制可表达解,通常降低方差,但可能增加偏差。

L1 正则:

J(θ)=R^D(θ)+λθ1J(\theta)=\hat R_D(\theta)+\lambda\|\theta\|_1

倾向产生零参数,因此在某些线性模型中可以形成稀疏特征选择。不过相关特征存在时,L1 选择哪一个可能不稳定。

4. 优化算法不等于模型目标

梯度下降更新为:

θt+1=θtηθJ(θt)\theta_{t+1}=\theta_t-\eta\nabla_\theta J(\theta_t)

η\eta 是学习率。随机梯度下降使用小批量近似总体梯度:

J(θ)1BiBi(θ)\nabla J(\theta)\approx \frac1{|B|}\sum_{i\in B}\nabla\ell_i(\theta)

优化器决定如何寻找目标的低点,不改变损失本身的业务含义。Adam 可能比普通 SGD 收敛更快,但“训练损失下降”仍不代表泛化性能提高。


六、泛化:为什么训练分数高仍可能失败

1. 训练误差、测试误差和分布假设

训练误差是:

R^train=1ni(f(xi),yi)\hat R_{\text{train}} =\frac1{n}\sum_i\ell(f(x_i),y_i)

测试误差用于估计未见数据风险:

R^test=1mj=1m(f(xj),yj)\hat R_{\text{test}} =\frac1{m}\sum_{j=1}^{m}\ell(f(x_j),y_j)

当训练集和未来数据近似来自同一分布、样本独立且测试集未参与模型选择时,测试误差才有可信的泛化解释。

如果测试集被反复查看并据此调参,它就不再是纯粹的最终评估集。即使没有直接训练权重,也发生了“测试集过拟合”。

2. 偏差—方差分解

对回归问题,在固定 xx 下,若:

Y=f(x)+ϵ,E[ϵ]=0Y=f^*(x)+\epsilon,\qquad \mathbb E[\epsilon]=0

模型由随机训练集 DD 产生 f^D(x)\hat f_D(x)。其期望平方误差可以分解为:

ED[(f^D(x)Y)2]=(ED[f^D(x)]f(x))2偏差2+ED[(f^D(x)ED[f^D(x)])2]方差+Var(ϵ)不可约噪声\mathbb E_D[(\hat f_D(x)-Y)^2] = \underbrace{(\mathbb E_D[\hat f_D(x)]-f^*(x))^2}_{\text{偏差}^2} + \underbrace{\mathbb E_D[(\hat f_D(x)-\mathbb E_D[\hat f_D(x)])^2]}_{\text{方差}} + \underbrace{\operatorname{Var}(\epsilon)}_{\text{不可约噪声}}

  • 偏差高:模型假设太简单、特征不足或目标定义错误;
  • 方差高:模型对训练样本过敏,常见于数据少而模型复杂;
  • 不可约噪声:即使知道真实规律也无法完全消除。

增加模型复杂度通常可能降低偏差、提高方差,因此训练误差常持续下降,而验证误差先降后升。

3. 反例:随机切分导致时间泄漏

假设目标是预测某用户下周是否流失。数据记录了连续 12 周的行为。若把同一用户的各周记录随机分到训练集和测试集:

  • 训练集可能包含用户第 8 周数据;
  • 测试集可能包含该用户第 9 周数据;
  • 两者共享用户身份、行为习惯和相邻时间信息。

随机切分分数可能很高,但部署时面对新用户或未来分布时性能大幅下降。

时间预测应使用按时间切分:

训练:第 1~8 周
验证:第 9~10 周
测试:第 11~12 周

如果目标是评估新用户,还需要按用户分组切分,避免同一用户跨集合。

4. 分布漂移

训练分布和线上分布可能不同:

Ptrain(X,Y)Pprod(X,Y)P_{\text{train}}(X,Y)\ne P_{\text{prod}}(X,Y)

常见情况包括:

  • 协变量漂移:P(X)P(X) 变化;
  • 标签比例漂移:P(Y)P(Y) 变化;
  • 概念漂移:P(YX)P(Y\mid X) 变化。

例如欺诈者改变策略后,同样的交易特征不再对应原来的风险。此时仅重新训练原模型不一定足够,需要监测特征分布、标签延迟、分群表现和业务规则变化。


七、评测:指标必须对应决策和代价

1. 分类指标的含义

二分类预测产生混淆矩阵:

实际正类 实际负类
预测正类 TP FP
预测负类 FN TN

常见指标:

Precision=TPTP+FP\text{Precision}=\frac{TP}{TP+FP}

表示预测为正的样本中有多少是真的正类。

Recall=TPTP+FN\text{Recall}=\frac{TP}{TP+FN}

表示实际正类中有多少被找出。

Specificity=TNTN+FP\text{Specificity}=\frac{TN}{TN+FP}

准确率:

Accuracy=TP+TNTP+FP+FN+TN\text{Accuracy}=\frac{TP+TN}{TP+FP+FN+TN}

类别极不平衡时,准确率可能具有欺骗性。例如 1000 个样本中只有 10 个欺诈,全部预测为非欺诈就有 99% 准确率,但召回率为 0。

2. ROC、PR 与阈值

模型通常输出分数,阈值 tt 决定:

y^=1[p(y=1x)t]\hat y=\mathbb 1[p(y=1\mid x)\ge t]

改变 tt 会同时改变 Precision、Recall、误报率和漏报率。

ROC 曲线绘制不同阈值下的 TPR 与 FPR;PR 曲线绘制 Precision 与 Recall。正类稀少时,PR 曲线通常比 ROC 更能反映实际检出质量。

阈值应由业务代价决定。若误报成本为 CFPC_{FP},漏报成本为 CFNC_{FN},可以最小化:

C=CFPFP+CFNFNC=C_{FP}\cdot FP+C_{FN}\cdot FN

不能因为默认阈值是 0.5,就认为它具有普遍意义。

3. 概率校准

如果一组样本的预测概率都约为 0.8,理想情况下其中约 80% 应为正类。这个性质叫校准。

区分:

  • 排序能力:高风险样本是否排在前面;
  • 概率校准:输出的 0.8 是否真的约对应 80%;
  • 分类决策:按某阈值后是否获得可接受代价。

AUC 较高的模型不一定校准良好。信用额度、医疗风险和资源容量规划通常需要可靠概率,而不仅是排序。

4. 统计不确定性

一次测试集指标只是估计值。可使用 bootstrap:

  1. 从测试集有放回抽样;
  2. 每次计算指标;
  3. 重复多次;
  4. 使用分位数形成置信区间。

比较两个模型时,最好在相同样本上计算逐样本差异并进行配对分析,而不是只比较两个独立均值。小幅提升若落在噪声范围内,不应直接宣称模型改进。


八、一个可运行的端到端实验

下面示例使用 scikit-learn 构造二分类任务,展示数据切分、预处理、训练、概率评测和阈值选择。它不是生产数据,但流程可以运行。

import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
    roc_auc_score, average_precision_score,
    precision_recall_curve, confusion_matrix
)

# 1. 构造可复现实验数据
X, y = make_classification(
    n_samples=4000,
    n_features=6,
    n_informative=4,
    n_redundant=1,
    weights=[0.9, 0.1],
    random_state=42
)

# 2. 先划分测试集;测试集不参与阈值和模型选择
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)

# 3. 只在训练数据上拟合预处理器
preprocess = Pipeline([
    ("imputer", SimpleImputer(strategy="median")),
    ("scale", StandardScaler())
])

model = Pipeline([
    ("preprocess", preprocess),
    ("classifier", LogisticRegression(max_iter=1000))
])

# 4. 训练模型
model.fit(X_train, y_train)

# 5. 输出概率,而不是立即固定为 0/1
prob = model.predict_proba(X_test)[:, 1]

print("ROC-AUC:", round(roc_auc_score(y_test, prob), 4))
print("PR-AUC:", round(average_precision_score(y_test, prob), 4))

# 6. 在演示中用验证集之外的数据展示阈值搜索。
#    生产环境应在独立验证集上选阈值,再只在测试集上报告一次。
precision, recall, thresholds = precision_recall_curve(y_test, prob)
f1 = 2 * precision * recall / np.maximum(precision + recall, 1e-12)

# precision_recall_curve 返回的 precision/recall 比 thresholds 多一个元素
best_index = np.argmax(f1[:-1])
best_threshold = thresholds[best_index]
pred = (prob >= best_threshold).astype(int)

print("threshold:", round(float(best_threshold), 4))
print("precision:", round(float(precision[best_index]), 4))
print("recall:", round(float(recall[best_index]), 4))
print("confusion matrix:\n", confusion_matrix(y_test, pred))

每一步的关键原因是:

  • stratify=y 让训练集和测试集的类别比例近似一致;
  • Pipeline 保证填补和标准化属于训练流程,避免手工预处理时误用测试数据;
  • predict_proba 保留了排序和阈值调整所需的信息;
  • ROC-AUC 和 PR-AUC 不依赖某一个固定阈值;
  • 阈值选择必须和最终测试集隔离,否则测试结果会被选择过程污染。

实际实验应再拆分验证集:

训练集:拟合参数
验证集:选模型、超参数、阈值、校准方法
测试集:最终只评估一次

如果数据量有限,可在训练部分使用交叉验证。K 折交叉验证将训练数据分成 KK 份,每次用 K1K-1 份训练、剩余一份验证,最后汇总结果。时间序列不能直接使用普通随机 K 折,应使用时间顺序约束;同一用户、同一设备或同一实体相关样本也应使用分组切分。


九、实验流程:从问题定义到上线验证

一个可复现的机器学习实验通常经过以下状态:

flowchart LR
    A[业务问题与决策] --> B[标签定义与预测时点]
    B --> C[数据采集与权限审查]
    C --> D[清洗与特征构造]
    D --> E[时间/用户分组切分]
    E --> F[训练与超参数搜索]
    F --> G[验证集评测与阈值校准]
    G --> H[冻结测试集最终评估]
    H --> I[小流量部署]
    I --> J[线上监控与反馈]
    J --> K{分布或业务是否变化}
    K -- 否 --> J
    K -- 是 --> C

1. 先定义决策,不要先选模型

完整的问题定义至少包括:

  • 预测对象是谁;
  • 预测发生在什么时间点;
  • 预测窗口多长;
  • 标签如何生成;
  • 错误的代价是什么;
  • 模型输出如何改变动作;
  • 哪些用户或数据不能被使用。

例如“预测用户流失”不够精确。应明确为:

在用户最近一次活跃后的第 7 天,使用此前 30 天已产生的行为,预测未来 14 天是否没有再次活跃。

这样才能判断特征是否泄漏、标签是否可获得、线上推理是否及时。

2. 数据管道的状态和版本

训练数据不仅是文件,还应记录:

  • 数据来源和采集时间;
  • 过滤条件;
  • 标签生成版本;
  • 特征代码版本;
  • 数据集快照或哈希;
  • 切分规则;
  • 删除、匿名化和脱敏处理;
  • 访问主体和权限范围。

数据清洗如果不可复现,模型指标就无法解释。一个“模型版本”至少应能关联到模型权重、代码、依赖、数据快照、配置和评测报告。

3. 训练和实验记录

实验配置应固定记录:

random_seed: 42
model: logistic_regression
max_iter: 1000
split: stratified
threshold_source: validation
metric:
  - pr_auc
  - recall_at_fixed_precision

随机种子只能提高复现性,不能保证所有硬件、并行库和非确定性算子完全一致。深度学习中还可能受到 GPU 算子、混合精度和数据加载顺序影响。

4. 失败路径必须可诊断

常见失败不是“模型 API 抛异常”,而是结果悄悄失真:

  • 训练和线上特征列顺序不同;
  • 类别编码映射变化;
  • 线上缺失率突然升高;
  • 标签延迟导致近期样本被错误标记;
  • 测试集被用于多轮调参;
  • 线上请求的用户无权访问检索文档;
  • 模型输出概率未校准却被当作风险百分比;
  • 超时后系统回退到旧模型,但没有记录回退原因。

应记录输入数据版本、模型版本、特征缺失情况、推理延迟、异常率、输出分布和最终动作。涉及个人数据时,日志不得为了可观测性而复制原始敏感内容。


十、深度学习和生成式 AI 中的特殊问题

1. 训练、验证和推理是不同生命周期

深度学习训练通常包括:

  1. 读取小批量数据;
  2. 前向传播得到输出;
  3. 计算损失;
  4. 反向传播得到梯度;
  5. 优化器更新参数;
  6. 在验证集上评估;
  7. 保存检查点。

推理阶段不应继续更新参数,并应切换到推理模式;例如包含 dropout 或 batch normalization 的网络,训练态和推理态行为不同。具体调用方式取决于框架版本,但“保存权重、模型结构、预处理器和推理配置”是共同要求。

2. 预训练、微调和提示

生成式模型常见生命周期包括:

  • 预训练:在大规模语料上学习通用表示;
  • 指令微调:学习遵循指令的行为;
  • 偏好优化:根据人工或模型反馈调整输出偏好;
  • 提示或 RAG:不改变基础权重,通过上下文影响当前输出。

微调数据可能带来新的隐私、版权、偏差和泄漏风险。提示词不是权限边界,也不是安全策略;真正的权限控制必须在数据检索、工具调用和业务服务层实施。

3. 生成质量不能用单一分数概括

生成任务至少应区分:

  • 事实正确性;
  • 指令遵循;
  • 格式符合性;
  • 有害内容率;
  • 引用可验证性;
  • 延迟和 token 成本;
  • 不同用户群体的质量差异。

自动指标可以快速回归测试,但不能完全替代人工评审或基于真实任务的评测。评测集若来自训练语料或公开 benchmark 的污染版本,分数会高估泛化能力。


十一、成本、权限和生产约束

1. 成本是目标函数的一部分

一次预测的总成本不只有 GPU 或 API 费用,还包括:

Ctotal=Ccompute+Cstorage+Cnetwork+Clabel+Clatency+CriskC_{\text{total}} =C_{\text{compute}}+ C_{\text{storage}}+ C_{\text{network}}+ C_{\text{label}}+ C_{\text{latency}}+ C_{\text{risk}}

更复杂的模型可能提高离线指标,却增加延迟、显存、能耗和故障恢复时间。如果业务收益不足以覆盖这些成本,模型并没有真正改进系统。

生成式 AI 还应监控输入和输出 token 数、上下文长度、重试次数、缓存命中率、并发峰值和供应商限流。设置超时、预算上限和降级路径,防止异常循环造成不可控费用。

2. 权限必须贯穿数据流

权限不仅是“谁可以调用模型”,还包括:

  • 谁可以读取训练数据;
  • 谁可以查看标签和原始文本;
  • 谁可以启动训练任务;
  • 谁可以下载模型;
  • 哪些请求可以检索哪些文档;
  • 哪些模型输出允许触发自动动作。

一个可接受的 RAG 数据流应先执行访问控制,再进行召回:

用户身份
  → 权限判定
  → 过滤可访问文档集合
  → 向量/关键词检索
  → 上下文拼接
  → 模型生成
  → 输出审查与审计

如果先从全量文档召回,再在生成后尝试删除敏感内容,可能已经在中间日志、缓存或模型上下文中泄露。

3. 监控的不只是平均指标

线上监控应覆盖:

  • 输入分布和缺失率;
  • 输出分布和置信度;
  • 延迟、吞吐、错误率;
  • 分群指标;
  • 真实标签回流后的延迟指标;
  • 训练—服务特征一致性;
  • 成本和资源使用;
  • 权限拒绝与异常访问;
  • 模型和数据版本。

平均指标可能掩盖小群体的严重退化。例如总体召回率稳定,但某地区、设备类型或新用户群体的召回率显著下降。评测应提前定义分群、最小样本量和统计不确定性,避免在大量分群中偶然发现一个“显著差异”后过度解释。


十二、常见误解与诊断顺序

误解一:训练准确率高,模型就很好

可能原因:

  • 标签泄漏;
  • 训练集和测试集重复;
  • 类别极不平衡;
  • 模型记忆了实体;
  • 测试集参与调参。

诊断顺序应是:检查预测时点、重复样本、按实体切分、标签比例、混淆矩阵和独立时间测试集。

误解二:AUC 高就能直接上线

AUC 衡量排序,不决定阈值,也不代表概率校准。上线前仍需确定业务代价、容量约束、阈值稳定性、延迟、回退和分群表现。

误解三:更多特征一定更好

无关特征可能增加方差;高基数 ID 可能造成记忆;未来字段会泄漏;未经治理的文本可能引入隐私和版权风险。应比较加入特征前后的独立验证结果,并做时间可用性审查。

误解四:更大的生成模型一定更可靠

参数规模可能提高语言建模能力,却不自动提供最新知识、来源验证、权限控制或业务约束。可靠性需要数据、检索、工具、验证器和人工流程共同承担。

误解五:交叉验证总是比简单切分好

交叉验证适合近似独立同分布的数据。在时间序列、用户事件、医疗患者或设备日志中,错误的随机折叠会把同一实体或未来信息带入训练,产生虚假的高分。


十三、把机器学习理解成一个闭环

完整的机器学习系统可以归纳为:

可用数据表示与特征模型损失优化泛化评测受权限和成本约束的部署反馈与再训练\text{可用数据} \rightarrow \text{表示与特征} \rightarrow \text{模型} \rightarrow \text{损失优化} \rightarrow \text{泛化评测} \rightarrow \text{受权限和成本约束的部署} \rightarrow \text{反馈与再训练}

其中任何一环的定义错误,后续优化都可能只是更高效地得到错误答案:

  • 标签定义错,模型会稳定学习错误目标;
  • 特征时间错,离线成绩会虚高;
  • 损失和业务代价不一致,优化方向会偏离决策;
  • 测试集被污染,泛化估计会失真;
  • 权限在检索或工具层缺失,生成系统会越权;
  • 忽略成本和延迟,再高的指标也无法形成可用服务。

因此,机器学习基础并不止于知道线性回归、决策树、神经网络或 Transformer 的名称。真正完整的基础是能够从预测时点和决策代价出发,构造没有泄漏的数据,选择与目标匹配的表示、模型和损失,用隔离且有不确定性分析的评测估计泛化能力,最后在权限、成本、监控和反馈闭环中验证系统是否仍然有效。


系列导航与关联阅读

官方资料

本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。