【強基固本】深度學習從入門到放飛自我:完全解析triplet loss

2021-02-08 人工智慧前沿講習

「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本」專欄,講解AI領域的基礎知識,為你的科研學習提供助力,夯實理論基礎,提升原始創新能力,敬請關注。

地址:https://www.zhihu.com/people/liu-xin-chen-64


https://omoindrot.github.io/triplet-loss在人臉識別領域,triplet loss常被用來提取人臉的embedding。
之前實驗室有個做無監督特徵學習的小任務,因為沒有類別的監督信息,因此也可以用triplet loss來設計約束,以期得到discriminative embedding。triplet loss原理是比較簡單的,關鍵在於搞懂各種採樣triplets的策略。

01

通常在有監督學習中,我們有固定數量的類別(比如針對Cifar10的圖像分類任務,類別數就是10),因此在訓練網絡時我們通常會在最後一層使用softmax,並結合cross entropy loss作為監督信息。
但是在有些情況下我們需要能夠有一個變化數量的類別。比如對實例人臉識別(face recognition for instance),我們需要能夠比較兩張未知的臉,然後判斷這兩張臉是否來自同一個人。這種情況下使用triplet loss就可以獲得不錯的表徵,在表徵空間,同一個人的臉的表徵彼此接近,而不同人的臉的表徵則能夠被很好分隔。FaceNet: A Unified Embedding for Face Recognition and Clustering 這篇論文就介紹了triplet loss在人臉識別領域的應用,感興趣的同學可以關注。其實除此之外,在無監督學習應用中,也常使用triplet loss來表徵。

02

positive是針對anchor的正樣本,表示與anchor來自同一個人以上  共同構成一個triplet.具有相同label的樣本,它們的embedding在embedding空間儘可能接近具有不同label的樣本,它們的embedding距離儘可能拉遠對於embedding空間的某個距離  ,一個triplet的loss可以定義為:最小化loss  的目標是:使得  接近  ,  大於  .一旦  成為"easy negative",loss就會變成  .

03

根據loss的定義,我們可以定義3種類型的triplet:easy triplets: 此時loss為  ,這種情況是我們最希望看到的,可以理解成是容易分辨的triplets。即 hard triplets: 此時negative比positive更接近anchor,這種情況是我們最不希望看到的,可以理解成是處在模糊區域的triplets。即 semi-hard triplets: 此時negative比positive距離anchor更遠,但是距離差沒有達到一個margin,可以理解成是一定會被誤識別的triplets。確定anchor和positive,negative的位置決定了triplet的類型:easy, semi-hard和hard據此我們也可以把negative劃分為:easy negative, semi-hard negative, hard negative因此,基於哪種類型的triplet訓練將非常大地影響我們的實驗效果。在FaceNet這篇論文種,作者是為每一對anchor和positive隨機選擇一個semi-hard negative構建semi-hard triplet,並在這些triplets上訓練。

04

Offline and online triplet mining目前我們已經定義了一種基於triplet embedding的loss,接下來最重要的問題就是我們該採樣什麼樣的triplet?我們該如何採樣目標triplet?等第一種生產triplet的方式:offline mining在訓練每個epoch的開始階段,計算訓練集種所有的embedding,並挑選出所有的hard triplets和semi-hard triplets,並在該epoch內訓練這些triplets.這種方式不是很高效,因為每個epoch我們都需要遍歷整個數據集來生產triplets。第二種生產triplet的方式:online mining這種想法就是對於每個batch的輸入,動態地計算有用的triplets。給定batch size為  的樣本,我們計算其對應的  embeddings,此時我們最多可以找到  triplets. 當然這其中很多triplet都不是合法的(因為triplet中需要有2個是相同label,1個是不同label)這種方式顯然比offline mining高效得多接下來我們來仔細討論討論online mining策略:我們主要討論如何從一個batch的B embeddings中產生triplets。其中  和   具有相同label,  具有不同label,此時  被稱為是一個valid triplet.我們接下來基於valid triplets來挑選triplets,計算loss我們還是以人臉識別為例,假設一個batch的人臉,batch-size為  ,由  個人,每個人  張人臉圖像構成。一般來說  .batch all:挑選出所有合規的triplets,將hard triplets和semi-hard triplets的loss平均這個過程產生了  個合規的triplets,其中anchor有  個,positive  個,negative  個batch hard: 對於每個anchor,挑選出hardest positive  ( 距離最大)和hardest negative  (  距離最小)。這個過程產生了  個triplets這種方式得到的triplets被稱為這個batch中的hardest triplets

05

triplet loss原理還是比較簡單的,因此我們不難直觀實現如下:

anchor_output = ...    # shape [None, 128]positive_output = ...  # shape [None, 128]negative_output = ...  # shape [None, 128]
d_pos = tf.reduce_sum(tf.square(anchor_output - positive_output), 1)d_neg = tf.reduce_sum(tf.square(anchor_output - negative_output), 1)
loss = tf.maximum(0.0, margin + d_pos - d_neg)loss = tf.reduce_mean(loss)

我們使用網絡提取anchor, positive, negative的embedding。anchor_output, positive_output, negative_output分別表示  anchor embeddings,  positive embeddings,  negative embeddings以上這種方式雖然簡單,但卻非常低效,因為以上採用的是offline triplet mining接下來我們來嘗試下online triplet mining版本的triplet loss:triplet loss需要計算  和  ,因此我們需要高效地計算pairwise distance matrix對於輸入的  embeddings,我們期待得到  的距離矩陣。距離計算公式:參數squared為True表示計算的是距離的平方,為False表示計算的是歐式距離
def _pairwise_distance(embeddings, squared=False):  '''      計算兩兩embedding的距離      --      Args:          embedding: 特徵向量, 大小(batch_size, vector_size)          squared:   是否距離的平方,即歐式距離      Returns:          distances: 兩兩embeddings的距離矩陣,大小 (batch_size, batch_size)  '''      # 矩陣相乘,得到(batch_size, batch_size),因為計算歐式距離|a-b|^2 = a^2 -2ab + b^2,   # 其中 ab 可以用矩陣乘表示  dot_product = tf.matmul(embeddings, tf.transpose(embeddings))     # dot_product對角線部分就是 每個embedding的平方  square_norm = tf.diag_part(dot_product)  # |a-b|^2 = a^2 - 2ab + b^2  # tf.expand_dims(square_norm, axis=1)是(batch_size, 1)大小的矩陣,減去 (batch_size, batch_size)大小的矩陣,相當於每一列操作  distances = tf.expand_dims(square_norm, axis=1) - 2.0 * dot_product + tf.expand_dims(square_norm, axis=0)  distances = tf.maximum(distances, 0.0)   # 小於0的距離置為0  if not squared:          # 如果不平方,就開根號,但是注意有0元素,所以0的位置加上 1e*-16      distances = distances + mask * 1e-16      distances = tf.sqrt(distances)      distances = distances * (1.0 - mask)    # 0的部分仍然置為0
return distances

Online triplet mining strategy 1: batch all strategy 的label相同,  的label不同此時代碼中所謂的mask,就是一個3D tensor,就是將mask在合規triplet index位置置為1,其它位置置為0.
def _get_triplet_mask(labels):  '''      得到一個3D的mask [a, p, n], 對應triplet(a, p, n)是valid的位置是True      ----      Args:          labels: 對應訓練數據的labels, shape = (batch_size,)
Returns: mask: 3D,shape = (batch_size, batch_size, batch_size) ''' # 初始化一個二維矩陣,坐標(i, j)不相等置為1,得到indices_not_equal indices_equal = tf.cast(tf.eye(tf.shape(labels)[0]), tf.bool) indices_not_equal = tf.logical_not(indices_equal) # 因為最後得到一個3D的mask矩陣(i, j, k),增加一個維度,則 i_not_equal_j 在第三個維度增加一個即,(batch_size, batch_size, 1), 其他同理 i_not_equal_j = tf.expand_dims(indices_not_equal, 2) i_not_equal_k = tf.expand_dims(indices_not_equal, 1) j_not_equal_k = tf.expand_dims(indices_not_equal, 0) # 想得到i!=j!=k, 三個不等取and即可, 最後可以得到當下標(i, j, k)不相等時才取True distinct_indices = tf.logical_and(tf.logical_and(i_not_equal_j, i_not_equal_k), j_not_equal_k) # 同樣根據labels得到對應i=j, i!=k label_equal = tf.equal(tf.expand_dims(labels, 0), tf.expand_dims(labels, 1)) i_equal_j = tf.expand_dims(label_equal, 2) i_equal_k = tf.expand_dims(label_equal, 1) valid_labels = tf.logical_and(i_equal_j, tf.logical_not(i_equal_k)) # mask即為滿足上面兩個約束,所以兩個3D取and mask = tf.logical_and(distinct_indices, valid_labels)
return mask

我們需要一個形狀為  的3D tensor,其中  表示triplet  的loss我們通過_get_triplet_mask來獲得合規triplets的index mask,從而獲得合規的triplets統計合規triplets中loss不為0.0的triplets,最後計算平均得到batch_all_triplet_loss.
def batch_all_triplet_loss(labels, embeddings, margin, squared=False):  '''      triplet loss of a batch      -      Args:          labels:     標籤數據,shape = (batch_size,)          embeddings: 提取的特徵向量, shape = (batch_size, vector_size)          margin:     margin大小, scalar
Returns: triplet_loss: scalar, 一個batch的損失值 fraction_postive_triplets : valid的triplets佔的比例 ''' # 得到每兩兩embeddings的距離,然後增加一個維度,一維需要得到(batch_size, batch_size, batch_size)大小的3D矩陣 # 然後再點乘上valid 的 mask即可 pairwise_dis = _pairwise_distance(embeddings, squared=squared) anchor_positive_dist = tf.expand_dims(pairwise_dis, 2) assert anchor_positive_dist.shape[2] == 1, "{}".format(anchor_positive_dist.shape) anchor_negative_dist = tf.expand_dims(pairwise_dis, 1) assert anchor_negative_dist.shape[1] == 1, "{}".format(anchor_negative_dist.shape) triplet_loss = anchor_positive_dist - anchor_negative_dist + margin mask = _get_triplet_mask(labels) mask = tf.to_float(mask) triplet_loss = tf.multiply(mask, triplet_loss) triplet_loss = tf.maximum(triplet_loss, 0.0) # 計算valid的triplet的個數,然後對所有的triplet loss求平均 valid_triplets = tf.to_float(tf.greater(triplet_loss, 1e-16)) num_positive_triplets = tf.reduce_sum(valid_triplets) num_valid_triplets = tf.reduce_sum(mask) fraction_postive_triplets = num_positive_triplets / (num_valid_triplets + 1e-16) triplet_loss = tf.reduce_sum(triplet_loss) / (num_positive_triplets + 1e-16)
return triplet_loss, fraction_postive_triplets

Online triplet mining strategy 2: batch hard strategy在batch hard strategy中,我們期待為每個anchor找到hardest positive和hardest negative.step 1. 構建embedding pairwise距離矩陣step 2. 計算合規pair的2D mask(合規要求:  且  和  具有相同的label). 距離矩陣在mask之外的位置均置為0step 3. 此時取距離矩陣中每一行的最大值,其所對應的triplet,就是該行對應anchor的hardest positive.提取方法與上面hardest positive類似,不再贅述。

triplet_loss = tf.maximum(hardest_positive_dist - hardest_negative_dist + margin, 0.0)

所以batch hard策略計算triplet loss的代碼實現如下所示:

def batch_hard_triplet_loss(labels, embeddings, margin, squared=False):    """Build the triplet loss over a batch of embeddings.    For each anchor, we get the hardest positive and hardest negative to form a triplet.    Args:        labels: labels of the batch, of size (batch_size,)        embeddings: tensor of shape (batch_size, embed_dim)        margin: margin for triplet loss        squared: Boolean. If true, output is the pairwise squared euclidean distance matrix.                 If false, output is the pairwise euclidean distance matrix.    Returns:        triplet_loss: scalar tensor containing the triplet loss    """    pairwise_dist = _pairwise_distances(embeddings, squared=squared)
mask_anchor_positive = _get_anchor_positive_triplet_mask(labels) mask_anchor_positive = tf.to_float(mask_anchor_positive)
anchor_positive_dist = tf.multiply(mask_anchor_positive, pairwise_dist)
hardest_positive_dist = tf.reduce_max(anchor_positive_dist, axis=1, keepdims=True)
mask_anchor_negative = _get_anchor_negative_triplet_mask(labels) mask_anchor_negative = tf.to_float(mask_anchor_negative)
max_anchor_negative_dist = tf.reduce_max(pairwise_dist, axis=1, keepdims=True) anchor_negative_dist = pairwise_dist + max_anchor_negative_dist * (1.0 - mask_anchor_negative)
hardest_negative_dist = tf.reduce_min(anchor_negative_dist, axis=1, keepdims=True)
triplet_loss = tf.maximum(hardest_positive_dist - hardest_negative_dist + margin, 0.0)
triplet_loss = tf.reduce_mean(triplet_loss)
return triplet_loss

本文目的在於學術交流,並不代表本公眾號贊同其觀點或對其內容真實性負責,版權歸原作者所有,如有侵權請告知刪除。




分享、點讚、在看,給個三連擊唄!

相關焦點

  • Siamese網絡,Triplet Loss以及Circle Loss的解釋的
    最小化triplet loss函數之前(左)和之後(右)Triplet Loss函數背後的想法是,我們推遠或最大化錨和負樣本之間的距離,同時拉近或最小化錨和正樣本嵌入之間的距離因此,我們最終可以將triplet loss函數定義為:
  • 【強基固本】深度強化學習(Deep Reinforcement Learning)入門
    「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本
  • 直播 | Circle Loss:從對相似性優化的統一視角進行深度特徵學習
    本期 PW Live,我們邀請到曠視科技上海研究院算法研究員程昌茂,為大家帶來Circle Loss:從對相似性優化的統一視角進行深度特徵學習的主題分享。深度特徵學習一直受到學術界的廣泛關注,眾多的損失函數被提出用於學習好的特徵表示。例如,用於分類學習的 softmax cross entropy loss 及其變種 AM-Softmax(CosFace)、ArcFace 等,用於樣本對距離優化的 contrastive loss 和 triplet loss 等。
  • 【強基固本】深度學習: 數學知識基礎
    「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本
  • 【深度度量學習系列】​Triplet-loss原理與應用
    深度度量學習(Deep Metric Learning, DML)的一個經典的應用就是人臉識別,Google 的FaceNet模型使用Triplet-Loss刷新了當時人臉識別的記錄。Ranking loss被用在很多不同的領域,它有非常廣泛應用,但缺乏命名標準化,導致了這個損失函數擁有很多其他別名,比如對比損失Contrastive loss,邊緣損失Margin loss,鉸鏈損失hinge loss和我們常見的三元組損失Triplet loss等。
  • 【乾貨】Lossless Triplet Loss: 一種高效的Siamese網絡損失函數
    儘管Google的FaceNet利用Triplet Loss效果顯著,但作者認為,原來網絡中triplet_loss函數存在一定的瑕疵:「每當你的損失小於0時,損失函數就不能提供任何信息」。為解決這種問題,作者構建一個能夠捕捉到小於0的損失——Lossless Triplet Loss。在文中充分分析了不同傳統Triplet Loss及其變體的不足,然後通過實驗初步證明了提出的損失函數的有效性。
  • FAT:一種快速的Triplet Loss近似方法,學習更魯棒的特徵表示,並進行有噪聲標籤的提純
    本文的貢獻:提出了FAT loss,提升了標準的triplet loss的效率。首次證明了處理了標註噪聲可以進一步提升ReID的性能。通過分配soft label可以學到更魯棒的特徵。2.方法2.1 Fast Approximated Triplet (FAT) LossFAT loss的推導如下:
  • 度量學習中的pair-based loss
    度量學習應用在很多領域中,比如圖像檢索,人臉識別,目標跟蹤等等。在深度學習中,很多度量學習的方法都是使用成對成對的樣本進行loss計算的,這類方法被稱為 pair-based deep metric learning。例如,在訓練模型的過程,我們隨意的選取兩個樣本,使用模型提取特徵,並計算他們特徵之間的距離。
  • 【強基固本】我們真的需要深度圖神經網絡嗎?
    「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本
  • 【損失函數合集】Yann Lecun的Contrastive Loss 和 Google的Triplet Loss
    Triplet Loss的目標:Triplet Loss的目標是使得相同標籤的特徵在空間位置上儘量靠近,同時不同標籤的特徵在空間位置上儘量遠離,同時為了不讓樣本的特徵聚合到一個非常小的空間中要求對於同一類的兩個正例和一個負例,負例應該比正例的距離至少遠margin。如下圖所示:
  • 【爭做精誠法院人,文化固本、強基提質篇】如何擔當作為?聽聽這名...
    【爭做精誠法院人,文化固本、強基提質篇】如何擔當作為?講座上,趙建新副院長引用《論語》子路問政的典故直接點題,結合《關於進一步激勵廣大幹部新時代新擔當新作為的意見》的規定,分別從「什麼是擔當作為」、「如何體現擔當作為」、「如何做到擔當作為」三個方面,對擔當作為的內涵、擔當精神的具體體現、擔當精神從何而來及黨員領導幹部必須做到的「五個過硬」要求進行了深度解析,對新時代法院人怎樣實現新擔當新作為進行了全新闡釋。
  • 「每周CV論文推薦」初學深度學習人臉識別和驗證必讀文章
    在這個專欄裡,還是本著有三AI一貫的原則,專注於讓大家能夠系統性完成學習,所以我們推薦的文章也必定是同一主題的。人臉識別和驗證是當前人臉圖像在身份認證領域中最廣泛的應用,今天給大家介紹入門深度學習人臉識別必讀的文章。
  • 固本強基 蹈厲奮發
    2015年,原南空黨委籌劃實施「強基固本」工程正式拉開序幕,他們計劃用3年時間,按照「先抓航空兵部隊、新組改建部隊、邊遠艱苦基層單位,後抓其他地面部隊,再拾遺補漏、固強補弱」的思路,一步一動把全區所有建制基層單位抓建一遍,推動基層基礎建設全面邁上新臺階。
  • GitHub | 機器學習&深度學習&nlp&cv從入門到深入全套資源分享
    深度學習之目標檢測的前世今生(Mask R-CNN)深度學習目標檢測模型全面綜述:Faster R-CNN、R-FCN和SSD從RCNN到SSD,這應該是最全的一份目標檢測算法盤點目標檢測算法綜述三部曲基於深度學習的目標檢測算法綜述(一)基於深度學習的目標檢測算法綜述(二)基於深度學習的目標檢測算法綜述
  • 深度學習變革視覺實例搜索
    這篇文章的另一個改進工作就是Weakly supervised triplet ranking loss。為了實現該效果,常用的方法是通過優化triplet ranking loss,去訓練CNN網絡。但是,作者發現原始的triplet ranking loss存在一些問題,如下圖所示:
  • 乾貨分享 | 機器學習、深度學習、nlp、cv從入門到深入全套資源分享
    深度學習之目標檢測的前世今生(Mask R-CNN)深度學習目標檢測模型全面綜述:Faster R-CNN、R-FCN和SSD從RCNN到SSD,這應該是最全的一份目標檢測算法盤點目標檢測算法綜述三部曲基於深度學習的目標檢測算法綜述(一)基於深度學習的目標檢測算法綜述(二)基於深度學習的目標檢測算法綜述
  • CVPR 2020 Oral|曠視研究院提出Circle Loss,統一優化視角
    論文連結:https://arxiv.org/abs/2002.10857深度特徵學習有兩種基本範式,分別是使用類標籤和使用正負樣本對標籤進行學習。使用類標籤時,一般需要用分類損失函數(比如 softmax + cross entropy)優化樣本和權重向量之間的相似度;使用樣本對標籤時,通常用度量損失函數(比如 triplet 損失)來優化樣本之間的相似度。這兩種學習方法之間並無本質區別,其目標都是最大化類內相似度(s_p)和最小化類間相似度(s_n)。
  • 【強基固本】樣本量極少如何機器學習?Few-Shot Learning概述
    「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本
  • 【強基固本】邊框回歸(Bounding Box Regression)詳解
    「強基固本,行穩致遠」,科學研究離不開理論基礎,人工智慧學科更是需要數學、物理、神經科學等基礎學科提供有力支撐,為了緊扣時代脈搏,我們推出「強基固本
  • 國網甘肅蘭州供電:強基固本補短板 提質增效促發展
    作為「十大工程」之一的「組織建設強基工程」重點實踐單位,國網蘭州供電公司進一步夯實基層基礎、創新方法載體、提升質效價值,以高質量黨建工作推動國家電網公司戰略目標落實落地。同時,創新基層黨組織設置方式和工作模式,堅持業務擴展到哪裡,黨組織建設就覆蓋到哪裡,在抗洪搶險、脫貧攻堅配農網改造、元山330千伏輸變電工程等工作一線成立7個臨時黨支部,充分發揮黨支部戰鬥堡壘作用。 基礎不牢、地動山搖。