FaceNet解读整理


背景

论文地址:FaceNet: A Unified Embedding for Face Recognition and Clustering 
代码地址:GitHub(非官方) 

谷歌人脸检测算法,发表于 CVPR 2015,利用相同人脸在不同角度等姿态的照片下有高内聚性,不同人脸有低耦合性,提出使用 cnn + triplet mining 方法,在 LFW 数据集上准确度达到 99.63%,在 youtube 人脸数据集上准确度 95.12%,比以往准确度提升了将近 30%。

方法

通过 CNN 将人脸映射到欧式空间的特征向量上,计算不同图片人脸特征的距离,通过相同个体的人脸的距离,总是小于不同个体的人脸这一先验知识训练网络。 
测试时只需要计算人脸特征,然后计算距离使用阈值即可判定两张人脸照片是否属于相同的个体。

实现

Facenet的结构如下图:

前面就是一个传统的卷积神经网络,然后在求L2范数之前进行归一化,就建立了这个嵌入空间,最后损失函数。

  1. 对图片使用 CNN 网络提取特征向量。 
    1. 存在特征向量的维度选择问题,维度约小计算越快,但是太小的话很难区分不同图片;维度越大越容易区分不同图片,但是太大训练模型不易收敛,且测试时计算慢,占用空间大。作者实验证明 128 维的特征能够较好的平衡这个问题。
    2. CNN 模型的选择,高精度的模型往往参数多,计算量大。移动设备上最好使用体积小,精度略低的模型;服务器上可以使用高精度,高计算量的模型。
    3. 另外一点embeding这层实现方式就是linear,这点在论文上找了一会儿才找到,通过模型训练收敛得到一个合适的线性欧式向量提取器。
  2. 使用三元损失函数。 
    1. 之前的工作有人使用的是二元损失函数,二元损失函数的目标是把相同个体的人脸特征映射到空间中的相同点,而三元损失函数目标是映射到相同的区域,使得类内距离小于类间距离。 
      这里写图片描述
    2. 假设 x 是输入的图片,f(x)df(x)∈Rd 是 CNN 表示后的特征向量,三元函数为:

          

    3. ,所以最终的损失函数为:

  3. 可以看到上面的公式中需要三个输入人像,如何选择这一个三元组训练呢?为了保证训练收敛速度,我们就选择距离最远的相同人像,和距离最近的不同人像来训练好了。于是作者在每个 mini-batch 中进行上述选择。
  4. 卷积网络。选择模型是常见的问题,作者针对 ZF/GoogLeNet 做了不同的测试。
  5. 最终验证。通过计算不同图片的特征向量的距离,使用阈值后得到结果。

实验结果

不同的网络模型

这里写图片描述

不同的训练集合大小

这里写图片描述

不同的特征维度大小

这里写图片描述

不同图片质量

这里写图片描述

总结

  • 提取特征直接计算距离,比之前的使用 PCA + SVM 更加简单,训练的损失函数直接针对实际误差,end-to-end 方式训练都能提高精度
  • 只要有个人脸的 bounding box 就行