---
# System prepended metadata

title: Person Re-Identification - RMNet
tags: [IVA, paper, PR]

---

# Person Re-Identification - RMNet
> [name=謝朋諺(Adam Hsieh)]
> [time=Thu, Jul 4, 2019 10:46 AM]
###### tags: `paper`,`IVA`,`PR`

---

## Reference
> [基于GRU和am-softmax的句子相似度模型](https://kexue.fm/archives/5743)

---

# Fast and Accurate Person Re-Identification with RMNet

[論文連結](https://arxiv.org/pdf/1812.02465.pdf)
{%pdf https://arxiv.org/pdf/1812.02465.pdf %}

## 摘要重點
* RMNet 的骨幹是參考 ResNet 跟 MobileNet。
* 期望建立一個可以用在 mobile 的有限計算裝置上。
* 全新的輕量權重的網路接頭結合了低 loss 與高 loss 的優點，而且還不會增加參數量。

![](https://i.imgur.com/cF3qICb.png)
:::info
:bulb: 上圖是作者在思考他們如何建造輕量版權重網路的思考流程
:::


## BackBone Design
* 本文遵循 "top-down" 的原則架設網路架構。
* 在 Deep 與 Shallow 中選擇了 Deep 的架構。原因是在 Bottlenet 的 Residual 架構可以被解釋為是在為同個 Level 的特徵做迭代增強，所以越深的 Level 才能看得越多，在 ResNet-18 或 ResNet-50 都太過淺，不能滿足我們的需求。e
* 因此本文的網路參考了幾個架構特點：
    * 有著 100 多層的深層網路。
    * 與 ResNet 相似的架構。
    * Residual blocks 使用三層的 CNN （$1\times1 \rightarrow 3\times3 \rightarrow 1\times1$）以及非線形函數，用此方式比起兩層的 CNN ($3\times3$)可以減少許多參數量。
* RMNet Backbone:
    * Residual blocks 第一個 ($1\times1$)CNN 負責縮減通道數，第二個 ($3\times3$)CNN 負責空間混合，最後一層 ($1\times1$)CNN 負責將它還原到最初的輸入大小。
    * 在內部卷積之後保留了非線性函數，外面的卷積也進行了 Max-Pooling 與 CNN 降到只剩 1/4 的強因子去相加。
    ![](https://i.imgur.com/5jAfb8N.png)

    * 使用 ELU 替代常用的 ReLU 會有顯著的改善。
    * 正交權重初始化（不適用於所有 Filter）。
    * 使用巨大的通用數據集進行預訓練。
    * 在每個 Bottleneck 結束前使用 Dropout 正規化。
    
    ![](https://i.imgur.com/UkkTGxQ.png)

## ReID Network
### Losses
* 本文定義了兩種 Loss: **Global and Local structure losses**
* **Global Loss**: 定義映射函數的 Global Rule，希望能夠讓相同類別的元素越近不同類別的越遠。
    * 對具有 Cross-Entropy Loss 的 Softmax 進行修改（下方第一個公式），變為關注在類之間具有較大 margin 的變數，也就是 **AM-Softmax loss**，公式如下第二個：
        ![](https://i.imgur.com/Cu5U0D8.png)
        ![](https://i.imgur.com/UOdaBm2.png)
:::info
:fire: **AM-Softmax**
假設原來的 softmax 是 $p=softmax(zW)$，設 $W=(c_1,c_2,...,c_n)$

那麼 softmax 可以重新寫為 $p=softmax(<z,c_1>,<z,c_2>,...,<z,c_n>)$

然後 loss 取交叉熵，也就是：$-log \space p_t=-log \dfrac{e^{<z,c_t>}}{\sum_{i=1}^{n}e^{<z,c_i>}}$

$t$ 為目標標籤，而 AM-Softmax 做了兩件事：

:::warning
1. 將 $z$ 和 $c$ 都做 l2 Normalization，也就是說內積變成 cosine 值。
2. 對目標 cosine 值減去一個正整數 $m$，然後做比例縮放 $s$。
:::
:::info
* Loss 最終就會變成

    * $-log \space p_t=-log \dfrac{e^{s\cdot(cos \theta _t -m)}}{e^{s\cdot(cos \theta _t-m)}+\sum_{i\neq t}e^{s\cdot cos\theta_t}}$

* 其中 $\theta_t$代表$z,c_i$的夾角。在 **AM-Softmax** 原論文中 $s=30, m=0.35$

* $s$ 的存在是必要的，因為要讓 cosine 的範圍是 $[1,-1]$，需要做好比例縮放，才允許 $p_t$ 能夠逐漸接近 $1$。
* 但整體核心是原來的 $cos\space\theta_t$ 換成了 $cos\space\theta_t-m$
:::
以下是用基本方式實作 **AM-Softmax** Loss 的範例程式碼：
```python=
from keras.models import Model
from keras.layers import *
import keras.backend as K
from keras.constraints import unit_norm


x_in = Input(shape=(maxlen,))
x_embedded = Embedding(len(chars)+2,
                       word_size)(x_in)
x = CuDNNGRU(word_size)(x_embedded)
x = Lambda(lambda x: K.l2_normalize(x, 1))(x)

pred = Dense(num_train,
             use_bias=False,
             kernel_constraint=unit_norm())(x)

encoder = Model(x_in, x) # 最终的目的是要得到一个编码器
model = Model(x_in, pred) # 用分类问题做训练

def amsoftmax_loss(y_true, y_pred, scale=30, margin=0.35):
    y_pred = y_true * (y_pred - margin) + (1 - y_true) * y_pred
    y_pred *= scale
    return K.categorical_crossentropy(y_true, y_pred, from_logits=True)

model.compile(loss=amsoftmax_loss,
              optimizer='adam',
              metrics=['accuracy'])
```

* **Local Loss**:
    * 不使用單純的 Triplet Loss 原因是他的採樣方式將會顯著影響 model 的準確率，而且 Triplet 每次只比一個負樣本。
    * 為了改善上述情況，本文將 Triplet Loss 變為: **Push and Pull Losses**
    * 這種 Loss 提出一種 $(N+1)$-Tuplet Loss 來同時優化一個正樣本和 $N-1$ 個負樣本，當 $N$ 為 $2$ 時等價於 Triplet。
    * 當 $N$ 很大時也會承擔很大的計算負擔，因此為了解決這問題，有一種高效的 **Batch Construction** 策略可以解決，僅僅使用 $2N$ 個樣本而不是 $N(N+1)$ 個樣本就能完成 $N$ 類的優化。
    * 通過 "smart" 變數 $m$ 來設定邊距。
    * 最後變為三個 Losses 的架構：
    ![](https://i.imgur.com/jKsmNbh.png)
* 最後整體 Loss 就是將 global 與 local 的 loss 相加（$w_i$ 是指預估每個 loss 在總和中的影響）：
![](https://i.imgur.com/gKvZksp.png)

## Re-identification Head
* 網路的最後一層 re-identification head 負責把骨幹中的輸出結果映射到 embedding，並且可以利用此 embedding 去計算 **cosine similarity** 或**歐式距離**。
* 一般我們都會使用 **Fully Connected** 去當最後一層輸出，但它卻會==浪費太多運算資源==，不便於移動裝置。
* 另外有些人會使用 global-pooling 當作輸出層，像是 max-pooling 或是 average-pooling，如下圖所示：

![](https://i.imgur.com/8tFtRSD.png)

* 本文的 Re-identification 有兩個關鍵元件：
    * 第一個是在 GMP 之後的 inverted bottleneck，裡面由 CNN ($1\times1$) 組成，將 channel 數由 256 變為 512 再壓回 256。
    * 第二個是利用 **Global Loss** 和 **Local Loss**，只用 **Local Loss** 進行訓練，然後通過學習 **Global Loss** 來校準它。
    * 對這兩種 Loss，本文皆使用 **L2 Normalization** 來遵循 **AM-Softmax** 提出的 embedding 限制（與 **Cosine Similarity** 兼容）。最後網絡輸出是最後一次校正 embedding。

## Network Architecture
* 這個網路主要由兩個元件組成：輕量級特徵提取器 (**RMNet-based Backcone**) 和單個 **Re-Identification Head**。
* 為了減少整體運算時間，本文遵循**完全卷積網路**(Fully Convolutional Network，FCN)，沒有任何的全連接網路 (Fully Connected Network)。
* 最後透過 **$L_2$ Normalization** 擷取出的向量來當作此圖的 Embedding，並可拿來與其他圖片做 Cosine Similarity 計算距離。

## Optimization
* 本論文使用 Caffe 的框架。
* 使用有著 momentum 的 **SGD** Optimization，並以每 50k 迭代後將 Learning Rate 做 $10^{-1}$ 的 Decay，起始 Learning rate 設為 $10^{-2}$。
* 初始化方式使用混合策略：
    * 每個 Bottleneck 的 CNN($1\times1$) 被==正交初始化==，其餘權重使用 ==MSRA== 方法初始化。 
    * 本文還在 ==OpenImages== 上先做預訓練，預訓練的圖片是將擷取後的物件 crop 出大小為 $224\times224$，並且是在上面做分類的任務。
* 訓練輕量級網路有個重點，就是==盡量利用大部分的參數，避免修剪模型(Pruning model)== 而是使用 ==Dropout 去正規化 (Ratio: 10%)==。
* 但 Dropout 縮減了整體網路的容量，並且不適用於本文一開始說的小型架構，為了解決這問題，本文在==後期的迭代就禁用了 Dropout (當 Learning rate 夠小的時候)==，這種架構將會讓本模型早期除了不會過度擬合以外，而且可以再後期用盡所有的網路容量。
* 為了==解決資料不平衡==的問題，有了以下的做法 **(Hard Sample Mining，HSM)**：
    1. 每個分類採樣 k 個增強的影像。
    2. 估算每個樣本的 Loss 值：$w_1L_{glob}+w_2L_{center}+w_3L_{gpush}$
    3. 選擇最難的前 50% Loss。
    4. 在最難的樣本上做小批次的訓練。
    5. 最後增加難度的數量並開始訓練。
* 除了標準==水平翻轉== 以及==Random Crop== 外，最有用的方法是==Random Erasing==。

## Ablation Study (控制變量法、對比實驗、參數敏感性分析)
### ReLU & ELU
![](https://i.imgur.com/vTg9hNf.png)
* 上圖是利用 ReLU 跟 ELU 的比較，為了證明 ReLU 並不適用於這個問題，本文計算每個 CNN 中的濾波器權重絕對值之間的比例 $w_{max}/w_{min}$，高比例的值代表有不合理的濾波器在現今的 Level 上。
* 可以看出來在 ReLU 的網路架構上有超過一半以上的 Noisy Filter，而且這些濾波器往往都會變成被修剪掉以用來壓縮模型所使用。
* ELU 的結果就有顯著差別，基本上不太需要修剪 Filter，因此在不影響模型品質上本文選擇用 ELU 當作 Activation Function。

### Ablation Study on Marlet-1501 Dataset
![](https://i.imgur.com/hkFVEvi.png)

第一項僅使用 AM-Softmax Loss 而且模型大小有限，因此如果要跟其他最先進的(SOTA)結果比較還有段距離。

1. 本文先解決資料不平衡的問題，而使用的方法就是利用 Hard Sample Mining (HSM)，但未執行上面 HSM 的第 2 步驟。
2. 通過引入不同的局部結構 loss 來深入研究 manifold 學習方法：Center、Push、GlobPush，每個步驟都改善了我們的模型。
3. 尤其是在 Push 跟 GlobPush 使用了 Smart Margins 更是獲得了顯著的改進。
4. 本文一開始有說有使用 Dropout 可能導致模型的容量受限，因此在訓練後期禁用 Dropout 之後，也獲得了顯著的上升。
5. 最後一個增加效果的方法是將多個 Loss 混合到排名標準中來使 Sample Mining 過程更靈活(上面 HSM 的第二點，更聰明地考慮不同 Level Loss 的複雜度)，主要改進了 mAP 的結果。
6. 為了跟效果最好的幾個 Paper 做比較，本文也做了不同解析度的輸入測試，本文主要用 $160\times64$ 的解析度當輸入，也測試了 $384\times128$ 可以看出效果的確也有上升，但速度會變慢。

## Result
### OpenVINO on Intel Core i7-6700K CPU@2.90GHz
![](https://i.imgur.com/cGlwBtw.png)

* 由上表可以看出本文的效果快上很多，這是由於本文不是用 ResNet-50 而是用 RMNet 的 Backbone。
* 本文提出的 Loss 跟訓練策略是使我們可以用這麼少參數還可以訓練這麼好的原因。
* 依照本文的做法 FPS 可以跑到 923，甚至可即時處理每個 Frame 約 30 人，目前沒有技術可以做到。

## 實作後的模型
![](https://i.imgur.com/n3qcohH.jpg)
