五、损失函数
5.1 匹配策略(Matching strategy)
我们分配了许多prior bboxes
,要想让其预测类别和目标框信息,我们就要先知道每个prior bbox
和哪个目标对应,进而才能判断预测的是否准确,从而将训练进行下去。
不同方法 ground truth boxes
与 prior bboxes
的匹配策略大致都是类似的,但是细节会有所不同。这里我们采用SSD中的匹配策略,具体如下:
- 第一个原则:
从ground truth box
出发,寻找与每一个ground truth box
有最大的交并比的prior bbox
,这样就能保证每一个groundtruth box
一定与一个prior bbox
对应起来。反之,若一个prior bbox
没有与任何ground truth
进行匹配,那么该prior bbox
只能与背景匹配,就是负样本。
一般的,一张图片中的ground truth
是非常少的,而prior bbox
很多,我们如果仅按照第一个原则进行匹配,那么很多的prior bbox
将会被预测为负样本,从而导致正负样本极其不平衡,所以我们就会需要第二个原则;
- 第二个原则:从
prior bbox
出发,对剩余的还没有配对的prior bbox
与任意一个ground truth box
尝试配对,只要两者之间的交并比大于阈值(一般是0.5),那么该prior bbox
也与这个ground truth
进行匹配。这意味着某个ground truth
可能与多个Prior box
匹配,这是可以的。但是反过来却不可以,因为一个prior bbox
只能匹配一个ground truth
,如果多个ground truth
与某个prior bbox
的 IOU 大于阈值,那么prior bbox
只与IOU最大的那个`ground truth进行匹配。
注意: 第二个原则一定在第一个原则之后进行,仔细考虑一下这种情况,如果某个ground truth
所对应最大IOU的prior bbox
小于阈值,并且所匹配的prior bbox
却与另外一个ground truth
的IOU大于阈值,那么该prior bbox
应该匹配谁,答案应该是前者,因为我们首先要确保每个ground truth
一定有一个prior bbox
与之匹配。
用一个示例来说明上述的匹配原则:
在图像中共有7个红色的框代表先验框,黄色的为ground truth
,在这张图像中一共有三个真实的目标,按照前面列出的步骤将生成以下匹配项:
5.2 损失函数
接下来我们看一下如何设计损失函数:
将总体的目标损失函数定义为 定位损失(Ioc)和 置信度损失(conf)的加权和:
$$
L(x,c,l,g) = \frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc} (x,l,g)) (1)
$$
其中N是匹配到GT(Ground Truth)的prior bbox
数量,如果N=0,则将损失设为0;而 α 参数用于调整confidence loss
和location loss
之间的比例,默认 α=1。
confidence loss
是在多类别置信度(c)上的softmax loss
,公式如下:
$$
L_{conf}(x,c) = -\sum_{i \in Pos}^N x^{p}{ij} log(\hat{c}^{i}{p}) – \sum_{i \in Neg} log(\hat{c}^{0}{i}) Where \hat{c}^{p}{i} = \frac{exp(c^{p}{i})}{\sum_p exp(c^{p}{i})} (2)
$$
其中i指代搜索框序号,j指代真实框序号,p指代类别序号,p=0表示背景。其中$x^{p}{ij}=\left{1,0\right}$ 中取1表示第i个prior bbox匹配到第 j 个GT box,而这个GT box的类别为 p 。$x^{p}{i}$ 表示第i个搜索框对应类别p的预测概率。此处有一点需要关注,公式前半部分是正样本(Pos)的损失,即分类为某个类别的损失(不包括背景),后半部分是负样本(Neg)的损失,也就是类别为背景的损失。
而location loss(位置回归)是典型的smooth L1 loss
$$
L_{loc}(x,l,g) = \sum_{i \in Pos m \in \left{c_x,c_y,w,h\right}}^N \sum x^{k}{ij} smooth{L1}(l^{m}{i}-\hat{g}^{m}{j}) (3)
$$
$$
\hat{g}^{c_x}{j}=(g^{c_x}{j}-d^{c_x}{i})/d^{w}{i}
$$
$$
\hat{g}^{c_y}{j}=(g^{c_y}{j}-d^{c_y}{i})/d^{h}{i}
$$
$$
\hat{g}^{w}{j}=log(\frac{g^{w}{j}}{d^{w}_{i}})
$$
$$
\hat{g}^{h}{j}=log(\frac{g^{h}{j}}{d^{h}_{i}})
$$
其中,l为预测框,g为ground truth
。(cx,xy)为补偿(regress to offsets)后的默认框d的中心,(w,h)为默认框的宽和高.
5.3 Hard negative mining
一般情况下negative prior bboxes
的数量 远大于 positive prior bboxes
的数量,直接训练会导致网络过于重视负样本,从而降低预测效果。为了保证正负样本尽量平衡,我们这里使用SSD使用的在线难例挖掘策略(hard negative mining),即依据confidience loss
对属于负样本的prior bbox
进行排序,只挑选其中confidience loss
高的bbox进行训练,将正负样本的比例控制在positive:negative=1:3
。其核心作用就是只选择负样本中容易被分错类的困难负样本来进行网络训练,来保证正负样本的平衡和训练的有效性。
举个例子:假设在这 441 个 prior bbox 里,经过匹配后得到正样本先验框P个,负样本先验框 441−P 个。将负样本prior bbox按照prediction loss从大到小顺序排列后选择最高的M个prior bbox。这个M需要根据我们设定的正负样本的比例确定,比如我们约定正负样本比例为1:3时。我们就取M=3P,这M个loss最大的负样本难例将会被作为真正参与计算loss的prior bboxes,其余的负样本将不会参与分类损失的loss计算。
5.4 小结
本小节介绍的内容围绕如何进行训练展开,主要是3块:
- 先验框与GT框的匹配策略
- 损失函数计算
- 难例挖掘
这3部分是需要结合在一起理解,我们再整个梳理下计算loss的步骤
1)先验框与GT框的匹配
按照我们介绍的方案,为每个先验框都分配好类别,确定是正样本还是负样本。
2) 计算loss
按照我们定义的损失函数计算 分类loss 和 目标框回归loss
负样本不计算目标框的回归loss
3) 难例挖掘
上面计算的loss中分类loss的部分还不是最终的loss
因为负样本先验框过多,我们要按一定的预设比例,一般是1:3,将loss最高的那部分负样本先验框拿出来,其余的负样本忽略,重新计算分类loss
完整loss计算过程的代码见model.py
中的 MultiBoxLoss
类。