• 度量学习整理笔记


    深度度量学习初步整理

    知乎:triplet loss 在深度学习中主要应用在什么地方?有什么明显的优势?

    文章链接

    Triplet loss通常是在个体级别的细粒度识别上使用,传统的分类是花鸟狗的大类别的识别,但是有
    些需求是要精确到个体级别,比如精确到哪个人的人脸识别,所以triplet loss的最主要应用也就是
    face identification, person re-identification, vehicle re -identification的各种identification识
    别问题上

    • 当然你可以把每个人当做一个类别来进行分类训练,但是往往最后会造成softmax的维数远大于
      feature的维数,想想resnet50 global ap出来- -个2048的feature对应到一 -个几万,几十万的分
      类softmax就可怕。

    • 另外一个结论就是triplet loss通常能比classification得到更好的feature,我个人测试triplet loss
      至少比classification高10个点。

    • 还有一个优点就是triplet loss可以卡阈值, triplet losi训练的时候要设置- 个margin, 这个
      margin可以控制正负样本的距离,当feature 进行normalization之后,可以更加方便的卡个阈
      值来判断是不是同一个ID

    当然triplet loss也有缺点,就是收敛慢,而且比classification更容 易overfitting (此条待考究,并且即使过拟合了也比classification性能要好),此外需 要对输入的数据按照label进行特别的排列,非常重要的一点是没有triplet loss的API,新手小白可能连十行代码都不到的triplet loss都写不出 来,所以deep learning不只是调库调参而已现在triplet loss已经有很多改进版本了,可以搜索improved triplet loss,in defense of triplet loss,beyond triplet loss等论文

    知乎:Triplet Loss

    文章链接

    Triplet Loss

    三元组(Triplet)计算而来的损失(Loss)

    由Anchor(A),Negative(N),Positive§组成,基点为A,正匹配为P,负匹配为N。

    Triplet Loss的学习目标可以形象的表示如下图:

    img

    网络没经过学习之前,A和P的欧式距离可能很大,A和N的欧式距离可能很小,如上图左边,在网络的学习过程中,A和P的欧式距离会逐渐减小,而A和N的距离会逐渐拉大。

    网络会直接学习特征间的可分性:同一类的特征之间的距离要尽可能的小,而不同类之间的特征距离要尽可能的大。

    通过学习,使得类间的距离要大于类内的距离

    损失函数为:

    img

    其中,左边的二范数表示类内距离,右边的二范数表示类间距离,α是一个常量。优化过程就是使用梯度下降法使得损失函数不断下降,即类内距离不断下降,类间距离不断提升。
    argminxipf(xia)f(xip)22 argmin_{x^p_i}||f(x^a_i)-f(x^p_i)||_2^2
    以及hard negative
    argmaxxinf(xia)f(xin)22 argmax_{x^n_i}||f(x^a_i)-f(x^n_i)||_2^2
    来作为我们的三元组

    Hard Triplets应该是满足类内距离最大化并且类间距离最小化的三元组。

    深度度量学习中的损失函数

    度量学习(metric learning)研究如何在一个特定的任务上学习一个距离函数,使得该距离函数能够帮助基于近邻的算法(kNN、k-means等)取得较好的性能。深度度量学习(deep metric learning)是度量学习的一种方法,它的目标是学习一个从原始特征到低维稠密的向量空间(称之为嵌入空间,embedding space)的映射,使得同类对象在嵌入空间上使用常用的距离函数(欧氏距离、cosine距离等)计算的距离比较近,而不同类的对象之间的距离则比较远。深度度量学习在计算机视觉领域取得了非常多的成功的应用,比如人脸识别、人脸验证、图像检索、签名验证、行人重识别等。

    损失函数在深度度量学习中起到了非常重要的作用。很多深度度量学习的损失函数构建在样本对(pair)或者样本三元组(triplet)之上,因而样本空间的量级(O(N2)O(N^2)或者O(N3)O(N^3))非常大。一般而言,模型在训练过程中很难穷举学习所有的样本对;并且大多数样本对或者样本三元组的信息量是很小的,尤其在模型训练的后期,这些样本对或者样本三元组上梯度值几乎为0。若不做任何针对性的优化,学习算法的收敛速度会很慢,且易陷入局部最优。

    困难样本挖掘是加快学习算法的收敛速度,并改进学习效果的一种重要手段。它通常和特定的损失函数一起使用,以期望达到最好的效果。困难样本挖掘可以理解为在学习过程中给每一个样本对动态赋予一个权重。在学习不同样本对时给它们不同的权重,如果某个样本对包含的信息比较多或比较难学习,那么它就需要比较大的权重。信息量较少的样本对则会被赋予较小的权重。若某些样本对被赋予的权重为0,则意味着在计算梯度时不考虑这些样本对,相当于这些样本对被丢弃了。

    不同的损失函数在设计时,对于样本对的赋权是不同的,或者说与这些损失函数配合使用的困难样本挖掘方法是不同的。下面列举一些常用的深度度量学习中使用的损失函数,同时了解一下它们是如何来给做困难样本挖掘的。

    损失函数(Loss functions)

    1. Contrastive loss

    Contrastive loss的输入是两个样本组成的样本对,label为该样本对是否属于同一类。
    L(xi,xj;f)=1{yi=yj}fifj22+1{yiyj}max(0,mfifj2)2 Lleft(x_{i}, x_{j} ; f ight)=mathbf{1}left{y_{i}=y_{j} ight}left|f_{i}-f_{j} ight|_{2}^{2}+mathbf{1}left{y_{i} eq y_{j} ight} max left(0, m-left|f_{i}-f_{j} ight|_{2} ight)^{2}
    其中,fif_i 是函数 f(xi)f(x_i) 的简写,表示输入 xix_i 映射之后的embedding向量;1{.}1{.} 是指示函数,在输入为true时返回1,否则返回0;mm 是预先设定的超参数,表示不同类样本之间的距离应超过该margin值。

    img

    最原始的contrastive loss只考虑了输入样本对本身的相似性。

    2. Triplet loss

    Triplet loss的输入由一个三元组组成,每个三元组包含一个query、一个与query属于同一类的正样本、一个与query属于不同类的负样本。
    L(x,x+,x;f)=max(0,ff+22ff22+m) Lleft(x, x^{+}, x^{-} ; f ight)=max left(0,left|f-f^{+} ight|_{2}^{2}-left|f-f^{-} ight|_{2}^{2}+m ight)
    Triplet loss要求query到负样本的距离与query到正样本的距离之差要大于 mm

    Contrastive loss和triplet loss都很常用,一般来说,Triplet-Loss的效果比Contrastive Loss的效果要好,因为他考虑了正负样本与锚点的距离关系。然而,这两种loss函数如果单独使用则会遭遇收敛速度慢的问题。在学习过程的后期,大多数样本都能满足损失函数的约束条件,这些样本对应进一步学习的贡献很小。因此,这两种损失函数都需要配合hard sample mining的学习策略一起使用,例如FaceNet提出的simi-hard negative sample mining方法。

    Contrastive loss能够让正样本对尽可能的近,负样本对尽可能的远,这样可以增大类间差异,减小类内差异。但是其需要指定一个固定的margin,即公式中的 mm,因为 mm 是固定的,所以这里就隐含了一个很强的假设,即每个类目的样本分布都是相同的,不过一般情况下这个强假设未必成立

    例如,有一个数据集有三种动物,分别是狗、狼 、猫,直观上狗和狼比较像,狗和猫的差异比较大,所以狗狼之间的margin应该小于狗猫之间的margin,但是Contrastive loss使用的是固定的margin,如果margin设定的比较大,模型可能无法很好的区分狗和狼,而margin设定的比较小的话,可能又无法很好的区分狗和猫。

    6. Ranked list loss

    上述的损失函数都存在如下的两点局限性:

    1. 这些损失函数虽然都提出了加入更多的负样本来获得结构化的信息,但是使用的负样本仅仅是一小部分;
    2. 另外这些损失函数没有考虑类内的数据分布,都追求将同一个class压缩到一个点上。

    假设 X={(xi,yi)}i=1NX=left{left(x_{i}, y_{i} ight) ight}_{i=1}^{N} 表示训练集, 其中每一组元素 (xi,yi)left(x_{i}, y_{i} ight) 表示成对的样 本与其标签, 总共包括 CC 个类别, 即 yi[i,2,,C],{xic}i=1Ncy_{i} in[i, 2, cdots, C], quadleft{x_{i}^{c} ight}_{i=1}^{N_{c}} 表示属于 类别 cc 的所有样本, Ncquad N_{c} 表示相应类别的样本数量。
    我们的目标是学习到一个函数 ff 使得正样本对之间的相似度高于负样本之间的 相似度。为了将正负样本区分开,Ranked List Loss希望负样本之间的距离大 于某个间值 α,alpha, 并目正样本之间的距离小于 αmalpha-m ,即正负样本之间至少有 mm 的间隔。基于此, 提出了pairwise margin loss:
    Lm(xi,xj;f)=(1yij)[αdij]++yij[dij(αm)]+ L_{m}left(x_{i}, x_{j} ; f ight)=left(1-y_{i j} ight)left[alpha-d_{i j} ight]_{+}+y_{i j}left[d_{i j}-(alpha-m) ight]_{+}
    其中,当 yi=yjy_i=y_j 时,yij=1y_{ij}=1 ,否则 yij=0y_{ij}=0dijd_{ij} 表示 f(xi),f(xj)f(x_i),f(x_j) 之间的欧式距离, [公式] 是hinge函数。

    对样本进行合适采样可以加快模型的收敛速率和提高模型性能。Ranked List Loss使用的采样策略很简单,就是损失函数不为0的样本,具体来说,对于正样本,损失函数不为0意味着它们与anchor之间的距离大于 αmalpha-m , 类似的,对于负样本,损失函数不为0意味着它们与anchor之间的距离小于 αalpha ,相当于使得同一类别位于一个半径为 αmalpha-m 大小的超球体内。

    img

    给定一个anchor xicx_{i}^{c} 基于相似度对其他样本进行排序, 在这个排序结果中, 有 Nc1N_{c}-1 个正样本, 用 Pc,i={xjcji}P_{c, i}=left{x_{j}^{c} mid j eq i ight} 表示。 同样地, 有 kcNksum_{k eq c} N_{k} 个负样 本, 用 Nc,i={xjkkc}N_{c, i}=left{x_{j}^{k} mid k eq c ight} 表示。于每个anchor xic,x_{i}^{c}, 我们希望使得它与正样本集 Pc,iP_{c, i} 的距离越近越好, 并且与负样本集 Nc,iN_{c, i} 之间存在着 mm 的间隔, 同时,我们还希望使得anchor与负样本的距离大于边界 αalpha 。在执行困难样本挖掘后,得到困难的正样本集合为 Pc,i={xjcji,dij>(αm)},P_{c, i}^{*}=left{x_{j}^{c} mid j eq i, d_{i j}>(alpha-m) ight}, 困难的负
    样本集合为 Nc,i={xjkkc,dij<α}N_{c, i}^{*}=left{x_{j}^{k} mid k eq c, d_{i j}<alpha ight}
    因此, 对于正样本我们使用的损失函数为:
    LP(xic;f)=1Pc,ixjcPc,jLm(xic,xjc;f) L_{P}left(x_{i}^{c} ; f ight)=frac{1}{left|P_{c, i}^{*} ight|} sum_{x_{j}^{c} in P_{c, j}^{*}} L_{m}left(x_{i}^{c}, x_{j}^{c} ; f ight)
    对于负样本集,考虑到它的样本数量比较大,对每个负样本使用加权的方式:
    LN(xic;f)=xjkNc,iwijxjkPc,jwijLm(xic,xjk;f) L_{N}left(x_{i}^{c} ; f ight)=sum_{x_{j}^{k} in N_{c, i}^{*}} frac{w_{i j}}{sum_{x_{j}^{k} in P_{c, j}^{*}} w_{i j}} L_{m}left(x_{i}^{c}, x_{j}^{k} ; f ight)
    其中, wij=exp(T(αdij),Tw_{i j}=exp left(T cdotleft(alpha-d_{i j} ight), quad T ight. 是超参数 0_{0}
    最终, 整个损失为: LRLL(xic;f)=LP(xic;f)+λLN(xic;f)quad L_{R L L}left(x_{i}^{c} ; f ight)=L_{P}left(x_{i}^{c} ; f ight)+lambda L_{N}left(x_{i}^{c} ; f ight)

    通常情况下,设置 λ=1lambda =1

    img

    上述几种loss函数的对比如下图所示:

    img

    其中,蓝色圆形表示anchor(query)样本,不同的形状表示来自不同类的样本。

    7. Multi-Similarity loss

    前面说过,困难样本挖掘可以理解为在学习过程中给每一个样本对动态赋予一个权重。给样本赋权的核心在于判断样本的局部分布,即它们之间的相似性,局部样本之间的分布和相互关系并不仅仅取决于当前两个样本之间的距离或相似性,还取决于当前样本对与其周围样本对之间的关系。

    因此,对于每一个样本对,我们不仅需要考虑样本对本身的自相似性,同时还要考虑它与其它样本对的相对相似性。其中相对相似性又可以分为正相对相似性 (正样本)、负相对相似性(负样本)两种相似性。

    1. 自相似性:根据样本对自身计算出的相似性,这是一种最常用也是最重要的相似性。例如,当一个负样本对的余弦相似性较大时,意味着很难把该样本对所对应的两种类别区分开来,这样的样本对对模型来说是困难的,也是有信息量的,对于模型学习更有区分度的特征很有帮助。另一方面,自相似性很难完整地描述embedding空间的样本分布情况。

    2. 正相对相似性:不仅考虑当前样本对自身的相似性,还考虑局部邻域内正样本对之间的相对关系。

    3. 负相对相似性:不仅考虑当前样本对自身的相似性,还考虑局部邻域内负样本对之间的相对关系。

      img

    各种损失函数都在给样本加权以确定「拉或推」的力度,那么使用什么样的函数来加权就非常重要了,在学习不同样本对时给它们不同的权重,如果某个样本包含的信息比较多或比较难学习,那么它就需要比较大的权重。不同的损失函数在设计时,对于样本对的赋权是不同的,往往会涉及到上述三种相似性的其中一种或多种的计算。以一个负样本对为例,上文提到的几个loss函数涉及到的相似性计算类型如下表所示。

    preview

    Multi-Similarity Loss(MS loss) 综合考虑了三种相似性,它们能概括目前大多数基于样本对的损失函数。MS Loss 通过采样和加权两次迭代,实现更加高效的样本训练。它通过定义自相似性和相对相似性,在训练过程中更加全面地考虑了局部样本分布,从而能更高效精确的对重要样本对进行采用和加权。

    对于一个给定的负样本对 <xi,xj>Ni,<x_{i}, x_{j}>in N_{i}, MS loss给它赋予的权重为 :
    wij=1eβ(λSij)+kNieβ(SikSij) w_{i j}^{-}=frac{1}{e^{etaleft(lambda-S_{i j} ight)}+sum_{k in N_{i}} e^{etaleft(S_{i k}-S_{i j} ight)}}
    类似地, 对于一个给定的负样本对 <xi,xj>Pi,<x_{i}, x_{j}>in P_{i}, MS loss给它赋予的权重 为:
    wij+=1eα(λSij)+kPieα(SikSij) quad w_{i j}^{+}=frac{1}{e^{-alphaleft(lambda-S_{i j} ight)}+sum_{k in P_{i}} e^{-alphaleft(S_{i k}-S_{i j} ight)}}
    最终,MS loss的定义为:
    LMS=1mi=1m{1αlog[1+kPieα(Sikλ)]+1βlog[1+kNieβ(Sikλ)]} L_{M S}=frac{1}{m} sum_{i=1}^{m}left{frac{1}{alpha} log left[1+sum_{k in P_{i}} e^{-alphaleft(S_{i k}-lambda ight)} ight]+frac{1}{eta} log left[1+sum_{k in N_{i}} e^{etaleft(S_{i k}-lambda ight)} ight] ight}
    LMSL_{M S} 相对于 SijS_{i j} 求得的梯度刚好为上述样本权重。

    img

    MS Loss 在大部分图像检索基准数据库上都有很好的性能,且相比最新的方法也有较大的优势。

    知乎:度量学习中的pair-based loss

    1. Triplet center loss

    Triplet Loss是让正样本对之间的距离小于负样本对之间的距离,并且存在一定的margin。因此triplet样本的选取至关重要,如果选取的triplet对没啥难度,很容就能进行区分,那大部分的时间生成的loss都为0,模型不更新,而如果使用hard mining的方法对难例进行挖掘,又会导致模型对噪声极为敏感。为了对Triplet loss的缺点进行改进,Triplet center loss就被提出来了。

    Triplet Center loss[3]的思想非常简单,原来的Triplet是计算anchor到正负样本之间的距离,现在Triplet Center是计算anchor到正负样本所在类别的中心的距离。类别中心就是该类别所有样本embedding向量的中心。

    img

    Triplet Center Loss形式如下:
    L({D})=[DapcDanc+m]+ mathcal{L}({D})=sumleft[D_{a p_{c}}-D_{a n_{c}}+m ight]_{+}
    其中 DapcD_{ap_c}表示的是anchor样本到正样本类别中心的距离, DancD_{an_c} 表示的是anchor样本到负样本类别中心的距离。[][] 是hinge 函数:[x]+=max(0,x)[x]_+=max(0,x)

    2. N-pair loss

    triplet loss同时拉近一对正样本和一对负样本,这就导致在选取样本对的时候,当前样本对只能够关注一对负样本对,而缺失了对其他类别样本的区分能力。

    为了改善这种情况,N-pair loss[4]就选取了多个负样本对,即一对正样本对,选取其他所有不同类别的样本作为负样本与其组合得到负样本对。

    如果数据集中有NN个类别,则每个正样本对yiiy_{ii}都对应了N1N-1 个负样本对。

    img

    N-pair loss的形式如下:
    L({Dik})=yii=1log(1+yik=0exp(DiiDik)) mathcal{L}left(left{D_{i k} ight} ight)=sum_{y_{i i}=1} log left(1+sum_{y_{i k}=0} exp left(D_{i i}-D_{i k} ight) ight)

    其中 {Diki,k=1,,N;yii=1; and yik=0, if ki}left{D_{i k} mid i, k=1, cdots, N ; y_{i i}=1 ; ext { and } y_{i k}=0, ext { if } k eq i ight}

    DikD_{ik} 代表样本 iijj之间的距离 。

    3. Quadruplet loss

    Quadruplet loss[5] 由两部分组成:

    一部分就是正常的triplet loss,这部分loss能够让模型区分出正样本对和负样本对之间的相对距离。

    另一部分是正样本对和其他任意负样本对之前的相对距离。这一部分约束可以理解成最小的类间距离都要大于类内距离,不管这些样本对是否有同样的anchor。即不仅要要求A1A2<A1B2A_1A_2<A_1B_2 ,还需要 A1A2<B1C1A_1A_2<B_1C_1
    Quadruplet loss的形式如下:
    L({Dij})=(i,j,k),yij=1,yik=0([DijDik+m]++ykaakb=0[DijDkakb+m]+) mathcal{L}left(left{D_{i j} ight} ight)=sum_{(i, j, k), atop y_{i j}=1, y_{i k}=0}left(left[D_{i j}-D_{i k}+m ight]_{+}+sum_{y_{k_a a k_b}=0}left[D_{i j}-D_{k_{a} k_{b}}+m ight]_{+} ight)

    3. Lifted Structure Loss

    Lifted Structure loss[6]的思想是对于一对正样本对而言,不去区分这个样本对中谁是anchor,谁是positive,而是让这个正样本对中的每个样本与其他所有负样本的距离都大于给定的阈值。此方法能够充分的利用mini-batch中的所有样本,挖掘出所有的样本对。
    L({Dij})=yij=1[Dij+log(yik=0exp(mDik))+log(yjl=0exp(mDjl))] mathcal{L}left(left{D_{i j} ight} ight)=sum_{y_{i j}=1}left[D_{i j}+log left(sum_{y_{i k}=0} exp left(m-D_{i k} ight) ight)+log left(sum_{y_{j l}=0} exp left(m-D_{j l} ight) ight) ight]
    另一种定义:

    Lifted Struct loss基于训练集(mini batch)中所有的正负样本对来计算loss,其定义如下:
    L=12P^(i,j)P^max(0,Li,j)2Li,j=max(max(i,k)N^αDi,k,max(j,l)N^αDj,l)+Di,j egin{aligned} L &=frac{1}{2|hat{P}|} sum_{(i, j) in hat{P}} max left(0, L_{i, j} ight)^{2} \ L_{i, j} &=max left(max _{(i, k) in hat{N}} alpha-D_{i, k}, max _{(j, l) in hat{N}} alpha-D_{j, l} ight)+D_{i, j} end{aligned}
    其中, P^hat{P} 是正样本对(pair的左变量和右边量来自同一个类)的集合; NN 是负样本对的集合; Di,jD_{i,j} 是样本对 {i,j}{i,j} 的距离。

    仔细分析该loss function,发现对于每一个正样本对 {i,j}{i,j} ,模型分别挖掘其左变量 ii 和右边量 jj 对应的最困难的负样本,独立地找到距离左变量最近的负样本,假设为 kk ;同时找到距离右边量最近的负样本,假设为 ll 。接着通过比较 Di,kD_{i,k}Dj,lD_{j,l} ,找出其中较小的距离对应的负样本,假设为 nn 。最后,计算三元组 {i,j,n}{i,j,n} 确定的triplet loss函数。如下图所示:

    img

    Hard negative edge is mined with respect to each left and right example per each positive pairs. In this illustration with 6 examples in the batch, both x3 and x4 independently compares against all other negative edges and mines the hardest negative edge.

    Lifted Struct loss与triplet loss的不同之处就在于,triplet loss的样本三元组是提前确定好的,而Lifted Struct loss是为每一个正样本对动态构建最困难的三元组,在构建的过程中考虑了(mini batch中)所有的负样本。

    由于上述定义的Lifted Struct loss函数是不光滑的函数,嵌套的max函数在实际中容易导致网络陷入较差的局部最优,因此可以改写为一个光滑的上界函数来避免此问题。
    L~i,j=log((i,k)Nexp{αDi,k}+(j,l)Nexp{αDj,l})+Di,jL~=12P(i,j)Pmax(0,L~i,j)2 egin{aligned} ilde{L}_{i, j} &=log left(sum_{(i, k) in N} exp left{alpha-D_{i, k} ight}+sum_{(j, l) in N} exp left{alpha-D_{j, l} ight} ight)+D_{i, j} \ ilde{L} &=frac{1}{2|P|} sum_{(i, j) in P} max left(0, ilde{L}_{i, j} ight)^{2} end{aligned}
    img

    5. Proxy NCA loss

    这个方法提出的目的是去解决采样的问题。假设W代表着训练集中的一小部分数据,在采样时通过选择与W中距离最近的一个样本u作为代理(proxy), 即:
    KaTeX parse error: No such environment: align at position 8: egin{̲a̲l̲i̲g̲n̲}̲ p(u)=argmin_{w…
    基于选择的proxy, NCA损失为:
    L(a,u)=log(exp(d(a,p(u)))zZexp(d(a,p(z)))) L(a, u)=-log left(frac{exp (-d(a, p(u)))}{sum_{z in Z} exp (-d(a, p(z)))} ight)

    总结

    度量学习中还有很多其他类型的pair-based loss,通过上文可以发现,这些不同的loss基本上都是在Contrastive loss和Triplet loss的基础上改进而来。这些改进思想很值得我们借鉴,尤其是通过观察分析已经存在的loss的缺陷,从而提出针对性的改进,构造一个适合自己应用场景的loss。

    参考文献

    保持对优秀的热情
  • 相关阅读:
    如何编写一个简单的依赖注入容器
    网站框架的动态编译的实现原理
    Python实现语音识别和语音合成
    OpenCV图像处理以及人脸识别
    Shell教程快速入门
    TensorFlow入门教程
    如何免费使用Google的GPU跑深度学习代码
    高等数学系列文章
    Git系列教程
    一键构造你的博客园目录
  • 原文地址:https://www.cnblogs.com/luckforefforts/p/13642695.html
Copyright © 2020-2023  润新知