Android制造 FaceID [FaceNet + MobileNet]

1. Abstract

好久没有在简书上写文章,最近在弄关于人脸识别的内容和研读一些论文。碰巧Apple的新iPhone X搭配了Face ID进行刷脸,我有一个想法,给Android做一个类似的Face ID。我这里主要使用2015年Google发的一篇论文FaceNet: A Unified Embedding for Face Recognition and Clustering 和2017年Google发布的一个MobileNet模型MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

2. Method and Related Work

2.1. FaceNet

FaceNet是一个Face identification的训练模型。我认为其最大的不同是损失函数。在我现阶段的知识范畴里面,Face Recognition通常的训练方法是利用softmax函数做分类,然后用cross_entropy作为损失函数(使用max likelihood)。然而在Face identification中是不太符合的,因为我们需要的判断两张脸是否相同,而不是判断这个脸的类别,因此我们需要计算两张脸之间的相似度,通过给定的threshold判断是否为同一个人。这才是identification的需要。

2.1.1 Triplet Loss

triplet loss就是代替我们熟悉的cross_entropy损失函数,作为训练网络模型的损失函数。我们组织三元组(anchor, positive, negative)作为一个样本,其中anchor为基准人脸图片,positive与anchor都是同一个人的图片,negative与anchor不是同一人的照片。我们希望anchor与positive的距离小于anchor与negative的距离。

《Android制造 FaceID [FaceNet + MobileNet]》 anchor与positive的距离小于anchor与negative的距离

这里的alpha是一个positive距离和negative距离之间margin。因此我们有这样一个损失函数:

《Android制造 FaceID [FaceNet + MobileNet]》 Triplet Loss

若 anchor和positive的距离 + alpha值 <= anchor和negative的距离,Triplet Loss就为正,若大于alpha值Triplet Loss为0。

《Android制造 FaceID [FaceNet + MobileNet]》 Triplet learning

这是Triplet Loss学习的目标,anchor作为标准,positive与anchor是同类,negative与anchor不同。简单来说,我们尽可能让negative远离anchor,让positive靠近anchor。

2.1.2 Triplet Selection

对于Triplet Loss这个损失函数,我们需要选择一个合理的三元组。假如我们选择一个满足损失函数的三元组,那么Triplet Loss总是为0而且其梯度也是为0。因此我们需要选择一个违背Triplet Loss的三元组进行训练,这样才有意义。那么我就选择一组 anchor与negative的距离 – anchor与positive的距离 < alpha。选择步骤如下:

  1. 我们选择anchor和positive应该是针对有多张人脸照片的人,在这个人的人脸照片中两两组合成为<anchor, positive>的二元组
  2. 根据选择好的<anchor, positive>的二元组后,我们计算其他照片与<anchor, positive>差距小于alpha的negative。由于每pair <anchor, positive>都可能存在多个negative照片。我们每次随机选取一个negative组成<anchor, positive, negative>,因为可以保证我们尽可能学习每一张图片避免了poor training。
  3. 对于以上步骤我们在每一个mini batch的时候需要重新计算一次,因为这种组成<anchor, positive, negative>是很多的。假如有100个人,每个人有平均有4张照片,我们起码有100 * 4 * 3 / 2 = 600个。这是很不适合一次性计算全局所有的triplet sample。因此我们每次从不同人取照片样本和学习完一遍triplet sample时,应该重新计算获得triplet sample。这样才有机会学习不同的triplet sample。

2.2 MoblieNet

MoblieNet是Google今年4月出的内容,它是对CNNs在尽可能减少其准确率的情况下去缩减模型的MFLOPs和Million parameters。其当中主要的方法有两个:

  • 1 x 1 convolution
  • depthwise convolution
    其实这两个不是什么新的东西,在Inception v1 到 v4都有出现过。但是没想到两者结合可以如此有效。

《Android制造 FaceID [FaceNet + MobileNet]》 Depthwise + Pointwise

假设输入数据大小为D_F × D_F × M,而最后需要输出是大小为D_F × D_F × N。如上图,标准的卷积操作需要运算时间大约是:

《Android制造 FaceID [FaceNet + MobileNet]》 standard convolutions have the computational cost

而在MobileNet中,我们先对数据进行depthwise convolution操作,所谓的depthwise convolution就是有M个D_K × D_K × 1的filter对输入对应的channel进行卷积操作,如下图:

《Android制造 FaceID [FaceNet + MobileNet]》 Depthwise convolution

最后得到一个D_F × D_F × M features map。
接下来我们就对depthwise convolution操作后得到的features map进行一个1 x 1的卷积操作,每个filter kernel的大小为1 x 1 x M一共N这个的kernel。最后我们就得到一个大小为D_F × D_F × N的features map。

与标准卷积操作得到相同大小的features map,但是计算复杂度为:

《Android制造 FaceID [FaceNet + MobileNet]》 depthwise convolutions + pointwise convolution

第一项是depthwise conv的计算复杂度,第二项是pointwise conv的计算复杂度。对比起标准的卷积操作,我们需要的浮点计算量和参数存取容量少了很多:

《Android制造 FaceID [FaceNet + MobileNet]》 浮点运算量对比
《Android制造 FaceID [FaceNet + MobileNet]》 左图是标准卷积后再进行Batch Normal和ReLu操作,右图是没进行一次卷积都进行Batch Normal和ReLu操作

按照论文里面说:理论上,相比于标准卷积操作少8到9倍的运算量,足够在移动设备上面运行。但作者认为还可以再继续把运算量降下去,那就是使用Width Multiplier。所谓的width multiplier,就是一个标量乘子,它的目的是减少每层channel的数量。本来该层有64 channels,而我们设置的width multiplier为0.5,那么该层有32 channels,但同时模型的精确度也会相应的降低。

在github上面我们可以找到mobileNet用tensorflow的实现:https://github.com/Zehaos/MobileNet

《Android制造 FaceID [FaceNet + MobileNet]》 这是MobileNet对不同年份ImageNet winner进行对比

我们可以看到当MobileNet的width multiplier为1且image大小为224 x 224时,其得分超越了GoogleNet。那是多么振奋人心的事情。

3. IDea

其实很明显我们就是用FaceNet的tripletloss作为损失函数,用MobileNet作为CNNs模型进行训练,最后嵌入到android手机上。而Face detection我们使用android sdk上面的FaceDetectionListener来进行人脸检测。获取到最主要Face(可以采用面积最大作为主要主要的Face)的矩阵我们进行一些对齐操作以后,我们就可以放入网络当中获得该脸的embedding向量。在录入Face ID信息时(也就是获取embedding向量时),我们需要多次录入同一个脸的信息,因为多个embedding我们可以增加判断的鲁棒性,或者你对这些embedding求一个平均值来作为最终的Face ID,当然这只是一个baseline啦。要记住以防那些搞事的人用不同的人脸录入信息,我们需要在每次录入后判断该次录入脸部信息(embedding向量)与之前几次的embedding向量的欧式距离是否小于某一个threshold。好啦,最后我们就是在解锁时候,获取主要人物的脸部图片求出对应的embedding向量再与录入时的embedding算他们之间欧式距离是否小于某一个threshold值,若小于我们可以判断该人是同一个人,解锁,否则相反。

4. Conclusion

在MobileNet的论文当中,我们可以看到作者也把MobileNet融入到FaceNet进行训练,相对于苹果iPhone X而言,Google早已对移动设备进行Face identification做好了准备。其结果如下:

《Android制造 FaceID [FaceNet + MobileNet]》 MobileNet 在FaceNet当中的效果

其实MobileNet是17年4月份的产物,相对比较新的是Face++的shuffleNet。它是基于MobileNet的一个移动设备上面的CNNs,无论模型的浮点运算量还是在ImageNet上面的准确率都比MobileNet更胜一筹。shuffleNet加入的group操作后使得卷积操作更加快和轻,这里我就不详细解释啦,毕竟我还没认真看,我总结完的话有机会跟大家分享一下。

很抱歉,因为我个人时间和能力有限,仅仅用LFW的数据集对MobileNet的模型进行训练,但还没融入到android手机上面。可能我们还需一些时间去学习和完成相关的android代码。假如我写出来希望能分享给各位。

5. References

6. Thank

好了, 感谢大家的收看吧。差不多要睡觉啦!早唞!好梦!

    原文作者:Salon_sai
    原文地址: https://www.jianshu.com/p/62514315757f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞