赞
踩
前言:
进入正题:
主要应用管道主要分为四部分,分别为帧捕获,人脸检测,人脸识别和用户交互与外部事件激活。
GAP8 SDK已经包含了一个摄像头驱动程序和一个用于静态图像和视频流捕获到L2内存的API。这就可以解释上面这幅图的具体意思:摄像机识别人脸,转换成二进制网络结构捕获到L2中识别,可以识别出正确存在于内存的人的信息同时也区别出陌生人,当然陌生人的面部信息也可以被User加入到内存中。(仅为自己理解)
作者从网络架构开始论述,为了适应L2内存大小,网络内存应该尽可能小,作者通过对比以下网络框架MobileNet v1/v2, ShuffleNet v1/v2, SqueezeNet 1.0和1.1如下图。(MFLOPs(每秒百万浮点指令)用128x128 RGB的输入计算)
SqueezeNet架构的另一个优点是没有残余连接。残余连接提供了具有更好训练能力的深度模型,但对于内存占用小的应用程序有一个主要缺点,残余连接的使用增加了(大部分时间翻倍)存储层激活所需的内存,从而增加了网络工作推断所需的内存。选择了SqueezeNet 1.1架构还有一个原因,引文它是最小、最简单的架构,因为它只包含3x3、1x1卷积、poolings和一个完全连接的层。
因为此应用是使用灰度相机,又由于使用的是彩色输入,于是我们在网络工作的开始添加了1个输入和3个输出通道的1x1卷积,以使用来自ImageNet数据的迁移学习。
使用VGGFace2数据集进行网络训练。LFW用于算法的验证。## 损失函数
使用XE + LS损耗函数训练的网络进行进一步的量化和移植过程。【标准交叉熵损失(XE)lift Structured loss (LS)】
在保证量化后精度尽可能减少的少的情况下作者保守的采用十六位量化。(因为量化比较显著的缺点是质量下降)
量化步骤如下:
估计用于存储输入、输出特征映射的整数部分的比特数,以及每个卷积的权值张量,通过网络对一些数据进行推理,估计每个张量的最大绝对值。如果我们有X张量,X张量的最大绝对值是Xmax,那么我们需要[log2 Xmax]位来存储X张量的整数部分。
让我们将存储输入、输出特征映射的整数部分和卷积层的权值张量的比特数表示为IN int, OUTint, W int。
如果我们有N位来存储激活值和权重值,并且N个int位用于整数部分,那么我们有以下位数用于分数部分:
有符号数
无符号数
我们假设使用带符号的数字,并将输入、输出特征映射和权重张量的分数位表示为IN frac、OUTfrac、Wf rac。
下一步是量化卷积权值和偏差为N定点值。
比如对于卷积层权重,我们做如下式子:
输入张量与权值进行卷积后,再将卷积偏差加到输出张量中,卷积偏差应该具有与输出相同的分数位数:B frac =OUT frac
下一步是选择卷积的范数参数,需要注意:我们不能失去一个数字的高阶,应该保留尽可能多的最低有效位。
第一步是估计存储输出激活结果的比特数:
然后
此时还需解决32位累加器的溢出问题;
累加器的分数位:
累加器整数位:
判断(各个数前面都已经定义过 )
如果不满足此条件,则溢出,应减少分数部分。作者使用的方法是减少卷积权重的分数位的数量(怪不得作者说最简单的方法,确实是容易理解,若是溢出,则权重直接减去超出小数部分):
确保仿真结果与主板结果相差不超过最后一位,因为pytorch的舍入操作有所偏差,所以这个准确率误差作者可以接受。
作者提出了不同的想法,通常,数据归一化用于预处理图像,作者建议取消这些计算。这样我们就有了量化的网络输入,减少了图像预处理的操作。卷积运算包括两种运算:带权值的输入卷积和偏置相加(线性运算),故而有了下面的操作链:
最后一个公式等于非标准化输入与
的卷积再加上个
(从表三中看出这个操作并不影响质量,表4显示了浮点PyTorch模型和在PC上进行卷积仿真的量化模型的精度值。精度只下降了0.0005)
此外,我们还确定了不同方面如何影响我们算法的质量:bounding box origination(B)(我更倾向于理解为边界框大小)、 face alignment(A)、量化(Q)和人脸识别网络运行的设备。
结果表明,bounding box origination和face alignment严重影响度量,同时量化对质量的影响很小(如下表)。
作者结论:我们的量化模型在PC上的质量比通常的PyTorch模型高0.0007。最后,我们使用在目标设备上计算的嵌入物来测量质量。图表显示移植后我们的质量只比非量化模型差0.0023。(移植后精度下降0.0023算是一个很可以的一个范围了,这是作者保守的使用16位量化)
包括以下几个部分:数据转换为合适的布局;DNN模型实现与现有GAP8 SDK原语操作融合;内存布局优化;与现有组件集成,如人脸检测;
(移植过程表明,L2利用率是应用程序最重要的瓶颈。)
提升L2的利用率可以从多方面入手,作者简述了一个例子:人脸检测和人脸识别不是同时执行,应用程序可以重用相同的内存缓冲区,从而减少L2占用。
作者初步研究时是发现512kib的L2肯定是不足以存储所有数据,实现这一目标的唯一方法是将权重存储在外部L3内存中,并在每层推理之前下载到L2内存中。不仅仅是权重、激活值,还有推理用到的各个数据,由于内存资源非常有限,作者找到的唯一解决方案是在每一层的连续内存池之上分配静态编译时缓冲区,并在接下来的步骤中考虑层输出的使用情况,这种解决方案需要对不同的网络子图进行推理图分析和不同的技术。
然后作者详细介绍了两种内存管理方式L:层的线性链、SqueezeNet Fire模块。分别如下图:
其中第i层的输出被用作第i+1层的输入,对于这种情况,应用了带有浮动边界的两个缓冲区链.输入和输出从内存池开始分配,并从浮动边界开始分配。选择浮动边界地址以适应当前层的输入和下一层的输出,不重新分配已经计算的数据,实现释放连续内存缓冲区。第二个缓冲区后的内存块用作外部L3内存的重量和偏置加载区域。Border地址由式(12)计算。
该模块由挤压卷积和两个使用挤压运算的卷积组成输入。两个扩展卷积的结果被连接起来,并且必须在扩展的两个阶段都被存储在L2的连续缓冲区中。带有浮动内存边界的方法也可以适用于Fire模块,但它包括三层,而不是之前的两层。
该图说明了如何使用缓冲区的左侧部分作为挤压输入,并将其作为展开层的连接位置。缓冲区的右侧既是挤压层的输出,又是展开层的输入,不能作为中间数据丢弃。边界地址由表单计算:
通过使用两种内存管理方法,我们可以估计每层网络工作推断所需的最小L2缓冲区大小,而不需要内存移动和与外部内存之间的日期数据交换。最大的内存使用量是由架构中的前两个卷积和所有Fire模块消耗的。内存消耗的统计数据如下:
作者非常合理的进行了重用其他部分和内存缓冲区,这一部分解释了缓冲区的使用与各个模块之间的重用才达到它本身的目的!512kib RAM足矣(详细请看原文6.3部分)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。