2. 深度学习基础回顾:卷积神经网络(CNN)核心原理、激活函数、损失函数、优化器
做高准确率人脸比对,说白了就是让模型学会「看脸」。但模型不是天生就会看的,它得先理解什么是像素、什么是边缘、什么是五官。这一章,我们就把这些基础过一遍。嗯,都是后面实战的硬底子。
2.1 卷积神经网络(CNN)核心原理
CNN 为什么适合做图像?因为它有三大法宝:局部连接、权值共享、池化下采样。你想想看,一张人脸图几百个像素,如果用全连接网络,参数量直接爆炸。CNN 用一个滑动窗口(卷积核)扫过整张图,参数少得多,还能提取空间特征。
我个人习惯把 CNN 拆成四个阶段理解:
- 卷积层:提取局部特征,比如边缘、纹理、眼睛、鼻子。
- 激活层:引入非线性,让网络能拟合复杂函数。
- 池化层:降维,保留主要特征,减少计算量。
- 全连接层:把特征映射到输出空间,比如分类或特征向量。
我在项目中遇到过一个问题:人脸光照变化大,浅层卷积核根本学不到稳定特征。后来我加了 Batch Normalization,收敛速度快了一倍。这里先提一嘴,后面会细讲。
核心要点:CNN 通过堆叠卷积层,从低级边缘到高级语义逐层抽象。人脸比对模型通常用预训练的 CNN 骨干(如 ResNet、MobileNet)提取特征,再接入度量学习模块。
下面这张图,是我自己画的一个简化版 CNN 人脸特征提取流程:
2.2 激活函数:ReLU 与 PReLU
激活函数的作用,就是给网络「挠痒痒」,让它醒过来。没有激活函数,再多层也只是线性变换,白搭。
2.2.1 ReLU(Rectified Linear Unit)
公式很简单:f(x) = max(0, x)。正数保留,负数变零。优点很明显:计算快、梯度不饱和、收敛快。缺点呢?负数区域梯度为 0,神经元一旦「死掉」就再也活不过来。
避坑指南:我曾经在一个深层人脸模型里用了 ReLU,训练到一半 loss 不动了。查了半天,发现大量神经元输出恒为 0,死了。学习率调小后缓解了一些,但最终还是换成了 PReLU。
2.2.2 PReLU(Parametric ReLU)
PReLU 给负数区域加了一个可学习的斜率:f(x) = max(0, x) + a * min(0, x)。这里的 a 是网络自己学出来的,不是人工设定的。
| 激活函数 | 公式 | 优点 | 缺点 |
|---|---|---|---|
| ReLU | max(0, x) | 计算快、梯度不饱和 | 神经元死亡、负数无响应 |
| PReLU | max(0, x) + a·min(0, x) | 负数有梯度、自适应 | 参数略增、过拟合风险 |
我建议人脸比对模型优先用 PReLU。原因很简单:人脸特征有大量负值响应(比如对比度差异),ReLU 一刀切会丢掉信息。PReLU 让网络自己决定「负多少保留」,灵活得多。
2.3 损失函数:Softmax 与 Triplet Loss
损失函数是模型的「老师」。老师教得好不好,直接决定学生能不能认出人脸。
2.3.1 Softmax Loss(分类损失)
Softmax 把网络输出变成概率分布,然后用交叉熵衡量预测和真实标签的差距。公式不写了,你记住一句话:Softmax 让不同类别的人脸尽量分开。
但 Softmax 有个问题:它只要求类间可分,不要求类内紧凑。说白了,同一个人两张照片,Softmax 不关心它们是否靠近。这就导致人脸比对时,同一个人不同照片的特征向量可能距离很远。
小技巧:我在做人脸识别 baseline 时,先用 Softmax 训练一个分类模型,然后去掉最后一层,拿前面的特征向量做比对。效果还行,但远不如加 Triplet Loss 好。
2.3.2 Triplet Loss(三元组损失)
Triplet Loss 直接优化特征空间的距离。它每次取三张图:Anchor(锚点)、Positive(正样本)、Negative(负样本)。目标是让 Anchor 和 Positive 的距离小于 Anchor 和 Negative 的距离,而且要小一个 margin。
公式长这样:L = max(d(A,P) - d(A,N) + margin, 0)。
我刚开始用 Triplet Loss 时踩过一个坑:三元组选不好,模型学不动。全是简单三元组(正负样本差距很大),loss 一直为 0。后来我用了 难样本挖掘(Hard Mining),只选那些距离接近的正负样本对,训练才真正开始。
| 损失函数 | 优化目标 | 适用场景 | 注意事项 |
|---|---|---|---|
| Softmax Loss | 类间可分 | 分类任务、baseline | 类内不够紧凑 |
| Triplet Loss | 类内紧凑+类间分离 | 人脸比对、度量学习 | 需要难样本挖掘 |
2.4 优化器:SGD 与 Adam
优化器就是模型「下山的步伐」。步伐太大容易跳过最优解,太小又走不动。
2.4.1 SGD(随机梯度下降)
SGD 每次用一个 batch 的梯度更新参数。加上动量(Momentum)后,能加速收敛并减少震荡。我习惯用 SGD + Momentum,学习率设 0.1 起步,配合余弦退火调度。
优点:泛化能力强,最终收敛效果往往更好。缺点:对学习率敏感,调参麻烦。
2.4.2 Adam(自适应矩估计)
Adam 结合了动量和自适应学习率。每个参数有自己的学习率,前期收敛飞快。我刚开始做人脸模型时特别喜欢 Adam,因为不用怎么调参就能看到 loss 下降。
但 Adam 有个问题:后期可能不收敛,或者泛化能力不如 SGD。我在一个公开数据集上对比过,SGD 最终准确率比 Adam 高 0.5% 左右。
| 优化器 | 收敛速度 | 泛化能力 | 调参难度 | 推荐场景 |
|---|---|---|---|---|
| SGD+Momentum | 慢 | 强 | 高 | 大规模数据、最终模型 |
| Adam | 快 | 中等 | 低 | 快速实验、小数据集 |
我的建议:做人脸比对模型,前期用 Adam 快速找到合适参数,后期切 SGD 精调。我自己就是这么干的,效果比单用任何一个都好。
2.5 本章小结
这一章我们回顾了 CNN 的核心原理、激活函数、损失函数和优化器。这些东西看起来基础,但每一个都直接影响人脸比对的最终准确率。嗯,后面几章我们会把这些组件串起来,搭一个真正能用的高准确率人脸比对模型。