由PyRetri淺談基於深度學習的圖像檢索

前言

最近發現face++開源了一個圖像檢索和行人重識別的基於深度學習的軟件包,最近一段時間也一直在接觸圖像檢索相關的東西。故藉此機會,對裏面涉及的一些常用的方法模塊進行一個簡單的介紹總結,便於日後回顧。

PyRetri是什麼?

PyRetri是由曠視開源的第一個基於深度學習的無監督圖像檢索庫,它是基於PyTorch進行開發的python庫。

paper: https://128.84.21.199/abs/2005.02154

GitHub: https://github.com/PyRetri/PyRetri

PyRetri將基於深度學習的無監督CBIR分爲了三個重要的部分:特徵提取(feature extraction)、索引(indexing)和評估(evaluation)。其主要的整體框架圖如下:

PyRetri

圖像檢索常用公開數據集

圖像檢索並不是一個新興的研究方向,現階段針對不同場景以及需求的圖像檢索都或多或少有數據集公開。強烈推薦一個總結了常用的計算機視覺數據集列表的網站:Yet Another Computer Vision Index To Datasets (YACVID)

下面簡單介紹一些常見的圖像檢索數據集概況,針對實例檢索,往往很多場景也都會使用大規模的分類數據集。

收集方式: 通過關鍵字在Flickr上查詢下載圖片 每一個query對應good、OK、junk list文件,作爲ground truth

規模: total :5062 query: 55 (11*5)

特點: 除提供.jpg格式圖片外,還提供sift描述符的壓縮二進制文件等

paper: Object retrieval with large vocabularies and fast spatial matching(CVPR 2007)

收集方式: 與Oxford5K相同(查詢關鍵字不同)

規模: total :6412 query: 55(11*5)

特點: 僅提供.jpg格式圖片

paper: Lost in Quantization: Improving Particular Object Retrieval in Large Scale Image Databases(CVPR 2008)

收集方式: 基於Oxford5K

規模: query 50->70

特點: 修復原來數據標註問題 增加數據 標籤細化

paper: Revisiting Oxford and Paris: Large-Scale Image Retrieval Benchmarking(CVPR 2018)

收集方式: 基於Paris6K

規模: query 50->70

特點: 修復原來數據標註問題 增加數據 標籤細化

paper: Revisiting Oxford and Paris: Large-Scale Image Retrieval Benchmarking(CVPR 2018)

規模: total :200萬張圖片 3萬個獨特地標

特點: kaggle 比賽

paper: Large-Scale Image Retrieval with Attentive Deep Local Features( ICCV 2017)

收集方式: 攝影社區衆包進行實例標註

規模: total:超過500萬張圖像 超過20萬個不同的地標

特點: kaggle 比賽

paper: Detect-to-Retrieve: Efficient Regional Aggregation for Image Search (CVPR 2019)

收集方式: web 圖片和3D模型(點雲)

規模: total :45180

特點: 25個地標 ;45,180個數據庫圖像(每個地標1.4K-2K);10,000個正面query用於評估(每個標誌400個);3D模型中約270萬個3D點(每個地標29K-223K); 約有5800萬個SIFT

paper: 3D Visual Phrases for Landmark Recognition". in Proc. of the 25th IEEE Conference on Computer Vision and Pattern Recognition (CVPR 2012)

收集方式: 數據集是從Flickr和Panoramio收集的地標圖像。圖像具有“自然”分佈,數據集非常具有挑戰性,因爲存在重複和近似重複,以及大量不相關的圖像,例如派對,寵物等的照片

規模: total :501,356

特點: 提供79個地標建築的94303張圖片clustering ground truth

paper: Discovering Details and Scene Structure with Hierarchical Iconoid Shift(ICCV 2013)

收集方式: ZuBuD+ 是對ZuBuD的擴展,主要是增加了測試圖片 評估方式:TOP5

規模: total :1005 training data/1005 test_balance data

特點: 每個圖像有201個建築物,每個視圖有五個視圖,提供訓練數據、相同數量的測試數據、ground truth file 和 用於評估的python程序

paper: A location-aware embedding technique for accurate landmark recognition(2017)

收集方式:是 CUB-200數據集 的擴展

規模:total : 11788, 200類別

特點:每個圖片都有註釋 15 Part Locations, 312 Binary Attributes, 1 Bounding Box 圖片與ImageNet重疊 常用於細粒度分類、檢索等

paper: Wah C., Branson S., Welinder P., Perona P., Belongie S. “The Caltech-UCSD Birds-200-2011 Dataset.” Computation & Neural Systems Technical Report, CNS-TR-2011-001.

規模:total :15620 67個室內場景 train set :67*80 test set :67*20

特點:圖片有annotation (實例分割) LabelMe格式

paper: A. Quattoni, and A.Torralba. Recognizing Indoor Scenes. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2009.

規模:101個類別,每類40-80張

特點:通用的分類的數據集(有annotation),注:往往分類數據集也會用來實例檢索

paper: Learning generative visual models from few training examples: an incremental Bayesian approach tested on 101 object categories. CVPR 2004

行人重識別常用數據集

行人重識別(person re-id)是圖像檢索的子領域,近幾年從各大計算機視覺會議的論文收錄情況也可以看出,行人重識別已經成爲了計算機視覺領域的研究熱點。無論是從社會意義還是從商業角度上來看,行人重識別都具有一定的研究意義。因爲PyRetri提到了其也適用於行人重識別任務,那麼我們也簡單的介紹一下行人重識別常用的數據集。

針對行人重識別數據集,推薦網站: awesome-reid-dataset

  • Market-1501

    Market-1501 數據集最早是 2015 年 公佈的, 是至今使用廣泛的大規模行人重識別數據集之一。該數據集使用 6 個攝像頭(5 個高分辨率,一個低分辨率)在清華大學超市前收集的。爲了保證跨攝像頭搜索,不同攝像頭之間存在重疊,並且保證每一個被標註的行人至少來自兩個攝像頭。更具體地,數據集包括 1501 個行人共 32668 張圖片。網上所提供的公開數據集已將 32668張圖片分爲了訓練集和測試集,其中測試集文件夾中包含 19732 張圖片,訓練集文件夾中包含 12936 張圖片。另外將每個攝像頭隨機選出的一張 ID 行人共3368 張圖片(750 個 ID,每個 ID 至多 6 張)作爲待選集單獨分開。
    paper: Scalable Person Re-identification: A Benchmark (ICCV 2016)

  • CUHK01

    CUHK01 數據集由香港中文大學研究團隊公開, 相關信息首次發表於2012 年的亞洲計算機視覺會議上。該數據集採自一對不相交的相機(即具有兩個攝像視角)在大學校園收集的。一個視角主要捕獲行人的正面和背面,另一個視角主要捕獲行人的側面。該數據集共收集了 971 個行人的 3884 張圖片,每個行人包含來自兩個視角的共4 張圖片。由於採集環境和設備的關係以及採用手工裁剪標註的形式致使CUHK01 數據集行人圖片的質量相對較好。
    paper: Human re-identification with transferred metric learning (ACCV 2012)

  • CUHK03

    2014 年起深度學習進入行人重識別領域,爲解決之前數據集太小無法滿足深度學習訓練的問題,香港中文大學的 Li 等人建立了較大規模的行人重識別數據集,名爲 CUHK03,此前,他們已經建立了 CUHK01 和 CUHK02 數據集。CUHK03數據集由 5對不同的監控視角拍攝,包含 1360個行人的 13164張圖片。此外, CUHK03 數據集還具有以下幾個特點: 1) CUHK03 除了手工裁剪的圖片以外,還有使用檢測算法進行檢測裁剪的圖片。這使得 CUHK03 的數據集更接近於真實的環境,錯位、遮擋、部位缺失都是常見的情況。 2) CUHK03 的樣本是通過複雜的交叉視圖混合變換採集的。 3)由於數據集中的圖像獲取是經過了幾個月的時間,導致不同圖片間存在着光照的不同。這些都使得 CUHK03 數據集上的行人重識別任務更具有挑戰性。
    paper: DeepReID: Deep Filter Pairing Neural Network for Person Re-identification (CVPR 2014)

  • DukeMTMC-reID

    DukeMTMC數據集是一個大規模的多目標多攝像機行人跟蹤數據集。數據集包含了 85 分鐘的高分辨率視頻,收集了來自8 個不同的攝像頭, 超過 2700 個不同行人數據信息。基於該原始數據集,兩個行人重識別擴展數據集 DukeMTMC-reID 和 DukeMTMC4ReID 分別被創建。其主要區別在於行人邊界框的生成方式,前者採用的是直接手工標註,後者則採用 Doppia 作爲檢測器進行目標檢測標註。DukeMTMC-reID作爲DukeMTMC 數據集的行人重識別子集,共有36,411 張圖像(原始視頻中每 120 幀採樣一張)。數據集中共包括 1812 個行人,其中 1404 個行人在至少兩個攝像頭以上出現,餘下的 408 個行人只出現在單一 攝像頭下。故在將該數據集按照 Market-1501 數據集格式組織時,隨機採樣 702個行人圖片作爲訓練集,另外 702 個行人圖片作爲測試集。 查詢集(query) 中爲 1404 個行人 ID 每個攝像頭下的一張圖片,剩下的所有圖片作爲搜索庫(gallery),其中也包括 408 個行人的圖片作爲干擾信息項。最終 DukeMTMC-reID 的數據構成訓練集 16522 張、查詢集 2228 張圖片、 以及搜素庫 17661 張圖片。其命名規則與 Market-1501 數據集圖片命名規則相同。
    paper: Performance Measures and a Data Set for Multi-target,Multi-camera Tracking (ECCV 2016)

特徵提取 feature extraction

圖片預處理方法

無論是圖像檢索還是其他計算機視覺相關的任務都會多多少少涉及到圖片預處理相關的方法,同樣的圖片預處理對於圖像相關任務也有這重要的作用,往往簡單的進行圖片增強就可以提高網絡的performance。因爲由PyRetri而起,這邊也主要介紹一下,PyRetri提供的預處理方法以及探索一下其在代碼實現上有什麼可以借鑑的亮點之處。

  • 縮放

    1)DirectResize:

    功能:按指定大小resize

    參數:目標size(w,h)\ 插值方式

    2)PadResize:

    功能:指定長邊的長度,短邊通過填充到相同大小resize

    參數:長邊長度\padding的像素值\插值方式

    3)ShorterResize

    功能:指定短邊的長度,並保持原來圖像寬高比進行resize

    參數:短邊長度\插值方式

  • 裁剪

    1)CenterCrop:

    功能:從圖片中心按指定大小進行裁剪

    參數:指定的圖片大小

    2)TenCrop:

    功能:按指定大小將原圖進行上下左右中心裁剪,並進行翻轉(默認水平)得到10張圖片

    參數:指定的圖片大小

  • 翻轉

    TwoFlip:

    功能:返回原圖和水平翻轉後的圖片

    參數:圖片

  • 其他

    1)ToTensor:

    功能:將圖片轉爲Tensor

    注:PIL的圖片size是(w,h) 轉爲的tensor是(c,h,w)

    2)ToCaffeTensor:

    功能:將圖片轉爲適應在Caffe中預訓練的模型

    注:在PyTorch中圖片的組織方式是PIL——RGB,而在Caffe中圖片的組織方式是OpenCV——BGR

    3)Normalize:

    功能:使用特定的均值和方差來normalize tensor,減均值除方差

    參數:指定的均值和方差

上述是PyRetri中提供的圖片預處理的方法,簡單看了代碼基本上在torchvision.transforms的基礎上進行的二次開發。從更大的層面看,在計算機視覺中的圖片增強預處理方法遠遠不止上述所述。常見的數據增強方法概括上來說,包括:翻轉、旋轉、縮放、裁剪、平移、加噪聲、隨機擦除、顏色亮度對比度方面進行變化等等,更一般地,針對增強還可以採用一些生成方法來進行圖片生成。

基礎網絡Backbone

在很多計算機視覺任務中都會使用源於分類的基本網絡骨架,在此基礎上再進行一些特定任務的擴展與延伸。發展至今,經典網絡從最開始的AlexNet、VGG等到現在的通過NAS涌現的一些網絡(例如EfficientNet),可選擇的網絡很多。對於基於深度學習的圖像檢索,在特徵提取部分往往也是採用在數據集上訓練好的經典網絡,然後抽取某層的輸出(最開始是全連接層、現在一般是中間層特徵然後在進行融合)。PyRetri庫中提供了VGG16和ResNet50(後續應該會增加更多),在其進行的性能試驗中也是通過採用在不同的數據上面訓練的這兩個模型的比較。

經典網絡介紹: https://blog.csdn.net/u014448054/article/details/102612195

PyRetri 提供的MODEL ZOO: https://github.com/PyRetri/PyRetri/blob/master/docs/MODEL_ZOO.md

特徵融合Aggregation

深度學習最早應用到圖像檢索的特徵提取中時,最常使用的是全連接層輸出的特徵描述。然而選用上層的語義層其實是不利於object retrieval,因爲上層的語義層丟失了object的空間信息,並且多篇論文都從實驗的角度說明了選取中間層的特徵更利於object retrieval。

實際上,在選取中間層來表達特徵的過程中,我們可以去掉全連接層,從而使得我們可以擺脫掉輸入圖像尺寸約束(比如224*224)的約束,而保持原圖大小的輸入。

通常,圖像分辨率越大,對於分類、檢測等圖像任務是越有利的。因而,從這一方面講,選取上層的全連接層作爲特徵,並不利於我們的object retrieval任務。一種可能的猜想是,上層全連接層的語義特徵,應該更適合做全局的相似。

雖然中間層更適合於做object retrieval,但是在選用中間層的feature map作爲raw feature的時候,我們面臨的一個主要問題是:如何將3d的tensor轉成一個有效的向量特徵表示? 這就涉及到了一些特徵融合處理的方式,在深度學習中,一般會採用池化的方式進行特徵融合,接下來會詳細地介紹一些常用的特徵融合方法。

  • 最大池化 max pooling

    MAX pooling指的是對於每一個channel(假設有N個channel),將該channel的feature map的像素值選取其中最大值作爲該channel的代表,從而得到一個N維向量表示。

  • 求和池化 sum pooling

    SUM pooling指的是對於每一個channel(假設有N個channel),將該channel的feature map的所有像素值求和,這樣每一個channel得到一個實數值,N個channel最終會得到一個長度爲N的向量。

  • 全局平均池化 global average pooling

    AVG pooling指的是對於每一個channel(假設有N個channel),將**該channel的feature map的所有像素值求和在除以像素個數求平均值,**這樣每一個channel得到一個實數值,N個channel最終會得到一個長度爲N的向量。

# feature.shape (b,c,h,w)
feature = feature.mean(dim=3).mean(dim=2)
  • SPoC:sum-pooled convolutional

    這種特徵融合方式在sum pooling的基礎上面考慮到了ROI的思想。具體地,針對深度特徵向量,假定座標點的空間位置與權重服從二維高斯分佈,中心點爲μ\mu,方差σ\sigma爲中心點距離最近邊界的距離的三分之一。據此,通過特徵點的空間座標求出權重矩陣,在進行加權求和來進行特徵融合。

# SPoC核心代碼
h, w = feature.shape[2:]
sigma = min(h, w) / 2.0 / 3.0
x = torch.Tensor(range(w))
y = torch.Tensor(range(h))[:, None]
spatial_weight = torch.exp(-((x - (w - 1) / 2.0) ** 2 + (y - (h - 1) / 2.0) ** 2) / 2.0 / (sigma ** 2)) #求權重
feature = (feature * spatial_weight).sum(dim=(2, 3)) #加權求和
  • CROW pooling : Cross-dimensional Weighting 跨維加權池化
    CROW pooling 也是基於ROI的思想提供的池化方法,通過構建Spatial權重和Channel權重,其能夠在一定程度上加大感興趣區域的權重,降低非物體區域的權重。

    1)針對Spatial Weight,考慮到通過卷積濾波,響應強的地方一般都是物體的邊緣等,因而將多個通道相加求和後,那些非零且響應大的區域,也一般都是物體所在的區域,因而我們可以將它作爲feature map的權重。計算公式如下:
    Sij=(Sij(m,nSm,na)1a)1bS_{ij}=(\frac{S'_{ij}}{(\sum_{m,n}S_{m,n}^{'a})^{\frac{1}{a}}})^{\frac{1}{b}}

    2)針對Channel Weight,借用了IDF權重的思想。比如某一個channel,其feature map每個像素值都是非零的,且都比較大,從視覺上看上去,白色區域佔據了整個feature map,我們可以想到,這個channel的feature map是不利於我們去定位物體的區域的,因此我們需要降低這個channel的權重,而對於白色區域佔feature map面積很小的channel,我們認爲它對於定位物體包含有很大的信息,因此應該加大這種channel的權重。簡單的說,計算每一個通道的非零數據的比例,然後對所有通道非零的比例求和,某個通道非零數據比例除以總非零數據比例的log就是Channel Weight,和IDF思想不謀而合。

# CROW Pool 核心代碼
# Spatial weight 計算
spatial_weight = feature.sum(dim=1, keepdims=True)
z = (spatial_weight ** spatial_a).sum(dim=(2, 3), keepdims=True)
z = z ** (1.0 / spatial_a)
spatial_weight = (spatial_weight / z) ** (1.0 / spatial_b)

# Channel weight 計算
c, w, h = feature.shape[1:]
nonzeros = (feature!=0).float().sum(dim=(2, 3)) / 1.0 / (w * h) + 1e-6
channel_weight = torch.log(nonzeros.sum(dim=1, keepdims=True) / nonzeros)

# 聯合計算融合特徵
feature = feature * spatial_weight
feature = feature.sum(dim=(2, 3))
feature = feature * channel_weight
  • MOP Pooling : Multi-Scale Orderless Pooling 多尺度無序池化

    此pooling方法未在PyRetri中實現,但是在介紹R-MAC之前有必要簡單的瞭解一下這種方法。其算法主要過程如下:

    對圖片分爲三級尺度,將輸入圖片resize到256*256:

    1)將256*256大小的圖片輸入到網絡中,在全連接層後得到1*4096D向量

    2)在256*256的圖片上以大小128*128,步長爲32進行塊採樣,得到5*5個128*128的patch,對每一個patch,上採樣到256*256並輸入網絡中,得到1*4096D向量

    3)在256*256的圖片上以大小64*64,步長爲32進行塊採樣,得到7*7個64*64的patch,對每一個patch,上採樣到256*256並輸入網絡中,得到1*4096D向量

    4)對所得到的向量進行PCA降維至500D

    5)將降維後的向量使用VLAD進行融合,VLAD聚類中心爲100,融合後的特徵爲500*100D

    6)對融合後的特徵進行PCA降維至4096

  • R-MAC: Regional Maximum activation of convolutions
    和MOP有些相似地,R-MAC也考慮到了圖片的局部區域特徵,而不同於在圖片上進行塊採樣的方式,R-MAC採用在feature map進行滑動窗口的方式來體現Local feature的思想,此外不同於使用VLAD,R-MAC則處理得更簡單,直接將local特徵相加得到最終的global特徵。

R-MAC

圖中x代表滑窗中心,以上述三種方式在feature map上進行滑窗採樣,共20個local feature,每一個子滑窗,採用max pooling的方式進行區域融合。20個local feature和一個global feature(整個feature map + max pooling) 進行求和,得到最後的特徵向量。另外,也可以將20個local feature求和合並並與global feature串聯拼接。

# R-MAC實現代碼
def rmac(x, L=3, eps=1e-6):
    ovr = 0.4 # desired overlap of neighboring regions
    steps = torch.Tensor([2, 3, 4, 5, 6, 7]) # possible regions for the long dimension
    W = x.size(3)
    H = x.size(2)
    w = min(W, H)
    w2 = math.floor(w/2.0 - 1)
    b = (max(H, W)-w)/(steps-1)
    (tmp, idx) = torch.min(torch.abs(((w**2 - w*b)/w**2)-ovr), 0) # steps(idx) regions for long dimension
 
    # region overplus per dimension
    Wd = 0;
    Hd = 0;
    if H < W: 
        Wd = idx.item() + 1
    elif H > W:
        Hd = idx.item() + 1
 
    v = F.max_pool2d(x, (x.size(-2), x.size(-1)))
    v = v / (torch.norm(v, p=2, dim=1, keepdim=True) + eps).expand_as(v)
 
    for l in range(1, L+1):
        wl = math.floor(2*w/(l+1))
        wl2 = math.floor(wl/2 - 1)
 
        if l+Wd == 1:
            b = 0
        else:
            b = (W-wl)/(l+Wd-1)
        cenW = torch.floor(wl2 + torch.Tensor(range(l-1+Wd+1))*b) - wl2 # center coordinates
        if l+Hd == 1:
            b = 0
        else:
            b = (H-wl)/(l+Hd-1)
        cenH = torch.floor(wl2 + torch.Tensor(range(l-1+Hd+1))*b) - wl2 # center coordinates
             
        for i_ in cenH.tolist():
            for j_ in cenW.tolist():
                if wl == 0:
                    continue
                R = x[:,:,(int(i_)+torch.Tensor(range(wl)).long()).tolist(),:]
                R = R[:,:,:,(int(j_)+torch.Tensor(range(wl)).long()).tolist()]
                vt = F.max_pool2d(R, (R.size(-2), R.size(-1)))
                vt = vt / (torch.norm(vt, p=2, dim=1, keepdim=True) + eps).expand_as(vt)
                v += vt
    return v
  • SCDA:Selective Convolutional Descriptor Aggregation

    仍是源於希望針對細粒度檢索任務,能夠在無監督的情況下對物體進行定位。基於對卷積層輸出特徵響應情況的觀察。SCDA使用以下方式,進行特徵融合:首先在channel方向進行求和即將H*W*C的tensor變成H*W*1大小,然後將各個值與通道方向的均值進行對比,如果大於就設爲1否則爲0,生成一個H*W的mask。針對這個mask可以使用BFS的方式找到最大的連通區域,近一步得到只含有最大連通域的mask。然後將原始特徵與mask進行相乘,得到的結果在H*W方向求均值和最大值,將兩者連接得到最終融合後的特徵向量2C*1。

    具體實現代碼可以看PyRetri中的scda.py

  • PWA:Part-Based Weighting Aggregation

    此融合方法來自AAAI2018的一篇無監督圖像檢索的文章,與一些融合方法相似,這種融合方式也是出於在無監督的情況下,可以通過融合的方式來強化各個組件的特徵。具體地,在訓練階段,將feature map在channel方向按照方差進行從大到小進行排序並取前N個,得到N*H*W的probabilistic proposals。在測試階段,針對每一張圖片的輸出feature C*H*W與N*H*W進行點乘求和(“加權求和”)得到N*C,近一步得到1*NC的向量,在後處理階段可以近一步對該向量採用降維等方式降低維度。

  • GeM:Generalized-mean pooling

    GeM是更一般的池化方式,計算公式如下:
    f(g)=[f1(g)fk(g)fK(g)]Tf^{(g)} = [f_{1}^{(g)}…f_{k}^{(g)}…f_{K}^{(g)}]^{T}

    fk(g)=(1XkxXkxpk)1pkf_{k}^{(g)} = (\frac{1}{|X_{k}|}\sum_{x\in X_{k}}x^{p_{k}})^{\frac{1}{p_{k}}}

    pkp_{k}趨近於正無窮時,上式相當於max pooling。當pkp_{k}=1時,上式相當於avg pool,可以說Generalized-mean pooling是更普遍的池化公式,理論上在每一層上,我們可以使用不用的pkp_{k},來進行不一樣的池化操作。

    實驗中發現,pkp_{k}可以固定爲一個值,並且效果也不差。

def gem(feature,p = 3,eps = 1e-6):
	feature = feature.clamp(min=eps) ** p
	h, w = feature.shape[2:]
	feature = feature.sum(dim=(2, 3)) * 1.0 / w / h
	feature = feature ** (1.0 / p)

對於Object Retrieval,在使用CNN提取特徵的時候,我們所希望的是在有物體的區域進行特徵提取,就像提取局部特徵比如SIFT特徵構BoW、VLAD、FV向量的時候,可以採用MSER、Saliency等手段將SIFT特徵限制在有物體的區域。同樣基於這樣一種思路,在採用CNN做Object Retrieval的時候,我們有兩種方式來更細化Object Retrieval的特徵:一種是先做物體檢測然後在檢測到的物體區域裏面提取CNN特徵;另一種方式是我們通過某種權重自適應的方式,加大有物體區域的權重,而減小非物體區域的權重。在上述所介紹的方法中,我們也可以看到很多特徵融合池化方法所提出的初衷和思想也是基於這一思路的。

索引indexing

PyRetri中並沒有針對大規模數據的向量索引的建立,有時間會根據milvus或faiss來分析:基於樹的搜索算法;基於哈希的空間劃分法;向量量化的編碼算法;基於圖的搜索方法等。

維度處理 Dimension Process

  • L2正則化
    L2範數歸一化放在維度處理這邊多少有些不合適,但是其確實是圖像檢索中常用到的對特徵向量進行處理的一種方式。其計算方式就是特徵向量除以其自身的L2範數,經過L2範數歸一化後,一組向量的歐式距離和它們的餘弦相似度可以等價。
def l2n(x, eps=1e-6):
	return x / (torch.norm(x, p=2, dim=1, keepdim=True) + eps).expand_as(x)
  • PCA: Principal Component Analysis 主成成分分析
    PCA是一種常用的數據分析方法。PCA通過線性變換將原始數據變換爲一組各維度線性無關的表示,可用於提取數據的主要特徵分量,常用於高維數據的降維。涉及到的數學知識點: 向量表示,內積,基變換,協方差,特徵值,特徵向量,協方差矩陣對角化。

    PCA過程:1.輸入矩陣X行零均值化 2.求出協方差矩陣 3.求出協方差矩陣的特徵值及對應的特徵向量 (求解特徵方程的解)4.將特徵向量按對應特徵值大小從上到下按行排列成矩陣,取前k行組成矩陣U 5.X’=UX即爲降維到k維後的數據。

    代碼實現上,可以直接使用sklearn.decomposition中的PCA進行處理。PyRetri中還提到了part-PCA的概念,就是不是針對整個圖片feature map來進行pca而是將feature map分成幾個part,對每個part進行PCA操作再將處理後的特徵拼接在一起。

    寫給自己:PCA是無監督的方法,但是注意瞭解訓練的含義。

  • SVD:Singular Value Decomposition 奇異值分解
    推薦閱讀:奇異值分解(SVD)原理與在降維中的應用
    同樣的代碼實現可使用sklearn.decomposition中的SVD進行處理。

特徵增強 Feature Enhance

PyRetri中介紹的特徵增強的方法源自文章:Three things everyone should know to improve object retrieval

主要思想就是將特徵中的每個值都用它自身的值和K近鄰點的值得加權求和來代替。

距離度量 Distance Metric

談到距離的度量離不開數據格式,在檢索中常出現的數據格式就是浮點型和二值型,而針對浮點型數據距離計算有歐式距離、餘弦相似度等,而對於二值型數據常採用Jaccard距離、Hamming距離等。

  • 歐式距離(L2)
    歐氏距離計算的是兩點之間最短的直線距離。歐氏距離的計算公式爲:
    d(a,b)=d(b,a)=i=1n(biai)2d(a,b) = d(b,a) = \sqrt{\sum_{i=1}^{n}(b_{i}-a_{i})^{2}}
    其中 a = (a1, a2,…, an) 和 b = (b1, b2,…, bn) 是 n 維歐氏空間中的兩個點。歐氏距離是最常用的距離計算方式之一,應用廣泛,適合數據完整,數據量綱統一的場景。

  • 內積 (IP)
    內積計算兩條向量之間的夾角餘弦,並返回相應的點積。內積距離的計算公式爲:
    cosθ=ABABcos\theta = \frac{A\cdot B}{||A||\cdot||B||}
    假設有 A 和 B 兩條向量,則 ||A|| 與 ||B|| 分別代表 A 和 B 歸一化後的值。cosθ 代表 A 與 B 之間的餘弦夾角。內積更適合計算向量的方向而不是大小。

    注:在向量歸一化之後,內積與餘弦相似度等價。

  • 傑卡德距離
    傑卡德相似係數計算數據集之間的相似度,計算方式爲:數據集交集的個數和並集個數的比值。計算公式可以表示爲:
    J(A,B)=ABA+BAB J(A,B) = \frac{|A\cap B|}{|A|+|B|-|A\cap B|}
    傑卡德距離是用來衡量兩個數據集差異性的一種指標,被定義爲 1 減去傑卡德相似係數。對於二值變量,傑卡德距離等價於谷本系數。
    dj(A,B)=1J(A,B)=ABABABd_{j}(A,B) = 1-J(A,B)=\frac{|A\cup B|-|A\cap B|}{|A\cup B|}
    傑卡德距離適合字符串相似性度量。

  • 漢明距離
    漢明距離計算二進制字符串之間的距離。兩個等長字符串之間的漢明距離定義爲將其中一個變爲另外一個所需要作的最小替換次數。

    比如,假設有兩條字符串 1101 1001 和 1001 1101。比較時,如果字符相同用 0 表示,如果字符不同則用 1 表示。

    11011001 ⊕ 10011101 = 01000100
    所以以上兩條字符串之間的漢明距離爲 2。

重排序 Re-Rank

在大規模索引中,最簡單的重排序,會使用原始的未經壓縮和索引過的特徵在返回的小範圍結果集的重新搜索排序一遍。 另外常用的重排序方法還有擴展查詢等。

  • QE:query expansion 擴展查詢
    擴展查詢的思想很簡單,在圖像檢索中就是將待查圖片的特徵和搜索出來的topk的圖片特徵取均值,再次進行一次查詢。

  • K-reciprocal:
    寫在開頭,這種re-rank方法在大規模的數據集上是時間上面的巨大犧牲。
    首先解釋什麼是k-reciprocal nearest neighbors,簡單地說要滿足兩個圖片都在對方的knn列表中。爲了應對光照、光照、姿態、視角等一系列變化,正樣本可能會被排除到k-nn列表外情況,論文中定義了一個更魯棒的k-rnn的集合。約束條件如下:

    R(p,k)R(p,k)R(q,12k R^{*}(p,k) \leftarrow R(p,k)\cap R(q,\frac{1}{2}k

    s.t.R(p,k)R(q,12k)23R(q,12k),qR(p,k)s.t. |R(p,k)\cap R(q,\frac{1}{2}k)|\geq \frac{2}{3}|R(q,\frac{1}{2}k),\forall q \in R(p,k)

    作者認爲,假如兩張圖片相似,那麼它們的k-rnn集合會重疊,即會有重複的樣本。重複的樣本越多,這兩張圖片就越相似。那麼很自然地就想到用Jaccard Distance度量它們k-rnn集合的相似度。但是這樣距離度量有一些缺點,比如說耗時間、將近鄰樣本中的每個都認爲同等重要、魯棒性不高。基於上述考慮,文章中將Jaccard距離進行了改造,將集合比較穩妥轉化爲了向量計算問題。具體說明和複雜度分析可以參考原論文。

    具體實現代碼可以看PyRetri裏面的k-reciprocal.py 也可以直接看論文的github。

評估 Evaluation

在圖像檢索中常用到的就是CMC曲線和mAP這兩個評估指標,PyRetri中實現了評估的代碼以及可視化的代碼。

  • CMC曲線
    CMC曲線衡量了識別系統的性能,反映了目標行人在候選列表每個位置出現的概率。假設查詢集中共有M張圖像,則一共執行M次查詢。對查詢圖像q,爲了提高訓練難度,在測試集中去除與q來自相同攝像視角的同一行人的圖像。取測試集中與𝑞距離最近的圖像,則與其相同標籤的圖片在候選列表中的位置rqr_{q},即爲查詢圖像𝑞的查詢結果。

  • mAP
    以查準率爲縱軸,召回率爲橫軸作圖,就得到了“查準率-召回率曲線”,簡稱“P-R 曲線”,而P-R曲線下的面積,就是查詢樣本q的AP值(Average Percision)APqAP_{q}。而mAP則爲查詢集中所有圖像的AP值的均值。

針對評估方法的詳細介紹,推薦閱讀:
ReID任務中的CMC和mAP

總結

PyRetri中提供很多方法,並且用戶可以直接進行使用,支持自動配置。後面有時間會寫一些關於大型圖像檢索上面所要面對的問題以及索引的一些方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章