使用CNN的边界框回归的损失函数

时间:2016-06-01 16:54:29

标签: regression theano bounding-box loss

我试图了解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,它计算边界框参数平方差的平方根。但是,这并未考虑重叠边界框的区域,而只考虑左,右,上,下参数的差异。我把它实现为:

def euclidean_loss(A, B):
    l = lasagne.objectives.squared_error(A, B)
    return l.mean()

如果我在这里做错了什么,有人可以指导我这个用例或点的边界框回归的最佳损失函数。在实践中通常使用哪种损失函数?

1 个答案:

答案 0 :(得分:0)

从个人实施经验上讲,与使用欧几里得(MSE或L2)损失相比,使用IOU作为损失函数训练CNN的效果要好得多。没有使用平方直径差损失。通常,最好使用损失函数来明确表示输出对您希望完成的任务的好处。

关于IOU的值为零,您可以在公式中引入一些附加项,以便它可以根据bbox中心之间的标准化距离优雅地趋于0。这可能会带来额外的效果,即有助于使边界框相对于地面真相居中。

此回复主要是概念性的,但如果需要,我很乐意提供代码示例。