TripletMarginLoss原理和源码实现

TripletMarginLoss最早是在 FaceNet 提出的,它是用于衡量不同人脸特征之间的距离,进而实现人脸识别和聚类

TripletMarginLoss原理和源码实现

现在被广泛应用于不同业务场景中,比如推荐场景和搜索场景下的向量召回模型。TripletMarginLoss的公司如下:L ( a , p , n ) = m a x { d ( a , p ) − d ( a , n ) + m a r g e , 0 } L(a,p,n)=max{d(a,p)-d(a,n)+marge,0}L (a ,p ,n )=m a x {d (a ,p )−d (a ,n )+m a r g e ,0 },其中d默认表示欧氏距离。
该Loss针对不同样本配对,有以下三种情况:
1.简单样本,即d ( a i , p i ) − d ( a i , n i ) + m a r g e < 0 d(a_i,p_i)-d(a_i,n_i)+marge此时 正样本距离anchor的距离d ( a i , p i ) + M a r g i n d(a_i, p_i) + Margin d (a i ​,p i ​)+M a r g i n仍然小于负样本距离anchor的距离d ( a i , n i ) d(a_i, n_i)d (a i ​,n i ​),该情况认为正样本距离足够小,不需要进行优化,因此Loss为0;

2.难样本,即d ( a i , p i ) − d ( a i , n i ) > 0 d(a_i,p_i)-d(a_i,n_i)>0 d (a i ​,p i ​)−d (a i ​,n i ​)>0此时 负样本距离anchor的距离d ( a i , n i ) d(a_i, n_i)d (a i ​,n i ​) 小于 正样本距离anchor的距离d ( a i , p i ) d(a_i, p_i)d (a i ​,p i ​),需要进行优化。

半难样本,即d ( a i , p i ) − d ( a i , n i ) < 0 并 且 d ( a i , p i ) − d ( a i , n i ) + m a r g e > 0 d(a_i,p_i)-d(a_i,n_i)d (a i ​,p i ​)−d (a i ​,n i ​)<0 并且d (a i ​,p i ​)−d (a i ​,n i ​)+m a r g e >0此时虽然 负样本距离anchor的距离$d(a_i, n_i) 大 于 正 样 本 距 离 a n c h o r 的 距 离 大于 正样本距离anchor的距离大于正样本距离a n c h o r 的距离d(a_i, p_i)$,但是还不够大,没有超过 Margin,需要优化。

TripletMarginLoss原理和源码实现

此外论文作者还提出了 swap 这个概念,原因是我们公式里只考虑了anchor距离正类和负类的距离,而没有考虑正类和负类之间的距离,考虑以下情况:

TripletMarginLoss原理和源码实现

可能Anchor距离正样本和负样本的距离相同,但是负样本和正样本的距离很近,不利于模型区分,因此会做一个swap,即交换操作,在代码里体现的操作是取最小值。


if swap:
    D(a, n) = min(D(a,n), D(p, n))

这样取了最小值后,在Loss计算公式中,Loss值会增大,进一步帮助区分负样本。下面是numpy的对应代码:

def np_triplet_margin_loss(anchor, postive, negative, margin, swap, reduction="mean", p=2, eps=1e-6):
    def _np_distance(input1, input2, p, eps):

        np_pnorm = np.power(np.abs((input1 - input2 + eps)), p)
        np_pnorm = np.power(np.sum(np_pnorm, axis=-1), 1.0 / p)
        return np_pnorm

    dist_pos = _np_distance(anchor, postive, p, eps)
    dist_neg = _np_distance(anchor, negative, p, eps)

    if swap:
        dist_swap = _np_distance(postive, negative, p, eps)
        dist_neg = np.minimum(dist_neg, dist_swap)
    output = np.maximum(margin + dist_pos - dist_neg, 0)

    if reduction == "mean":
        return np.mean(output)
    elif reduction == "sum":
        return np.sum(output)
    else:
        return output

Original: https://blog.csdn.net/qq_40176087/article/details/123590777
Author: 谈笑风生…
Title: TripletMarginLoss原理和源码实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/545207/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球