基于gluon的人脸识别算法工具包gluon-face


#1

使用gluon和mxnet作为主要试验和部署工具已经一年了,这么久以来在这个社区里学习到了很多东西,也拉了几个小伙伴入坑。最近几个人商量着也想搞一搞事情。受gluon-cv、gluon-nlp、gluon-reid、gluon-ranking的启发,我们干脆也做一个人脸识别专用的工具包吧。

先放项目地址:

为什么做FR

人脸识别已经是目前应用最广泛的一项AI技术,这个问题从deepfacetriplet loss开始,伴随着人脸数据集从数千张增长到百万级,再到现在主流公司几亿量级的训练数据,可以说已经在某种程度上被解决了。现在关于人脸识别的资源已经非常丰富,刚入门这一领域的研究者或工程师可以很容易找到大量相关的资料, 不过这些资料太分散不利于迅速验证。另外,很多研究还在基于caffe实现,目前最流行的insightface项目代码也是用mxnet symbol实现,研究和学习成本很高(当然, 我们的项目在很大程度上参考了这个项目,包括使用他们提供的clean dataset, :P)。因此,我们希望通过这个项目对人脸识别的资源进行整合,提供基于gluon-api的人脸识别算法,在锻炼个人能力的同时也为这个社区的繁荣做一些微不足道的工作:grimacing:

gluon-face有什么

  • 近年来主流人脸识别损失函数的实现,包括ArcLoss,TripletLoss,RingLoss,CosLoss,L2Softmax,ASoftmax,CenterLoss,ContrastiveLoss等, 并在今后会持续更新。
  • 基于gluon语法的数据读取和nvidia-dali库配合gluon的使用样例。
  • 1:1人脸验证metric。
  • 人脸识别pretrained model。

gluon-face使用

熟悉gluon的小伙伴可以无压力使用:

# 部分训练代码,完整请参考项目内的例子
train_set = get_recognition_dataset("emore", transform=transform_train)
train_data = DataLoader(train_set, batch_size, shuffle=True, num_workers=num_worker)
loss = ArcLoss(train_set.num_classes, s=64, m=0.5)

while it < iters:
 
    for batch in tqdm(train_data):
        if it == lr_steps[lr_counter]:
            trainer.set_learning_rate(trainer.learning_rate * 0.1)
            lr_counter += 1

        data = gluon.utils.split_and_load(batch[0], ctx_list=ctx, batch_axis=0, even_split=False)
        labels = gluon.utils.split_and_load(batch[1], ctx_list=ctx, batch_axis=0, even_split=False)

        with ag.record():
            outputs = [net(X)[1] for X in data]
            losses = [loss(yhat, y) for yhat, y in zip(outputs, labels)]
        for l in losses:
            ag.backward(l)
        trainer.step(batch_size)
        metric.update(labels, outputs)
        loss_mtc.update(0, losses)
        it += 1

Losses in gluon-fr

下表中最后一列是论文中在LFW上的最优结果,数据、网络结构都可能不同,仅供参考。

Method Paper Visualization of MNIST LFW
Contrastive Loss ContrastiveLoss - -
Triplet 1503.03832 - 99.63±0.09
Center Loss CenterLoss 99.28
L2-Softmax 1703.09507 - 99.33
A-Softmax 1704.08063 - 99.42
CosLoss/AMSoftmax 1801.05599/1801.05599 99.17
Arcloss 1801.07698 99.82
Ring loss 1803.00130 99.52
LGM Loss 1803.02988 99.20±0.03

Verification结果

我们目前所有结果都是在4*GTX1080上训练得到,由于训练资源有限,目前难以提供对paper最佳结果的完全复现。后续会争取更多的资源,参考1812.01187中的技巧重新训练,提供更多SOTA模型。

Network Loss Train Dataset Weight Norm Feature Norm Hyperparameter LFW Best Details
mobile-facenet ringloss emore Yes No lamda=0.01, lr=0.01, emb_size=512, batch_size=96*4 0.988167±0.006431 Initialize of R is important, it’s preferred to use a large value, like 20.
mobile-facenet arcloss emore Yes Yes lr=0.01, emb_size=512, s=32, m=0.5, batch_size=128*4 0.994667±0.004137 Finetune the model of ringloss with acc 0.988
se_resnet18L arcloss emore Yes Yes lr=0.1, emb_size=512, s=64, m=0.5, batch_size=128*4 0.992167±0.004947 Finetune the model of L2Loss with acc 0.655070
se_resnet50L arcloss emore Yes Yes lr=0.1, emb_size=512, s=64, m=0.5, batch_size=(32*4)*4 0.997000±0.002867 Finetune the model of L2Loss with acc 0.97
attention56-nobnp-relu arcloss emore Yes Yes lr=0.1, emb_size=256, s=64, m=0.5, batch_size=32*32 0.997000±0.002867 Finetune the model of L2Loss at iter 5000

除了LFW在其他1:1数据集的结果:

  • SE_LResnet50 with arcloss
Flip False True
lfw: 0.997000±0.002867 0.997167±0.002587
calfw: 0.957167±0.010410 0.977083±0.020488
cplfw: 0.914333±0.013421 0.955389±0.033797
cfp_fp: 0.968714±0.008438 0.955800±0.025998
agedb_30: 0.963167±0.008896 0.958387±0.023843
cfp_ff: 0.997429±0.002195 0.964105±0.025539
vgg2_fp: 0.951400±0.008002 0.962209±0.022288

TODO

  • 1812.01187 test in Gluon-fr.
  • More pretrained models
  • IJB and Megaface Results
  • Other losses
  • Dataloader for loss depand on how to provide batches like Triplet, ContrastiveLoss, RangeLoss…
  • Speaker Recognition based on deep features
  • Create hosted docs
  • Test module
  • Pypi package

Authors

@Kralkatorrik @PistonY @xhhyd123 @smartadpole

References

  1. MXNet Documentation and Tutorials,现在我们对这个框架很有感情:D,希望能够越来越好用。
  2. Deepinsight insightface 强烈感谢deepinsight在这一领域的贡献,我们学到了很多:P。
  3. NVIDIA DALI documentationNVIDIA DALI documentation, 这个库目前坑还比较深,期待nvidia开发者继续完善。
  4. Papers. 略。

#2

大型人脸识别翻车节目已经上线,前排出售花生瓜子,后排群众请不要乱扔西瓜皮,生鸡蛋等杂物.
:sneezing_face:


#4

手动赞!!
有个小建议,要不要考虑改个名字叫gluon-face之类的?fr感觉不是很容易让人想到是人脸识别


于全站置顶 #5

#6

太厉害了,给你们点赞


#9

大赞。同建议gluon-face,fr容易认为是法语。


#10

改成gluon-face包含的内容就要扩展到人脸检测、关键点、属性等一大堆内容了,压力好大:joy::joy:,我们可以先把repo名改了,里边的内容慢慢来


#12

我们大致做了1-2个月的项目,算是不小的项目了吧,付出了很大努力了,还算比较完善了吧.
后期主要是一些维护工作,bug的修复,以及把最主流的方法(Arcface)train到论文水平(只差一点点),和更多loss的训练结果.
喜欢的小伙伴点点赞呀~有各种代码或者疑问可以提出来一起讨论~~
哎呀~其实不管什么都可以出来瞎扯:rofl:,
也欢迎各路大神提出意见和建议~~:kissing_heart:


#13

手动点赞,:clap::clap::clap::clap::clap::clap:


#14

赞赞赞~


#15

谢谢,请问这项目日后是否会加入gluoncv的model zoo中?


#16

contribute to gluon-cv至少test module要写完,这个有点头疼,在Arcface SOTA之前可能不会研究这个东西,这是仅仅贡献ArcFace相关工作的前提,要是想整体合库,那恐怕遥遥无期了,坑还太多了,TODO还那么长:sob:


#17

:+1:赞,以后有时间想给你们pr!


#18

欢迎哈, 有什么想法可以一起讨论:grinning:


#19

手动点赞!


#20

贡献一个star:smile:


#21

浏览到了这里。哈哈哈,点赞:+1:


#22

可以共享一下训练log吗,用resnet100训练出现NaN


#23

我用arcloss训练的时候, 经常遇到这种情况, 暂时的解决方法是:

  1. 降低学习率从之前保存的参数开始继续训练
  2. 用一种比较稳定的损失函数(比如Softmax)做warmup的训练, 然后在网络收敛到一定程度后切换到arcloss.

一个参考的log文件log.zip (11.6 KB), 这个例子在训练时第二轮出现两次NaN, 然后用第一轮保存的参数继续训练, 第三次时正常收敛(所有参数都没修改). 猜测原因是loss本身不稳定, 或训练的batch size比较小.


#25

赞回复。看精度与insightface的结果还有差异,有改进计划吗?我看网络的实现与insightface有些不一致的地方。比如


self.features.add(nn.BatchNorm(scale=False, center=False))
insightface的center是True,且后面没有PReLU,我把center设置成True就比较容易出现NaN的问题。