本节摘要:模型在论文里跑通,离上线还差十万八千里。本节聚焦 CV 工程化的三大高频考点:迁移学习怎么用(小数据场景的救命稻草)、生成模型怎么选(GAN vs 扩散模型的代际更替)、端到端部署怎么做(从 PyTorch 到 TensorRT 的优化链路)。这些是工程岗面试的重头戏——面试官想确认你不是只会跑 demo,而是能把模型真正交付到用户手里。读完你会理解迁移学习的冻结策略、扩散模型为什么取代了 GAN、模型服务化的完整流水线。
阅读完本节,你应当能够:
学术研究和工程落地之间有一道巨大的鸿沟,很多人没意识到。论文里的模型在干净标注的标准数据集上跑,工程里要面对的是混乱的真实数据——标注不一致、类别长尾、光照变化、摄像头角度偏移、目标被遮挡。一个在 COCO 上 mAP 50% 的检测器,部署到真实街道可能直接掉到 30%。
痛点还在于交付。学术指标(mAP、PSNR)和业务指标(用户投诉率、转化率)常常脱节。模型推理慢一秒,视频流应用就卡;模型大 10MB,移动端就装不下;模型对某个肤色识别差,业务直接面临公关危机。这些都不是论文会讲的,但工程岗天天面对。
所以本节的组织逻辑是:先讲迁移学习——这是"小数据场景下让大模型能用"的核心技术;再讲生成模型——这是 CV 里最活跃的前沿,理解 GAN 到扩散的代际更替能让你跟上面试热点;最后讲部署——这是模型上线的最后一公里。三块合起来,覆盖了 CV 工程师从"拿到需求"到"模型上线"的完整能力链。
迁移学习的核心洞察是:深度模型的浅层学到的是通用特征(边缘、纹理、颜色),这些特征跨任务通用;深层学到的是任务特定特征。所以可以把在大数据集(如 ImageNet)上预训练的模型,迁移到自己的小数据任务上。
冻结策略有三种,按数据量选择:
| 数据量 | 策略 | 冻结范围 |
|---|---|---|
| 极少(< 100 张/类) | 只训分类头 | 冻结全部卷积层 |
| 少(100-1000 张/类) | 微调最后几层 | 冻结前 80% 卷积层 |
| 多(> 1000 张/类) | 全网络微调 | 不冻结,用小学习率 |
def setup_transfer_learning(model, num_classes, freeze_ratio=0.8): # 冻结前 freeze_ratio 的层 total_layers = len(list(model.parameters())) for i, param in enumerate(model.parameters()): if i < total_layers * freeze_ratio: param.requires_grad = False # 替换分类头 model.fc = nn.Linear(model.fc.in_features, num_classes) # 只优化需要梯度的参数,用更小学习率 optimizer = optim.Adam( filter(lambda p: p.requires_grad, model.parameters()), lr=1e-4 # 比从零训小一个数量级 ) return optimizer
⚠️ 常见坑:迁移学习时新分类头要用比预训练层更大的学习率。因为分类头是随机初始化的,需要快速收敛;预训练层已经很好了,大学习率会破坏已学特征。标准做法是分组学习率:分类头 1e-3,预训练层 1e-5。
图像生成是 CV 最迷人的方向。从 GAN 到 VAE 再到扩散模型,是一场代际更替。
GAN(生成对抗网络) 用博弈论思想训练:生成器造假,判别器辨真,两者对抗提升。生成器的目标是骗过判别器,判别器的目标是识破生成器。
GAN 的核心问题是训练不稳定——生成器和判别器要势均力敌,一旦一方过强,另一方就学不动。模式崩溃(mode collapse)是另一个顽疾:生成器只生成少数几种样本骗判别器,丢失了数据多样性。
VAE(变分自编码器) 用概率建模生成:编码器把图像映射到潜在分布,解码器从潜在分布重建图像。VAE 训练稳定但生成模糊。
扩散模型(Diffusion) 是当前的主流。它的思想是:前向过程逐步给图像加噪直到变成纯噪声,反向过程训练一个网络逐步去噪还原图像。
扩散模型为什么取代了 GAN?三个原因:训练更稳定(不用对抗,纯监督学习)、生成质量更高(Stable Diffusion、DALL-E 的效果有目共睹)、多样性更好(不会模式崩溃)。代价是采样慢(要迭代多步去噪),但通过 DDIM、一致性模型等加速技术,这个差距正在缩小。
CLIP 是多模态的里程碑。它用对比学习对齐图像和文本:训练时给一批图文对,让匹配的图文向量靠近、不匹配的远离。
# CLIP 对比学习的简化伪代码 def clip_contrastive_loss(image_features, text_features, temperature=0.07): # 归一化 image_features = image_features / image_features.norm(dim=-1, keepdim=True) text_features = text_features / text_features.norm(dim=-1, keepdim=True) # 相似度矩阵 logits = (image_features @ text_features.T) / temperature # 对称的交叉熵:图像找文本、文本找图像 labels = np.arange(len(image_features)) loss_i = cross_entropy(logits, labels) loss_t = cross_entropy(logits.T, labels) return (loss_i + loss_t) / 2
CLIP 的意义在于它把图像和文本映射到同一个向量空间,于是可以用文本检索图像、用图像生成描述、做零样本分类。后续的 DALL-E、Stable Diffusion 都基于 CLIP 的文本编码器做文本引导生成。
| 阶段 | 工具 | 关键优化 |
|---|---|---|
| 训练 | PyTorch | 混合精度、分布式 |
| 导出 | ONNX | 统一中间表示 |
| 推理优化 | TensorRT | 算子融合、INT8 量化、内核自动调优 |
| 服务化 | FastAPI / Triton | 批处理、动态 batching |
| 监控 | Prometheus + Grafana | 延迟、吞吐、精度衰退 |
基础增强(翻转、旋转)之外,Mixup 和 CutMix 是两个强有力的增强技术。
def cutmix(images, labels, alpha=1.0): lam = np.random.beta(alpha, alpha) rand_index = np.random.permutation(len(images)) # 随机裁剪区域 bbx1, bby1, bbx2, bby2 = rand_bbox(images.shape, lam) images[:, :, bbx1:bbx2, bby1:bby2] = images[rand_index, :, bbx1:bbx2, bby1:bby2] lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / images.shape[-1] / images.shape[-2]) return images, labels, labels[rand_index], lam
推理时对图像做多个增强(如四个方向的翻转),分别预测后取平均。这相当于集成,能稳定提升 1-2 个点的精度,代价是推理变慢。
模型上线后会面临数据漂移——真实数据的分布慢慢偏离训练集(比如自动驾驶遇到新季节的光照、新型号的车辆)。监控方案:
| 监控项 | 检测方法 | 触发动作 |
|---|---|---|
| 输入分布 | 特征统计量、KS 检验 | 告警,准备重训 |
| 预测分布 | 类别比例突变 | 检查输入异常 |
| 精度衰退 | 抽样人工标注评估 | 重训 |
| 延迟增加 | P99 延迟监控 | 排查资源或模型 |
💡 关键直觉:模型部署不是终点而是起点。一个好的 MLOps 流水线能让模型持续学习——监控发现漂移 → 自动采集新数据 → 触发重训 → 灰度发布新模型。面试时能讲清这套闭环,说明你理解"AI 系统是活的"。
移动端部署要在精度和资源之间反复权衡:
| 约束 | 优先方案 | 代价 |
|---|---|---|
| 模型大小 < 10MB | 量化 + MobileNet | 精度降 2-5% |
| 推理延迟 < 30ms | TensorRT + INT8 | 精度降 1-3% |
| 内存 < 100MB | 剪枝 + 蒸馏 | 精度降 3-8% |
| 无 GPU | 轻量化设计 | 任务范围受限 |
⚠️ 常见坑:量化后精度掉得多的层(如第一层、最后一层)可以保留 FP16,只对中间层量化,这种混合精度比全 INT8 精度好很多。
下一章转向自然语言处理,看深度学习如何从处理图像转向处理文本——词向量、序列模型、预训练语言模型构成了 NLP 的三大支柱。
面试官问"你做过什么项目"时,真正在评估的是你有没有走过从 demo 到上线的完整链路。很多候选人的项目停在"notebook 里跑通了",而对工程化环节一无所知。这一节补齐这条链路上每一步的考点。
第一步是数据管道。训练数据从哪来、怎么清洗、怎么划分,这三问里藏着一半的工程坑。典型陷阱包括:按时间顺序的数据被随机划分导致时间泄漏、训练集和测试集存在重复样本、标注质量没有抽检机制。面试时能主动讲"我们做了按时间的切分并且对标注做了双重抽检",立刻和只调过参的候选人拉开差距。
第二步是训练管理。实验可复现是底线:随机种子固定、配置文件版本化、每次实验的指标记录在案。进阶考点是超参搜索的策略选择——网格、随机、贝叶斯优化各适合什么场景(维度低用网格、维度高用随机、算力允许用贝叶斯)。这些细节体现的是"科学实验素养",算法岗面试里权重逐年上升。
第三步是模型压缩与部署,这是近年的必考题。四大件:量化(FP32 转 INT8,精度略降、体积和速度大幅优化)、剪枝(去掉冗余通道,结构化剪枝对硬件友好)、蒸馏(大模型教小模型,soft label 携带类间关系)、紧凑架构(MobileNet 系列的深度可分离卷积)。追问点在各方法的精度损失来源和组合顺序——通常先蒸馏再量化,量化感知训练比训后量化精度更好但成本更高。
第四步是上线后的监控。模型在真实数据分布上的表现会漂移,监控什么?输入分布(图片亮度、分辨率、类别比例)、输出分布(置信度直方图)、业务指标(准确率的代理指标)。发现漂移怎么办?重标注新数据、增量微调、必要时回滚。这部分内容多数候选人完全空白,你只要能讲出框架就赢了。
给一个具体的数字案例,感受工程权衡的真实质感。某工业质检项目:原始 ResNet50 在 GPU 服务器上单张 12ms,精度 99.2%;产线要求边缘设备上单张 30ms 内、精度不低于 98.5%。方案演进:直接换 MobileNetV3 精度掉到 97.8%,不达标;加蒸馏后恢复到 98.6%,勉强达标但置信度分布不稳;最后用 INT8 量化感知训练加输入分辨率从 448 降到 320,最终单张 21ms、精度 98.7%,满足全部约束且留了余量。
这个案例的面试价值在于每个决策都有因果:为什么不用 ResNet18(精度掉太多)、为什么蒸馏在量化前(量化误差叠加蒸馏误差会失控)、为什么降分辨率是最后的招(它同时改了数据分布,需要重训)。讲述自己的项目时套用这个"约束—尝试—失败—调整—达标"的结构,比平铺直叙"我们用了什么"有说服力得多。