SSD介绍SSD(SingleShotMultiBoxDetector)于2016年提出,是经典的单级目标检测模型之一。其精度与Fasterrcnn两阶段目标检测方法相当,但速度达到59FPS(512x512,TitanV)。SSD速度更快的主要原因是它消除了候选边界框以及特征上采样过程。它也存在一些缺点,如对小目标检测不佳、定位不准确等。但它各方面的优势都足以让它成为经典的目标检测模型。下面介绍一下SSD的原理。SSD网络结构下图是SSD的整体结构。整个网络是全卷积网络结构,骨干网采用VGG16网络。SSD将backbone中的fc6改为3*3的卷积层,fc7改为1*1的卷积层,pooling层pool5由原来的2*2stride=2变为3*3stride=1。为了不改变featuremap的大小,获得更大的感受野,Conv6是dilation=6的空心卷积。在主干之后,添加了8个卷积层(ExtraFeatureLayers)。网络中一共有6个卷积层(Conv4_3、Conv7、Conv8_2、Conv9_2、Conv10_2、Conv11_2)特征图用于检测,这6个特征图预测不同尺寸(scale)和纵横比(ratios)框的边界。SSD为每个检测层预定义了不同大小的先验框。Conv4_3、Conv10_2和Conv11_2分别有4种先验框,而Conv7、Conv8_2和Conv9_2分别有6种先验框,即对应特征图上的每个像素点,生成K(先验框类型)个先验框。priorbox类似于Fasterrcnn中的anchor。网络6个检测层预测的边界框总数为8732(38*38*4+19*19*6+10*10*6+5*5*6+3*3*4+1*1*4)。下图详细展示了SSD的各个模块。整个SSD网络可以分为主干、额外和头部模块。头部模块包含检测器(用于定位)和分类器(用于分类)。Detector和Classfier对每个featuremap使用不同的3*3卷积核进行预测,卷积核的数量由每个featuremap上定义的priorsbox类型决定。例如Conv4_3输出的featuremap定义了4种priorbox,那么Detector得到的featuremap通道数为4*4,Classifier得到的featuremap通道数为4*21(voc类别数,包括背景)。Detector输出每个priorbox的坐标偏移量,Classifier输出每个类的类别概率得分。网络输入大小为300*300,数据集使用Voc数据集(20类)。网络训练先验帧的匹配过程在目标检测任务中,通常会产生大量的先验帧,网络会对所有先验帧产生相应的坐标偏移量,因此网络在计算定位误差时必须知道groundtruth与每个先前框相对应的框。匹配条件1,对于每个真实帧,找到IOU最大的先验帧,保证每个真实帧都有一个先验帧负责检测它。通常情况下,网络生成的先验框的数量远大于真实框的数量。如果只按照策略1进行匹配,大量与真实框不匹配的先验框将被标记为背景,那么这将导致类别严重不平衡。这时候还需要第二个条件。对于其余未匹配的先验帧,如果存在真实帧且其IOU大于某个阈值(一般为0.5),则真实帧也将与之匹配。一般情况下,每个ground-truthbox会同时匹配多个prioribox,每个prioribox只能匹配一个ground-truthbox。匹配过程需要先满足第一个条件,再满足第二个条件。即使每个真实帧可以同时与多个先验帧匹配,背景先验帧的数量仍然明显大于对象先验帧的数量。因此,论文也采用了Hardnegativemining的策略,根据先验框的类别置信度误差从高到低排序,只选取top_k个先验框作为训练背景先验框(采样背景先验框frame),最终的正负样本比例约为1:3。损失函数SSD的损失函数是多任务损失函数,包括定位损失和分类损失。如下图所示,N代表匹配先验帧的个数,α为权重项,平衡分类和定位损失,通过交叉验证设置为1。$$L(x,c,l,g)=\frac{1}{N}(L_{conf}(x,c)+\alphaL_{loc}(x,l,g))$$定位误差和fasterrcnn一样,也使用了SmoothL1error。l是预测坐标,d是先验帧,g是真实帧。分类误差使用多类交叉熵误差。$$L_{conf}=-\sum_{i\inPos}^Nx_{ij}^plog(\hat{c_i}^p)-\sum_{i\inNeg}log(\hat{c_i}^0)\quadwhere\quad\hat{c_i}^p=\frac{exp(c_i^p)}{\sum_pexp(c_i^p)}$$需要注意的是只有正样本才需要计算定位误差。使用未解码的预测坐标和编码的地面实况坐标计算定位误差。下图展示了boundingbox的解码过程(decode)。(tx,ty,tw,th)是预测的边界框坐标,(px,py,pw,ph)是先验框,(x,y,w,h)是预测的边界框。解码过程还使用Viriance参数。$$\begin{cases}x=p_w+t_x*p_x*Viriance[0]\\y=p_h+t_y*p_y\timesViriance[0]\\w=??exp(t_w*Viriance[1])*p_w\\h=exp(t_h*Viriance[1])*p_h\end{cases}$$OthertricksL2Norm层Conv4_3是检测的第一个featuremap。由于这个featuremap的范数比较大,所以在Conv4_3之后增加了一个L2_Norm层,将featuremap上每个位置的featurenorm缩放到20,这个缩放参数是在反向传播的时候学习到的。这是为了保证和后面的featuremap不会有太大的差异。L2范数与BatchNorm不同。BatchNorm在三个维度(通道、宽度、高度)进行归一化,而L2Norm只在通道维度进行归一化。classL2Norm(nn.Module):"""不像batchnorm在宽度、高度和通道3维度上归一化,l2norm只是在通道维度上归一化Params:channels:输入特征图的通道scales:初始比例参数,它将通过梯度学习descent"""def__init__(self,channels,scales):super(L2Norm,self).__init__()自我。channels=channels#gamma是网络自我学习的参数。gamma=尺度或无自我。eps=1e-10#通道维度的归一化self.weights=nn.Parameter(t.Tensor(self.channels))nn.init.constant_(self.weights,self.gamma)defforward(self,x):norm=x.pow(2).sum(dim=1,keepdim=True).sqrt()+self.epsx=t.div(x,norm)out=self.weights.view(1,-1,1,1).expand_as(x)*xreturnoutPriorbox的选择前面已经说过了,六个检测层的featuremaps定义了不同的priorboxes,那么这些priorboxes的size和aspectratios是怎么得到的呢?六个特征图的维度分别为(38,19,10,5,3,1),它们对应的priorframesize随着featuremap$$s_k=s_{min}+\frac{s_{max}-s_{min}}{m-1}(k-1)的收缩线性增加,k\in[1,m]$$m表示特征图的个数,m=5(不包括Conv4_3),Sk表示先验帧尺寸与图片尺寸的比值,Smin表示最小比值,设为0.2,Smax表示最大比值,设为0.9。对于第一个featuremapConv4_3,单独设置scale为Smin/2=0.1,对应的size为300*0.1=30。对于后面的featuremaps,priorframe的size按照上面的公式线性增加,但尺度需要扩大100倍:$$s_k=s_{min}*100+\frac{s_{max}*100-s_{min}*100}{m-1}(k-1),k\in[1,m]$$这样计算出来的step=(90-20)/(5-1)=17.5,因为像素点已经是最小的单位了,无法再进一步划分,需要步长进行四舍五入,step=17,从而得到第二层之后Sk*100=(20,37,54,71,88),再除以100得到一组近似的缩放比例(0.1,0.2,0.37,0.54,0.71,0.88),用这组缩放比例计算先验框的大小,6个特征图对应的先验框大小分别为30,60,111,162,213,264.得到每个对应的基本先验框大小(最中间小方块的大小)后featuremap,需要根据基本尺寸生成k个先验框。基本先验框的大小对应于特征图定义的最小正方形先验框。最外面的大方形先验框的大小为:$$s_k'=\sqrt{s_k*s_{k+1}}$$而最后一层最大的方形先验框大小直接由300*1.05=315给出。正方形的大小确定了,如何确定矩形先验框的大小,网络定义了一组纵横比ar={1,2,3,1/2,1/3},Sk作为基础框尺寸。只定义了4种priorframe的featuremaps,不会使用3和1/3的纵横比。$$w_k^a=s_k\sqrt{a_r},h_k^a=\frac{s_k}{a_r}$$每个单元的先验框的中心在每个单元的中心,即:$(\frac{i+0.5}{|f_k|},\frac{j+0.5}{|f_k|}),i,j\in[0,|f_k|]$,其中$f_k$是特征的大小地图。需要注意的是,上面计算的先验框的大小是根据输入图像的大小计算的。数据增强SSD中的数据增强主要采用了以下几种方法:水平翻转(randomlyhorizo??ntalflip)、颜色失真(colordistortion)、随机扩展(randomexpansion)根据指定的扩展因子对图像进行随机缩放。为了满足输入的尺寸要求,将缩放后的图像在边缘进行填充。这提高了网络检测小物体的能力。随机patch采样(randomlysamplepatch)根据约束条件(被采样patch和gtbox的iou需要大于指定阈值)从图像中随机进行patch采样。总结SSD网络的关键在于MultiBoxdetection,多特征图的多尺度检测。后来Yolov3也借鉴了这个思路。同时,它还使用了更精挑细选的先验框(共30种先验框,共8732个),使网络的检测效果更好。SSD对小物体检测效果不太好的主要原因可能是大featuremap负责检测小物体,小featuremap负责检测大物体。大的featuremap有更多的位置信息,但是缺乏足够的语义信息,而smallfeaturemap有更多的语义信息,但是由于不断的降采样丢失了大量的位置信息。后来的Yolov3在借鉴SSD的多尺度、多帧思想的同时,也使用skipconnections来融合高分辨率的featuremaps和包含更多语义信息的featuremaps,从而更好的定位。参考https://arxiv.org/pdf/1512.02...https://arleyzhang.github.io/...https://blog.csdn.net/u010712...https://blog.csdn.net/zbzb100...
