2

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()

このユースケースのバウンディングボックス回帰に最適な損失関数、またはここで何か間違ったことをしている場合のスポットについて、誰かが私を案内してくれませんか。通常、実際に使用される損失関数はどれですか?

4

1 に答える 1

2

個人的な実装経験から言えば、ユークリッド (MSE または L2) 損失ではなく、損失関数として IOU を使用して CNN をトレーニングした方がはるかに優れた結果が得られました。二乗径差損失は使用していません。一般に、達成したいタスクの出力の良さを明示的に表す損失関数がおそらく最適です。

ゼロの値を持つ IOU に関しては、おそらく bbox 中心間の正規化された距離に基づいて、適切に 0 に向かうように定式化にいくつかの追加項を導入できます。これにより、グラウンド トゥルースに対してバウンディング ボックスを中央に配置するのに役立つという追加の効果が得られる可能性があります。

この回答はほとんど概念的なものですが、必要に応じてコード例を提供できれば幸いです。

于 2019-09-04T13:59:47.157 に答える