# 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 的優點,而且還不會增加參數量。

:::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 的強因子去相加。

* 使用 ELU 替代常用的 ReLU 會有顯著的改善。
* 正交權重初始化(不適用於所有 Filter)。
* 使用巨大的通用數據集進行預訓練。
* 在每個 Bottleneck 結束前使用 Dropout 正規化。

## ReID Network
### Losses
* 本文定義了兩種 Loss: **Global and Local structure losses**
* **Global Loss**: 定義映射函數的 Global Rule,希望能夠讓相同類別的元素越近不同類別的越遠。
* 對具有 Cross-Entropy Loss 的 Softmax 進行修改(下方第一個公式),變為關注在類之間具有較大 margin 的變數,也就是 **AM-Softmax loss**,公式如下第二個:


:::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 的架構:

* 最後整體 Loss 就是將 global 與 local 的 loss 相加($w_i$ 是指預估每個 loss 在總和中的影響):

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

* 本文的 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

* 上圖是利用 ReLU 跟 ELU 的比較,為了證明 ReLU 並不適用於這個問題,本文計算每個 CNN 中的濾波器權重絕對值之間的比例 $w_{max}/w_{min}$,高比例的值代表有不合理的濾波器在現今的 Level 上。
* 可以看出來在 ReLU 的網路架構上有超過一半以上的 Noisy Filter,而且這些濾波器往往都會變成被修剪掉以用來壓縮模型所使用。
* ELU 的結果就有顯著差別,基本上不太需要修剪 Filter,因此在不影響模型品質上本文選擇用 ELU 當作 Activation Function。
### Ablation Study on Marlet-1501 Dataset

第一項僅使用 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

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