如何使用InsightFace做人脸识别训练?

什么是 InsightFace

InsightFace 是一个与人脸检测、人脸识别有关的工具箱。已经被封装好 Python Package,达到了开箱即用的效果。其上层接口可以直接做人脸检测、性别判断等。其底层实现其实是训练好的各类模型。

OneFlow 提供的模型是 InsightFace 项目的后端之一。

关于 InsightFace 的推理效果展示,可以参考 OneFlow 云平台上的项目 人脸识别权限系统演示

本项目主要介绍与超大规模人脸识别训练有关的原理和技术实践。

如何使用该项目

首先,需要注册OneFlow云平台的账号,进入本项目并 “Fork” 。然后点击“运行”,连接容器,运行以下命令。

cd /workspace && bash ./train_graph_distributed.sh
复制代码

会有类似如下输出,分别包含了:

  • 训练的基本配置
Training: 2021-12-14 14:49:44,690-rank_id: 0
Training: 2021-12-14 14:49:44,720-: loss                     cosface
Training: 2021-12-14 14:49:44,720-: network                  r50
Training: 2021-12-14 14:49:44,720-: resume                   False
Training: 2021-12-14 14:49:44,720-: output                   model
Training: 2021-12-14 14:49:44,720-: dataset                  ms1m-retinaface-t1
Training: 2021-12-14 14:49:44,720-: embedding_size           512
Training: 2021-12-14 14:49:44,721-: fp16                     True
Training: 2021-12-14 14:49:44,721-: model_parallel           True
Training: 2021-12-14 14:49:44,721-: sample_rate              0.1
Training: 2021-12-14 14:49:44,721-: partial_fc               0
Training: 2021-12-14 14:49:44,721-: graph                    True
Training: 2021-12-14 14:49:44,721-: synthetic                False
Training: 2021-12-14 14:49:44,721-: scale_grad               False
Training: 2021-12-14 14:49:44,721-: momentum                 0.9
Training: 2021-12-14 14:49:44,721-: weight_decay             0.0005
Training: 2021-12-14 14:49:44,722-: batch_size               128
Training: 2021-12-14 14:49:44,722-: lr                       0.1
Training: 2021-12-14 14:49:44,722-: val_image_num            {'lfw': 12000, 'cfp_fp': 14000, 'agedb_30': 12000}
Training: 2021-12-14 14:49:44,722-: ofrecord_path            /dataset/18fad635/v1/ofrecord
Training: 2021-12-14 14:49:44,722-: num_classes              93432
Training: 2021-12-14 14:49:44,722-: num_image                5179510
Training: 2021-12-14 14:49:44,722-: num_epoch                25
Training: 2021-12-14 14:49:44,722-: warmup_epoch             -1
Training: 2021-12-14 14:49:44,722-: decay_epoch              [10, 16, 22]
Training: 2021-12-14 14:49:44,723-: val_targets              ['lfw', 'cfp_fp', 'agedb_30']
Training: 2021-12-14 14:49:44,723-: ofrecord_part_num        32
复制代码
  • 加载验证集数据的日志
Training: 2021-12-14 14:49:50,124-loading bin:0
Training: 2021-12-14 14:49:51,372-loading bin:1000
Training: 2021-12-14 14:49:52,649-loading bin:2000
Training: 2021-12-14 14:50:17,039-loading bin:9000
Training: 2021-12-14 14:50:18,300-loading bin:10000
Training: 2021-12-14 14:50:19,576-loading bin:11000
Training: 2021-12-14 14:50:20,839-loading bin:12000
Training: 2021-12-14 14:50:22,099-loading bin:13000
Training: 2021-12-14 14:50:23,353-oneflow.Size([14000, 3, 112, 112])
Training: 2021-12-14 14:50:23,709-loading bin:0
Training: 2021-12-14 14:50:24,991-loading bin:1000
Training: 2021-12-14 14:50:26,292-loading bin:2000
Training: 2021-12-14 14:50:27,590-loading bin:3000
Training: 2021-12-14 14:50:28,886-loading bin:4000
Training: 2021-12-14 14:50:30,174-loading bin:5000
Training: 2021-12-14 14:50:31,463-loading bin:6000
Training: 2021-12-14 14:50:32,744-loading bin:7000
Training: 2021-12-14 14:50:34,029-loading bin:8000
Training: 2021-12-14 14:50:35,315-loading bin:9000
Training: 2021-12-14 14:50:36,593-loading bin:10000
Training: 2021-12-14 14:50:37,867-loading bin:11000
Training: 2021-12-14 14:50:39,144-oneflow.Size([12000, 3, 112, 112])
复制代码
  • 训练时的基本信息(速度、loss 变化、预估剩余时间等)
Training: 2021-12-14 14:51:02,452-Speed 883.82 samples/sec   Loss 52.6974   LearningRate 0.1000   Epoch: 0   Global Step: 100   Required: 202 hours
Training: 2021-12-14 14:51:09,722-Speed 880.33 samples/sec   Loss 53.4146   LearningRate 0.1000   Epoch: 0   Global Step: 150   Required: 149 hours
Training: 2021-12-14 14:51:16,968-Speed 883.24 samples/sec   Loss 51.8446   LearningRate 0.1000   Epoch: 0   Global Step: 200   Required: 122 hours
Training: 2021-12-14 14:51:24,237-Speed 880.57 samples/sec   Loss 50.9537   LearningRate 0.1000   Epoch: 0   Global Step: 250   Required: 106 hours
Training: 2021-12-14 14:51:31,526-Speed 877.99 samples/sec   Loss 50.5335   LearningRate 0.1000   Epoch: 0   Global Step: 300   Required: 95 hours
Training: 2021-12-14 14:51:38,831-Speed 876.17 samples/sec   Loss 49.6624   LearningRate 0.1000   Epoch: 0   Global Step: 350   Required: 87 hours
Training: 2021-12-14 14:51:46,151-Speed 874.42 samples/sec   Loss 48.9462   LearningRate 0.1000   Epoch: 0   Global Step: 400   Required: 82 hours
Training: 2021-12-14 14:51:53,476-Speed 873.76 samples/sec   Loss 48.3082   LearningRate 0.1000   Epoch: 0   Global Step: 450   Required: 77 hours
Training: 2021-12-14 14:52:00,810-Speed 872.72 samples/sec   Loss 48.0000   LearningRate 0.1000   Epoch: 0   Global Step: 500   Required: 73 hours
复制代码

其中剩余时间一项,开始阶段会有短暂的波动,属于正常现象。会随着静态图构图完成,逐渐稳定、准确。 训练完成后,训练日志和模型保存在 /workspace/model/下面。

人脸识别训练的技术演变

在深度学习领域,被大家最为津津乐道的一个故事,是Hiton 在神经网络遇冷期,坚守数十年,终于在2012年,带领学生携 AlexNet,参加了 Imagnet 的图像识别比赛,一举夺冠,并且准确率比同行一下高出好几个百分点,从此开启了深度学习的时代。

深度学习主要特点,就是利用深度神经网络,作为特征提取器,进行端到端的特征提取,取代了传统机器学习中需要严重依赖人工设计特征提取规则的方法。

基于深度学习的人脸识别,也从2014年 DeepID(CVPR 2014) 将卷积神经网络引入人脸识别的算法开始,到2019年的 InsightFace,基本趋于成熟。

深度学习的过程,直观地理解是通过损失函数作为优化目标,然后通过迭代式的优化方法,比如我们熟知的梯度下降法,指导模型从大数据中发现规律,并将学习到的经验沉淀到神经网络的参数上面。

人脸识别模型多使用卷积神经网络,尤其是2015年出现的 ResNet,在图像领域的有着非常优秀表现,因此,近年来,人脸识别在模型上的创新不多,基本上都是基于卷积神经网络。人脸识别技术的创新,很大程度上,是损失函数的创新。

从普通常见的 Softmax Loss 到 InsightFace 所使用的 ArcFace Loss,演变过程如下图所示:

image.png

在本项目中,主要实现了cosface 和arcface两种最常用的 loss,代码如下,oneflow原生接口支持用房方便的设置m1、m2和m3:

# loss
if cfg.loss == "cosface":
    self.margin_softmax = flow.nn.CombinedMarginLoss(1, 0., 0.4).to("cuda")
else:
    self.margin_softmax = flow.nn.CombinedMarginLoss(1, 0.5, 0.).to("cuda")
复制代码

它对应的数学公式是:

image.png

OneFlow 如何简单优雅地解决超大规模人脸识别训练难题

工业界的实际应用中,遇到的人脸ID规模,可能是上千万、上亿级别的,这时候,单机单卡无法完成训练。 通常框架支持的成熟并行方案只有数据并行,简单的数据并行,也是无法高效支持超大规模人脸识别训练的。

关于分布式训练的常见策略,和相关基础知识,可以参考 常见的分布式并行策略

超大规模人脸识别的训练模型的特点是:

  1. 最后的全连接层计算量巨大,占用较高的显存
  2. 作为特征提取器的前半部分的卷积神经网络并不算很大

这样的特点使得它既不适合用纯数据并行,也不适合用纯模型并行,而是适合使用混合并行:作为特征提取器的卷积网络使用数据并行,全连接层用模型并行,这样效率是最高的。oneflow还原生接口支持Partial FC,可以进一步降低全连接层的计算量,极大的降低显存的占用。oneflow优化实现的并行Softmax可以进一步加快训练速度,原理实现介绍:如何实现一个高效的Softmax CUDA kernel

本项目中的相关实现:

#function.py line :118
self.backbone = backbone.to_consistent(placement=placement, sbp=flow.sbp.broadcast)
复制代码

以上代码让作为特征提取器的卷积网络,做数据并行训练。

#function.py line :110~117
if cfg.model_parallel:
    input_size = cfg.embedding_size
    output_size = int(cfg.num_classes/world_size)
    self.fc = FC7(input_size, output_size, cfg, partial_fc=cfg.partial_fc).to_consistent(
    placement=placement, sbp=flow.sbp.split(0))
else:
    self.fc = FC7(cfg.embedding_size, cfg.num_classes, cfg).to_consistent(
    placement=placement, sbp=flow.sbp.broadcast)
复制代码

以上代码,让全连接层做模型并行训练。

其它的通信、调度、同步等统统交给 OneFlow 高效完成。

更多详细内容,请看我们的官方教程:InsightFace 从青铜到王者

おすすめ

転載: juejin.im/post/7044793131161616391