我正在尝试了解 CNN 中边界框回归的损失函数。目前我使用 Lasagne 和 Theano,这使得编写损失表达式非常容易。许多消息来源提出了不同的方法,我问自己在实践中通常使用哪一种。
边界框坐标按顺序表示为归一化坐标[left, top, right, bottom]
(使用T.matrix('targets', dtype=theano.config.floatX)
)。
到目前为止,我已经尝试了以下功能;但是,它们都有其缺点。
联合交叉口
有人建议我使用该Intersection over Union
度量来确定 2 个边界框对齐和重叠的程度。但是,当框不重叠并且交集为0时会出现问题;然后无论边界框相距多远,整个商都变为 0。我将其实现为:
def get_area(A):
return (A[:,2] - A[:,0]) * (A[:,1] - A[:,3])
def get_intersection(A, B):
return (T.minimum(A[:,2], B[:,2]) - T.maximum(A[:,0], B[:,0])) \
* (T.minimum(A[:,1], B[:,1]) - T.maximum(A[:,3], B[:,3]))
def bbox_overlap_loss(A, B):
"""Computes the bounding box overlap using the
Intersection over union"""
intersection = get_intersection(A, B)
union = get_area(A) + get_area(B) - intersection
# Turn into loss
l = 1.0 - intersection / union
return l.mean()
平方直径差
为了为非重叠边界框创建误差度量,我尝试计算边界框直径的平方差。它似乎有效,但我几乎可以肯定有更好的方法来做到这一点。我将其实现为:
def squared_diameter_loss(A, B):
# Represent the squared distance from the real diameter
# in normalized pixel coordinates
l = (abs(A[:,0:2]-B[:,0:2]) + abs(A[:,2:4]-B[:,2:4]))**2
return l.mean()
欧几里得损失
最简单的函数是Euclidean Loss
计算边界框参数平方差的平方根。但是,这并没有考虑重叠边界框的面积,而只考虑了参数left,right,top,bottom的差异。我将其实现为:
def euclidean_loss(A, B):
l = lasagne.objectives.squared_error(A, B)
return l.mean()
如果我在这里做错了什么,有人可以指导我对于这个用例或现场的边界框回归,哪个是最好的损失函数。实践中通常使用哪种损失函数?