
之前的方法主要基于softmax损失函数的改进,但训练大量人脸比较困难。
softmax损失中的负类在人脸表示中的重要性并不如想象中重要,文中为了softmax-based损失函数只随机采样了10%的类别,比全量训练精度并没有下降。
同时使用了高效分布式采样算法,同时考虑到模型精度与训练效率。
8张显卡完成1千万人的分类任务。
介绍
人脸识别学习过程中,单人的特征被映射到嵌入空间,基于欧几里得距离,属于同一个人的特征被拉到一起、属于不同人的被推开。
黄金法则就是,人越多,模型学习到的信息越多,区分这些特征的能力越强。
softmax及其变体用于人脸识别的目标函数,一般是在嵌入特征与线性变换矩阵的相乘过程中进行全局的特征到类别的比较。
有方法通过并行减轻GPU压力,很少的通信进行full-class softmax的计算;但人多到如1千万的数量级时,通过特征取类别的计算量(logits)还是不可忽视,分布式GPU的内存节约有瓶颈。GPU多了确可以解决权重矩阵的存储问题,但最后的logits还是给GPU新增负担。
文中提出一种高效人脸识别训练策略,用于超大人脸集。
- 首先在所有GPU上均匀按序存储softmax线性转换矩阵的不交叠子集。
- 每个GPU负责计算存储在自身的采样子矩阵和输入特征的点积的和。
- 每个GPU集结其他GPU的局部和,以近似full-class的softmax损失,通过少量的通信采样到局部和,以近似full-class的softmax。大大减少单块GPU的通信、计算和存储成本,效率提升好几倍。
Glint360K中含有干净的、合并了的现有公开人脸数据集,本文方法只需用10%的类别计算softmax,就与当前最好效果不相上下。
贡献:
- softmax近似算法,使用10%类别中心便可以维持准确度
- 高效分布式训练策略,很容易地用大数量类别来训练分类任务
- 干净合并后的公开数集,最大最干净的人脸数据集Glint360K,在此数据集训练、用此训练策略的基准模型达到最优效果轻而易举。
相关工作
1)人脸识别
深度神经网络在人脸识别领域越来越重要,pipeline一般是深度神经网络在给每个图像提取特征,学习过程就是逐渐减小类内距离、增大类间距离的过程。
目前有很多成功的softmax分类器及其变体,但人脸识别需要更大量的人脸。
基于softmax损失函数的方法中,人变多了,线性转换矩阵会线性增长,人多到一定程度则单卡无法承担这样的权重矩阵。
2)softmax加速
- 选active类中心构建随机hash森林,通过特征取出近似的最近类中心(但类中心放在RAM中,取特征的计算时间不容忽视)
- 将softmax损失分为类内和类间目标,减少类间目标的冗余计算(但对其他softmax-based损失不可拓展)
这些方法在多GPU训练时基于数据并行,GPU间通信代价高昂。ArcFace提出模型并行,将softmax权重矩阵分给不同的GPU,然后用很小代价计算full-class的softmax损失,其在单机上使用多卡很成功,但有内存限制——人多到一定程度,GPU内存消耗会到顶,尽管GPU数量多了也不行。
所以本文分析的是模型并行中的GPU内存使用。
方法
- 详述模型并行,分析其中设备间通信开销、存储代价和内存限制
- 不降性能的近似方法
- 分布式近似方法
1)模型并行
划分softmax权重矩阵为k个给不同的GPU,每个GPU集结其他的GPU的特征。
数据并行要传递权重矩阵梯度,但模型并行只要传达局部和,通信代价大小为batchsize*4(float32)。
通信和矩阵操作描述第i个GPU上的模型并行过程,包括前后向传播,大大减小GPU之间的通信。其中类别数C>>N*(k+1),N为每个GPU上mini-batch的大小。
2)模型并行的内存限制
不管C多大,因为模型并行完全可以解决权重的存储、传达问题,所以加GPU就可以了。
每个GPU存储子矩阵w的内存大小不变:
Mem_w = d*(C/k) *4 bytes
C变大,k也变大,此处C/k不变。
此外预测的logits也存在GPU上,logits = X*w
Mem_logits = N*k*(C/k)*4bytes
因此分类层占据的GPU内存表示为:
Men_FC = 3*Mem_w + 2*Mem_logits
如果每个GPU上mini-batch的大小为64且嵌入特征维度为512,则1百万分类任务需8个GPU,1千万则需至少80个,logits会花费w的10倍的内存,则使存储logits成为模型并行的新瓶颈(训练大量人脸并不仅仅增加GPU就可以)。
3)近似策略
-
正负类角色:
广泛使用的softmax分类损失:
x_i表示第i个样本的深度特征,属于y_i类,w_j表示权重矩阵W(R_{d*C})的第j列。
f_j表示带有w、b的全连接层的激活值,简便起见b设为1:
w和x都l2归一化后,预测值只取决于特征和权重之间的角度。
线性权重矩阵的每一列表示一个类中心,第j列表示第j类的类中心,x_i的正类中心是w_y_i,其他就是负类中心。
用类中心的子集来近似softmax:全部采样正类中心,随机采样负类中的10%,即正类加随机负类(PPRN)
训练时x_i和w_y_i之间的余弦距离的平均值CA_pcc:

实验表明,不采样正类中心,x_i梯度只会使样本远离负中心而不会考虑类内聚集的目标;
没有采样P_i时,和带有PPRN的采样策略P_i_{^}预测到的概率,在一定情况下很相似:


其中S表示采样到的类别集,r表示采样率。
PPRN不断优化正类中心,正类概率P_gt和采样到的类别和sum_P_j不断增大,训练后期,负类概率之间的gap越来越小,就是说,负类中心的方向、放大和采样率关系不大,采样率0.1、0.5、1.0结果相似。
-
分布式近似:
采样正类以及采样随机负类,可以达到与最优效果不相上下的结果。
为训练大量人脸,模型并行中,为平衡每个GPU的计算和存储开销,每个GPU上的类别中心个数应相等,采样过程如下:
【1】 获得该GPU上的正类中心
根据顺序均分W:
k是GPU个数,x_i样本的标签是y_i,其正类中心是W线性矩阵的第j列, 所以当前GPU上的正类中心集W_i_{p},很容易就从当前batch中特征的标签y得到。
【2】计算负类中心的个数
当前GPU存储的类中心个数为|w_i|, 正类就是|w_i_{p}|, 随机采样的负类中心的个数就是:

r就是PPRN采样率
【3】随机采样负类
在w_i和w_i_{p}之间差集中随机采样负类中心,得到负类中心为w_i_{n}:

将所有的类中心放到softmax计算中, W_{s}:

其中,W_{p} = [w_1_{p}, ..w_k_{p}], W_{n} = [w_1_{n}, .. w_k_{n} ].
W_{n}:
这种方法就是一种平衡每个GPU负载的近似算法。
参考:
paper: https://arxiv.org/pdf/2010.05222.pdf
code: https://github.com/deepinsight/insightface/tree/master/recognition/partial_fc#glint360k
网友评论